mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 01:20:42 -05:00
display: Move the pointer event handling code to work in terms of Clutter events
There is now a meta_display_handle_event alongside the meta_display_handle_xevent function which handles events in terms of Clutter events instead of X events. A Clutter event filter is registered so that all Clutter events will pass through this function. The pointer event handling code from the X event version has been moved into this new function and has been modified to use the details from the Clutter event instead of the X event. This is a step towards moving all of the event handling code over to use Clutter events. Based-heavily-on-a-patch-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
parent
d69d566087
commit
13a7c8da85
@ -39,6 +39,7 @@
|
|||||||
#include "keybindings-private.h"
|
#include "keybindings-private.h"
|
||||||
#include <meta/prefs.h>
|
#include <meta/prefs.h>
|
||||||
#include <meta/barrier.h>
|
#include <meta/barrier.h>
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||||
#include <libsn/sn.h>
|
#include <libsn/sn.h>
|
||||||
@ -189,7 +190,7 @@ struct _MetaDisplay
|
|||||||
MetaWindow* autoraise_window;
|
MetaWindow* autoraise_window;
|
||||||
|
|
||||||
/* Alt+click button grabs */
|
/* Alt+click button grabs */
|
||||||
unsigned int window_grab_modifiers;
|
ClutterModifierType window_grab_modifiers;
|
||||||
|
|
||||||
/* current window operation */
|
/* current window operation */
|
||||||
MetaGrabOp grab_op;
|
MetaGrabOp grab_op;
|
||||||
@ -485,6 +486,9 @@ guint meta_display_get_above_tab_keycode (MetaDisplay *display);
|
|||||||
gboolean meta_display_handle_xevent (MetaDisplay *display,
|
gboolean meta_display_handle_xevent (MetaDisplay *display,
|
||||||
XEvent *event);
|
XEvent *event);
|
||||||
|
|
||||||
|
gboolean meta_display_handle_event (MetaDisplay *display,
|
||||||
|
const ClutterEvent *event);
|
||||||
|
|
||||||
#ifdef HAVE_XI23
|
#ifdef HAVE_XI23
|
||||||
gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
||||||
XIEvent *event);
|
XIEvent *event);
|
||||||
|
@ -174,7 +174,9 @@ static void meta_spew_event (MetaDisplay *display,
|
|||||||
XEvent *event);
|
XEvent *event);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static gboolean event_callback (XEvent *event,
|
static gboolean xevent_callback (XEvent *event,
|
||||||
|
gpointer data);
|
||||||
|
static gboolean event_callback (const ClutterEvent *event,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
static Window event_get_modified_window (MetaDisplay *display,
|
static Window event_get_modified_window (MetaDisplay *display,
|
||||||
XEvent *event);
|
XEvent *event);
|
||||||
@ -603,8 +605,9 @@ meta_display_open (void)
|
|||||||
|
|
||||||
/* Get events */
|
/* Get events */
|
||||||
meta_ui_add_event_func (the_display->xdisplay,
|
meta_ui_add_event_func (the_display->xdisplay,
|
||||||
event_callback,
|
xevent_callback,
|
||||||
the_display);
|
the_display);
|
||||||
|
clutter_event_add_filter (event_callback, the_display);
|
||||||
|
|
||||||
the_display->xids = g_hash_table_new (meta_unsigned_long_hash,
|
the_display->xids = g_hash_table_new (meta_unsigned_long_hash,
|
||||||
meta_unsigned_long_equal);
|
meta_unsigned_long_equal);
|
||||||
@ -1134,8 +1137,9 @@ meta_display_close (MetaDisplay *display,
|
|||||||
|
|
||||||
/* Stop caring about events */
|
/* Stop caring about events */
|
||||||
meta_ui_remove_event_func (display->xdisplay,
|
meta_ui_remove_event_func (display->xdisplay,
|
||||||
event_callback,
|
xevent_callback,
|
||||||
display);
|
display);
|
||||||
|
clutter_event_remove_filter (event_callback, display);
|
||||||
|
|
||||||
/* Free all screens */
|
/* Free all screens */
|
||||||
tmp = display->screens;
|
tmp = display->screens;
|
||||||
@ -1866,6 +1870,32 @@ handle_net_restack_window (MetaDisplay* display,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static MetaWindow *
|
||||||
|
get_window_for_actor (ClutterActor *actor,
|
||||||
|
gboolean *frame_was_receiver)
|
||||||
|
{
|
||||||
|
/* Look for any ancestor that is a MetaWindowActor to determine
|
||||||
|
which window the actor's event belongs to */
|
||||||
|
|
||||||
|
*frame_was_receiver = TRUE;
|
||||||
|
|
||||||
|
while (actor)
|
||||||
|
{
|
||||||
|
if (META_IS_WINDOW_ACTOR (actor))
|
||||||
|
return meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor));
|
||||||
|
|
||||||
|
/* If the frame is the receiver then the source will directly be
|
||||||
|
the MetaWindowActor, otherwise it will be a child of a
|
||||||
|
MetaWindowActor so if we make it here then the event isn't
|
||||||
|
referring to the frame. */
|
||||||
|
*frame_was_receiver = FALSE;
|
||||||
|
|
||||||
|
actor = clutter_actor_get_parent (actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static XIEvent *
|
static XIEvent *
|
||||||
get_input_event (MetaDisplay *display,
|
get_input_event (MetaDisplay *display,
|
||||||
XEvent *event)
|
XEvent *event)
|
||||||
@ -2193,26 +2223,260 @@ handle_window_focus_event (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_display_handle_event (MetaDisplay *display,
|
||||||
|
const ClutterEvent *event)
|
||||||
|
{
|
||||||
|
MetaWindow *window;
|
||||||
|
gboolean frame_was_receiver;
|
||||||
|
|
||||||
|
window = get_window_for_actor (event->any.source, &frame_was_receiver);
|
||||||
|
|
||||||
|
display->current_time = event->any.time;
|
||||||
|
|
||||||
|
if (window && !window->override_redirect && event->type == CLUTTER_BUTTON_PRESS)
|
||||||
|
{
|
||||||
|
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 (event->type)
|
||||||
|
{
|
||||||
|
case CLUTTER_BUTTON_PRESS:
|
||||||
|
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||||
|
break;
|
||||||
|
|
||||||
|
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) ||
|
||||||
|
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");
|
||||||
|
|
||||||
|
/* XXX: I'm not sure if this is the right thing to do.
|
||||||
|
The pre-Wayland code was only calling
|
||||||
|
meta_stack_set_positions if the modified window was a
|
||||||
|
root window */
|
||||||
|
if (event->any.source == CLUTTER_ACTOR (event->any.stage) && window && window->screen)
|
||||||
|
meta_stack_set_positions (window->screen->stack,
|
||||||
|
display->grab_old_window_stacking);
|
||||||
|
}
|
||||||
|
meta_display_end_grab_op (display,
|
||||||
|
event->any.time);
|
||||||
|
}
|
||||||
|
else if (window && display->grab_op == META_GRAB_OP_NONE)
|
||||||
|
{
|
||||||
|
gboolean begin_move = FALSE;
|
||||||
|
ClutterModifierType grab_mask;
|
||||||
|
gboolean unmodified;
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
unmodified = (event->button.modifier_state & grab_mask) == 0;
|
||||||
|
|
||||||
|
if (unmodified ||
|
||||||
|
event->button.button == 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, 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;
|
||||||
|
}
|
||||||
|
else if (!unmodified && ((int) event->button.button == meta_prefs_get_mouse_button_resize ()))
|
||||||
|
{
|
||||||
|
if (window->has_resize_func)
|
||||||
|
{
|
||||||
|
gboolean north, south;
|
||||||
|
gboolean west, east;
|
||||||
|
int root_x, root_y;
|
||||||
|
MetaGrabOp op;
|
||||||
|
|
||||||
|
meta_window_get_position (window, &root_x, &root_y);
|
||||||
|
|
||||||
|
west = event->button.x < (root_x + 1 * window->rect.width / 3);
|
||||||
|
east = event->button.x > (root_x + 2 * window->rect.width / 3);
|
||||||
|
north = event->button.y < (root_y + 1 * window->rect.height / 3);
|
||||||
|
south = event->button.y > (root_y + 2 * window->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,
|
||||||
|
event->button.button,
|
||||||
|
0,
|
||||||
|
event->any.time,
|
||||||
|
event->button.x,
|
||||||
|
event->button.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((int) event->button.button == meta_prefs_get_mouse_button_menu ())
|
||||||
|
{
|
||||||
|
if (meta_prefs_get_raise_on_click ())
|
||||||
|
meta_window_raise (window);
|
||||||
|
meta_window_show_menu (window,
|
||||||
|
event->button.x,
|
||||||
|
event->button.y,
|
||||||
|
event->button.button,
|
||||||
|
event->any.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) event->any.time);
|
||||||
|
|
||||||
|
/* XXX -- implement this in Wayland */
|
||||||
|
XIAllowEvents (display->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
|
||||||
|
XIReplayDevice, event->any.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (begin_move && 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CLUTTER_BUTTON_RELEASE:
|
||||||
|
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_event (window, event);
|
||||||
|
break;
|
||||||
|
case CLUTTER_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_event (window, event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
handle_input_xevent (MetaDisplay *display,
|
handle_input_xevent (MetaDisplay *display,
|
||||||
XIEvent *input_event,
|
XIEvent *input_event,
|
||||||
gulong serial)
|
gulong serial)
|
||||||
{
|
{
|
||||||
XIDeviceEvent *device_event = (XIDeviceEvent *) input_event;
|
|
||||||
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
|
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
|
||||||
Window modified;
|
Window modified;
|
||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
gboolean frame_was_receiver;
|
|
||||||
|
|
||||||
if (input_event == NULL)
|
if (input_event == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
modified = xievent_get_modified_window (display, input_event);
|
modified = xievent_get_modified_window (display, input_event);
|
||||||
window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL;
|
window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL;
|
||||||
frame_was_receiver = (window && window->frame && modified == window->frame->xwindow);
|
|
||||||
|
|
||||||
if (window && !window->override_redirect &&
|
if (window && !window->override_redirect && input_event->type == XI_KeyPress)
|
||||||
((input_event->type == XI_KeyPress) || (input_event->type == XI_ButtonPress)))
|
|
||||||
{
|
{
|
||||||
if (CurrentTime == display->current_time)
|
if (CurrentTime == display->current_time)
|
||||||
{
|
{
|
||||||
@ -2245,206 +2509,6 @@ handle_input_xevent (MetaDisplay *display,
|
|||||||
if (meta_display_process_key_event (display, window, (XIDeviceEvent *) input_event))
|
if (meta_display_process_key_event (display, window, (XIDeviceEvent *) input_event))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
break;
|
break;
|
||||||
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))
|
|
||||||
{
|
|
||||||
MetaScreen *screen;
|
|
||||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
|
||||||
"Syncing to old stack positions.\n");
|
|
||||||
screen =
|
|
||||||
meta_display_screen_for_root (display, device_event->event);
|
|
||||||
|
|
||||||
if (screen!=NULL)
|
|
||||||
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;
|
|
||||||
int root_x, root_y;
|
|
||||||
MetaGrabOp op;
|
|
||||||
|
|
||||||
meta_window_get_position (window, &root_x, &root_y);
|
|
||||||
|
|
||||||
west = device_event->root_x < (root_x + 1 * window->rect.width / 3);
|
|
||||||
east = device_event->root_x > (root_x + 2 * window->rect.width / 3);
|
|
||||||
north = device_event->root_y < (root_y + 1 * window->rect.height / 3);
|
|
||||||
south = device_event->root_y > (root_y + 2 * window->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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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_event (window, device_event);
|
|
||||||
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_event (window, device_event);
|
|
||||||
break;
|
|
||||||
case XI_Enter:
|
case XI_Enter:
|
||||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||||
break;
|
break;
|
||||||
@ -3251,7 +3315,7 @@ meta_display_handle_xevent (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
event_callback (XEvent *event,
|
xevent_callback (XEvent *event,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
MetaDisplay *display = data;
|
MetaDisplay *display = data;
|
||||||
@ -3274,6 +3338,15 @@ event_callback (XEvent *event,
|
|||||||
return meta_display_handle_xevent (display, event);
|
return meta_display_handle_xevent (display, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
event_callback (const ClutterEvent *event,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
MetaDisplay *display = data;
|
||||||
|
|
||||||
|
return meta_display_handle_event (display, event);
|
||||||
|
}
|
||||||
|
|
||||||
static Window
|
static Window
|
||||||
xievent_get_modified_window (MetaDisplay *display,
|
xievent_get_modified_window (MetaDisplay *display,
|
||||||
XIEvent *input_event)
|
XIEvent *input_event)
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
#include <clutter/clutter.h>
|
||||||
#include "meta-wayland-types.h"
|
#include "meta-wayland-types.h"
|
||||||
|
|
||||||
typedef struct _MetaWindowQueue MetaWindowQueue;
|
typedef struct _MetaWindowQueue MetaWindowQueue;
|
||||||
@ -643,7 +644,7 @@ void meta_window_update_sync_request_counter (MetaWindow *window,
|
|||||||
#endif /* HAVE_XSYNC */
|
#endif /* HAVE_XSYNC */
|
||||||
|
|
||||||
void meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
void meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||||
XIDeviceEvent *xev);
|
const ClutterEvent *event);
|
||||||
|
|
||||||
GList* meta_window_get_workspaces (MetaWindow *window);
|
GList* meta_window_get_workspaces (MetaWindow *window);
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
#include <X11/extensions/Xcomposite.h>
|
#include <X11/extensions/Xcomposite.h>
|
||||||
|
|
||||||
#include "meta-wayland-private.h"
|
#include "meta-wayland-private.h"
|
||||||
|
#include "meta/compositor-mutter.h"
|
||||||
|
|
||||||
/* Windows that unmaximize to a size bigger than that fraction of the workarea
|
/* Windows that unmaximize to a size bigger than that fraction of the workarea
|
||||||
* will be scaled down to that size (while maintaining aspect ratio).
|
* will be scaled down to that size (while maintaining aspect ratio).
|
||||||
@ -9901,96 +9902,20 @@ update_resize (MetaWindow *window,
|
|||||||
g_get_current_time (&window->display->grab_last_moveresize_time);
|
g_get_current_time (&window->display->grab_last_moveresize_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
Window window;
|
|
||||||
int count;
|
|
||||||
guint32 last_time;
|
|
||||||
} EventScannerData;
|
|
||||||
|
|
||||||
static Bool
|
|
||||||
find_last_time_predicate (Display *display,
|
|
||||||
XEvent *ev,
|
|
||||||
XPointer arg)
|
|
||||||
{
|
|
||||||
EventScannerData *esd = (void*) arg;
|
|
||||||
XIEvent *xev;
|
|
||||||
|
|
||||||
if (ev->type != GenericEvent)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
/* We are peeking into events not yet handled by GDK,
|
|
||||||
* Allocate cookie events here so we can handle XI2.
|
|
||||||
*
|
|
||||||
* GDK will handle later these events, and eventually
|
|
||||||
* free the cookie data itself.
|
|
||||||
*/
|
|
||||||
XGetEventData (display, &ev->xcookie);
|
|
||||||
xev = (XIEvent *) ev->xcookie.data;
|
|
||||||
|
|
||||||
if (xev->evtype != XI_Motion)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if (esd->window != ((XIDeviceEvent *) xev)->event)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
esd->count += 1;
|
|
||||||
esd->last_time = xev->time;
|
|
||||||
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
check_use_this_motion_notify (MetaWindow *window,
|
check_use_this_motion_notify (MetaWindow *window,
|
||||||
XIDeviceEvent *xev)
|
const ClutterEvent *event)
|
||||||
{
|
{
|
||||||
EventScannerData esd;
|
/* XXX: Previously this code would walk through the X event queue
|
||||||
XEvent useless;
|
and filter out motion events that are followed by a later motion
|
||||||
|
event. There currently isn't any API to do the equivalent
|
||||||
/* This code is copied from Owen's GDK code. */
|
procedure with the Clutter event queue so this function does
|
||||||
|
nothing. Clutter does its own motion event squashing so it may be
|
||||||
if (window->display->grab_motion_notify_time != 0)
|
the case that this function isn't necessary. If it turns out that
|
||||||
{
|
we do need additional motion event squashing we could add some
|
||||||
/* == is really the right test, but I'm all for paranoia */
|
extra API to the Clutter event queue and implement this function
|
||||||
if (window->display->grab_motion_notify_time <=
|
properly. */
|
||||||
xev->time)
|
|
||||||
{
|
|
||||||
meta_topic (META_DEBUG_RESIZING,
|
|
||||||
"Arrived at event with time %u (waiting for %u), using it\n",
|
|
||||||
(unsigned int)xev->time,
|
|
||||||
window->display->grab_motion_notify_time);
|
|
||||||
window->display->grab_motion_notify_time = 0;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
|
||||||
else
|
|
||||||
return FALSE; /* haven't reached the saved timestamp yet */
|
|
||||||
}
|
|
||||||
|
|
||||||
esd.window = xev->event;
|
|
||||||
esd.count = 0;
|
|
||||||
esd.last_time = 0;
|
|
||||||
|
|
||||||
/* "useless" isn't filled in because the predicate never returns True */
|
|
||||||
XCheckIfEvent (window->display->xdisplay,
|
|
||||||
&useless,
|
|
||||||
find_last_time_predicate,
|
|
||||||
(XPointer) &esd);
|
|
||||||
|
|
||||||
if (esd.count > 0)
|
|
||||||
meta_topic (META_DEBUG_RESIZING,
|
|
||||||
"Will skip %d motion events and use the event with time %u\n",
|
|
||||||
esd.count, (unsigned int) esd.last_time);
|
|
||||||
|
|
||||||
if (esd.last_time == 0)
|
|
||||||
return TRUE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Save this timestamp, and ignore all motion notify
|
|
||||||
* until we get to the one with this stamp.
|
|
||||||
*/
|
|
||||||
window->display->grab_motion_notify_time = esd.last_time;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -10065,16 +9990,22 @@ meta_window_update_sync_request_counter (MetaWindow *window,
|
|||||||
|
|
||||||
void
|
void
|
||||||
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||||
XIDeviceEvent *xev)
|
const ClutterEvent *event)
|
||||||
{
|
{
|
||||||
switch (xev->evtype)
|
gboolean is_window_root = (event->any.stage != NULL &&
|
||||||
|
window &&
|
||||||
|
window->screen &&
|
||||||
|
CLUTTER_ACTOR (event->any.stage) ==
|
||||||
|
meta_get_stage_for_screen (window->screen));
|
||||||
|
|
||||||
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case XI_ButtonRelease:
|
case CLUTTER_BUTTON_RELEASE:
|
||||||
if (xev->detail == 1)
|
if (event->button.button == 1)
|
||||||
{
|
{
|
||||||
meta_display_check_threshold_reached (window->display,
|
meta_display_check_threshold_reached (window->display,
|
||||||
xev->root_x,
|
event->button.x,
|
||||||
xev->root_y);
|
event->button.y);
|
||||||
/* If the user was snap moving then ignore the button
|
/* If the user was snap moving then ignore the button
|
||||||
* release because they may have let go of shift before
|
* release because they may have let go of shift before
|
||||||
* releasing the mouse button and they almost certainly do
|
* releasing the mouse button and they almost certainly do
|
||||||
@ -10087,19 +10018,19 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
|||||||
{
|
{
|
||||||
if (window->tile_mode != META_TILE_NONE)
|
if (window->tile_mode != META_TILE_NONE)
|
||||||
meta_window_tile (window);
|
meta_window_tile (window);
|
||||||
else if (xev->root == window->screen->xroot)
|
else if (is_window_root)
|
||||||
update_move (window,
|
update_move (window,
|
||||||
xev->mods.effective & ShiftMask,
|
event->button.modifier_state & CLUTTER_SHIFT_MASK,
|
||||||
xev->root_x,
|
event->button.x,
|
||||||
xev->root_y);
|
event->button.y);
|
||||||
}
|
}
|
||||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||||
{
|
{
|
||||||
if (xev->root == window->screen->xroot)
|
if (is_window_root)
|
||||||
update_resize (window,
|
update_resize (window,
|
||||||
xev->mods.effective & ShiftMask,
|
event->button.modifier_state & CLUTTER_SHIFT_MASK,
|
||||||
xev->root_x,
|
event->button.x,
|
||||||
xev->root_y,
|
event->button.y,
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
/* If a tiled window has been dragged free with a
|
/* If a tiled window has been dragged free with a
|
||||||
@ -10111,37 +10042,36 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
|||||||
*/
|
*/
|
||||||
update_tile_mode (window);
|
update_tile_mode (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta_display_end_grab_op (window->display, event->any.time);
|
||||||
}
|
}
|
||||||
meta_display_end_grab_op (window->display, xev->time);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XI_Motion:
|
case CLUTTER_MOTION:
|
||||||
meta_display_check_threshold_reached (window->display,
|
meta_display_check_threshold_reached (window->display,
|
||||||
xev->root_x,
|
event->motion.x,
|
||||||
xev->root_y);
|
event->motion.y);
|
||||||
if (meta_grab_op_is_moving (window->display->grab_op))
|
if (meta_grab_op_is_moving (window->display->grab_op))
|
||||||
{
|
{
|
||||||
if (xev->root == window->screen->xroot)
|
if (is_window_root)
|
||||||
{
|
{
|
||||||
if (check_use_this_motion_notify (window,
|
if (check_use_this_motion_notify (window, event))
|
||||||
xev))
|
|
||||||
update_move (window,
|
update_move (window,
|
||||||
xev->mods.effective & ShiftMask,
|
event->button.modifier_state & CLUTTER_SHIFT_MASK,
|
||||||
xev->root_x,
|
event->motion.x,
|
||||||
xev->root_y);
|
event->motion.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||||
{
|
{
|
||||||
if (xev->root == window->screen->xroot)
|
if (is_window_root)
|
||||||
{
|
{
|
||||||
if (check_use_this_motion_notify (window,
|
if (check_use_this_motion_notify (window, event))
|
||||||
xev))
|
|
||||||
update_resize (window,
|
update_resize (window,
|
||||||
xev->mods.effective & ShiftMask,
|
event->button.modifier_state & CLUTTER_SHIFT_MASK,
|
||||||
xev->root_x,
|
event->motion.x,
|
||||||
xev->root_y,
|
event->motion.y,
|
||||||
FALSE);
|
FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user