When the user cancels a window move, restore workspace & maximisation, jump to that workspace and make sure that the restored window has the input focus. Fix problems with misplaced button release events on a cancelled move/resize by retaining the grab until the button which was used to start the operation is released. (Without this, unwanted middle-button pastes etc. could happen.) Signed-Off-By: Darren Salt Index: src/client.c =================================================================== --- src/client.c (revision 22220) +++ src/client.c (working copy) @@ -98,6 +98,8 @@ gboolean grab; gboolean is_transient; gboolean move_resized; + gboolean released; + int button; int cancel_x, cancel_y; /* for cancellation (either position or size) */ int mx, my; int ox, oy; @@ -3123,6 +3125,23 @@ } static eventFilterStatus +clientMoveResize_release_filter (XEvent * xevent, gpointer data) +{ + MoveResizeData *passdata = (MoveResizeData *) data; + + TRACE ("entering clientMoveResize_release_filter"); + + if ((xevent->type == ButtonRelease) && + (xevent->xbutton.button == passdata->button)) + { + gtk_main_quit (); + return EVENT_FILTER_STOP; + } + + return EVENT_FILTER_CONTINUE; +} + +static eventFilterStatus clientMove_event_filter (XEvent * xevent, gpointer data) { static int edge_scroll_x = 0; @@ -3214,6 +3233,7 @@ if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_CANCEL].keycode) { moving = FALSE; + passdata->released = passdata->use_keys; if (screen_info->params->box_move) { @@ -3247,6 +3267,7 @@ if (!passdata->use_keys) { moving = FALSE; + passdata->released = (xevent->xbutton.button == passdata->button); } } else if (xevent->type == MotionNotify) @@ -3516,13 +3537,15 @@ passdata.cancel_y = passdata.oy = c->y; passdata.use_keys = FALSE; passdata.grab = FALSE; + passdata.released = FALSE; + passdata.button = ev->xbutton.button; passdata.is_transient = clientIsValidTransientOrModal (c); passdata.move_resized = FALSE; if (ev->type == KeyPress) { cursor = None; - passdata.use_keys = TRUE; + passdata.released = passdata.use_keys = TRUE; passdata.mx = ev->xkey.x_root; passdata.my = ev->xkey.y_root; } @@ -3614,6 +3637,15 @@ clientConfigure (c, &wc, changes, NO_CFG_FLAG); myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info)); + if (!passdata.released) + { + /* If this is a drag-move, wait for the button to be released. + * If we don't, we might get release events in the wrong place. + */ + eventFilterPush (display_info->xfilter, clientMoveResize_release_filter, &passdata); + gtk_main (); + eventFilterPop (display_info->xfilter); + } myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info)); if (passdata.grab && screen_info->params->box_move) { @@ -3791,6 +3823,7 @@ if (xevent->xkey.keycode == screen_info->params->keys[KEY_MOVE_CANCEL].keycode) { resizing = FALSE; + passdata->released = passdata->use_keys; if (screen_info->params->box_resize) { @@ -3970,6 +4003,7 @@ if (!passdata->use_keys) { resizing = FALSE; + passdata->released = (xevent->xbutton.button == passdata->button); } } else if ((xevent->type == UnmapNotify) && (xevent->xunmap.window == c->window)) @@ -4020,13 +4054,15 @@ passdata.cancel_y = passdata.oy = c->height; passdata.use_keys = FALSE; passdata.grab = FALSE; + passdata.released = FALSE; + passdata.button = ev->xbutton.button; passdata.corner = corner; w_orig = c->width; h_orig = c->height; if (ev->type == KeyPress) { - passdata.use_keys = TRUE; + passdata.released = passdata.use_keys = TRUE; passdata.mx = ev->xkey.x_root; passdata.my = ev->xkey.y_root; } @@ -4118,6 +4154,15 @@ clientConfigure (c, &wc, CWX | CWY | CWHeight | CWWidth, CFG_NOTIFY); myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info)); + if (!passdata.released) + { + /* If this is a drag-resize, wait for the button to be released. + * If we don't, we might get release events in the wrong place. + */ + eventFilterPush (display_info->xfilter, clientMoveResize_release_filter, &passdata); + gtk_main (); + eventFilterPop (display_info->xfilter); + } myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info)); if (passdata.grab && screen_info->params->box_resize) {