From 1c5ab5fa36ce82b8cbb7e33dbeb350e57f927d03 Mon Sep 17 00:00:00 2001 From: Lukas K Date: Tue, 27 Jan 2015 22:58:48 +0100 Subject: [PATCH] Support _NET_WM_MOVERESIZE 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 | 1 + src/ewmh.c | 3 ++- src/handlers.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/atoms.xmacro b/include/atoms.xmacro index 2755d6cb..1f28c014 100644 --- a/include/atoms.xmacro +++ b/include/atoms.xmacro @@ -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) diff --git a/src/ewmh.c b/src/ewmh.c index 0746a5e1..844a0db9 100644 --- a/src/ewmh.c +++ b/src/ewmh.c @@ -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); } diff --git a/src/handlers.c b/src/handlers.c index 569a8ec3..27e899ea 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -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;