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:
Jasper St. Pierre
2013-10-03 15:29:44 -04:00
parent 4ea4658abf
commit e86c53230f
4 changed files with 340 additions and 332 deletions

View File

@@ -63,6 +63,7 @@
#include <X11/extensions/Xcomposite.h>
#include "meta-wayland-private.h"
#include "meta/compositor-mutter.h"
/* Windows that unmaximize to a size bigger than that fraction of the workarea
* will be scaled down to that size (while maintaining aspect ratio).
@@ -9899,96 +9900,20 @@ update_resize (MetaWindow *window,
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
check_use_this_motion_notify (MetaWindow *window,
XIDeviceEvent *xev)
check_use_this_motion_notify (MetaWindow *window,
const ClutterEvent *event)
{
EventScannerData esd;
XEvent useless;
/* This code is copied from Owen's GDK code. */
if (window->display->grab_motion_notify_time != 0)
{
/* == is really the right test, but I'm all for paranoia */
if (window->display->grab_motion_notify_time <=
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;
}
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;
}
/* XXX: Previously this code would walk through the X event queue
and filter out motion events that are followed by a later motion
event. There currently isn't any API to do the equivalent
procedure with the Clutter event queue so this function does
nothing. Clutter does its own motion event squashing so it may be
the case that this function isn't necessary. If it turns out that
we do need additional motion event squashing we could add some
extra API to the Clutter event queue and implement this function
properly. */
return TRUE;
}
static void
@@ -10062,17 +9987,23 @@ meta_window_update_sync_request_counter (MetaWindow *window,
#endif /* HAVE_XSYNC */
void
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
XIDeviceEvent *xev)
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
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:
if (xev->detail == 1)
case CLUTTER_BUTTON_RELEASE:
if (event->button.button == 1)
{
meta_display_check_threshold_reached (window->display,
xev->root_x,
xev->root_y);
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
@@ -10085,19 +10016,19 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
{
if (window->tile_mode != META_TILE_NONE)
meta_window_tile (window);
else if (xev->root == window->screen->xroot)
else if (is_window_root)
update_move (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y);
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->button.x,
event->button.y);
}
else if (meta_grab_op_is_resizing (window->display->grab_op))
{
if (xev->root == window->screen->xroot)
if (is_window_root)
update_resize (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y,
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->button.x,
event->button.y,
TRUE);
/* If a tiled window has been dragged free with a
@@ -10109,37 +10040,36 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *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;
case XI_Motion:
case CLUTTER_MOTION:
meta_display_check_threshold_reached (window->display,
xev->root_x,
xev->root_y);
event->motion.x,
event->motion.y);
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,
xev))
if (check_use_this_motion_notify (window, event))
update_move (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y);
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->motion.x,
event->motion.y);
}
}
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,
xev))
if (check_use_this_motion_notify (window, event))
update_resize (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y,
event->button.modifier_state & CLUTTER_SHIFT_MASK,
event->motion.x,
event->motion.y,
FALSE);
}
}