[cogl/fosdem-2012: 7/16] xlib: Internally retrieve XEvents
- From: Robert Bragg <rbragg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/fosdem-2012: 7/16] xlib: Internally retrieve XEvents
- Date: Wed, 4 Jan 2012 19:36:42 +0000 (UTC)
commit a6bda9cd6fbcf60b50b825056860b3b145df9b2d
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..20b25bd 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_begin_idle (CoglRenderer *renderer,
+ CoglPollFD **poll_fds,
+ int *n_poll_fds,
+ gint64 *timeout);
+
+void
+_cogl_xlib_renderer_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..34a9ba6 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_begin_idle (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_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..0d19894 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_context_begin_idle (CoglContext *context,
+ CoglPollFD **poll_fds,
+ int *n_poll_fds,
+ gint64 *timeout)
+{
+ _cogl_xlib_renderer_begin_idle (context->display->renderer,
+ poll_fds,
+ n_poll_fds,
+ timeout);
+}
+
+static void
+_cogl_winsys_context_dispatch (CoglContext *context,
+ const CoglPollFD *poll_fds,
+ int n_poll_fds)
+{
+ _cogl_xlib_renderer_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.context_begin_idle = _cogl_winsys_context_begin_idle;
+ vtable.context_dispatch = _cogl_winsys_context_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..594e377 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_context_begin_idle (CoglContext *context,
+ CoglPollFD **poll_fds,
+ int *n_poll_fds,
+ gint64 *timeout)
+{
+ _cogl_xlib_renderer_begin_idle (context->display->renderer,
+ poll_fds,
+ n_poll_fds,
+ timeout);
+}
+
+static void
+_cogl_winsys_context_dispatch (CoglContext *context,
+ const CoglPollFD *poll_fds,
+ int n_poll_fds)
+{
+ _cogl_xlib_renderer_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,
+ .context_begin_idle = _cogl_winsys_context_begin_idle,
+ .context_dispatch = _cogl_winsys_context_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]