[mutter] backend: Poll events from the host X11 server ourselves



commit 3d091e514df1cb13b080413fa22351ec4ac4b3d9
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Tue Apr 22 10:14:59 2014 -0400

    backend: Poll events from the host X11 server ourselves
    
    I was accidentally pulling events from the Xwayland server under
    nested for the idle monitor, which is wrong. Whoops.

 src/backends/meta-backend-private.h |    2 +
 src/backends/meta-backend.c         |   16 +++
 src/backends/x11/meta-backend-x11.c |  172 ++++++++++++++++++++++++++++-------
 src/core/events.c                   |    6 -
 4 files changed, 157 insertions(+), 39 deletions(-)
---
diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h
index d0de72b..1f866d0 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 42a4197..cda4bc3 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -78,12 +78,20 @@ meta_backend_finalize (GObject *object)
 }
 
 static void
+meta_backend_real_post_init (MetaBackend *backend)
+{
+  /* Do nothing */
+}
+
+static void
 meta_backend_class_init (MetaBackendClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (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 c8fa772..2a3636d 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 <gdk/gdkx.h>
 #include <clutter/x11/clutter-x11.h>
 
+#include <X11/extensions/sync.h>
+
 #include <meta/util.h>
 #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 5a70c6d..370c3af 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;
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]