]> git.sur5r.net Git - i3/i3/commitdiff
Support _NET_WM_MOVERESIZE 1462/head
authorLukas K <lu@0x83.eu>
Tue, 27 Jan 2015 21:58:48 +0000 (22:58 +0100)
committerLukas K <lu@0x83.eu>
Tue, 10 Feb 2015 23:07:28 +0000 (00:07 +0100)
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

include/atoms.xmacro
src/ewmh.c
src/handlers.c

index 2755d6cb83cf0b3148ae62266065113dc8e09da2..1f28c01405209022c8567c6d9370fe0a1d7426e7 100644 (file)
@@ -1,6 +1,7 @@
 xmacro(_NET_SUPPORTED)
 xmacro(_NET_SUPPORTING_WM_CHECK)
 xmacro(_NET_WM_NAME)
+xmacro(_NET_WM_MOVERESIZE)
 xmacro(_NET_WM_STATE_FULLSCREEN)
 xmacro(_NET_WM_STATE_DEMANDS_ATTENTION)
 xmacro(_NET_WM_STATE_MODAL)
index 0746a5e189e6e710e965060ef43d1ad1ffcaeb21..844a0db921ada15d78cea84818ef82b282da19ac 100644 (file)
@@ -234,5 +234,6 @@ void ewmh_setup_hints(void) {
     /* 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, 23, supported_atoms);
+    /* only send the first 24 atoms (last one is _NET_CLOSE_WINDOW) increment that number when adding supported atoms */
+    xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A__NET_SUPPORTED, XCB_ATOM_ATOM, 32, 24, supported_atoms);
 }
index 569a8ec3deb1b36a0875f255a5062ca9c5c7cc00..27e899ea89072e6380c25239b8b6c338d6c94aba 100644 (file)
@@ -651,6 +651,19 @@ static void handle_expose_event(xcb_expose_event_t *event) {
     return;
 }
 
+#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT      0
+#define _NET_WM_MOVERESIZE_SIZE_TOP          1
+#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT     2
+#define _NET_WM_MOVERESIZE_SIZE_RIGHT        3
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT  4
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOM       5
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT   6
+#define _NET_WM_MOVERESIZE_SIZE_LEFT         7
+#define _NET_WM_MOVERESIZE_MOVE              8  /* movement only */
+#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD     9  /* size via keyboard */
+#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD     10 /* move via keyboard */
+#define _NET_WM_MOVERESIZE_CANCEL            11 /* cancel operation */
+
 /*
  * Handle client messages (EWMH)
  *
@@ -856,6 +869,33 @@ static void handle_client_message(xcb_client_message_event_t *event) {
         } else {
             DLOG("Couldn't find con for _NET_CLOSE_WINDOW request. (window = %d)\n", event->window);
         }
+    } else if (event->type == A__NET_WM_MOVERESIZE) {
+        /*
+         * Client-side decorated Gtk3 windows emit this signal when being
+         * dragged by their GtkHeaderBar
+         */
+        Con *con = con_by_window_id(event->window);
+        if (!con || !con_is_floating(con)) {
+            DLOG("Couldn't find con for _NET_WM_MOVERESIZE request, or con not floating (window = %d)\n", event->window);
+            return;
+        }
+        DLOG("Handling _NET_WM_MOVERESIZE request (con = %p)\n", con);
+        uint32_t direction = event->data.data32[2];
+        uint32_t x_root = event->data.data32[0];
+        uint32_t y_root = event->data.data32[1];
+        /* construct fake xcb_button_press_event_t */
+        xcb_button_press_event_t fake = {
+            .root_x = x_root,
+            .root_y = y_root,
+            .event_x = x_root - (con->rect.x),
+            .event_y = y_root - (con->rect.y)};
+        if (direction == _NET_WM_MOVERESIZE_MOVE) {
+            floating_drag_window(con->parent, &fake);
+        } else if (direction >= _NET_WM_MOVERESIZE_SIZE_TOPLEFT && direction <= _NET_WM_MOVERESIZE_SIZE_LEFT) {
+            floating_resize_window(con->parent, FALSE, &fake);
+        } else {
+            DLOG("_NET_WM_MOVERESIZE direction %d not implemented\n", direction);
+        }
     } else {
         DLOG("unhandled clientmessage\n");
         return;