diff --git a/clutter/cogl/cogl/cogl-renderer-private.h b/clutter/cogl/cogl/cogl-renderer-private.h index 8668270a2..660082553 100644 --- a/clutter/cogl/cogl/cogl-renderer-private.h +++ b/clutter/cogl/cogl/cogl-renderer-private.h @@ -37,6 +37,8 @@ struct _CoglRenderer #ifdef COGL_HAS_XLIB_SUPPORT Display *foreign_xdpy; #endif + /* List of callback functions that will be given every native event */ + GSList *event_filters; void *winsys; }; diff --git a/clutter/cogl/cogl/cogl-renderer-xlib-private.h b/clutter/cogl/cogl/cogl-renderer-xlib-private.h index 13f946419..bc8ccb5ee 100644 --- a/clutter/cogl/cogl/cogl-renderer-xlib-private.h +++ b/clutter/cogl/cogl/cogl-renderer-xlib-private.h @@ -34,8 +34,6 @@ typedef struct _CoglRendererXlib Display *xdpy; - /* List of callback functions that will be given every Xlib event */ - GSList *event_filters; /* 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; diff --git a/clutter/cogl/cogl/cogl-renderer-xlib.c b/clutter/cogl/cogl/cogl-renderer-xlib.c index bd2cc2b8b..f8dbe504f 100644 --- a/clutter/cogl/cogl/cogl-renderer-xlib.c +++ b/clutter/cogl/cogl/cogl-renderer-xlib.c @@ -43,82 +43,6 @@ static char *_cogl_x11_display_name = NULL; static GList *_cogl_xlib_renderers = NULL; -CoglXlibFilterReturn -cogl_renderer_xlib_handle_event (CoglRenderer *renderer, - XEvent *xevent) -{ - CoglRendererXlib *xlib_renderer = renderer->winsys; - GSList *l; - - g_return_val_if_fail (xlib_renderer->xdpy != NULL, COGL_XLIB_FILTER_CONTINUE); - - /* XXX: should this be a more graceful check? */ - g_return_val_if_fail (xlib_renderer != NULL, COGL_XLIB_FILTER_CONTINUE); - - /* Pass the event on to all of the registered filters in turn */ - for (l = xlib_renderer->event_filters; l; l = l->next) - { - CoglXlibFilterClosure *closure = l->data; - - if (closure->func (xevent, closure->data) == COGL_XLIB_FILTER_REMOVE) - return COGL_XLIB_FILTER_REMOVE; - } - - switch (xevent->type) - { - /* TODO... */ - default: - break; - } - - return COGL_XLIB_FILTER_CONTINUE; -} - -void -cogl_renderer_xlib_add_filter (CoglRenderer *renderer, - CoglXlibFilterFunc func, - void *data) -{ - CoglRendererXlib *xlib_renderer; - CoglXlibFilterClosure *closure; - - xlib_renderer = renderer->winsys; - - closure = g_slice_new (CoglXlibFilterClosure); - closure->func = func; - closure->data = data; - - xlib_renderer->event_filters = - g_slist_prepend (xlib_renderer->event_filters, closure); -} - -void -cogl_renderer_xlib_remove_filter (CoglRenderer *renderer, - CoglXlibFilterFunc func, - void *data) -{ - CoglRendererXlib *xlib_renderer; - GSList *l, *prev = NULL; - - xlib_renderer = renderer->winsys; - - for (l = xlib_renderer->event_filters; l; prev = l, l = l->next) - { - CoglXlibFilterClosure *closure = l->data; - - if (closure->func == func && closure->data == data) - { - g_slice_free (CoglXlibFilterClosure, closure); - if (prev) - prev->next = g_slist_delete_link (prev->next, l); - else - xlib_renderer->event_filters = - g_slist_delete_link (xlib_renderer->event_filters, l); - break; - } - } -} - static void register_xlib_renderer (CoglRenderer *renderer) { @@ -245,8 +169,6 @@ _cogl_renderer_xlib_connect (CoglRenderer *renderer, GError **error) &damage_error)) x11_renderer->damage_base = -1; - xlib_renderer->event_filters = NULL; - xlib_renderer->trap_state = NULL; register_xlib_renderer (renderer); @@ -254,21 +176,11 @@ _cogl_renderer_xlib_connect (CoglRenderer *renderer, GError **error) return TRUE; } -static void -free_xlib_filter_closure (void *data, void *user_data) -{ - g_slice_free (CoglXlibFilterClosure, data); -} - void _cogl_renderer_xlib_disconnect (CoglRenderer *renderer) { CoglRendererXlib *xlib_renderer = renderer->winsys; - g_slist_foreach (xlib_renderer->event_filters, - free_xlib_filter_closure, NULL); - g_slist_free (xlib_renderer->event_filters); - if (!renderer->foreign_xdpy) XCloseDisplay (xlib_renderer->xdpy); diff --git a/clutter/cogl/cogl/cogl-renderer.c b/clutter/cogl/cogl/cogl-renderer.c index 2dffb2f2c..548c2f0ff 100644 --- a/clutter/cogl/cogl/cogl-renderer.c +++ b/clutter/cogl/cogl/cogl-renderer.c @@ -41,18 +41,36 @@ static void _cogl_renderer_free (CoglRenderer *renderer); COGL_OBJECT_DEFINE (Renderer, renderer); +typedef struct _CoglNativeFilterClosure +{ + CoglNativeFilterFunc func; + void *data; +} CoglNativeFilterClosure; + GQuark cogl_renderer_error_quark (void) { return g_quark_from_static_string ("cogl-renderer-error-quark"); } +static void +native_filter_closure_free (CoglNativeFilterClosure *closure) +{ + g_slice_free (CoglNativeFilterClosure, closure); +} + static void _cogl_renderer_free (CoglRenderer *renderer) { #ifdef COGL_HAS_FULL_WINSYS _cogl_winsys_renderer_disconnect (renderer); #endif + + g_slist_foreach (renderer->event_filters, + (GFunc) native_filter_closure_free, + NULL); + g_slist_free (renderer->event_filters); + g_free (renderer); } @@ -62,6 +80,7 @@ cogl_renderer_new (void) CoglRenderer *renderer = g_new0 (CoglRenderer, 1); renderer->connected = FALSE; + renderer->event_filters = NULL; return _cogl_renderer_object_new (renderer); } @@ -127,3 +146,66 @@ cogl_renderer_connect (CoglRenderer *renderer, GError **error) renderer->connected = TRUE; return TRUE; } + +CoglFilterReturn +cogl_renderer_handle_native_event (CoglRenderer *renderer, + void *event) +{ + GSList *l, *next; + + /* Pass the event on to all of the registered filters in turn */ + for (l = renderer->event_filters; l; l = next) + { + CoglNativeFilterClosure *closure = l->data; + + /* The next pointer is taken now so that we can handle the + closure being removed during emission */ + next = l->next; + + if (closure->func (event, closure->data) == COGL_FILTER_REMOVE) + return COGL_FILTER_REMOVE; + } + + /* If the backend for the renderer also wants to see the events, it + should just register its own filter */ + + return COGL_FILTER_CONTINUE; +} + +void +cogl_renderer_add_native_filter (CoglRenderer *renderer, + CoglNativeFilterFunc func, + void *data) +{ + CoglNativeFilterClosure *closure; + + closure = g_slice_new (CoglNativeFilterClosure); + closure->func = func; + closure->data = data; + + renderer->event_filters = g_slist_prepend (renderer->event_filters, closure); +} + +void +cogl_renderer_remove_native_filter (CoglRenderer *renderer, + CoglNativeFilterFunc func, + void *data) +{ + GSList *l, *prev = NULL; + + for (l = renderer->event_filters; l; prev = l, l = l->next) + { + CoglNativeFilterClosure *closure = l->data; + + if (closure->func == func && closure->data == data) + { + native_filter_closure_free (closure); + if (prev) + prev->next = g_slist_delete_link (prev->next, l); + else + renderer->event_filters = + g_slist_delete_link (renderer->event_filters, l); + break; + } + } +} diff --git a/clutter/cogl/cogl/cogl-renderer.h b/clutter/cogl/cogl/cogl-renderer.h index 684429988..6d23fe2e1 100644 --- a/clutter/cogl/cogl/cogl-renderer.h +++ b/clutter/cogl/cogl/cogl-renderer.h @@ -63,27 +63,57 @@ cogl_renderer_new (void); /* optional configuration APIs */ -#ifdef COGL_HAS_XLIB - -#define cogl_renderer_xlib_handle_event cogl_renderer_xlib_handle_event_EXP +#define cogl_renderer_handle_native_event cogl_renderer_handle_native_event_EXP /* - * cogl_renderer_xlib_handle_event: - * @xevent: pointer to XEvent structure + * cogl_renderer_handle_native_event: + * @event: pointer to native event structure * - * This function processes a single X event; it can be used to hook - * into external X event retrieval (for example that done by Clutter - * or GDK). + * This function processes a single event; it can be used to hook into + * external event retrieval (for example that done by Clutter or + * GDK). The type of the structure that event points to depends on the + * window system used for the renderer. On an xlib renderer it would + * be a pointer to an XEvent or an a Windows renderer it would be a + * pointer to a MSG struct. * - * Return value: #CoglXlibFilterReturn. %COGL_XLIB_FILTER_REMOVE - * indicates that Cogl has internally handled the event and the - * caller should do no further processing. %COGL_XLIB_FILTER_CONTINUE - * indicates that Cogl is either not interested in the event, - * or has used the event to update internal state without taking - * any exclusive action. + * Return value: #CoglFilterReturn. %COGL_FILTER_REMOVE indicates that + * Cogl has internally handled the event and the caller should do no + * further processing. %COGL_FILTER_CONTINUE indicates that Cogl is + * either not interested in the event, or has used the event to update + * internal state without taking any exclusive action. */ -CoglXlibFilterReturn -cogl_renderer_xlib_handle_event (CoglRenderer *renderer, - XEvent *xevent); +CoglFilterReturn +cogl_renderer_handle_native_event (CoglRenderer *renderer, + void *event); + +#define cogl_renderer_add_native_filter cogl_renderer_add_native_filter_EXP +/* + * _cogl_renderer_add_native_filter: + * + * Adds a callback function that will receive all native events. The + * function can stop further processing of the event by return + * %COGL_FILTER_REMOVE. What is considered a native event depends on + * the type of renderer used. An xlib based renderer would pass all + * XEvents whereas a Windows based renderer would pass MSGs. + */ +void +cogl_renderer_add_native_filter (CoglRenderer *renderer, + CoglNativeFilterFunc func, + void *data); + +#define cogl_renderer_remove_native_filter \ + cogl_renderer_remove_native_filter_EXP +/* + * _cogl_renderer_remove_native_filter: + * + * Removes a callback that was previously added with + * _cogl_renderer_add_native_filter(). + */ +void +cogl_renderer_remove_native_filter (CoglRenderer *renderer, + CoglNativeFilterFunc func, + void *data); + +#ifdef COGL_HAS_XLIB #define cogl_renderer_xlib_get_foreign_display \ cogl_renderer_xlib_get_foreign_display_EXP @@ -113,30 +143,6 @@ cogl_renderer_xlib_set_foreign_display (CoglRenderer *renderer, Display * cogl_renderer_xlib_get_display (CoglRenderer *renderer); -#define cogl_renderer_xlib_add_filter cogl_renderer_xlib_add_filter_EXP -/* - * _cogl_xlib_add_filter: - * - * Adds a callback function that will receive all X11 events. The - * function can stop further processing of the event by return - * %COGL_XLIB_FILTER_REMOVE. - */ -void -cogl_renderer_xlib_add_filter (CoglRenderer *renderer, - CoglXlibFilterFunc func, - void *data); - -#define cogl_renderer_xlib_remove_filter cogl_renderer_xlib_remove_filter_EXP -/* - * _cogl_xlib_remove_filter: - * - * Removes a callback that was previously added with - * _cogl_xlib_add_filter(). - */ -void -cogl_renderer_xlib_remove_filter (CoglRenderer *renderer, - CoglXlibFilterFunc func, - void *data); #endif /* COGL_HAS_XLIB */ #define cogl_renderer_check_onscreen_template \ diff --git a/clutter/cogl/cogl/cogl-types.h b/clutter/cogl/cogl/cogl-types.h index 1a1aac4bb..fb1ce729b 100644 --- a/clutter/cogl/cogl/cogl-types.h +++ b/clutter/cogl/cogl/cogl-types.h @@ -596,19 +596,19 @@ typedef enum { /*< prefix=COGL_RENDERER_ERROR >*/ } CoglRendererError; /* - * CoglXlibFilterReturn: - * @COGL_XLIB_FILTER_CONTINUE: The event was not handled, continues the - * processing - * @COGL_XLIB_FILTER_REMOVE: Remove the event, stops the processing + * CoglFilterReturn: + * @COGL_FILTER_CONTINUE: The event was not handled, continues the + * processing + * @COGL_FILTER_REMOVE: Remove the event, stops the processing * - * Return values for the #CoglXlibFilterFunc function. + * Return values for the #CoglFilterFunc function. * * Stability: Unstable */ -typedef enum _CoglXlibFilterReturn { /*< prefix=COGL_XLIB_FILTER >*/ - COGL_XLIB_FILTER_CONTINUE, - COGL_XLIB_FILTER_REMOVE -} CoglXlibFilterReturn; +typedef enum _CoglFilterReturn { /*< prefix=COGL_FILTER >*/ + COGL_FILTER_CONTINUE, + COGL_FILTER_REMOVE +} CoglFilterReturn; typedef enum _CoglWinsysFeature { @@ -651,20 +651,23 @@ typedef enum _CoglWinsysFeature * so although they aren't explicitly guarded they are implicitly * experimental too. */ -#ifdef COGL_HAS_XLIB - /* - * CoglXlibFilterFunc: + * CoglNativeFilterFunc: + * @native_event: A pointer to the native system event + * @data: The data that was given when the filter was added * * A callback function that can be registered with - * _cogl_xlib_add_filter. The function should return - * %COGL_XLIB_FILTER_REMOVE if it wants to prevent further processing - * or %COGL_XLIB_FILTER_CONTINUE otherwise. + * cogl_renderer_add_native_filter(). The function should return + * %COGL_FILTER_REMOVE if it wants to prevent further processing or + * %COGL_FILTER_CONTINUE otherwise. + * + * The type that @native_event points to depends on the type of the + * underlying renderer. On xlib based renderers this would point to an + * XEvent struct and on Windows it would point to a MSG struct. */ -typedef CoglXlibFilterReturn (* CoglXlibFilterFunc) (XEvent *xevent, - void *data); +typedef CoglFilterReturn (* CoglNativeFilterFunc) (void *native_event, + void *data); -#endif /* COGL_HAS_XLIB */ G_END_DECLS diff --git a/clutter/cogl/cogl/cogl-xlib-private.h b/clutter/cogl/cogl/cogl-xlib-private.h index 39bfeba66..564543988 100644 --- a/clutter/cogl/cogl/cogl-xlib-private.h +++ b/clutter/cogl/cogl/cogl-xlib-private.h @@ -40,12 +40,6 @@ struct _CoglXlibTrapState CoglXlibTrapState *old_state; }; -typedef struct _CoglXlibFilterClosure -{ - CoglXlibFilterFunc func; - void *data; -} CoglXlibFilterClosure; - void _cogl_xlib_query_damage_extension (void); @@ -66,7 +60,7 @@ _cogl_xlib_untrap_errors (CoglXlibTrapState *state); * %COGL_XLIB_FILTER_REMOVE. */ void -_cogl_xlib_add_filter (CoglXlibFilterFunc func, +_cogl_xlib_add_filter (CoglNativeFilterFunc func, void *data); /* @@ -76,7 +70,7 @@ _cogl_xlib_add_filter (CoglXlibFilterFunc func, * _cogl_xlib_add_filter(). */ void -_cogl_xlib_remove_filter (CoglXlibFilterFunc func, +_cogl_xlib_remove_filter (CoglNativeFilterFunc func, void *data); #endif /* __COGL_XLIB_PRIVATE_H */ diff --git a/clutter/cogl/cogl/cogl-xlib.c b/clutter/cogl/cogl/cogl-xlib.c index ce7fb1597..51fa71593 100644 --- a/clutter/cogl/cogl/cogl-xlib.c +++ b/clutter/cogl/cogl/cogl-xlib.c @@ -52,35 +52,6 @@ context is created */ static Display *_cogl_xlib_display = NULL; -CoglXlibFilterReturn -cogl_xlib_handle_event (XEvent *xevent) -{ - GSList *l; - - _COGL_GET_CONTEXT (ctx, COGL_XLIB_FILTER_CONTINUE); - - if (!ctx->stub_winsys) - return cogl_renderer_xlib_handle_event (ctx->display->renderer, xevent); - - /* Pass the event on to all of the registered filters in turn */ - for (l = ctx->event_filters; l; l = l->next) - { - CoglXlibFilterClosure *closure = l->data; - - if (closure->func (xevent, closure->data) == COGL_XLIB_FILTER_REMOVE) - return COGL_XLIB_FILTER_REMOVE; - } - - switch (xevent->type) - { - /* TODO... */ - default: - break; - } - - return COGL_XLIB_FILTER_CONTINUE; -} - Display * cogl_xlib_get_display (void) { @@ -104,59 +75,34 @@ cogl_xlib_set_display (Display *display) _cogl_xlib_display = display; } -void -_cogl_xlib_add_filter (CoglXlibFilterFunc func, - void *data) +/* These three functions are wrappers around the equivalent renderer + functions. They can be removed once all xlib-based backends in + Clutter know about the renderer */ +CoglFilterReturn +cogl_xlib_handle_event (XEvent *xevent) { - CoglXlibFilterClosure *closure; + _COGL_GET_CONTEXT (ctx, COGL_FILTER_CONTINUE); - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - if (!ctx->stub_winsys) - { - cogl_renderer_xlib_add_filter (ctx->display->renderer, - func, data); - return; - } - - closure = g_slice_new (CoglXlibFilterClosure); - closure->func = func; - closure->data = data; - - ctx->event_filters = - g_slist_prepend (ctx->event_filters, closure); + /* Pass the event on to the renderer */ + return cogl_renderer_handle_native_event (ctx->display->renderer, xevent); } void -_cogl_xlib_remove_filter (CoglXlibFilterFunc func, - void *data) +_cogl_xlib_add_filter (CoglNativeFilterFunc func, + void *data) { - GSList *l, *prev = NULL; - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - if (!ctx->stub_winsys) - { - cogl_renderer_xlib_remove_filter (ctx->display->renderer, - func, data); - return; - } + cogl_renderer_add_native_filter (ctx->display->renderer, func, data); +} - for (l = ctx->event_filters; l; prev = l, l = l->next) - { - CoglXlibFilterClosure *closure = l->data; +void +_cogl_xlib_remove_filter (CoglNativeFilterFunc func, + void *data) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); - if (closure->func == func && closure->data == data) - { - g_slice_free (CoglXlibFilterClosure, closure); - if (prev) - prev->next = g_slist_delete_link (prev->next, l); - else - ctx->event_filters = - g_slist_delete_link (ctx->event_filters, l); - break; - } - } + cogl_renderer_remove_native_filter (ctx->display->renderer, func, data); } static int diff --git a/clutter/cogl/cogl/cogl-xlib.h b/clutter/cogl/cogl/cogl-xlib.h index c776ece2d..d088dc9d8 100644 --- a/clutter/cogl/cogl/cogl-xlib.h +++ b/clutter/cogl/cogl/cogl-xlib.h @@ -78,7 +78,7 @@ cogl_xlib_set_display (Display *display); * Stability: Unstable */ #define cogl_xlib_handle_event cogl_xlib_handle_event_EXP -CoglXlibFilterReturn +CoglFilterReturn cogl_xlib_handle_event (XEvent *xevent); #endif /* __COGL_XLIB_H__ */ diff --git a/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c b/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c index 9f8ec6982..32e48dc57 100644 --- a/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c +++ b/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c @@ -203,13 +203,14 @@ process_damage_event (CoglTexturePixmapX11 *tex_pixmap, #endif } -static CoglXlibFilterReturn -_cogl_texture_pixmap_x11_filter (XEvent *event, gpointer data) +static CoglFilterReturn +_cogl_texture_pixmap_x11_filter (void *native_event, void *data) { + XEvent *event = native_event; CoglTexturePixmapX11 *tex_pixmap = data; int damage_base; - _COGL_GET_CONTEXT (ctxt, COGL_XLIB_FILTER_CONTINUE); + _COGL_GET_CONTEXT (ctxt, COGL_FILTER_CONTINUE); damage_base = _cogl_xlib_get_damage_base (); if (event->type == damage_base + XDamageNotify) @@ -220,7 +221,7 @@ _cogl_texture_pixmap_x11_filter (XEvent *event, gpointer data) process_damage_event (tex_pixmap, damage_event); } - return COGL_XLIB_FILTER_CONTINUE; + return COGL_FILTER_CONTINUE; } #ifdef COGL_HAS_GLX_SUPPORT diff --git a/clutter/cogl/cogl/winsys/cogl-winsys-glx.c b/clutter/cogl/cogl/winsys/cogl-winsys-glx.c index a5b07489c..8c163bd75 100644 --- a/clutter/cogl/cogl/winsys/cogl-winsys-glx.c +++ b/clutter/cogl/cogl/winsys/cogl-winsys-glx.c @@ -219,9 +219,10 @@ notify_swap_buffers (CoglContext *context, GLXDrawable drawable) } } -static CoglXlibFilterReturn -glx_event_filter_cb (XEvent *xevent, void *data) +static CoglFilterReturn +glx_event_filter_cb (void *native_event, void *data) { + XEvent *xevent = native_event; CoglContext *context = data; #ifdef GLX_INTEL_swap_event CoglRendererGLX *glx_renderer; @@ -242,7 +243,7 @@ glx_event_filter_cb (XEvent *xevent, void *data) } /* we let ConfigureNotify pass through */ - return COGL_XLIB_FILTER_CONTINUE; + return COGL_FILTER_CONTINUE; } #ifdef GLX_INTEL_swap_event @@ -255,11 +256,11 @@ glx_event_filter_cb (XEvent *xevent, void *data) notify_swap_buffers (context, swap_event->drawable); /* remove SwapComplete events from the queue */ - return COGL_XLIB_FILTER_REMOVE; + return COGL_FILTER_REMOVE; } #endif /* GLX_INTEL_swap_event */ - return COGL_XLIB_FILTER_CONTINUE; + return COGL_FILTER_CONTINUE; } gboolean @@ -672,9 +673,9 @@ _cogl_winsys_context_init (CoglContext *context, GError **error) { context->winsys = g_new0 (CoglContextGLX, 1); - cogl_renderer_xlib_add_filter (context->display->renderer, - glx_event_filter_cb, - context); + cogl_renderer_add_native_filter (context->display->renderer, + glx_event_filter_cb, + context); update_winsys_features (context); return TRUE; @@ -683,9 +684,9 @@ _cogl_winsys_context_init (CoglContext *context, GError **error) void _cogl_winsys_context_deinit (CoglContext *context) { - cogl_renderer_xlib_remove_filter (context->display->renderer, - glx_event_filter_cb, - context); + cogl_renderer_remove_native_filter (context->display->renderer, + glx_event_filter_cb, + context); g_free (context->winsys); } diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c index 1df37b4bd..f9e256151 100644 --- a/clutter/x11/clutter-backend-x11.c +++ b/clutter/x11/clutter-backend-x11.c @@ -131,16 +131,16 @@ cogl_xlib_filter (XEvent *xevent, gpointer data) { ClutterX11FilterReturn retval; - CoglXlibFilterReturn ret; + CoglFilterReturn ret; ret = cogl_xlib_handle_event (xevent); switch (ret) { - case COGL_XLIB_FILTER_REMOVE: + case COGL_FILTER_REMOVE: retval = CLUTTER_X11_FILTER_REMOVE; break; - case COGL_XLIB_FILTER_CONTINUE: + case COGL_FILTER_CONTINUE: default: retval = CLUTTER_X11_FILTER_CONTINUE; break;