i3 - improved tiling WM


Change drag_pointer return type to int

Patch status: needinfo

Patch by Tony Crisci

To apply this patch, use:
curl http://cr.i3wm.org/patch/233/raw.patch | git am

b/include/floating.h

14
@@ -138,10 +138,11 @@ void floating_toggle_hide(xcb_connection_t *conn, Workspace *workspace);
15
  * Every time you move your mouse, an XCB_MOTION_NOTIFY event will be received
16
  * and the given callback will be called with the parameters specified (client,
17
  * border on which the click originally was), the original rect of the client,
18
- * the event and the new coordinates (x, y).
19
+ * the event and the new coordinates (x, y). A return value of 1 indicates the
20
+ * user has cancelled the drag and the action should be undone.
21
  *
22
  */
23
-void drag_pointer(Con *con, const xcb_button_press_event_t *event,
24
+int drag_pointer(Con *con, const xcb_button_press_event_t *event,
25
                   xcb_window_t confine_to, border_t border, int cursor,
26
                   callback_t callback, const void *extra);
27
 

b/src/floating.c

32
@@ -561,7 +561,7 @@ void floating_resize_window(Con *con, const bool proportional,
33
  * the event and the new coordinates (x, y).
34
  *
35
  */
36
-void drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_window_t
37
+int drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_window_t
38
                 confine_to, border_t border, int cursor, callback_t callback, const void *extra)
39
 {
40
     uint32_t new_x, new_y;
41
@@ -587,16 +587,38 @@ void drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_window_t
42
 
43
     if ((reply = xcb_grab_pointer_reply(conn, cookie, NULL)) == NULL) {
44
         ELOG("Could not grab pointer\n");
45
-        return;
46
+        return 0;
47
     }
48
 
49
     free(reply);
50
 
51
+    /* Grab the keyboard */
52
+    xcb_grab_keyboard_cookie_t keyb_cookie;
53
+    xcb_grab_keyboard_reply_t *keyb_reply;
54
+
55
+    keyb_cookie = xcb_grab_keyboard(conn,
56
+            false, /* get all keyboard events */
57
+            root, /* grab the root window */
58
+            XCB_CURRENT_TIME,
59
+            XCB_GRAB_MODE_ASYNC, /* continue processing pointer events as normal */
60
+            XCB_GRAB_MODE_ASYNC /* keyboard mode */
61
+            );
62
+
63
+    if ((keyb_reply = xcb_grab_keyboard_reply(conn, keyb_cookie, NULL)) == NULL) {
64
+        ELOG("Could not grab keyboard\n");
65
+        return 0;
66
+    }
67
+
68
+    free(keyb_reply);
69
+
70
     /* Go into our own event loop */
71
     xcb_flush(conn);
72
 
73
     xcb_generic_event_t *inside_event, *last_motion_notify = NULL;
74
+    xcb_key_press_event_t *inside_keyboard_event = NULL;
75
     bool loop_done = false;
76
+    /* The return value, set to 1 on user cancel */
77
+    int drag_result = 0;
78
     /* I’ve always wanted to have my own eventhandler… */
79
     while (!loop_done && (inside_event = xcb_wait_for_event(conn))) {
80
         /* We now handle all events we can get using xcb_poll_for_event */
81
@@ -621,13 +643,25 @@ void drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_window_t
82
                     break;
83
 
84
                 case XCB_UNMAP_NOTIFY:
85
-                case XCB_KEY_PRESS:
86
-                case XCB_KEY_RELEASE:
87
                     DLOG("Unmap-notify, aborting\n");
88
                     handle_event(type, inside_event);
89
                     loop_done = true;
90
                     break;
91
 
92
+                case XCB_KEY_PRESS:
93
+                case XCB_KEY_RELEASE:
94
+                    /* Cancel the drag if the ESC key was pressed */
95
+                    inside_keyboard_event = (xcb_key_press_event_t *)inside_event;
96
+
97
+                    if ((int)inside_keyboard_event->detail == 9) {
98
+                        DLOG("ESC key was pressed, drag cancelled.");
99
+                        loop_done = true;
100
+                        drag_result = 1;
101
+                    }
102
+
103
+                    handle_event(type, inside_event);
104
+                    break;
105
+
106
                 default:
107
                     DLOG("Passing to original handler\n");
108
                     /* Use original handler */
109
@@ -648,8 +682,12 @@ void drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_window_t
110
         FREE(last_motion_notify);
111
     }
112
 
113
-    xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
114
     xcb_flush(conn);
115
+
116
+    xcb_ungrab_keyboard(conn, XCB_CURRENT_TIME);
117
+    xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
118
+
119
+    return drag_result;
120
 }
121
 
122
 /*