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)
This commit is contained in:
Neil Roberts 2010-06-04 10:38:30 +01:00
parent 3abe26b913
commit a01b094630
4 changed files with 93 additions and 0 deletions

View File

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

View File

@ -24,11 +24,31 @@
#ifndef __COGL_CONTEXT_WINSYS_H
#define __COGL_CONTEXT_WINSYS_H
#ifdef COGL_HAS_XLIB_SUPPORT
#include <X11/Xlib.h>
#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 */

View File

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

View File

@ -25,6 +25,9 @@
#define __COGL_XLIB_H
#include "cogl.h"
#include "cogl-context-winsys.h"
#include <X11/Xlib.h>
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 */