From 9646e85ba77d7ffe5059b4cea1616a79f7fe5f52 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Wed, 19 May 2010 16:13:07 +0100 Subject: [PATCH] Pass all Xlib events through Cogl The Clutter X11 backend now passes all events through _cogl_xlib_handle_event. This function can now internally be hooked with _cogl_xlib_add_filter. These are added to a list of callbacks which are all called in turn by _cogl_xlib_handle_event. This is intended to be used internally in Cogl by any parts that need to see Xlib events. Cogl now also has an internally exposed function to set a pointer to the Xlib display. This is stored in a global variable. The Clutter X11 backend sets this. _cogl_xlib_handle_event and _cogl_xlib_set_display can be removed once Cogl gains a proper window system abstraction. --- cogl/Makefile.am | 11 +++-- cogl/cogl-internal.h | 52 +++++++++++++++++++++ cogl/winsys/cogl-context-winsys.c | 20 ++++++++ cogl/winsys/cogl-context-winsys.h | 7 +++ cogl/winsys/cogl-xlib.c | 77 +++++++++++++++++++++++++++++++ cogl/winsys/cogl-xlib.h | 37 +++++++++++++++ 6 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 cogl/winsys/cogl-xlib.h diff --git a/cogl/Makefile.am b/cogl/Makefile.am index 8acdd7f25..41f140827 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -162,15 +162,18 @@ libclutter_cogl_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/cog libclutter_cogl_la_SOURCES = $(BUILT_SOURCES) $(cogl_sources_c) +if SUPPORT_XLIB +libclutter_cogl_la_SOURCES += \ + $(srcdir)/winsys/cogl-xlib.h \ + $(srcdir)/winsys/cogl-xlib.c +endif if SUPPORT_GLX libclutter_cogl_la_SOURCES += \ - $(srcdir)/winsys/cogl-glx.c \ - $(srcdir)/winsys/cogl-xlib.c + $(srcdir)/winsys/cogl-glx.c endif if SUPPORT_EGL_PLATFORM_POWERVR_X11 libclutter_cogl_la_SOURCES += \ - $(srcdir)/winsys/cogl-egl.c \ - $(srcdir)/winsys/cogl-xlib.c + $(srcdir)/winsys/cogl-egl.c endif if SUPPORT_EGL_PLATFORM_POWERVR_NULL libclutter_cogl_la_SOURCES += \ diff --git a/cogl/cogl-internal.h b/cogl/cogl-internal.h index aa32f04c5..df074687a 100644 --- a/cogl/cogl-internal.h +++ b/cogl/cogl-internal.h @@ -145,6 +145,17 @@ typedef enum _CoglXlibFilterReturn { COGL_XLIB_FILTER_REMOVE } CoglXlibFilterReturn; +/* + * CoglXlibFilterFunc: + * + * 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. + */ +typedef CoglXlibFilterReturn (* CoglXlibFilterFunc) (XEvent *xevent, + gpointer data); + /* * cogl_xlib_handle_event: * @xevent: pointer to XEvent structure @@ -163,6 +174,47 @@ typedef enum _CoglXlibFilterReturn { CoglXlibFilterReturn _cogl_xlib_handle_event (XEvent *xevent); +/* + * _cogl_xlib_get_display: + * + * Return value: the Xlib display that will be used by the Xlib winsys + * backend. The display needs to be set with _cogl_xlib_set_display() + * before this function is called. + */ +Display * +_cogl_xlib_get_display (void); + +/* + * cogl_xlib_set_display: + * + * Sets the Xlib display that Cogl will use for the Xlib winsys + * backend. This function should eventually go away when Cogl gains a + * more complete winsys abstraction. + */ +void +_cogl_xlib_set_display (Display *display); + +/* + * _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_xlib_add_filter (CoglXlibFilterFunc func, + gpointer data); + +/* + * _cogl_xlib_remove_filter: + * + * Removes a callback that was previously added with + * _cogl_xlib_add_filter(). + */ +void +_cogl_xlib_remove_filter (CoglXlibFilterFunc func, + gpointer data); + #endif /* COGL_HAS_XLIB_SUPPORT */ typedef enum _CoglFeatureFlagsPrivate diff --git a/cogl/winsys/cogl-context-winsys.c b/cogl/winsys/cogl-context-winsys.c index 91402e7ba..e984f14bb 100644 --- a/cogl/winsys/cogl-context-winsys.c +++ b/cogl/winsys/cogl-context-winsys.c @@ -30,9 +30,29 @@ void _cogl_create_context_winsys (CoglContext *context) { +#ifdef COGL_HAS_XLIB_SUPPORT + context->winsys.event_filters = NULL; +#endif } +#ifdef COGL_HAS_XLIB_SUPPORT + +#include "cogl-xlib.h" + +static void +free_xlib_filter_closure (gpointer data, gpointer user_data) +{ + g_slice_free (CoglXlibFilterClosure, data); +} + +#endif + void _cogl_destroy_context_winsys (CoglContext *context) { +#ifdef COGL_HAS_XLIB_SUPPORT + g_slist_foreach (context->winsys.event_filters, + free_xlib_filter_closure, NULL); + g_slist_free (context->winsys.event_filters); +#endif } diff --git a/cogl/winsys/cogl-context-winsys.h b/cogl/winsys/cogl-context-winsys.h index c67ee3453..f0e28daed 100644 --- a/cogl/winsys/cogl-context-winsys.h +++ b/cogl/winsys/cogl-context-winsys.h @@ -26,6 +26,13 @@ typedef struct { + /* These are specific to winsys backends supporting Xlib. This + should probably eventually be moved into a separate file specific + to Xlib when Cogl gains a more complete winsys abstraction */ +#ifdef COGL_HAS_XLIB_SUPPORT + GSList *event_filters; +#endif + int stub; } CoglContextWinsys; diff --git a/cogl/winsys/cogl-xlib.c b/cogl/winsys/cogl-xlib.c index f403f5d4c..d25553966 100644 --- a/cogl/winsys/cogl-xlib.c +++ b/cogl/winsys/cogl-xlib.c @@ -37,11 +37,28 @@ #include +#include "cogl-xlib.h" + +/* This can't be in the Cogl context because it can be set before + 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); + /* Pass the event on to all of the registered filters in turn */ + for (l = ctx->winsys.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... */ @@ -52,3 +69,63 @@ _cogl_xlib_handle_event (XEvent *xevent) return COGL_XLIB_FILTER_CONTINUE; } +Display * +_cogl_xlib_get_display (void) +{ + _COGL_GET_CONTEXT (ctx, NULL); + + /* _cogl_xlib_set_display should be called before this function */ + g_assert (_cogl_xlib_display != NULL); + + return _cogl_xlib_display; +} + +void +_cogl_xlib_set_display (Display *display) +{ + /* This can only be called once before the Cogl context is created */ + g_assert (_cogl_xlib_display == NULL); + + _cogl_xlib_display = display; +} + +void +_cogl_xlib_add_filter (CoglXlibFilterFunc func, + gpointer data) +{ + CoglXlibFilterClosure *closure; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + closure = g_slice_new (CoglXlibFilterClosure); + closure->func = func; + closure->data = data; + + ctx->winsys.event_filters = + g_slist_prepend (ctx->winsys.event_filters, closure); +} + +void +_cogl_xlib_remove_filter (CoglXlibFilterFunc func, + gpointer data) +{ + GSList *l, *prev = NULL; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + for (l = ctx->winsys.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 + ctx->winsys.event_filters = + g_slist_delete_link (ctx->winsys.event_filters, l); + break; + } + } +} diff --git a/cogl/winsys/cogl-xlib.h b/cogl/winsys/cogl-xlib.h new file mode 100644 index 000000000..b31783f68 --- /dev/null +++ b/cogl/winsys/cogl-xlib.h @@ -0,0 +1,37 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __COGL_XLIB_H +#define __COGL_XLIB_H + +#include "cogl.h" + +typedef struct _CoglXlibFilterClosure CoglXlibFilterClosure; + +struct _CoglXlibFilterClosure +{ + CoglXlibFilterFunc func; + gpointer data; +}; + +#endif /* __COGL_XLIB_H */