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
next
Lukas K 2015-01-27 22:58:48 +01:00
parent 663235c714
commit 1c5ab5fa36
3 changed files with 43 additions and 1 deletions

View 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)

View File

@ -234,5 +234,6 @@ void ewmh_setup_hints(void) {
/* Im 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);
}

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