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; |