Adds a way for Cogl to control event_mask of foreign wins

This extends cogl_onscreen_x11_set_foreign_xid to take a callback to a
function that details the event mask the Cogl requires the application
to select on foreign windows. This is required because Cogl, for
example, needs to track size changes of a window and may also in the
future want other notifications such as map/unmap.

Most applications wont need to use the foreign xwindow apis, but those
that do are required to pass a valid callback and update the event mask
of their window according to Cogl's requirements.
This commit is contained in:
Robert Bragg 2011-05-04 17:02:04 +01:00
parent 50d688399b
commit 4d3bf09e60
9 changed files with 151 additions and 18 deletions

View File

@ -118,6 +118,8 @@ struct _CoglOnscreen
#ifdef COGL_HAS_X11_SUPPORT
guint32 foreign_xid;
CoglOnscreenX11MaskCallback foreign_update_mask_callback;
void *foreign_update_mask_data;
#endif
gboolean swap_throttled;

View File

@ -1624,9 +1624,17 @@ cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
#ifdef COGL_HAS_X11_SUPPORT
void
cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
guint32 xid)
guint32 xid,
CoglOnscreenX11MaskCallback update,
void *user_data)
{
/* We don't wan't applications to get away with being lazy here and not
* passing an update callback... */
g_return_if_fail (update);
onscreen->foreign_xid = xid;
onscreen->foreign_update_mask_callback = update;
onscreen->foreign_update_mask_data = user_data;
}
guint32

View File

@ -86,11 +86,67 @@ CoglOnscreen *
cogl_onscreen_new (CoglContext *context, int width, int height);
#ifdef COGL_HAS_X11
typedef void (*CoglOnscreenX11MaskCallback) (CoglOnscreen *onscreen,
guint32 event_mask,
void *user_data);
/**
* cogl_onscreen_x11_set_foreign_window_xid:
* @onscreen: The unallocated framebuffer to associated with an X
* window.
* @xid: The XID of an existing X window
* @update: A callback that notifies of updates to what Cogl requires
* to be in the core X protocol event mask.
*
* Ideally we would recommend that you let Cogl be responsible for
* creating any X window required to back an onscreen framebuffer but
* if you really need to target a window created manually this
* function can be called before @onscreen has been allocated to set a
* foreign XID for your existing X window.
*
* Since Cogl needs, for example, to track changes to the size of an X
* window it requires that certain events be selected for via the core
* X protocol. This requirement may also be changed asynchronously so
* you must pass in an @update callback to inform you of Cogl's
* required event mask.
*
* For example if you are using Xlib you could use this API roughly
* as follows:
* [{
* static void
* my_update_cogl_x11_event_mask (CoglOnscreen *onscreen,
* guint32 event_mask,
* void *user_data)
* {
* XSetWindowAttributes attrs;
* MyData *data = user_data;
* attrs.event_mask = event_mask | data->my_event_mask;
* XChangeWindowAttributes (data->xdpy,
* data->xwin,
* CWEventMask,
* &attrs);
* }
*
* {
* *snip*
* cogl_onscreen_x11_set_foreign_window_xid (onscreen,
* data->xwin,
* my_update_cogl_x11_event_mask,
* data);
* *snip*
* }
* }]
*
* Since: 2.0
* Stability: Unstable
*/
#define cogl_onscreen_x11_set_foreign_window_xid \
cogl_onscreen_x11_set_foreign_window_xid_EXP
void
cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
guint32 xid);
guint32 xid,
CoglOnscreenX11MaskCallback update,
void *user_data);
#define cogl_onscreen_x11_get_window_xid cogl_onscreen_x11_get_window_xid_EXP
guint32

View File

@ -68,6 +68,8 @@
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
#include <X11/Xlib.h>
#define COGL_ONSCREEN_X11_EVENT_MASK StructureNotifyMask
#endif
typedef struct _CoglRendererEGL
@ -922,6 +924,11 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
_cogl_framebuffer_winsys_update_size (framebuffer,
attr.width, attr.height);
/* Make sure the app selects for the events we require... */
onscreen->foreign_update_mask_callback (onscreen,
COGL_ONSCREEN_X11_EVENT_MASK,
onscreen->foreign_update_mask_data);
}
else
{
@ -957,7 +964,9 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
DefaultRootWindow (xlib_renderer->xdpy),
xvisinfo->visual,
AllocNone);
mask = CWBorderPixel | CWColormap;
attr.event_mask = COGL_ONSCREEN_X11_EVENT_MASK;
mask = CWBorderPixel | CWColormap | CWEventMask;
xwin = XCreateWindow (xlib_renderer->xdpy,
DefaultRootWindow (xlib_renderer->xdpy),

View File

@ -64,6 +64,8 @@ typedef CoglFuncPtr (*GLXGetProcAddressProc) (const GLubyte *procName);
#include <errno.h>
#endif
#define COGL_ONSCREEN_X11_EVENT_MASK StructureNotifyMask
typedef struct _CoglContextGLX
{
GLXDrawable current_drawable;
@ -756,6 +758,11 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
_cogl_framebuffer_winsys_update_size (framebuffer,
attr.width, attr.height);
/* Make sure the app selects for the events we require... */
onscreen->foreign_update_mask_callback (onscreen,
COGL_ONSCREEN_X11_EVENT_MASK,
onscreen->foreign_update_mask_data);
}
else
{
@ -792,7 +799,9 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
DefaultRootWindow (xlib_renderer->xdpy),
xvisinfo->visual,
AllocNone);
mask = CWBorderPixel | CWColormap;
xattr.event_mask = COGL_ONSCREEN_X11_EVENT_MASK;
mask = CWBorderPixel | CWColormap | CWEventMask;
xwin = XCreateWindow (xlib_renderer->xdpy,
DefaultRootWindow (xlib_renderer->xdpy),

View File

@ -5,6 +5,24 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
static void
update_cogl_x11_event_mask (CoglOnscreen *onscreen,
guint32 event_mask,
void *user_data)
{
XDisplay *xdpy = user_data;
XSetWindowAttributes attrs;
guint32 xwin;
attrs.event_mask = event_mask;
xwin = cogl_onscreen_x11_get_window_xid (onscreen);
XChangeWindowAttributes (xdpy,
(Window)xwin,
CWEventMask,
&attrs);
}
int
main (int argc, char **argv)
{
@ -110,7 +128,9 @@ main (int argc, char **argv)
XFree (xvisinfo);
cogl_onscreen_x11_set_foreign_window_xid (onscreen, xwin);
cogl_onscreen_x11_set_foreign_window_xid (onscreen, xwin,
update_cogl_x11_event_mask,
xdpy);
fb = COGL_FRAMEBUFFER (onscreen);
/* Eventually there will be an implicit allocate on first use so this

View File

@ -121,8 +121,13 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window)
stage_glx->onscreen = cogl_onscreen_new (backend->cogl_context,
width, height);
if (stage_x11->xwin != None)
cogl_onscreen_x11_set_foreign_window_xid (stage_glx->onscreen,
stage_x11->xwin);
{
cogl_onscreen_x11_set_foreign_window_xid (
stage_glx->onscreen,
stage_x11->xwin,
_clutter_stage_x11_update_foreign_event_mask,
stage_x11);
}
clutter_vblank = _clutter_backend_glx_get_vblank ();
if (clutter_vblank && strcmp (clutter_vblank, "none") == 0)

View File

@ -387,6 +387,23 @@ clutter_stage_x11_unrealize (ClutterStageWindow *stage_window)
}
}
void
_clutter_stage_x11_update_foreign_event_mask (CoglOnscreen *onscreen,
guint32 event_mask,
void *user_data)
{
ClutterStageX11 *stage_x11 = user_data;
ClutterBackendX11 *backend_x11 = stage_x11->backend;
XSetWindowAttributes attrs;
attrs.event_mask = event_mask | CLUTTER_STAGE_X11_EVENT_MASK;
XChangeWindowAttributes (backend_x11->xdpy,
stage_x11->xwin,
CWEventMask,
&attrs);
}
static gboolean
clutter_stage_x11_realize (ClutterStageWindow *stage_window)
{
@ -412,17 +429,7 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window)
* because key events are broken with that extension, and will
* be fixed by XI2
*/
event_flags = StructureNotifyMask
| FocusChangeMask
| ExposureMask
| PropertyChangeMask
| EnterWindowMask
| LeaveWindowMask
| KeyPressMask
| KeyReleaseMask
| ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask;
event_flags = CLUTTER_STAGE_X11_EVENT_MASK;
/* we unconditionally select input events even with event retrieval
* disabled because we need to guarantee that the Clutter internal

View File

@ -78,8 +78,25 @@ struct _ClutterStageX11Class
GObjectClass parent_class;
};
#define CLUTTER_STAGE_X11_EVENT_MASK \
StructureNotifyMask | \
FocusChangeMask | \
ExposureMask | \
PropertyChangeMask | \
EnterWindowMask | \
LeaveWindowMask | \
KeyPressMask | \
KeyReleaseMask | \
ButtonPressMask | \
ButtonReleaseMask | \
PointerMotionMask;
GType _clutter_stage_x11_get_type (void) G_GNUC_CONST;
void _clutter_stage_x11_update_foreign_event_mask (CoglOnscreen *onscreen,
guint32 event_mask,
void *user_data);
/* Private to subclasses */
void _clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11,
guint32 user_time);