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 811bbba075
commit 9cdcc155f3
8 changed files with 211 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)
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 += \

View File

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

View File

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

View File

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

View File

@ -37,11 +37,28 @@
#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
_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;
}
}
}

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 */

View File

@ -53,6 +53,7 @@
#endif
#include "cogl/cogl.h"
#include "cogl/cogl-internal.h"
#include "../clutter-debug.h"
#include "../clutter-device-manager.h"
@ -241,6 +242,10 @@ clutter_backend_x11_post_parse (ClutterBackend *backend,
CLUTTER_NOTE (BACKEND, "Getting the X screen");
/* Cogl needs to know the Xlib display connection for
CoglTexturePixmapX11 */
_cogl_xlib_set_display (backend_x11->xdpy);
if (clutter_screen == -1)
backend_x11->xscreen = DefaultScreenOfDisplay (backend_x11->xdpy);
else

View File

@ -38,6 +38,8 @@
#include "../clutter-debug.h"
#include "../clutter-main.h"
#include "cogl/cogl-internal.h"
#include <string.h>
#include <glib.h>
@ -458,6 +460,10 @@ event_translate (ClutterBackend *backend,
}
}
/* Pass the event through Cogl */
if (_cogl_xlib_handle_event (xevent) == COGL_XLIB_FILTER_REMOVE)
return FALSE;
/* Do further processing only on events for the stage window (the x11
* filters might be getting events for other windows, so do not mess
* them about.