From c1ac9d1dff0d851f2b35983a7789b22e17a05904 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Tue, 20 Nov 2012 20:57:13 -0500 Subject: [PATCH] ui: Use XI2 to fake GDK events This removes our final dependency on Core Events, meaning we can remove support code for them soon. This commit is a bit ugly as it requires ui having a dependency on core, but this is already a hack, so this is thus a hack inside a hack, and two hacks make a right or however that goes. https://bugzilla.gnome.org/show_bug.cgi?id=688779 --- src/ui/ui.c | 94 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 37 deletions(-) diff --git a/src/ui/ui.c b/src/ui/ui.c index 097b2047e..e161d264d 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -78,6 +78,18 @@ meta_ui_get_screen_number (void) return gdk_screen_get_number (gdk_screen_get_default ()); } +/* For XInput2 */ +#include "display-private.h" + +static gboolean +is_input_event (XEvent *event) +{ + MetaDisplay *display = meta_get_display (); + + return (event->type == GenericEvent && + event->xcookie.extension == display->xinput_opcode); +} + /* We do some of our event handling in frames.c, which expects * GDK events delivered by GTK+. However, since the transition to * client side windows, we can't let GDK see button events, since the @@ -103,25 +115,33 @@ maybe_redirect_mouse_event (XEvent *xevent) GdkEvent *gevent; GdkWindow *gdk_window; Window window; + XIEvent *xev; + XIDeviceEvent *xev_d; + XIEnterEvent *xev_e; - switch (xevent->type) + if (!is_input_event (xevent)) + return FALSE; + + xev = (XIEvent *) xevent->xcookie.data; + + switch (xev->evtype) { - case ButtonPress: - case ButtonRelease: - window = xevent->xbutton.window; + case XI_ButtonPress: + case XI_ButtonRelease: + case XI_Motion: + xev_d = (XIDeviceEvent *) xev; + window = xev_d->event; break; - case MotionNotify: - window = xevent->xmotion.window; - break; - case EnterNotify: - case LeaveNotify: - window = xevent->xcrossing.window; + case XI_Enter: + case XI_Leave: + xev_e = (XIEnterEvent *) xev; + window = xev_e->event; break; default: return FALSE; } - gdisplay = gdk_x11_lookup_xdisplay (xevent->xany.display); + gdisplay = gdk_x11_lookup_xdisplay (xev->display); ui = g_object_get_data (G_OBJECT (gdisplay), "meta-ui"); if (!ui) return FALSE; @@ -140,11 +160,11 @@ maybe_redirect_mouse_event (XEvent *xevent) if (gdk_display_device_is_grabbed (gdisplay, gdevice)) return FALSE; - switch (xevent->type) + switch (xev->evtype) { - case ButtonPress: - case ButtonRelease: - if (xevent->type == ButtonPress) + case XI_ButtonPress: + case XI_ButtonRelease: + if (xev_d->evtype == XI_ButtonPress) { GtkSettings *settings = gtk_settings_get_default (); int double_click_time; @@ -155,11 +175,11 @@ maybe_redirect_mouse_event (XEvent *xevent) "gtk-double-click-distance", &double_click_distance, NULL); - if (xevent->xbutton.button == ui->button_click_number && - xevent->xbutton.window == ui->button_click_window && - xevent->xbutton.time < ui->button_click_time + double_click_time && - ABS (xevent->xbutton.x - ui->button_click_x) <= double_click_distance && - ABS (xevent->xbutton.y - ui->button_click_y) <= double_click_distance) + if (xev_d->detail == ui->button_click_number && + xev_d->event == ui->button_click_window && + xev_d->time < ui->button_click_time + double_click_time && + ABS (xev_d->event_x - ui->button_click_x) <= double_click_distance && + ABS (xev_d->event_y - ui->button_click_y) <= double_click_distance) { gevent = gdk_event_new (GDK_2BUTTON_PRESS); @@ -168,11 +188,11 @@ maybe_redirect_mouse_event (XEvent *xevent) else { gevent = gdk_event_new (GDK_BUTTON_PRESS); - ui->button_click_number = xevent->xbutton.button; - ui->button_click_window = xevent->xbutton.window; - ui->button_click_time = xevent->xbutton.time; - ui->button_click_x = xevent->xbutton.x; - ui->button_click_y = xevent->xbutton.y; + ui->button_click_number = xev_d->detail; + ui->button_click_window = xev_d->event; + ui->button_click_time = xev_d->time; + ui->button_click_x = xev_d->event_x; + ui->button_click_y = xev_d->event_y; } } else @@ -181,25 +201,25 @@ maybe_redirect_mouse_event (XEvent *xevent) } gevent->button.window = g_object_ref (gdk_window); - gevent->button.button = xevent->xbutton.button; - gevent->button.time = xevent->xbutton.time; - gevent->button.x = xevent->xbutton.x; - gevent->button.y = xevent->xbutton.y; - gevent->button.x_root = xevent->xbutton.x_root; - gevent->button.y_root = xevent->xbutton.y_root; + gevent->button.button = xev_d->detail; + gevent->button.time = xev_d->time; + gevent->button.x = xev_d->event_x; + gevent->button.y = xev_d->event_y; + gevent->button.x_root = xev_d->root_x; + gevent->button.y_root = xev_d->root_y; break; - case MotionNotify: + case XI_Motion: gevent = gdk_event_new (GDK_MOTION_NOTIFY); gevent->motion.type = GDK_MOTION_NOTIFY; gevent->motion.window = g_object_ref (gdk_window); break; - case EnterNotify: - case LeaveNotify: - gevent = gdk_event_new (xevent->type == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY); + case XI_Enter: + case XI_Leave: + gevent = gdk_event_new (xev_e->evtype == XI_Enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY); gevent->crossing.window = g_object_ref (gdk_window); - gevent->crossing.x = xevent->xcrossing.x; - gevent->crossing.y = xevent->xcrossing.y; + gevent->crossing.x = xev_e->event_x; + gevent->crossing.y = xev_e->event_y; break; default: g_assert_not_reached ();