i3 - improved tiling WM


Support _NET_WM_MOVERESIZE

Patch status: needinfo

Patch by Lukas K

Long description:

Add support for the _NET_WM_MOVERESIZE client message. This message
enables clients to initiate window moving or resizing. Toolkits like
Gtk3 use this message when the user drags a client-side decorated window
by its title bar. When Gtk detects that the window manager does not
support this client message, it uses a slow fallback implementation.

fixes #1432

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

b/include/atoms.xmacro

22
@@ -1,6 +1,7 @@
23
 xmacro(_NET_SUPPORTED)
24
 xmacro(_NET_SUPPORTING_WM_CHECK)
25
 xmacro(_NET_WM_NAME)
26
+xmacro(_NET_WM_MOVERESIZE)
27
 xmacro(_NET_WM_STATE_FULLSCREEN)
28
 xmacro(_NET_WM_STATE_DEMANDS_ATTENTION)
29
 xmacro(_NET_WM_STATE_MODAL)

b/src/ewmh.c

34
@@ -234,5 +234,6 @@ void ewmh_setup_hints(void) {
35
     /* I’m not entirely sure if we need to keep _NET_WM_NAME on root. */
36
     xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3"), "i3");
37
 
38
-    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 23, supported_atoms);
39
+    /* only send the first 24 atoms (last one is _NET_CLOSE_WINDOW) increment that number when adding supported atoms */
40
+    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 24, supported_atoms);
41
 }

b/src/handlers.c

46
@@ -651,6 +651,19 @@ static void handle_expose_event(xcb_expose_event_t *event) {
47
     return;
48
 }
49
 
50
+#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT      0
51
+#define _NET_WM_MOVERESIZE_SIZE_TOP          1
52
+#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT     2
53
+#define _NET_WM_MOVERESIZE_SIZE_RIGHT        3
54
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT  4
55
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOM       5
56
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT   6
57
+#define _NET_WM_MOVERESIZE_SIZE_LEFT         7
58
+#define _NET_WM_MOVERESIZE_MOVE              8  /* movement only */
59
+#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD     9  /* size via keyboard */
60
+#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD     10 /* move via keyboard */
61
+#define _NET_WM_MOVERESIZE_CANCEL            11 /* cancel operation */
62
+
63
 /*
64
  * Handle client messages (EWMH)
65
  *
66
@@ -856,6 +869,33 @@ static void handle_client_message(xcb_client_message_event_t *event) {
67
         } else {
68
             DLOG("Couldn't find con for _NET_CLOSE_WINDOW request. (window = %d)\n", event->window);
69
         }
70
+    } else if (event->type == A__NET_WM_MOVERESIZE) {
71
+        /*
72
+         * Client-side decorated Gtk3 windows emit this signal when being
73
+         * dragged by their GtkHeaderBar
74
+         */
75
+        Con *con = con_by_window_id(event->window);
76
+        if (!con || !con_is_floating(con)) {
77
+            DLOG("Couldn't find con for _NET_WM_MOVERESIZE request, or con not floating (window = %d)\n", event->window);
78
+            return;
79
+        }
80
+        DLOG("Handling _NET_WM_MOVERESIZE request (con = %p)\n", con);
81
+        uint32_t direction = event->data.data32[2];
82
+        uint32_t x_root = event->data.data32[0];
83
+        uint32_t y_root = event->data.data32[1];
84
+        /* construct fake xcb_button_press_event_t */
85
+        xcb_button_press_event_t fake = {
86
+            .root_x = x_root,
87
+            .root_y = y_root,
88
+            .event_x = x_root - (con->rect.x),
89
+            .event_y = y_root - (con->rect.y)};
90
+        if (direction == _NET_WM_MOVERESIZE_MOVE) {
91
+            floating_drag_window(con->parent, &fake);
92
+        } else if (direction >= _NET_WM_MOVERESIZE_SIZE_TOPLEFT && direction <= _NET_WM_MOVERESIZE_SIZE_LEFT) {
93
+            floating_resize_window(con->parent, FALSE, &fake);
94
+        } else {
95
+            DLOG("_NET_WM_MOVERESIZE direction %d not implemented\n", direction);
96
+        }
97
     } else {
98
         DLOG("unhandled clientmessage\n");
99
         return;