diff --git a/src/core/display-private.h b/src/core/display-private.h index 26b83a0f4..03acc7ac2 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -92,6 +92,7 @@ struct _MetaDisplay Display *xdisplay; int clutter_event_filter; + GSource *x11_event_source; Window leader_window; Window timestamp_pinging_window; diff --git a/src/core/display.c b/src/core/display.c index 648aaf4b2..776754cf6 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -446,7 +446,7 @@ meta_display_open (void) meta_verbose ("Opening display '%s'\n", XDisplayName (NULL)); - xdisplay = meta_ui_get_display (); + xdisplay = XOpenDisplay (NULL); if (xdisplay == NULL) { diff --git a/src/core/events.c b/src/core/events.c index 60167663e..881ecfcbc 100644 --- a/src/core/events.c +++ b/src/core/events.c @@ -78,9 +78,8 @@ get_input_event (MetaDisplay *display, { XIEvent *input_event; - /* NB: GDK event filters already have generic events - * allocated, so no need to do XGetEventData() on our own - */ + XGetEventData (display->xdisplay, &event->xcookie); + input_event = (XIEvent *) event->xcookie.data; switch (input_event->evtype) @@ -1750,12 +1749,12 @@ window_has_xwindow (MetaWindow *window, * busy around here. Most of this function is a ginormous switch statement * dealing with all the kinds of events that might turn up. */ -static gboolean +static void meta_display_handle_xevent (MetaDisplay *display, XEvent *event) { Window modified; - gboolean bypass_compositor = FALSE, bypass_gtk = FALSE; + gboolean bypass_compositor = FALSE; XIEvent *input_event; MetaMonitorManager *monitor; @@ -1766,15 +1765,11 @@ meta_display_handle_xevent (MetaDisplay *display, #ifdef HAVE_STARTUP_NOTIFICATION if (sn_display_process_event (display->sn_display, event)) { - bypass_gtk = bypass_compositor = TRUE; + bypass_compositor = TRUE; goto out; } #endif - /* Intercept XRandR events early and don't attempt any - processing for them. We still let them through to Gdk though, - so it can update its own internal state. - */ monitor = meta_monitor_manager_get (); if (meta_monitor_manager_handle_xevent (monitor, event)) { @@ -1803,7 +1798,7 @@ meta_display_handle_xevent (MetaDisplay *display, { if (meta_screen_handle_xevent (display->screen, event)) { - bypass_gtk = bypass_compositor = TRUE; + bypass_compositor = TRUE; goto out; } } @@ -1838,7 +1833,7 @@ meta_display_handle_xevent (MetaDisplay *display, #ifdef HAVE_XI23 if (meta_display_process_barrier_event (display, input_event)) { - bypass_gtk = bypass_compositor = TRUE; + bypass_compositor = TRUE; goto out; } #endif /* HAVE_XI23 */ @@ -1849,27 +1844,20 @@ meta_display_handle_xevent (MetaDisplay *display, */ if (handle_input_xevent (display, input_event, event->xany.serial)) { - bypass_gtk = bypass_compositor = TRUE; + bypass_compositor = TRUE; goto out; } if (handle_other_xevent (display, event)) - { - bypass_gtk = TRUE; - goto out; - } + goto out; out: if (!bypass_compositor) { MetaWindow *window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL; - if (meta_compositor_process_event (display->compositor, event, window)) - bypass_gtk = TRUE; + meta_compositor_process_event (display->compositor, event, window); } - - display->current_time = CurrentTime; - return bypass_gtk; } static void @@ -2180,19 +2168,6 @@ meta_display_handle_event (MetaDisplay *display, return bypass_clutter; } -static GdkFilterReturn -xevent_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data) -{ - MetaDisplay *display = data; - - if (meta_display_handle_xevent (display, xevent)) - return GDK_FILTER_REMOVE; - else - return GDK_FILTER_CONTINUE; -} - static gboolean event_callback (const ClutterEvent *event, gpointer data) @@ -2202,20 +2177,90 @@ event_callback (const ClutterEvent *event, return meta_display_handle_event (display, event); } +typedef struct { + GSource source; + + MetaDisplay *display; + GPollFD event_poll_fd; +} X11EventSource; + +static gboolean +x11_event_source_prepare (GSource *source, + gint *timeout) +{ + X11EventSource *source_x11 = (X11EventSource *) source; + MetaDisplay *display = source_x11->display; + + *timeout = -1; + + return XPending (display->xdisplay); +} + +static gboolean +x11_event_source_check (GSource *source) +{ + X11EventSource *source_x11 = (X11EventSource *) source; + MetaDisplay *display = source_x11->display; + + if (source_x11->event_poll_fd.revents & G_IO_IN) + return XPending (display->xdisplay); + else + return FALSE; +} + +static gboolean +x11_event_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + X11EventSource *source_x11 = (X11EventSource *) source; + MetaDisplay *display = source_x11->display; + XEvent event; + + XNextEvent (display->xdisplay, &event); + meta_display_handle_xevent (display, &event); + + return TRUE; +} + +static GSourceFuncs x11_event_source_funcs = { + x11_event_source_prepare, + x11_event_source_check, + x11_event_source_dispatch, +}; + +static GSource * +x11_event_source_new (MetaDisplay *display) +{ + GSource *source = g_source_new (&x11_event_source_funcs, sizeof (X11EventSource)); + X11EventSource *source_x11 = (X11EventSource *) source; + + source_x11->display = display; + source_x11->event_poll_fd.fd = ConnectionNumber (display->xdisplay); + source_x11->event_poll_fd.events = G_IO_IN; + g_source_add_poll (source, &source_x11->event_poll_fd); + + return source; +} + void meta_display_init_events (MetaDisplay *display) { - gdk_window_add_filter (NULL, xevent_filter, display); display->clutter_event_filter = clutter_event_add_filter (NULL, event_callback, NULL, display); + + display->x11_event_source = x11_event_source_new (display); + g_source_attach (display->x11_event_source, NULL); } void meta_display_free_events (MetaDisplay *display) { - gdk_window_remove_filter (NULL, xevent_filter, display); clutter_event_remove_filter (display->clutter_event_filter); display->clutter_event_filter = 0; + + g_source_unref (display->x11_event_source); + display->x11_event_source = NULL; } diff --git a/src/ui/ui.c b/src/ui/ui.c index b609f9b1d..f913c51f2 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -61,177 +61,6 @@ meta_ui_init (void) meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL)); } -Display* -meta_ui_get_display (void) -{ - return GDK_DISPLAY_XDISPLAY (gdk_display_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 - * client-side tracking of implicit and explicit grabs it does will - * get confused by our direct use of X grabs in the core code. - * - * So we do a very minimal GDK => GTK event conversion here and send on the - * events we care about, and then filter them out so they don't go - * through the normal GDK event handling. - * - * To reduce the amount of code, the only events fields filled out - * below are the ones that frames.c uses. If frames.c is modified to - * use more fields, more fields need to be filled out below. - */ - -static gboolean -maybe_redirect_mouse_event (MetaUI *ui, - XEvent *xevent) -{ - GdkDisplay *gdisplay; - GdkDeviceManager *gmanager; - GdkDevice *gdevice; - GdkEvent *gevent; - GdkWindow *gdk_window; - Window window; - XIEvent *xev; - XIDeviceEvent *xev_d = NULL; - XIEnterEvent *xev_e = NULL; - - if (!is_input_event (xevent)) - return FALSE; - - xev = (XIEvent *) xevent->xcookie.data; - - switch (xev->evtype) - { - case XI_ButtonPress: - case XI_ButtonRelease: - case XI_Motion: - xev_d = (XIDeviceEvent *) xev; - window = xev_d->event; - break; - case XI_Enter: - case XI_Leave: - xev_e = (XIEnterEvent *) xev; - window = xev_e->event; - break; - default: - return FALSE; - } - - gdisplay = ui->display; - gdk_window = gdk_x11_window_lookup_for_display (gdisplay, window); - if (gdk_window == NULL) - return FALSE; - - gmanager = gdk_display_get_device_manager (gdisplay); - gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID); - - /* If GDK already thinks it has a grab, we better let it see events; this - * is the menu-navigation case and events need to get sent to the appropriate - * (client-side) subwindow for individual menu items. - */ - if (gdk_display_device_is_grabbed (gdisplay, gdevice)) - return FALSE; - - switch (xev->evtype) - { - case XI_ButtonPress: - case XI_ButtonRelease: - if (xev_d->evtype == XI_ButtonPress) - { - GtkSettings *settings = gtk_settings_get_default (); - int double_click_time; - int double_click_distance; - - g_object_get (settings, - "gtk-double-click-time", &double_click_time, - "gtk-double-click-distance", &double_click_distance, - NULL); - - 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); - - ui->button_click_number = 0; - } - else - { - gevent = gdk_event_new (GDK_BUTTON_PRESS); - 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 - { - gevent = gdk_event_new (GDK_BUTTON_RELEASE); - } - - gevent->button.window = g_object_ref (gdk_window); - 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 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 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 = xev_e->event_x; - gevent->crossing.y = xev_e->event_y; - break; - default: - g_assert_not_reached (); - break; - } - - /* If we've gotten here, we've created the gdk_event and should send it on */ - gdk_event_set_device (gevent, gdevice); - gtk_main_do_event (gevent); - gdk_event_free (gevent); - - return TRUE; -} - -static GdkFilterReturn -ui_filter_func (GdkXEvent *xevent, - GdkEvent *event, - gpointer data) -{ - MetaUI *ui = data; - - if (maybe_redirect_mouse_event (ui, xevent)) - return GDK_FILTER_REMOVE; - else - return GDK_FILTER_CONTINUE; -} - MetaUI* meta_ui_new (void) { @@ -251,8 +80,6 @@ meta_ui_new (void) */ gtk_widget_show (GTK_WIDGET (ui->frames)); - gdk_window_add_filter (NULL, ui_filter_func, ui); - return ui; } @@ -261,8 +88,6 @@ meta_ui_free (MetaUI *ui) { gtk_widget_destroy (GTK_WIDGET (ui->frames)); - gdk_window_remove_filter (NULL, ui_filter_func, ui); - g_free (ui); } diff --git a/src/ui/ui.h b/src/ui/ui.h index 5f8f41582..1e40baa11 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -42,8 +42,6 @@ typedef enum void meta_ui_init (void); -Display* meta_ui_get_display (void); - MetaUI* meta_ui_new (void); void meta_ui_free (MetaUI *ui);