summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compositor/compositor.c31
-rw-r--r--src/core/display.c363
2 files changed, 95 insertions, 299 deletions
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index bb2092f0d..684a953dc 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -953,6 +953,29 @@ meta_compositor_window_surface_changed (MetaCompositor *compositor,
meta_window_actor_update_surface (window_actor);
}
+static gboolean
+grab_op_is_clicking (MetaGrabOp grab_op)
+{
+ switch (grab_op)
+ {
+ case META_GRAB_OP_CLICKING_MINIMIZE:
+ case META_GRAB_OP_CLICKING_MAXIMIZE:
+ case META_GRAB_OP_CLICKING_UNMAXIMIZE:
+ case META_GRAB_OP_CLICKING_DELETE:
+ case META_GRAB_OP_CLICKING_MENU:
+ case META_GRAB_OP_CLICKING_SHADE:
+ case META_GRAB_OP_CLICKING_UNSHADE:
+ case META_GRAB_OP_CLICKING_ABOVE:
+ case META_GRAB_OP_CLICKING_UNABOVE:
+ case META_GRAB_OP_CLICKING_STICK:
+ case META_GRAB_OP_CLICKING_UNSTICK:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
/* Clutter makes the assumption that there is only one X window
* per stage, which is a valid assumption to make for a generic
* application toolkit. As such, it will ignore any events sent
@@ -980,8 +1003,10 @@ maybe_spoof_event_as_stage_event (MetaCompScreen *info,
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
- /* If this is a window frame, let GTK+ handle it without mangling */
- if (window && window->frame && device_event->event == window->frame->xwindow)
+ /* If this is a window frame, and we think GTK+ needs to handle the event,
+ let GTK+ handle it without mangling */
+ if (window && window->frame && device_event->event == window->frame->xwindow &&
+ (display->grab_op == META_GRAB_OP_NONE || grab_op_is_clicking (display->grab_op)))
break;
case XI_KeyPress:
@@ -992,6 +1017,8 @@ maybe_spoof_event_as_stage_event (MetaCompScreen *info,
break;
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
+ device_event->event_x = device_event->root_x;
+ device_event->event_y = device_event->root_y;
break;
default:
break;
diff --git a/src/core/display.c b/src/core/display.c
index 9c1e72d1b..3631eebf0 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -2036,9 +2036,6 @@ meta_display_handle_event (MetaDisplay *display,
gboolean bypass_clutter = FALSE, bypass_wayland = FALSE;
MetaWaylandCompositor *compositor = NULL;
- /* XXX -- we need to fill this in properly at some point... */
- gboolean frame_was_receiver = FALSE;
-
if (meta_is_wayland_compositor ())
{
compositor = meta_wayland_compositor_get_default ();
@@ -2109,60 +2106,70 @@ meta_display_handle_event (MetaDisplay *display,
}
else if (window && display->grab_op == META_GRAB_OP_NONE)
{
- gboolean begin_move = FALSE;
ClutterModifierType grab_mask;
gboolean unmodified;
+ gboolean fully_modified;
grab_mask = display->window_grab_modifiers;
if (g_getenv ("MUTTER_DEBUG_BUTTON_GRABS"))
grab_mask |= CLUTTER_CONTROL_MASK;
- /* Two possible sources of an unmodified event; one is a
- * client that's letting button presses pass through to the
- * frame, the other is our focus_window_grab on unmodified
- * button 1. So for all such events we focus the window.
+ /* We have three passive button grabs:
+ * - on any button, without modifiers => focuses and maybe raises the window
+ * - on resize button, with modifiers => start an interactive resizing
+ * (normally <Super>middle)
+ * - on move button, with modifiers => start an interactive move
+ * (normally <Super>left)
+ * - on menu button, with modifiers => show the window menu
+ * (normally <Super>right)
+ *
+ * We may get here because we actually have a button
+ * grab on the window, or because we're a wayland
+ * compositor and thus we see all the events, so we
+ * need to check if the event is interesting.
+ * We want an event that is not modified, for a window
+ * that has (or would have, the wayland case) the
+ * button grab active.
+ *
+ * We may have other events on the window, for example
+ * a click on a frame button, but that's not for us to
+ * care about. Just let the event through.
*/
unmodified = (event->button.modifier_state & grab_mask) == 0;
+ fully_modified = (event->button.modifier_state & grab_mask) == grab_mask;
- if (unmodified ||
- event->button.button == 1)
+ if (unmodified && window && window->have_focus_click_grab)
{
- /* don't focus if frame received, will be lowered in
- * frames.c or special-cased if the click was on a
- * minimize/close button.
+ if (meta_prefs_get_raise_on_click ())
+ meta_window_raise (window);
+ else
+ meta_topic (META_DEBUG_FOCUS,
+ "Not raising window on click due to don't-raise-on-click option\n");
+
+ /* Don't focus panels--they must explicitly request focus.
+ * See bug 160470
*/
- if (!frame_was_receiver)
+ if (window->type != META_WINDOW_DOCK)
{
- if (meta_prefs_get_raise_on_click ())
- meta_window_raise (window);
- else
- meta_topic (META_DEBUG_FOCUS,
- "Not raising window on click due to don't-raise-on-click option\n");
-
- /* Don't focus panels--they must explicitly request focus.
- * See bug 160470
- */
- if (window->type != META_WINDOW_DOCK)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Focusing %s due to unmodified button %u press (display.c)\n",
- window->desc, event->button.button);
- meta_window_focus (window, event->any.time);
- }
- else
- /* However, do allow terminals to lose focus due to new
- * window mappings after the user clicks on a panel.
- */
- display->allow_terminal_deactivation = TRUE;
+ meta_topic (META_DEBUG_FOCUS,
+ "Focusing %s due to unmodified button %u press (display.c)\n",
+ window->desc, event->button.button);
+ meta_window_focus (window, event->any.time);
}
+ else
+ /* However, do allow terminals to lose focus due to new
+ * window mappings after the user clicks on a panel.
+ */
+ display->allow_terminal_deactivation = TRUE;
- /* you can move on alt-click but not on
- * the click-to-focus
- */
- if (!unmodified)
- begin_move = TRUE;
+ meta_verbose ("Allowing events time %u\n",
+ (unsigned int)event->button.time);
+
+ XIAllowEvents (display->xdisplay, clutter_input_device_get_device_id (event->button.device),
+ XIReplayDevice, event->button.time);
+ bypass_clutter = TRUE;
}
- else if (!unmodified && ((int) event->button.button == meta_prefs_get_mouse_button_resize ()))
+ else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_resize ())
{
if (window->has_resize_func)
{
@@ -2210,8 +2217,10 @@ meta_display_handle_event (MetaDisplay *display,
event->button.x,
event->button.y);
}
+ bypass_clutter = TRUE;
+ bypass_wayland = TRUE;
}
- else if ((int) event->button.button == meta_prefs_get_mouse_button_menu ())
+ else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_menu ())
{
if (meta_prefs_get_raise_on_click ())
meta_window_raise (window);
@@ -2223,20 +2232,22 @@ meta_display_handle_event (MetaDisplay *display,
bypass_clutter = TRUE;
bypass_wayland = TRUE;
}
-
- if (begin_move && window->has_move_func)
+ else if (fully_modified && (int) event->button.button == 1)
{
- meta_display_begin_grab_op (display,
- window->screen,
- window,
- META_GRAB_OP_MOVING,
- TRUE,
- FALSE,
- event->button.button,
- 0,
- event->any.time,
- event->button.x,
- event->button.y);
+ if (window->has_move_func)
+ {
+ meta_display_begin_grab_op (display,
+ window->screen,
+ window,
+ META_GRAB_OP_MOVING,
+ TRUE,
+ FALSE,
+ event->button.button,
+ 0,
+ event->any.time,
+ event->button.x,
+ event->button.y);
+ }
bypass_clutter = TRUE;
bypass_wayland = TRUE;
}
@@ -2320,250 +2331,8 @@ handle_input_xevent (MetaDisplay *display,
modified = xievent_get_modified_window (display, input_event);
window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL;
- frame_was_receiver = FALSE;
- if (window &&
- window->frame &&
- modified == window->frame->xwindow)
- {
- /* Note that if the frame and the client both have an
- * XGrabButton (as is normal with our setup), the event
- * goes to the frame.
- */
- frame_was_receiver = TRUE;
- meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event for %s\n",
- window->desc);
- }
-
- if (window && !window->override_redirect &&
- (input_event->evtype == XI_KeyPress || input_event->evtype == XI_ButtonPress))
- {
- if (CurrentTime == display->current_time)
- {
- /* We can't use missing (i.e. invalid) timestamps to set user time,
- * nor do we want to use them to sanity check other timestamps.
- * See bug 313490 for more details.
- */
- meta_warning ("Event has no timestamp! You may be using a broken "
- "program such as xse. Please ask the authors of that "
- "program to fix it.\n");
- }
- else
- {
- meta_window_set_user_time (window, display->current_time);
- sanity_check_timestamps (display, display->current_time);
- }
- }
-
switch (input_event->evtype)
{
- case XI_ButtonPress:
- if (display->grab_op == META_GRAB_OP_COMPOSITOR)
- break;
-
- display->overlay_key_only_pressed = FALSE;
-
- if (device_event->detail == 4 || device_event->detail == 5)
- /* Scrollwheel event, do nothing and deliver event to compositor below */
- break;
-
- if ((window &&
- meta_grab_op_is_mouse (display->grab_op) &&
- (device_event->mods.effective & display->window_grab_modifiers) &&
- display->grab_button != device_event->detail &&
- display->grab_window == window) ||
- grab_op_is_keyboard (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"));
- if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
- {
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Syncing to old stack positions.\n");
-
- if (device_event->root == device_event->event)
- meta_stack_set_positions (screen->stack,
- display->grab_old_window_stacking);
- }
- meta_display_end_grab_op (display,
- device_event->time);
- }
- else if (window && display->grab_op == META_GRAB_OP_NONE)
- {
- gboolean begin_move = FALSE;
- unsigned int grab_mask;
- gboolean unmodified;
-
- grab_mask = display->window_grab_modifiers;
- if (g_getenv ("MUTTER_DEBUG_BUTTON_GRABS"))
- grab_mask |= ControlMask;
-
- /* Two possible sources of an unmodified event; one is a
- * client that's letting button presses pass through to the
- * frame, the other is our focus_window_grab on unmodified
- * button 1. So for all such events we focus the window.
- */
- unmodified = (device_event->mods.effective & grab_mask) == 0;
-
- if (unmodified ||
- device_event->detail == 1)
- {
- /* don't focus if frame received, will be lowered in
- * frames.c or special-cased if the click was on a
- * minimize/close button.
- */
- if (!frame_was_receiver)
- {
- if (meta_prefs_get_raise_on_click ())
- meta_window_raise (window);
- else
- meta_topic (META_DEBUG_FOCUS,
- "Not raising window on click due to don't-raise-on-click option\n");
-
- /* Don't focus panels--they must explicitly request focus.
- * See bug 160470
- */
- if (window->type != META_WINDOW_DOCK)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Focusing %s due to unmodified button %u press (display.c)\n",
- window->desc, device_event->detail);
- meta_window_focus (window, device_event->time);
- }
- else
- /* However, do allow terminals to lose focus due to new
- * window mappings after the user clicks on a panel.
- */
- display->allow_terminal_deactivation = TRUE;
- }
-
- /* you can move on alt-click but not on
- * the click-to-focus
- */
- if (!unmodified)
- begin_move = TRUE;
- }
- else if (!unmodified && device_event->detail == meta_prefs_get_mouse_button_resize())
- {
- if (window->has_resize_func)
- {
- gboolean north, south;
- gboolean west, east;
- MetaRectangle frame_rect;
- MetaGrabOp op;
-
- meta_window_get_frame_rect (window, &frame_rect);
-
- west = device_event->root_x < (frame_rect.x + 1 * frame_rect.width / 3);
- east = device_event->root_x > (frame_rect.x + 2 * frame_rect.width / 3);
- north = device_event->root_y < (frame_rect.y + 1 * frame_rect.height / 3);
- south = device_event->root_y > (frame_rect.y + 2 * frame_rect.height / 3);
-
- if (north && west)
- op = META_GRAB_OP_RESIZING_NW;
- else if (north && east)
- op = META_GRAB_OP_RESIZING_NE;
- else if (south && west)
- op = META_GRAB_OP_RESIZING_SW;
- else if (south && east)
- op = META_GRAB_OP_RESIZING_SE;
- else if (north)
- op = META_GRAB_OP_RESIZING_N;
- else if (west)
- op = META_GRAB_OP_RESIZING_W;
- else if (east)
- op = META_GRAB_OP_RESIZING_E;
- else if (south)
- op = META_GRAB_OP_RESIZING_S;
- else /* Middle region is no-op to avoid user triggering wrong action */
- op = META_GRAB_OP_NONE;
-
- if (op != META_GRAB_OP_NONE)
- {
- meta_display_begin_grab_op (display,
- window->screen,
- window,
- op,
- TRUE,
- FALSE,
- device_event->detail,
- 0,
- device_event->time,
- device_event->root_x,
- device_event->root_y);
- return TRUE;
- }
- }
- }
- else if (device_event->detail == meta_prefs_get_mouse_button_menu())
- {
- if (meta_prefs_get_raise_on_click ())
- meta_window_raise (window);
- meta_window_show_menu (window,
- device_event->root_x,
- device_event->root_y,
- device_event->detail,
- device_event->time);
- return TRUE;
- }
-
- if (!frame_was_receiver && unmodified)
- {
- /* This is from our synchronous grab since
- * it has no modifiers and was on the client window
- */
-
- meta_verbose ("Allowing events time %u\n",
- (unsigned int)device_event->time);
-
- XIAllowEvents (display->xdisplay, device_event->deviceid,
- XIReplayDevice, device_event->time);
- }
-
- if (begin_move && window->has_move_func)
- {
- meta_display_begin_grab_op (display,
- window->screen,
- window,
- META_GRAB_OP_MOVING,
- TRUE,
- FALSE,
- device_event->detail,
- 0,
- device_event->time,
- device_event->root_x,
- device_event->root_y);
- return TRUE;
- }
- }
- break;
- case XI_ButtonRelease:
- if (display->grab_op == META_GRAB_OP_COMPOSITOR)
- break;
-
- display->overlay_key_only_pressed = FALSE;
-
- if (display->grab_window == window &&
- meta_grab_op_is_mouse (display->grab_op))
- {
- meta_window_handle_mouse_grab_op_xevent (window, device_event);
- return TRUE;
- }
- break;
- case XI_Motion:
- if (display->grab_op == META_GRAB_OP_COMPOSITOR)
- break;
-
- if (display->grab_window == window &&
- meta_grab_op_is_mouse (display->grab_op))
- {
- meta_window_handle_mouse_grab_op_xevent (window, device_event);
- return TRUE;
- }
- break;
case XI_Enter:
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
break;