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.
This commit is contained in:
Neil Roberts 2010-05-19 16:13:07 +01:00
parent 2e5b4a5b81
commit 9646e85ba7
6 changed files with 200 additions and 4 deletions

View File

@ -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) 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 if SUPPORT_GLX
libclutter_cogl_la_SOURCES += \ libclutter_cogl_la_SOURCES += \
$(srcdir)/winsys/cogl-glx.c \ $(srcdir)/winsys/cogl-glx.c
$(srcdir)/winsys/cogl-xlib.c
endif endif
if SUPPORT_EGL_PLATFORM_POWERVR_X11 if SUPPORT_EGL_PLATFORM_POWERVR_X11
libclutter_cogl_la_SOURCES += \ libclutter_cogl_la_SOURCES += \
$(srcdir)/winsys/cogl-egl.c \ $(srcdir)/winsys/cogl-egl.c
$(srcdir)/winsys/cogl-xlib.c
endif endif
if SUPPORT_EGL_PLATFORM_POWERVR_NULL if SUPPORT_EGL_PLATFORM_POWERVR_NULL
libclutter_cogl_la_SOURCES += \ libclutter_cogl_la_SOURCES += \

View File

@ -145,6 +145,17 @@ typedef enum _CoglXlibFilterReturn {
COGL_XLIB_FILTER_REMOVE COGL_XLIB_FILTER_REMOVE
} CoglXlibFilterReturn; } 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: * cogl_xlib_handle_event:
* @xevent: pointer to XEvent structure * @xevent: pointer to XEvent structure
@ -163,6 +174,47 @@ typedef enum _CoglXlibFilterReturn {
CoglXlibFilterReturn CoglXlibFilterReturn
_cogl_xlib_handle_event (XEvent *xevent); _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 */ #endif /* COGL_HAS_XLIB_SUPPORT */
typedef enum _CoglFeatureFlagsPrivate typedef enum _CoglFeatureFlagsPrivate

View File

@ -30,9 +30,29 @@
void void
_cogl_create_context_winsys (CoglContext *context) _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 void
_cogl_destroy_context_winsys (CoglContext *context) _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
} }

View File

@ -26,6 +26,13 @@
typedef struct 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; int stub;
} CoglContextWinsys; } CoglContextWinsys;

View File

@ -37,11 +37,28 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#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 CoglXlibFilterReturn
_cogl_xlib_handle_event (XEvent *xevent) _cogl_xlib_handle_event (XEvent *xevent)
{ {
GSList *l;
_COGL_GET_CONTEXT (ctx, COGL_XLIB_FILTER_CONTINUE); _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) switch (xevent->type)
{ {
/* TODO... */ /* TODO... */
@ -52,3 +69,63 @@ _cogl_xlib_handle_event (XEvent *xevent)
return COGL_XLIB_FILTER_CONTINUE; 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;
}
}
}

37
cogl/winsys/cogl-xlib.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*
*
*/
#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 */