]> git.sur5r.net Git - i3/i3/blobdiff - src/floating.c
Merge pull request #3058 from d-e-s-o/fix-FREE
[i3/i3] / src / floating.c
index f0499e60a2d7020ed5701d124fe76417b0fb5c4e..14988818418c972e70a9d1181cf10d990c886256 100644 (file)
@@ -535,6 +535,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);
@@ -646,6 +651,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);
@@ -657,7 +667,7 @@ void floating_resize_window(Con *con, const bool proportional,
 
 /* Custom data structure used to track dragging-related events. */
 struct drag_x11_cb {
-    ev_check check;
+    ev_prepare prepare;
 
     /* Whether this modal event loop should be exited and with which result. */
     drag_result_t result;
@@ -676,7 +686,7 @@ struct drag_x11_cb {
     const void *extra;
 };
 
-static void xcb_drag_check_cb(EV_P_ ev_check *w, int revents) {
+static void xcb_drag_prepare_cb(EV_P_ ev_prepare *w, int revents) {
     struct drag_x11_cb *dragloop = (struct drag_x11_cb *)w->data;
     xcb_motion_notify_event_t *last_motion_notify = NULL;
     xcb_generic_event_t *event;
@@ -743,13 +753,20 @@ 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);
+
+    xcb_flush(conn);
 }
 
 /*
@@ -816,18 +833,18 @@ drag_result_t drag_pointer(Con *con, const xcb_button_press_event_t *event, xcb_
         .callback = callback,
         .extra = extra,
     };
-    ev_check *check = &loop.check;
+    ev_prepare *prepare = &loop.prepare;
     if (con)
         loop.old_rect = con->rect;
-    ev_check_init(check, xcb_drag_check_cb);
-    check->data = &loop;
+    ev_prepare_init(prepare, xcb_drag_prepare_cb);
+    prepare->data = &loop;
     main_set_x11_cb(false);
-    ev_check_start(main_loop, check);
+    ev_prepare_start(main_loop, prepare);
 
     while (loop.result == DRAGGING)
         ev_run(main_loop, EVRUN_ONCE);
 
-    ev_check_stop(main_loop, check);
+    ev_prepare_stop(main_loop, prepare);
     main_set_x11_cb(true);
 
     xcb_ungrab_keyboard(conn, XCB_CURRENT_TIME);