Check container existance during drag events

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
next
Orestis Floros 2017-09-22 19:25:02 +03:00 committed by Michael Stapelberg
parent 2e83d2193e
commit eadc9a8461
1 changed files with 21 additions and 6 deletions

View 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);
@ -743,12 +753,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);
}