diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h index d0de72bbe..1f866d08d 100644 --- a/src/backends/meta-backend-private.h +++ b/src/backends/meta-backend-private.h @@ -49,6 +49,8 @@ struct _MetaBackendClass { GObjectClass parent_class; + void (* post_init) (MetaBackend *backend); + MetaIdleMonitor * (* create_idle_monitor) (MetaBackend *backend, int device_id); MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend); diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c index 42a41978a..cda4bc36c 100644 --- a/src/backends/meta-backend.c +++ b/src/backends/meta-backend.c @@ -77,6 +77,12 @@ meta_backend_finalize (GObject *object) G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object); } +static void +meta_backend_real_post_init (MetaBackend *backend) +{ + /* Do nothing */ +} + static void meta_backend_class_init (MetaBackendClass *klass) { @@ -84,6 +90,8 @@ meta_backend_class_init (MetaBackendClass *klass) object_class->constructed = meta_backend_constructed; object_class->finalize = meta_backend_finalize; + + klass->post_init = meta_backend_real_post_init; } static void @@ -109,6 +117,12 @@ meta_backend_create_idle_monitor (MetaBackend *backend, return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id); } +static void +meta_backend_post_init (MetaBackend *backend) +{ + META_BACKEND_GET_CLASS (backend)->post_init (backend); +} + MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend, int device_id) @@ -217,4 +231,6 @@ meta_clutter_init (void) source = g_source_new (&event_funcs, sizeof (GSource)); g_source_attach (source, NULL); g_source_unref (source); + + meta_backend_post_init (_backend); } diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c index c8fa77281..2a3636d50 100644 --- a/src/backends/x11/meta-backend-x11.c +++ b/src/backends/x11/meta-backend-x11.c @@ -26,15 +26,149 @@ #include "meta-backend-x11.h" -#include #include +#include + #include #include "meta-idle-monitor-xsync.h" #include "meta-monitor-manager-xrandr.h" #include "backends/meta-monitor-manager-dummy.h" -G_DEFINE_TYPE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND); +struct _MetaBackendX11Private +{ + /* The host X11 display */ + Display *xdisplay; + GSource *source; + + int xsync_event_base; + int xsync_error_base; +}; +typedef struct _MetaBackendX11Private MetaBackendX11Private; + +G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND); + +static void +handle_alarm_notify (MetaBackend *backend, + XEvent *xevent) +{ + int i; + + for (i = 0; i <= backend->device_id_max; i++) + if (backend->device_monitors[i]) + meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*)xevent); +} + +static void +handle_host_xevent (MetaBackend *backend, + XEvent *xevent) +{ + MetaBackendX11 *x11 = META_BACKEND_X11 (backend); + MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); + + if (xevent->type == (priv->xsync_event_base + XSyncAlarmNotify)) + handle_alarm_notify (backend, xevent); + + clutter_x11_handle_event (xevent); +} + +typedef struct { + GSource base; + GPollFD event_poll_fd; + MetaBackend *backend; +} XEventSource; + +static gboolean +x_event_source_prepare (GSource *source, + int *timeout) +{ + XEventSource *x_source = (XEventSource *) source; + MetaBackend *backend = x_source->backend; + MetaBackendX11 *x11 = META_BACKEND_X11 (backend); + MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); + + *timeout = -1; + + return XPending (priv->xdisplay); +} + +static gboolean +x_event_source_check (GSource *source) +{ + XEventSource *x_source = (XEventSource *) source; + MetaBackend *backend = x_source->backend; + MetaBackendX11 *x11 = META_BACKEND_X11 (backend); + MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); + + return XPending (priv->xdisplay); +} + +static gboolean +x_event_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + XEventSource *x_source = (XEventSource *) source; + MetaBackend *backend = x_source->backend; + MetaBackendX11 *x11 = META_BACKEND_X11 (backend); + MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); + + while (XPending (priv->xdisplay)) + { + XEvent xev; + + XNextEvent (priv->xdisplay, &xev); + + handle_host_xevent (backend, &xev); + } + + return TRUE; +} + +static GSourceFuncs x_event_funcs = { + x_event_source_prepare, + x_event_source_check, + x_event_source_dispatch, +}; + +static GSource * +x_event_source_new (MetaBackend *backend) +{ + MetaBackendX11 *x11 = META_BACKEND_X11 (backend); + MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); + GSource *source; + XEventSource *x_source; + + source = g_source_new (&x_event_funcs, sizeof (XEventSource)); + x_source = (XEventSource *) source; + x_source->backend = backend; + x_source->event_poll_fd.fd = ConnectionNumber (priv->xdisplay); + x_source->event_poll_fd.events = G_IO_IN; + g_source_add_poll (source, &x_source->event_poll_fd); + + g_source_attach (source, NULL); + return source; +} + +static void +meta_backend_x11_post_init (MetaBackend *backend) +{ + MetaBackendX11 *x11 = META_BACKEND_X11 (backend); + MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); + int major, minor; + + priv->xdisplay = clutter_x11_get_default_display (); + + priv->source = x_event_source_new (backend); + + if (!XSyncQueryExtension (priv->xdisplay, &priv->xsync_event_base, &priv->xsync_error_base)) + meta_fatal ("Could not initialize XSync"); + + if (!XSyncInitialize (priv->xdisplay, &major, &minor)) + meta_fatal ("Could not initialize XSync"); + + META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend); +} static MetaIdleMonitor * meta_backend_x11_create_idle_monitor (MetaBackend *backend, @@ -62,6 +196,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass) { MetaBackendClass *backend_class = META_BACKEND_CLASS (klass); + backend_class->post_init = meta_backend_x11_post_init; backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor; backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager; } @@ -69,35 +204,6 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass) static void meta_backend_x11_init (MetaBackendX11 *x11) { - /* When running as an X11 compositor, we install our own event filter and - * pass events to Clutter explicitly, so we need to prevent Clutter from - * handling our events. - * - * However, when running as a Wayland compostior under X11 nested, Clutter - * Clutter needs to see events related to its own window. We need to - * eventually replace this with a proper frontend / backend split: Clutter - * under nested is connecting to the "host X server" to get its events it - * needs to put up a window, and GTK+ is connecting to the "inner X server". - * The two would the same in the X11 compositor case, but not when running - * XWayland as a Wayland compositor. - */ - if (!meta_is_wayland_compositor ()) - { - clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ())); - clutter_x11_disable_event_retrieval (); - } -} - -void -meta_backend_x11_handle_alarm_notify (MetaBackend *backend, - XEvent *xevent) -{ - int i; - - if (!META_IS_BACKEND_X11 (backend)) - return; - - for (i = 0; i <= backend->device_id_max; i++) - if (backend->device_monitors[i]) - meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*)xevent); + /* We do X11 event retrieval ourselves */ + clutter_x11_disable_event_retrieval (); } diff --git a/src/core/events.c b/src/core/events.c index 5a70c6dfa..370c3aff7 100644 --- a/src/core/events.c +++ b/src/core/events.c @@ -35,7 +35,6 @@ #include "bell.h" #include "workspace-private.h" #include "backends/meta-backend.h" -#include "backends/x11/meta-backend-x11.h" #include "backends/native/meta-idle-monitor-native.h" #include "x11/window-x11.h" @@ -1264,11 +1263,6 @@ handle_other_xevent (MetaDisplay *display, meta_window_update_sync_request_counter (alarm_window, new_counter_value); bypass_gtk = TRUE; /* GTK doesn't want to see this really */ } - else - { - MetaBackend *backend = meta_get_backend (); - meta_backend_x11_handle_alarm_notify (backend, event); - } goto out; }