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_event_retrieval_enabled() function. The
event retrieval will also automatically be disabled if the application
sets a foreign display.

Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2011-12-16 18:50:49 +00:00
parent 7497475295
commit 181b875a3d
7 changed files with 156 additions and 0 deletions

View File

@ -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;

View File

@ -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_event_retrieval_enabled (renderer, FALSE);
}
Display *
@ -192,6 +200,17 @@ cogl_xlib_renderer_get_foreign_display (CoglRenderer *renderer)
return renderer->foreign_xdpy;
}
void
cogl_xlib_renderer_set_event_retrieval_enabled (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

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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_event_retrieval_enabled() 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_event_retrieval_enabled:
* @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_event_retrieval_enabled (CoglRenderer *renderer,
gboolean enable);
#define cogl_xlib_renderer_get_display cogl_xlib_renderer_get_display_EXP
Display *
cogl_xlib_renderer_get_display (CoglRenderer *renderer);

View File

@ -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

View File

@ -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... */