[gnome-flashback] backends: open a connection to the X server



commit 2636c3d5bdec2945e144f234084eb41f59dd28a3
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Sat Sep 9 23:28:21 2017 +0300

    backends: open a connection to the X server

 backends/gf-backend-native.c      |   11 ++
 backends/gf-backend-private.h     |    2 +
 backends/gf-backend-x11-cm.c      |   12 +++
 backends/gf-backend-x11-nested.c  |   12 +++
 backends/gf-backend-x11-private.h |    6 +
 backends/gf-backend-x11.c         |  198 +++++++++++++++++++++++++++++++++++++
 backends/gf-backend.c             |    9 ++
 configure.ac                      |    1 +
 8 files changed, 251 insertions(+), 0 deletions(-)
---
diff --git a/backends/gf-backend-native.c b/backends/gf-backend-native.c
index 8ae51ba..4f1aef0 100644
--- a/backends/gf-backend-native.c
+++ b/backends/gf-backend-native.c
@@ -34,8 +34,19 @@ struct _GfBackendNative
 G_DEFINE_TYPE (GfBackendNative, gf_backend_native, GF_TYPE_BACKEND)
 
 static void
+gf_backend_native_post_init (GfBackend *backend)
+{
+  GF_BACKEND_CLASS (gf_backend_native_parent_class)->post_init (backend);
+}
+
+static void
 gf_backend_native_class_init (GfBackendNativeClass *native_class)
 {
+  GfBackendClass *backend_class;
+
+  backend_class = GF_BACKEND_CLASS (native_class);
+
+  backend_class->post_init = gf_backend_native_post_init;
 }
 
 static void
diff --git a/backends/gf-backend-private.h b/backends/gf-backend-private.h
index ac33adf..01643b3 100644
--- a/backends/gf-backend-private.h
+++ b/backends/gf-backend-private.h
@@ -33,6 +33,8 @@ G_BEGIN_DECLS
 struct _GfBackendClass
 {
   GObjectClass parent_class;
+
+  void (* post_init) (GfBackend *backend);
 };
 
 G_END_DECLS
diff --git a/backends/gf-backend-x11-cm.c b/backends/gf-backend-x11-cm.c
index f5ff12a..876e398 100644
--- a/backends/gf-backend-x11-cm.c
+++ b/backends/gf-backend-x11-cm.c
@@ -29,9 +29,21 @@ struct _GfBackendX11Cm
 
 G_DEFINE_TYPE (GfBackendX11Cm, gf_backend_x11_cm, GF_TYPE_BACKEND_X11)
 
+static gboolean
+gf_backend_x11_cm_handle_host_xevent (GfBackendX11 *x11,
+                                      XEvent       *event)
+{
+  return FALSE;
+}
+
 static void
 gf_backend_x11_cm_class_init (GfBackendX11CmClass *x11_cm_class)
 {
+  GfBackendX11Class *backend_x11_class;
+
+  backend_x11_class = GF_BACKEND_X11_CLASS (x11_cm_class);
+
+  backend_x11_class->handle_host_xevent = gf_backend_x11_cm_handle_host_xevent;
 }
 
 static void
diff --git a/backends/gf-backend-x11-nested.c b/backends/gf-backend-x11-nested.c
index 591eda0..a129df3 100644
--- a/backends/gf-backend-x11-nested.c
+++ b/backends/gf-backend-x11-nested.c
@@ -29,9 +29,21 @@ struct _GfBackendX11Nested
 
 G_DEFINE_TYPE (GfBackendX11Nested, gf_backend_x11_nested, GF_TYPE_BACKEND_X11)
 
+static gboolean
+gf_backend_x11_nested_handle_host_xevent (GfBackendX11 *x11,
+                                          XEvent       *event)
+{
+  return FALSE;
+}
+
 static void
 gf_backend_x11_nested_class_init (GfBackendX11NestedClass *x11_nested_class)
 {
+  GfBackendX11Class *backend_x11_class;
+
+  backend_x11_class = GF_BACKEND_X11_CLASS (x11_nested_class);
+
+  backend_x11_class->handle_host_xevent = gf_backend_x11_nested_handle_host_xevent;
 }
 
 static void
diff --git a/backends/gf-backend-x11-private.h b/backends/gf-backend-x11-private.h
index 22d9e6a..d3bd209 100644
--- a/backends/gf-backend-x11-private.h
+++ b/backends/gf-backend-x11-private.h
@@ -26,6 +26,7 @@
 #ifndef GF_BACKEND_X11_PRIVATE_H
 #define GF_BACKEND_X11_PRIVATE_H
 
+#include <X11/Xlib.h>
 #include "gf-backend-private.h"
 
 G_BEGIN_DECLS
@@ -37,8 +38,13 @@ G_DECLARE_DERIVABLE_TYPE (GfBackendX11, gf_backend_x11,
 struct _GfBackendX11Class
 {
   GfBackendClass parent_class;
+
+  gboolean (* handle_host_xevent) (GfBackendX11 *x11,
+                                   XEvent       *event);
 };
 
+Display *gf_backend_x11_get_xdisplay (GfBackendX11 *x11);
+
 G_END_DECLS
 
 #endif
diff --git a/backends/gf-backend-x11.c b/backends/gf-backend-x11.c
index 5101690..9f3f068 100644
--- a/backends/gf-backend-x11.c
+++ b/backends/gf-backend-x11.c
@@ -29,24 +29,165 @@
 
 #include "gf-backend-x11-private.h"
 
+typedef struct
+{
+  GSource    source;
+  GPollFD    event_poll_fd;
+
+  GfBackend *backend;
+} XEventSource;
+
+typedef struct
+{
+  Display *xdisplay;
+
+  GSource *source;
+} GfBackendX11Private;
+
 static void
 initable_iface_init (GInitableIface *initable_iface);
 
 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GfBackendX11, gf_backend_x11, GF_TYPE_BACKEND,
+                                  G_ADD_PRIVATE (GfBackendX11)
                                   G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
                                                          initable_iface_init))
 
+static void
+handle_host_xevent (GfBackend *backend,
+                    XEvent    *event)
+{
+  GfBackendX11 *x11;
+  GfBackendX11Private *priv;
+
+  x11 = GF_BACKEND_X11 (backend);
+  priv = gf_backend_x11_get_instance_private (x11);
+
+  XGetEventData (priv->xdisplay, &event->xcookie);
+
+  GF_BACKEND_X11_GET_CLASS (x11)->handle_host_xevent (x11, event);
+
+  XFreeEventData (priv->xdisplay, &event->xcookie);
+}
+
+static gboolean
+x_event_source_prepare (GSource *source,
+                        int     *timeout)
+{
+  XEventSource *x_source;
+  GfBackendX11 *x11;
+  GfBackendX11Private *priv;
+
+  x_source = (XEventSource *) source;
+  x11 = GF_BACKEND_X11 (x_source->backend);
+  priv = gf_backend_x11_get_instance_private (x11);
+
+  *timeout = -1;
+
+  return XPending (priv->xdisplay);
+}
+
+static gboolean
+x_event_source_check (GSource *source)
+{
+  XEventSource *x_source;
+  GfBackendX11 *x11;
+  GfBackendX11Private *priv;
+
+  x_source = (XEventSource *) source;
+  x11 = GF_BACKEND_X11 (x_source->backend);
+  priv = gf_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;
+  GfBackendX11 *x11;
+  GfBackendX11Private *priv;
+
+  x_source = (XEventSource *) source;
+  x11 = GF_BACKEND_X11 (x_source->backend);
+  priv = gf_backend_x11_get_instance_private (x11);
+
+  while (XPending (priv->xdisplay))
+    {
+      XEvent event;
+
+      XNextEvent (priv->xdisplay, &event);
+
+      handle_host_xevent (x_source->backend, &event);
+    }
+
+  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 (GfBackend *backend)
+{
+  GfBackendX11 *x11;
+  GfBackendX11Private *priv;
+  GSource *source;
+  XEventSource *x_source;
+
+  x11 = GF_BACKEND_X11 (backend);
+  priv = gf_backend_x11_get_instance_private (x11);
+
+  source = g_source_new (&x_event_funcs, sizeof (XEventSource));
+
+  x_source = (XEventSource *) source;
+  x_source->event_poll_fd.fd = ConnectionNumber (priv->xdisplay);
+  x_source->event_poll_fd.events = G_IO_IN;
+  x_source->backend = backend;
+
+  g_source_add_poll (source, &x_source->event_poll_fd);
+  g_source_attach (source, NULL);
+
+  return source;
+}
+
 static gboolean
 gf_backend_x11_initable_init (GInitable     *initable,
                               GCancellable  *cancellable,
                               GError       **error)
 {
   GfBackendX11 *x11;
+  GfBackendX11Private *priv;
   GInitableIface *parent_iface;
+  const gchar *display;
 
   x11 = GF_BACKEND_X11 (initable);
+  priv = gf_backend_x11_get_instance_private (x11);
   parent_iface = g_type_interface_peek_parent (G_INITABLE_GET_IFACE (x11));
 
+  display = g_getenv ("DISPLAY");
+  if (!display)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Unable to open display, DISPLAY not set");
+
+      return FALSE;
+    }
+
+  priv->xdisplay = XOpenDisplay (display);
+  if (!priv->xdisplay)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Unable to open display '%s'", display);
+
+      return FALSE;
+    }
+
   return parent_iface->init (initable, cancellable, error);
 }
 
@@ -57,11 +198,68 @@ initable_iface_init (GInitableIface *initable_iface)
 }
 
 static void
+gf_backend_x11_finalize (GObject *object)
+{
+  GfBackendX11 *x11;
+  GfBackendX11Private *priv;
+
+  x11 = GF_BACKEND_X11 (object);
+  priv = gf_backend_x11_get_instance_private (x11);
+
+  if (priv->source != NULL)
+    {
+      g_source_unref (priv->source);
+      priv->source = NULL;
+    }
+
+  if (priv->xdisplay != NULL)
+    {
+      XCloseDisplay (priv->xdisplay);
+      priv->xdisplay = NULL;
+    }
+
+  G_OBJECT_CLASS (gf_backend_x11_parent_class)->finalize (object);
+}
+
+static void
+gf_backend_x11_post_init (GfBackend *backend)
+{
+  GfBackendX11 *x11;
+  GfBackendX11Private *priv;
+
+  x11 = GF_BACKEND_X11 (backend);
+  priv = gf_backend_x11_get_instance_private (x11);
+
+  priv->source = x_event_source_new (backend);
+
+  GF_BACKEND_CLASS (gf_backend_x11_parent_class)->post_init (backend);
+}
+
+static void
 gf_backend_x11_class_init (GfBackendX11Class *x11_class)
 {
+  GObjectClass *object_class;
+  GfBackendClass *backend_class;
+
+  object_class = G_OBJECT_CLASS (x11_class);
+  backend_class = GF_BACKEND_CLASS (x11_class);
+
+  object_class->finalize = gf_backend_x11_finalize;
+
+  backend_class->post_init = gf_backend_x11_post_init;
 }
 
 static void
 gf_backend_x11_init (GfBackendX11 *x11)
 {
 }
+
+Display *
+gf_backend_x11_get_xdisplay (GfBackendX11 *x11)
+{
+  GfBackendX11Private *priv;
+
+  priv = gf_backend_x11_get_instance_private (x11);
+
+  return priv->xdisplay;
+}
diff --git a/backends/gf-backend.c b/backends/gf-backend.c
index 28f6d71..b822bf7 100644
--- a/backends/gf-backend.c
+++ b/backends/gf-backend.c
@@ -86,6 +86,11 @@ gf_backend_dispose (GObject *object)
 }
 
 static void
+gf_backend_real_post_init (GfBackend *backend)
+{
+}
+
+static void
 gf_backend_class_init (GfBackendClass *backend_class)
 {
   GObjectClass *object_class;
@@ -93,6 +98,8 @@ gf_backend_class_init (GfBackendClass *backend_class)
   object_class = G_OBJECT_CLASS (backend_class);
 
   object_class->dispose = gf_backend_dispose;
+
+  backend_class->post_init = gf_backend_real_post_init;
 }
 
 static void
@@ -139,5 +146,7 @@ gf_backend_new (GfBackendType type)
       return NULL;
     }
 
+  GF_BACKEND_GET_CLASS (backend)->post_init (backend);
+
   return backend;
 }
diff --git a/configure.ac b/configure.ac
index 983e4af..cacd905 100644
--- a/configure.ac
+++ b/configure.ac
@@ -102,6 +102,7 @@ PKG_CHECK_MODULES([BACKENDS], [
   gio-2.0 >= $GLIB_REQUIRED
   gio-unix-2.0 >= $GLIB_REQUIRED
   glib-2.0 >= $GLIB_REQUIRED
+  x11
 ])
 
 PKG_CHECK_MODULES([GNOME_FLASHBACK], [


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