window: Properly end grab ops started from a keybind / menu

If we start a grab op from a keybind / menu, we'll handle the
ButtonPress and drop the grab then, never giving the window a chance
to handle what it needs to do before the grab is dropped.

This means that if you use Alt+F7 to move a window around, move it
to a side-tiling or maximization area, and then left-click, it will
just hang there in the sky.
This commit is contained in:
Jasper St. Pierre 2014-04-20 12:45:40 -04:00
parent 064ef09c99
commit cef2745bc0
2 changed files with 66 additions and 54 deletions

View File

@ -1949,24 +1949,15 @@ meta_display_handle_event (MetaDisplay *display,
display->overlay_key_only_pressed = FALSE;
if ((window &&
meta_grab_op_is_mouse (display->grab_op) &&
(event->button.modifier_state & display->window_grab_modifiers) &&
display->grab_button != (int) event->button.button &&
display->grab_window == window) ||
meta_grab_op_is_keyboard (display->grab_op))
if (display->grab_window == window &&
meta_grab_op_is_moving_or_resizing (display->grab_op))
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Ending grab op %u on window %s due to button press\n",
display->grab_op,
(display->grab_window ?
display->grab_window->desc :
"none"));
meta_display_end_grab_op (display, event->any.time);
meta_window_handle_mouse_grab_op_event (window, event);
bypass_clutter = TRUE;
bypass_wayland = TRUE;
}
else if (window && display->grab_op == META_GRAB_OP_NONE)
if (window && display->grab_op == META_GRAB_OP_NONE)
{
ClutterModifierType grab_mask;
gboolean unmodified;

View File

@ -7518,56 +7518,77 @@ meta_window_update_sync_request_counter (MetaWindow *window,
}
#endif /* HAVE_XSYNC */
static void
end_grab_op (MetaWindow *window,
const ClutterEvent *event)
{
meta_display_check_threshold_reached (window->display,
event->button.x,
event->button.y);
/* If the user was snap moving then ignore the button
* release because they may have let go of shift before
* releasing the mouse button and they almost certainly do
* not want a non-snapped movement to occur from the button
* release.
*/
if (!window->display->grab_last_user_action_was_snap)
{
if (meta_grab_op_is_moving (window->display->grab_op))
{
if (window->tile_mode != META_TILE_NONE)
meta_window_tile (window);
else
update_move (window,
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->button.x,
event->button.y);
}
else if (meta_grab_op_is_resizing (window->display->grab_op))
{
update_resize (window,
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->button.x,
event->button.y,
TRUE);
/* If a tiled window has been dragged free with a
* mouse resize without snapping back to the tiled
* state, it will end up with an inconsistent tile
* mode on mouse release; cleaning the mode earlier
* would break the ability to snap back to the tiled
* state, so we wait until mouse release.
*/
update_tile_mode (window);
}
}
meta_display_end_grab_op (window->display, event->any.time);
}
void
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
const ClutterEvent *event)
{
switch (event->type)
{
case CLUTTER_BUTTON_PRESS:
/* This is the keybinding or menu case where we've
* been dragging around the window without the button
* pressed. */
if ((meta_grab_op_is_mouse (window->display->grab_op) &&
(event->button.modifier_state & window->display->window_grab_modifiers) &&
window->display->grab_button != (int) event->button.button) ||
meta_grab_op_is_keyboard (window->display->grab_op))
{
end_grab_op (window, event);
}
break;
case CLUTTER_BUTTON_RELEASE:
if (event->button.button == 1 ||
event->button.button == (unsigned int) meta_prefs_get_mouse_button_resize ())
{
meta_display_check_threshold_reached (window->display,
event->button.x,
event->button.y);
/* If the user was snap moving then ignore the button
* release because they may have let go of shift before
* releasing the mouse button and they almost certainly do
* not want a non-snapped movement to occur from the button
* release.
*/
if (!window->display->grab_last_user_action_was_snap)
{
if (meta_grab_op_is_moving (window->display->grab_op))
{
if (window->tile_mode != META_TILE_NONE)
meta_window_tile (window);
else
update_move (window,
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->button.x,
event->button.y);
}
else if (meta_grab_op_is_resizing (window->display->grab_op))
{
update_resize (window,
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->button.x,
event->button.y,
TRUE);
/* If a tiled window has been dragged free with a
* mouse resize without snapping back to the tiled
* state, it will end up with an inconsistent tile
* mode on mouse release; cleaning the mode earlier
* would break the ability to snap back to the tiled
* state, so we wait until mouse release.
*/
update_tile_mode (window);
}
}
meta_display_end_grab_op (window->display, event->any.time);
end_grab_op (window, event);
}
break;