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/707/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,35 @@ 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("Handling _NET_WM_MOVERESIZE request (con = %p)\n", con);
   | 
  
| 78 | 
	  
	  + uint32_t direction = event->data.data32[2];  | 
  
| 79 | 
	  
	  + uint32_t x_root = event->data.data32[0];  | 
  
| 80 | 
	  
	  + uint32_t y_root = event->data.data32[1];  | 
  
| 81 | 
	  
	  + /* construct fake xcb_button_press_event_t */  | 
  
| 82 | 
	  
	  +             xcb_button_press_event_t fake = {
   | 
  
| 83 | 
	  
	  + .root_x = x_root,  | 
  
| 84 | 
	  
	  + .root_y = y_root,  | 
  
| 85 | 
	  
	  + .event_x = x_root-(con->rect.x),  | 
  
| 86 | 
	  
	  + .event_y = y_root-(con->rect.y)  | 
  
| 87 | 
	  
	  + };  | 
  
| 88 | 
	  
	  +             if(direction == _NET_WM_MOVERESIZE_MOVE) {
   | 
  
| 89 | 
	  
	  + floating_drag_window(con->parent, &fake);  | 
  
| 90 | 
	  
	  +             } else if(direction >= _NET_WM_MOVERESIZE_SIZE_TOPLEFT && direction <= _NET_WM_MOVERESIZE_SIZE_LEFT) {
   | 
  
| 91 | 
	  
	  + floating_resize_window(con->parent, FALSE, &fake);  | 
  
| 92 | 
	  
	  +             } else {
   | 
  
| 93 | 
	  
	  +                DLOG("_NET_WM_MOVERESIZE direction %d not implemented\n", direction);
   | 
  
| 94 | 
	  
	  + }  | 
  
| 95 | 
	  
	  +  | 
  
| 96 | 
	  
	  +         } else {
   | 
  
| 97 | 
	  
	  +             DLOG("Couldn't find con for _NET_WM_MOVERESIZE request. or con not floating (window = %d)\n", event->window);
   | 
  
| 98 | 
	  
	  + }  | 
  
| 99 | 
	  
	       } else {
   | 
  
| 100 | 
	  
	           DLOG("unhandled clientmessage\n");
   | 
  
| 101 | 
	  
	  return;  |