]> git.sur5r.net Git - i3/i3/commitdiff
Check container existance during drag events 2977/head
authorOrestis Floros <orestisf1993@gmail.com>
Fri, 22 Sep 2017 16:25:02 +0000 (19:25 +0300)
committerOrestis Floros <orestisf1993@gmail.com>
Sat, 23 Sep 2017 08:19:56 +0000 (11:19 +0300)
This fixes a crash that occurs when disabling floating for a container
while it is being moved or resized.

@Deiz describes the problem:
> It occurs because the command that disables floating runs before the
event loop. So, the window is tiled, its floating parent is destroyed,
but then a key event is handled which causes the position/size of the
now-destroyed parent to be modified.

Fixes #1627

src/floating.c

index f29943393c208c60913449fedbfe04036ba5fb2d..6a95313264ee4b1e8e44eff785ed1719a6ac8c1f 100644 (file)
@@ -531,6 +531,11 @@ void floating_drag_window(Con *con, const xcb_button_press_event_t *event) {
     /* Drag the window */
     drag_result_t drag_result = drag_pointer(con, event, XCB_NONE, BORDER_TOP /* irrelevant */, XCURSOR_CURSOR_MOVE, drag_window_callback, event);
 
+    if (!con_exists(con)) {
+        DLOG("The container has been closed in the meantime.\n");
+        return;
+    }
+
     /* If the user cancelled, undo the changes. */
     if (drag_result == DRAG_REVERT)
         floating_reposition(con, initial_rect);
@@ -642,6 +647,11 @@ void floating_resize_window(Con *con, const bool proportional,
 
     drag_result_t drag_result = drag_pointer(con, event, XCB_NONE, BORDER_TOP /* irrelevant */, cursor, resize_window_callback, &params);
 
+    if (!con_exists(con)) {
+        DLOG("The container has been closed in the meantime.\n");
+        return;
+    }
+
     /* If the user cancels, undo the resize */
     if (drag_result == DRAG_REVERT)
         floating_reposition(con, initial_rect);
@@ -739,12 +749,17 @@ static void xcb_drag_check_cb(EV_P_ ev_check *w, int revents) {
     if (last_motion_notify == NULL)
         return;
 
-    dragloop->callback(
-        dragloop->con,
-        &(dragloop->old_rect),
-        last_motion_notify->root_x,
-        last_motion_notify->root_y,
-        dragloop->extra);
+    /* Ensure that we are either dragging the resize handle (con is NULL) or that the
+     * container still exists. The latter might not be true, e.g., if the window closed
+     * for any reason while the user was dragging it. */
+    if (!dragloop->con || con_exists(dragloop->con)) {
+        dragloop->callback(
+            dragloop->con,
+            &(dragloop->old_rect),
+            last_motion_notify->root_x,
+            last_motion_notify->root_y,
+            dragloop->extra);
+    }
     free(last_motion_notify);
 }