From 16c7d12e6c3ffe251ebc80463727b1074d8bdd59 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 4 Jun 2010 10:38:30 +0100 Subject: [PATCH] cogl: Add _cogl_xlib_{,un}trap_errors This is similar to clutter_x11_{,un}trap_errors except that it stores the previous trap state in a caller-allocated struct so that it can be re-entrant. Make _cogl_xlib_trap_errors re-entrant (this will be squashed into an earlier commit) --- cogl/winsys/cogl-context-winsys.c | 2 ++ cogl/winsys/cogl-context-winsys.h | 23 ++++++++++++++++++ cogl/winsys/cogl-xlib.c | 39 +++++++++++++++++++++++++++++++ cogl/winsys/cogl-xlib.h | 29 +++++++++++++++++++++++ 4 files changed, 93 insertions(+) diff --git a/cogl/winsys/cogl-context-winsys.c b/cogl/winsys/cogl-context-winsys.c index 5d6437b05..b730a00d9 100644 --- a/cogl/winsys/cogl-context-winsys.c +++ b/cogl/winsys/cogl-context-winsys.c @@ -94,6 +94,8 @@ _cogl_create_context_winsys (CoglContext *context) { #ifdef COGL_HAS_XLIB_SUPPORT context->winsys.event_filters = NULL; + + context->winsys.trap_state = NULL; #endif _cogl_winsys_features_init (context); diff --git a/cogl/winsys/cogl-context-winsys.h b/cogl/winsys/cogl-context-winsys.h index aa6563a43..80c5500d7 100644 --- a/cogl/winsys/cogl-context-winsys.h +++ b/cogl/winsys/cogl-context-winsys.h @@ -24,11 +24,31 @@ #ifndef __COGL_CONTEXT_WINSYS_H #define __COGL_CONTEXT_WINSYS_H +#ifdef COGL_HAS_XLIB_SUPPORT +#include +#endif + typedef enum { COGL_WINSYS_FEATURE_STUB /* no features are defined yet */ } CoglWinsysFeatureFlags; +#ifdef COGL_HAS_XLIB_SUPPORT + +typedef struct _CoglXlibTrapState CoglXlibTrapState; + +struct _CoglXlibTrapState +{ + /* These values are intended to be internal to + _cogl_xlib_{un,}trap_errors but they need to be in the header so + that the struct can be allocated on the stack */ + int (* old_error_handler) (Display *, XErrorEvent *); + int trapped_error_code; + CoglXlibTrapState *old_state; +}; + +#endif + typedef struct { /* These are specific to winsys backends supporting Xlib. This @@ -36,6 +56,9 @@ typedef struct to Xlib when Cogl gains a more complete winsys abstraction */ #ifdef COGL_HAS_XLIB_SUPPORT 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; #endif /* Function pointers for winsys specific extensions */ diff --git a/cogl/winsys/cogl-xlib.c b/cogl/winsys/cogl-xlib.c index d25553966..de56babc4 100644 --- a/cogl/winsys/cogl-xlib.c +++ b/cogl/winsys/cogl-xlib.c @@ -129,3 +129,42 @@ _cogl_xlib_remove_filter (CoglXlibFilterFunc func, } } } + +static int +error_handler (Display *xdpy, + XErrorEvent *error) +{ + _COGL_GET_CONTEXT (ctxt, 0); + + g_assert (ctxt->winsys.trap_state); + + ctxt->winsys.trap_state->trapped_error_code = error->error_code; + + return 0; +} + +void +_cogl_xlib_trap_errors (CoglXlibTrapState *state) +{ + _COGL_GET_CONTEXT (ctxt, NO_RETVAL); + + state->trapped_error_code = 0; + state->old_error_handler = XSetErrorHandler (error_handler); + + state->old_state = ctxt->winsys.trap_state; + ctxt->winsys.trap_state = state; +} + +int +_cogl_xlib_untrap_errors (CoglXlibTrapState *state) +{ + _COGL_GET_CONTEXT (ctxt, 0); + + g_assert (state == ctxt->winsys.trap_state); + + XSetErrorHandler (state->old_error_handler); + + ctxt->winsys.trap_state = state->old_state; + + return state->trapped_error_code; +} diff --git a/cogl/winsys/cogl-xlib.h b/cogl/winsys/cogl-xlib.h index b31783f68..62a216216 100644 --- a/cogl/winsys/cogl-xlib.h +++ b/cogl/winsys/cogl-xlib.h @@ -25,6 +25,9 @@ #define __COGL_XLIB_H #include "cogl.h" +#include "cogl-context-winsys.h" + +#include typedef struct _CoglXlibFilterClosure CoglXlibFilterClosure; @@ -34,4 +37,30 @@ struct _CoglXlibFilterClosure gpointer data; }; +/* + * _cogl_xlib_trap_errors: + * @state: A temporary place to store data for the trap. + * + * Traps every X error until _cogl_xlib_untrap_errors() called. You + * should allocate an uninitialised CoglXlibTrapState struct on the + * stack to pass to this function. The same pointer should later be + * passed to _cogl_xlib_untrap_errors(). Calls to + * _cogl_xlib_trap_errors() can be nested as long as + * _cogl_xlib_untrap_errors() is called with the corresponding state + * pointers in reverse order. + */ +void +_cogl_xlib_trap_errors (CoglXlibTrapState *state); + +/* + * _cogl_xlib_untrap_errors: + * @state: The state that was passed to _cogl_xlib_trap_errors(). + * + * Removes the X error trap and returns the current status. + * + * Return value: the trapped error code, or 0 for success + */ +int +_cogl_xlib_untrap_errors (CoglXlibTrapState *state); + #endif /* __COGL_XLIB_H */