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:
parent
7497475295
commit
181b875a3d
7 changed files with 156 additions and 0 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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... */
|
||||
|
|
Loading…
Reference in a new issue