i3 - improved tiling WM


Implement EWMH number of desktops property

Patch status: merged

Patch by Tony Crisci

Long description:

_NET_NUMBER_OF_DESKTOPS:

> This property SHOULD be set and updated by the Window Manager to
> indicate the number of virtual desktops.

We interpret this property as the number of noninternal workspaces.

To apply this patch, use:
curl http://cr.i3wm.org/patch/583/raw.patch | git am

b/include/atoms.xmacro

23
@@ -16,6 +16,7 @@ xmacro(_NET_WM_STRUT_PARTIAL)
24
 xmacro(_NET_CLIENT_LIST)
25
 xmacro(_NET_CLIENT_LIST_STACKING)
26
 xmacro(_NET_CURRENT_DESKTOP)
27
+xmacro(_NET_NUMBER_OF_DESKTOPS)
28
 xmacro(_NET_ACTIVE_WINDOW)
29
 xmacro(_NET_STARTUP_ID)
30
 xmacro(_NET_WORKAREA)

b/include/ewmh.h

35
@@ -19,6 +19,12 @@
36
 void ewmh_update_current_desktop(void);
37
 
38
 /**
39
+ * Updates _NET_NUMBER_OF_DESKTOPS which we interpret as the number of
40
+ * noninternal workspaces.
41
+ */
42
+void ewmh_update_number_of_desktops(void);
43
+
44
+/**
45
  * Updates _NET_ACTIVE_WINDOW with the currently focused window.
46
  *
47
  * EWMH: The window ID of the currently active window or None if no window has

b/src/ewmh.c

52
@@ -41,6 +41,27 @@ void ewmh_update_current_desktop(void) {
53
 }
54
 
55
 /*
56
+ * Updates _NET_NUMBER_OF_DESKTOPS which we interpret as the number of
57
+ * noninternal workspaces.
58
+ */
59
+void ewmh_update_number_of_desktops(void) {
60
+    Con *output;
61
+    uint32_t idx = 0;
62
+
63
+    TAILQ_FOREACH (output, &(croot->nodes_head), nodes) {
64
+        Con *ws;
65
+        TAILQ_FOREACH (ws, &(output_get_content(output)->nodes_head), nodes) {
66
+            if (STARTS_WITH(ws->name, "__"))
67
+                continue;
68
+            ++idx;
69
+        }
70
+    }
71
+
72
+    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
73
+            A__NET_NUMBER_OF_DESKTOPS, XCB_ATOM_CARDINAL, 32, 1, &idx);
74
+}
75
+
76
+/*
77
  * Updates _NET_ACTIVE_WINDOW with the currently focused window.
78
  *
79
  * EWMH: The window ID of the currently active window or None if no window has
80
@@ -133,7 +154,7 @@ void ewmh_setup_hints(void) {
81
         NULL);
82
     xcb_change_property(conn, XCB_PROP_MODE_REPLACE, child_window, A__NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 32, 1, &child_window);
83
     xcb_change_property(conn, XCB_PROP_MODE_REPLACE, child_window, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3"), "i3");
84
-    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 32, 1, &child_window);
85
+    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 33, 1, &child_window);
86
 
87
     /* I’m not entirely sure if we need to keep _NET_WM_NAME on root. */
88
     xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3"), "i3");

b/src/main.c

93
@@ -765,8 +765,9 @@ int main(int argc, char *argv[]) {
94
     x_set_i3_atoms();
95
     ewmh_update_workarea();
96
 
97
-    /* Set the _NET_CURRENT_DESKTOP property. */
98
+    /* Set the ewmh desktop properties. */
99
     ewmh_update_current_desktop();
100
+    ewmh_update_number_of_desktops();
101
 
102
     struct ev_io *xcb_watcher = scalloc(sizeof(struct ev_io));
103
     struct ev_io *xkb = scalloc(sizeof(struct ev_io));

b/src/workspace.c

108
@@ -92,6 +92,7 @@ Con *workspace_get(const char *num, bool *created) {
109
         con_attach(workspace, content, false);
110
 
111
         ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}");
112
+        ewmh_update_number_of_desktops();
113
         if (created != NULL)
114
             *created = true;
115
     } else if (created != NULL) {
116
@@ -424,6 +425,7 @@ static void _workspace_show(Con *workspace) {
117
             LOG("Closing old workspace (%p / %s), it is empty\n", old, old->name);
118
             tree_close(old, DONT_KILL_WINDOW, false, false);
119
             ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"empty\"}");
120
+            ewmh_update_number_of_desktops();
121
         }
122
     }
123