+ewmh_update_desktop_names(void)
+{
+ char *name_list = NULL, *p;
+ int num_screens, i, j, len = 0, tot = 0;
+
+ num_screens = get_screen_count();
+ for (i = 0; i < num_screens; ++i) {
+ for (j = 0; j < workspace_limit; ++j) {
+ if (screens[i].ws[j].name != NULL)
+ len += strlen(screens[i].ws[j].name);
+ ++len;
+ }
+
+ if((name_list = calloc(sizeof(char *), len)) == NULL)
+ err(1, "update_desktop_names: calloc: failed to "
+ "allocate memory.");
+
+ p = name_list;
+ for (j = 0; j < workspace_limit; ++j) {
+ if (screens[i].ws[j].name != NULL) {
+ len = strlen(screens[i].ws[j].name);
+ memcpy(p, screens[i].ws[j].name, len);
+ } else {
+ len = 0;
+ }
+
+ p += len + 1;
+ tot += len + 1;
+ }
+
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
+ screens[i].root, ewmh[_NET_DESKTOP_NAMES].atom,
+ a_utf8_string, 8, tot, name_list);
+
+ free(name_list);
+ name_list = NULL;
+ }
+
+ free(name_list);
+}
+
+void
+ewmh_get_desktop_names(void)
+{
+ char *names = NULL;
+ xcb_get_property_cookie_t c;
+ xcb_get_property_reply_t *r;
+ int num_screens, i, j, n, k;
+
+ num_screens = get_screen_count();
+ for (i = 0; i < num_screens; ++i) {
+ for (j = 0; j < workspace_limit; ++j) {
+ free(screens[i].ws[j].name);
+ screens[i].ws[j].name = NULL;
+ }
+
+ c = xcb_get_property(conn, 0, screens[i].root,
+ ewmh[_NET_DESKTOP_NAMES].atom,
+ a_utf8_string, 0, UINT32_MAX);
+ r = xcb_get_property_reply(conn, c, NULL);
+ if (r == NULL)
+ continue;
+
+ names = xcb_get_property_value(r);
+ n = xcb_get_property_value_length(r);
+
+ for (j = 0, k = 0; j < n; ++j) {
+ if (*(names + j) != '\0') {
+ screens[i].ws[k].name = strdup(names + j);
+ j += strlen(names + j);
+ }
+ ++k;
+ }
+ free(r);
+ }
+}
+
+void
+ewmh_update_client_list(void)
+{
+ struct ws_win *win;
+ int num_screens, i, j, k = 0, count = 0;
+ xcb_window_t *wins;
+
+ num_screens = get_screen_count();
+ for (i = 0; i < num_screens; ++i) {
+ for (j = 0; j < workspace_limit; ++j)
+ TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+ ++count;
+
+ DNPRINTF(SWM_D_PROP, "ewmh_update_client_list: win count: %d\n",
+ count);
+
+ if (count == 0)
+ continue;
+
+ wins = calloc(sizeof(xcb_window_t), count);
+ if (wins == NULL)
+ err(1, "ewmh_update_client_list: calloc: failed to "
+ "allocate memory.");
+
+ for (j = 0, k = 0; j < workspace_limit; ++j)
+ TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+ wins[k++] = win->id;
+
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
+ screens[i].root, ewmh[_NET_CLIENT_LIST].atom,
+ XCB_ATOM_WINDOW, 32, count, wins);
+
+ free(wins);
+ }
+}
+
+void
+ewmh_update_current_desktop(void)
+{
+ int num_screens, i;
+
+ num_screens = get_screen_count();
+ for (i = 0; i < num_screens; ++i)
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
+ screens[i].root, ewmh[_NET_CURRENT_DESKTOP].atom,
+ XCB_ATOM_CARDINAL, 32, 1, &screens[i].r_focus->ws->idx);
+}
+
+void
+ewmh_update_desktops(void)
+{
+ int num_screens, i, j;
+ uint32_t *vals;
+
+ vals = calloc(sizeof(uint32_t), workspace_limit * 2);
+ if (vals == NULL)
+ err(1, "ewmh_update_desktops: calloc: failed to allocate "
+ "memory.");
+
+ num_screens = get_screen_count();
+ for (i = 0; i < num_screens; i++) {
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
+ screens[i].root, ewmh[_NET_NUMBER_OF_DESKTOPS].atom,
+ XCB_ATOM_CARDINAL, 32, 1, &workspace_limit);
+
+ for (j = 0; j < workspace_limit; ++j) {
+ if (screens[i].ws[j].r != NULL) {
+ vals[j * 2] = X(screens[i].ws[j].r);
+ vals[j * 2 + 1] = Y(screens[i].ws[j].r);
+ } else if (screens[i].ws[j].old_r != NULL) {
+ vals[j * 2] = X(screens[i].ws[j].old_r);
+ vals[j * 2 + 1] = Y(screens[i].ws[j].old_r);
+ } else {
+ vals[j * 2] = vals[j * 2 + 1] = 0;
+ }
+ }
+
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE,
+ screens[i].root, ewmh[_NET_DESKTOP_VIEWPORT].atom,
+ XCB_ATOM_CARDINAL, 32, workspace_limit * 2, vals);
+ }
+
+ free(vals);
+}
+
+void