[cogl/fosdem-2012: 8/17] xlib: Internally retrieve XEvents



commit 3868e50f749ae0cd3e5fa2a58b83f481917b4b2c
Author: Neil Roberts <neil linux intel com>
Date:   Fri Dec 16 18:50:49 2011 +0000

    xlib: Internally retrieve XEvents
    
    Previously we relied on the application to send all X events through
    Cogl using cogl_xlib_renderer_handle_event. This breaks the
    abstraction that an application shouldn't need to know what winsys
    Cogl is using. Now that we have main loop integreation in Cogl, the
    Xlib-based winsys's can report that Cogl needs to block on the file
    descriptor of the X connection and it can manually handle the
    events.
    
    The event retrieval can be disabled by an application if it calls the
    new cogl_xlib_renderer_set_enable_event_retrieval() function. The
    event retrieval will also automatically be disabled if the application
    sets a foreign display.

 cogl/cogl-renderer-private.h      |    1 +
 cogl/cogl-renderer.c              |   19 +++++++++++++++
 cogl/cogl-xlib-renderer-private.h |   15 ++++++++++++
 cogl/cogl-xlib-renderer.c         |   45 +++++++++++++++++++++++++++++++++++++
 cogl/cogl-xlib-renderer.h         |   27 ++++++++++++++++++++++
 cogl/winsys/cogl-winsys-egl-x11.c |   25 ++++++++++++++++++++
 cogl/winsys/cogl-winsys-glx.c     |   24 +++++++++++++++++++
 7 files changed, 156 insertions(+), 0 deletions(-)
---
diff --git a/cogl/cogl-renderer-private.h b/cogl/cogl-renderer-private.h
index 2f7aaf1..47c0667 100644
--- a/cogl/cogl-renderer-private.h
+++ b/cogl/cogl-renderer-private.h
@@ -46,6 +46,7 @@ struct _CoglRenderer
   CoglWinsysID winsys_id_override;
 #ifdef COGL_HAS_XLIB_SUPPORT
   Display *foreign_xdpy;
+  gboolean xlib_enable_event_retrieval;
 #endif
 
   CoglDriver driver;
diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c
index fe4e225..d55588b 100644
--- a/cogl/cogl-renderer.c
+++ b/cogl/cogl-renderer.c
@@ -169,6 +169,10 @@ cogl_renderer_new (void)
   renderer->connected = FALSE;
   renderer->event_filters = NULL;
 
+#ifdef COGL_HAS_XLIB_SUPPORT
+  renderer->xlib_enable_event_retrieval = TRUE;
+#endif
+
   return _cogl_renderer_object_new (renderer);
 }
 
@@ -183,6 +187,10 @@ cogl_xlib_renderer_set_foreign_display (CoglRenderer *renderer,
   _COGL_RETURN_IF_FAIL (!renderer->connected);
 
   renderer->foreign_xdpy = xdisplay;
+
+  /* If the application is using a foreign display then we can assume
+     it will also do its own event retrieval */
+  cogl_xlib_renderer_set_enable_event_retrieval (renderer, FALSE);
 }
 
 Display *
@@ -192,6 +200,17 @@ cogl_xlib_renderer_get_foreign_display (CoglRenderer *renderer)
 
   return renderer->foreign_xdpy;
 }
+
+void
+cogl_xlib_renderer_set_enable_event_retrieval (CoglRenderer *renderer,
+                                               gboolean enable)
+{
+  _COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer));
+  /* NB: Renderers are considered immutable once connected */
+  _COGL_RETURN_IF_FAIL (!renderer->connected);
+
+  renderer->xlib_enable_event_retrieval = enable;
+}
 #endif /* COGL_HAS_XLIB_SUPPORT */
 
 gboolean
diff --git a/cogl/cogl-xlib-renderer-private.h b/cogl/cogl-xlib-renderer-private.h
index bad70ba..d0715c1 100644
--- a/cogl/cogl-xlib-renderer-private.h
+++ b/cogl/cogl-xlib-renderer-private.h
@@ -27,6 +27,7 @@
 #include "cogl-object-private.h"
 #include "cogl-xlib-private.h"
 #include "cogl-x11-renderer-private.h"
+#include "cogl-context.h"
 
 typedef struct _CoglXlibRenderer
 {
@@ -37,6 +38,9 @@ typedef struct _CoglXlibRenderer
   /* Current top of the XError trap state stack. The actual memory for
      these is expected to be allocated on the stack by the caller */
   CoglXlibTrapState *trap_state;
+
+  /* A poll FD for handling event retrieval within Cogl */
+  CoglPollFD poll_fd;
 } CoglXlibRenderer;
 
 gboolean
@@ -77,4 +81,15 @@ _cogl_xlib_renderer_untrap_errors (CoglRenderer *renderer,
 CoglXlibRenderer *
 _cogl_xlib_renderer_get_data (CoglRenderer *renderer);
 
+void
+_cogl_xlib_renderer_poll_get_info (CoglRenderer *renderer,
+                                   CoglPollFD **poll_fds,
+                                   int *n_poll_fds,
+                                   gint64 *timeout);
+
+void
+_cogl_xlib_renderer_poll_dispatch (CoglRenderer *renderer,
+                                   const CoglPollFD *poll_fds,
+                                   int n_poll_fds);
+
 #endif /* __COGL_RENDERER_XLIB_PRIVATE_H */
diff --git a/cogl/cogl-xlib-renderer.c b/cogl/cogl-xlib-renderer.c
index 3a96b51..1bbbe14 100644
--- a/cogl/cogl-xlib-renderer.c
+++ b/cogl/cogl-xlib-renderer.c
@@ -213,6 +213,9 @@ _cogl_xlib_renderer_connect (CoglRenderer *renderer, GError **error)
 
   xlib_renderer->trap_state = NULL;
 
+  xlib_renderer->poll_fd.fd = ConnectionNumber (xlib_renderer->xdpy);
+  xlib_renderer->poll_fd.events = COGL_POLL_FD_EVENT_IN;
+
   register_xlib_renderer (renderer);
 
   return TRUE;
@@ -267,3 +270,45 @@ cogl_xlib_renderer_remove_filter (CoglRenderer *renderer,
                                        (CoglNativeFilterFunc)func, data);
 }
 
+void
+_cogl_xlib_renderer_poll_get_info (CoglRenderer *renderer,
+                                   CoglPollFD **poll_fds,
+                                   int *n_poll_fds,
+                                   gint64 *timeout)
+{
+  CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
+
+  if (renderer->xlib_enable_event_retrieval)
+    {
+      *n_poll_fds = 1;
+      *poll_fds = &xlib_renderer->poll_fd;
+      if (XPending (xlib_renderer->xdpy))
+        *timeout = 0;
+      else
+        *timeout = -1;
+    }
+  else
+    {
+      *n_poll_fds = 0;
+      *poll_fds = NULL;
+      *timeout = -1;
+    }
+}
+
+void
+_cogl_xlib_renderer_poll_dispatch (CoglRenderer *renderer,
+                                   const CoglPollFD *poll_fds,
+                                   int n_poll_fds)
+{
+  CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
+
+  if (renderer->xlib_enable_event_retrieval)
+    while (XPending (xlib_renderer->xdpy))
+      {
+        XEvent xevent;
+
+        XNextEvent (xlib_renderer->xdpy, &xevent);
+
+        cogl_xlib_renderer_handle_event (renderer, &xevent);
+      }
+}
diff --git a/cogl/cogl-xlib-renderer.h b/cogl/cogl-xlib-renderer.h
index 0afd568..30e6429 100644
--- a/cogl/cogl-xlib-renderer.h
+++ b/cogl/cogl-xlib-renderer.h
@@ -112,11 +112,38 @@ cogl_xlib_renderer_get_foreign_display (CoglRenderer *renderer);
  *
  * Sets a foreign Xlib display that Cogl will use for and Xlib based winsys
  * backend.
+ *
+ * Note that calling this function will automatically call
+ * cogl_xlib_renderer_set_enable_event_retrieval() to disable Cogl's
+ * event retrieval. Cogl still needs to see all of the X events so the
+ * application should also use cogl_xlib_renderer_handle_event() if it
+ * uses this function.
  */
 void
 cogl_xlib_renderer_set_foreign_display (CoglRenderer *renderer,
                                         Display *display);
 
+/**
+ * cogl_xlib_renderer_set_enable_event_retrieval:
+ * @renderer: A #CoglRenderer
+ * @enable: The new value
+ *
+ * Sets whether Cogl should automatically retrieve events from the X
+ * display. This defaults to %TRUE unless
+ * cogl_xlib_renderer_set_foreign_display() is called. It can be set
+ * to %FALSE if the application wants to handle its own event
+ * retrieval. Note that Cogl still needs to see all of the X events to
+ * function properly so the application should call
+ * cogl_xlib_renderer_handle_event() for each event if it disables
+ * automatic event retrieval.
+ *
+ * Since: 1.10
+ * Stability: unstable
+ */
+void
+cogl_xlib_renderer_set_enable_event_retrieval (CoglRenderer *renderer,
+                                               gboolean enable);
+
 #define cogl_xlib_renderer_get_display cogl_xlib_renderer_get_display_EXP
 Display *
 cogl_xlib_renderer_get_display (CoglRenderer *renderer);
diff --git a/cogl/winsys/cogl-winsys-egl-x11.c b/cogl/winsys/cogl-winsys-egl-x11.c
index 3506ba9..e4fc6de 100644
--- a/cogl/winsys/cogl-winsys-egl-x11.c
+++ b/cogl/winsys/cogl-winsys-egl-x11.c
@@ -564,6 +564,28 @@ _cogl_winsys_xlib_get_visual_info (void)
   return get_visual_info (ctx->display, egl_display->egl_config);
 }
 
+static void
+_cogl_winsys_poll_get_info (CoglContext *context,
+                            CoglPollFD **poll_fds,
+                            int *n_poll_fds,
+                            gint64 *timeout)
+{
+  _cogl_xlib_renderer_poll_get_info (context->display->renderer,
+                                     poll_fds,
+                                     n_poll_fds,
+                                     timeout);
+}
+
+static void
+_cogl_winsys_poll_dispatch (CoglContext *context,
+                            const CoglPollFD *poll_fds,
+                            int n_poll_fds)
+{
+  _cogl_xlib_renderer_poll_dispatch (context->display->renderer,
+                                     poll_fds,
+                                     n_poll_fds);
+}
+
 #ifdef EGL_KHR_image_pixmap
 
 static gboolean
@@ -710,6 +732,9 @@ _cogl_winsys_egl_xlib_get_vtable (void)
 
       vtable.xlib_get_visual_info = _cogl_winsys_xlib_get_visual_info;
 
+      vtable.poll_get_info = _cogl_winsys_poll_get_info;
+      vtable.poll_dispatch = _cogl_winsys_poll_dispatch;
+
 #ifdef EGL_KHR_image_pixmap
       /* X11 tfp support... */
       /* XXX: instead of having a rather monolithic winsys vtable we could
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index 66252de..8779af6 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -2051,6 +2051,27 @@ _cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
   return glx_tex_pixmap->glx_tex;
 }
 
+static void
+_cogl_winsys_poll_get_info (CoglContext *context,
+                            CoglPollFD **poll_fds,
+                            int *n_poll_fds,
+                            gint64 *timeout)
+{
+  _cogl_xlib_renderer_poll_get_info (context->display->renderer,
+                                     poll_fds,
+                                     n_poll_fds,
+                                     timeout);
+}
+
+static void
+_cogl_winsys_poll_dispatch (CoglContext *context,
+                            const CoglPollFD *poll_fds,
+                            int n_poll_fds)
+{
+  _cogl_xlib_renderer_poll_dispatch (context->display->renderer,
+                                     poll_fds,
+                                     n_poll_fds);
+}
 
 static CoglWinsysVtable _cogl_winsys_vtable =
   {
@@ -2082,6 +2103,9 @@ static CoglWinsysVtable _cogl_winsys_vtable =
       _cogl_winsys_onscreen_remove_swap_buffers_callback,
     .onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility,
 
+    .poll_get_info = _cogl_winsys_poll_get_info,
+    .poll_dispatch = _cogl_winsys_poll_dispatch,
+
     /* X11 tfp support... */
     /* XXX: instead of having a rather monolithic winsys vtable we could
      * perhaps look for a way to separate these... */



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