]> git.sur5r.net Git - i3/i3/blobdiff - src/ewmh.c
Implement EWMH desktop names
[i3/i3] / src / ewmh.c
index 16c9858195dc093793d1c8d18822b505604a0398..da5dba5fe8c8fda5b5044095adfaf03898f7f313 100644 (file)
@@ -32,7 +32,7 @@ void ewmh_update_current_desktop(void) {
 
             if (ws == focused_ws) {
                 xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
-                        A__NET_CURRENT_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, &idx);
+                                    A__NET_CURRENT_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, &idx);
                 return;
             }
             ++idx;
@@ -40,6 +40,102 @@ void ewmh_update_current_desktop(void) {
     }
 }
 
+/*
+ * Updates _NET_NUMBER_OF_DESKTOPS which we interpret as the number of
+ * noninternal workspaces.
+ */
+void ewmh_update_number_of_desktops(void) {
+    Con *output;
+    uint32_t idx = 0;
+
+    TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+        Con *ws;
+        TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
+            if (STARTS_WITH(ws->name, "__"))
+                continue;
+            ++idx;
+        }
+    }
+
+    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
+                        A__NET_NUMBER_OF_DESKTOPS, XCB_ATOM_CARDINAL, 32, 1, &idx);
+}
+
+/*
+ * Updates _NET_DESKTOP_NAMES: "The names of all virtual desktops. This is a
+ * list of NULL-terminated strings in UTF-8 encoding"
+ */
+void ewmh_update_desktop_names(void) {
+    Con *output;
+    int msg_length = 0;
+
+    /* count the size of the property message to set */
+    TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+        Con *ws;
+        TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
+            if (STARTS_WITH(ws->name, "__"))
+                continue;
+            msg_length += strlen(ws->name) + 1;
+        }
+    }
+
+    char desktop_names[msg_length];
+    int current_position = 0;
+
+    /* fill the buffer with the names of the i3 workspaces */
+    TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+        Con *ws;
+        TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
+            if (STARTS_WITH(ws->name, "__"))
+                continue;
+
+            for (size_t i = 0; i < strlen(ws->name) + 1; i++) {
+                desktop_names[current_position++] = ws->name[i];
+            }
+        }
+    }
+
+    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
+                        A__NET_DESKTOP_NAMES, A_UTF8_STRING, 8, msg_length, desktop_names);
+}
+
+/*
+ * Updates _NET_DESKTOP_VIEWPORT, which is an array of pairs of cardinals that
+ * define the top left corner of each desktop's viewport.
+ */
+void ewmh_update_desktop_viewport(void) {
+    Con *output;
+    int num_desktops = 0;
+    /* count number of desktops */
+    TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+        Con *ws;
+        TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
+            if (STARTS_WITH(ws->name, "__"))
+                continue;
+
+            num_desktops++;
+        }
+    }
+
+    uint32_t viewports[num_desktops * 2];
+
+    int current_position = 0;
+    /* fill the viewport buffer */
+    TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
+        Con *ws;
+        TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
+            if (STARTS_WITH(ws->name, "__"))
+                continue;
+
+            viewports[current_position++] = output->rect.x;
+            viewports[current_position++] = output->rect.y;
+        }
+    }
+
+    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
+                        A__NET_DESKTOP_VIEWPORT, XCB_ATOM_CARDINAL, 32, current_position, &viewports);
+}
+
 /*
  * Updates _NET_ACTIVE_WINDOW with the currently focused window.
  *
@@ -49,7 +145,7 @@ void ewmh_update_current_desktop(void) {
  */
 void ewmh_update_active_window(xcb_window_t window) {
     xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
-            A__NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 32, 1, &window);
+                        A__NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 32, 1, &window);
 }
 
 /*
@@ -109,7 +205,7 @@ void ewmh_update_client_list_stacking(xcb_window_t *stack, int num_windows) {
  */
 void ewmh_setup_hints(void) {
     xcb_atom_t supported_atoms[] = {
-#define xmacro(atom) A_ ## atom,
+#define xmacro(atom) A_##atom,
 #include "atoms.xmacro"
 #undef xmacro
     };
@@ -122,21 +218,21 @@ void ewmh_setup_hints(void) {
     xcb_window_t child_window = xcb_generate_id(conn);
     xcb_create_window(
         conn,
-        XCB_COPY_FROM_PARENT, /* depth */
-        child_window, /* window id */
-        root, /* parent */
-        0, 0, 1, 1, /* dimensions (x, y, w, h) */
-        0, /* border */
+        XCB_COPY_FROM_PARENT,        /* depth */
+        child_window,                /* window id */
+        root,                        /* parent */
+        0, 0, 1, 1,                  /* dimensions (x, y, w, h) */
+        0,                           /* border */
         XCB_WINDOW_CLASS_INPUT_ONLY, /* window class */
-        XCB_COPY_FROM_PARENT, /* visual */
+        XCB_COPY_FROM_PARENT,        /* visual */
         0,
         NULL);
     xcb_change_property(conn, XCB_PROP_MODE_REPLACE, child_window, A__NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 32, 1, &child_window);
     xcb_change_property(conn, XCB_PROP_MODE_REPLACE, child_window, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3"), "i3");
-    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 32, 1, &child_window);
+    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 33, 1, &child_window);
 
     /* I’m not entirely sure if we need to keep _NET_WM_NAME on root. */
     xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3"), "i3");
 
-    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 19, supported_atoms);
+    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 21, supported_atoms);
 }