Rework the interaction between the Cogl and GDK / X11 backends.

Previously, the Cogl backend was at times a subclass of the X11
backend, and at times a standalone one. Now it is the other way
round, with GDK and X11 backends providing the concrete classes,
layered on top of the generic Cogl backend. A new EglNative backend
was introduced for direct to framebuffer rendering. This greatly
simplifies the API design (at the expense of some casts needed)
and reduces the amount of #ifdefs, without duplicating code.

https://bugzilla.gnome.org/show_bug.cgi?id=657434
This commit is contained in:
Giovanni Campagna 2011-08-27 00:16:12 +02:00 committed by Emmanuele Bassi
parent 610a9c17ba
commit 9c102b7c51
21 changed files with 996 additions and 813 deletions

View File

@ -368,12 +368,6 @@ backend_source_c_priv += $(x11_source_c_priv)
# the list of files we want to introspect on X11
x11_introspection = $(x11_source_c) $(x11_source_h)
# pkg-config file for the X11 meta-backend
clutter-x11-$(CLUTTER_API_VERSION).pc: clutter-$(CLUTTER_API_VERSION).pc
$(QUIET_GEN)cp -f $< $(@F)
pc_files += clutter-x11-$(CLUTTER_API_VERSION).pc
clutterx11_includedir = $(clutter_includedir)/x11
clutterx11_include_HEADERS = $(x11_source_h)
endif # SUPPORT_X11
@ -393,14 +387,20 @@ cogl_source_h_priv = \
cogl_source_c_priv =
# pkg-config file for the cogl meta-backend
clutter-cogl-$(CLUTTER_API_VERSION).pc: clutter-$(CLUTTER_API_VERSION).pc
$(QUIET_GEN)cp -f $< $(@F)
pc_files += clutter-cogl-$(CLUTTER_API_VERSION).pc
if SUPPORT_X11
# For compatability with the old GLX backend
#
# Note: there wasn't actually anything GLX specific so we can add
# the compatability if clutter supports x11
backend_source_c += $(srcdir)/cogl/clutter-glx-texture-pixmap.c
glx_source_h = $(srcdir)/cogl/clutter-glx-texture-pixmap.h \
$(srcdir)/cogl/clutter-glx.h
backend_source_c += $(srcdir)/x11/clutter-glx-texture-pixmap.c
glx_source_h = $(srcdir)/x11/clutter-glx-texture-pixmap.h \
$(srcdir)/x11/clutter-glx.h
clutterglx_includedir = $(clutter_includedir)/glx
clutterglx_include_HEADERS = $(glx_source_h)
@ -442,6 +442,9 @@ if SUPPORT_GDK
backend_source_h += $(cogl_source_h) $(gdk_source_h)
backend_source_c += $(cogl_source_c) $(gdk_source_c)
backend_source_h_priv += $(cogl_source_h_priv) $(gdk_source_h_priv)
cluttergdk_includedir = $(clutter_includedir)/gdk
cluttergdk_include_HEADERS = $(gdk_source_h)
endif # SUPPORT_GDK
# Windows backend rules

View File

@ -36,55 +36,19 @@
#include <errno.h>
#include "clutter-config.h"
#ifdef CLUTTER_WINDOWING_GDK
#include <gdk/gdk.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#endif
#include "clutter-backend-cogl.h"
#include "clutter-stage-cogl.h"
#ifdef HAVE_EVDEV
#include "clutter-device-manager-evdev.h"
#endif
#include "clutter-debug.h"
#include "clutter-private.h"
#include "clutter-main.h"
#include "clutter-stage-private.h"
#ifdef COGL_HAS_EGL_SUPPORT
#include "clutter-egl.h"
#endif
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
#include "clutter-cex100.h"
#endif
#include <cogl/cogl-xlib.h>
static ClutterBackendCogl *backend_singleton = NULL;
static gchar *clutter_vblank = NULL;
/* FIXME: We should have CLUTTER_ define for this... */
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
static gdl_plane_id_t gdl_plane = GDL_PLANE_ID_UPP_C;
static guint gdl_n_buffers = CLUTTER_CEX100_TRIPLE_BUFFERING;
#endif
#ifdef CLUTTER_WINDOWING_X11
G_DEFINE_TYPE (ClutterBackendCogl, _clutter_backend_cogl, CLUTTER_TYPE_BACKEND_X11);
#elif defined(CLUTTER_WINDOWING_GDK)
G_DEFINE_TYPE (ClutterBackendCogl, _clutter_backend_cogl, CLUTTER_TYPE_BACKEND_GDK);
#else
G_DEFINE_TYPE (ClutterBackendCogl, _clutter_backend_cogl, CLUTTER_TYPE_BACKEND);
#endif
const gchar*
_clutter_backend_cogl_get_vblank (void)
@ -100,13 +64,6 @@ clutter_backend_cogl_pre_parse (ClutterBackend *backend,
GError **error)
{
const gchar *env_string;
#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK)
ClutterBackendClass *parent_class =
CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class);
if (!parent_class->pre_parse (backend, error))
return FALSE;
#endif
env_string = g_getenv ("CLUTTER_VBLANK");
if (env_string)
@ -122,54 +79,7 @@ static gboolean
clutter_backend_cogl_post_parse (ClutterBackend *backend,
GError **error)
{
#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK)
ClutterBackendClass *parent_class =
CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class);
if (!parent_class->post_parse (backend, error))
return FALSE;
return TRUE;
#endif
return TRUE;
}
#if !(defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK))
static ClutterDeviceManager *
clutter_backend_cogl_get_device_manager (ClutterBackend *backend)
{
ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend);
if (G_UNLIKELY (backend_cogl->device_manager == NULL))
{
#ifdef HAVE_EVDEV
backend_cogl->device_manager =
g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_EVDEV,
"backend", backend_cogl,
NULL);
#endif
}
return backend_cogl->device_manager;
}
#endif /* !(X11 || GDK) */
static void
clutter_backend_cogl_init_events (ClutterBackend *backend)
{
#ifdef HAVE_TSLIB
/* XXX: This should be renamed to _clutter_events_tslib_init */
_clutter_events_tslib_init (CLUTTER_BACKEND_COGL (backend));
#endif
#ifdef HAVE_EVDEV
_clutter_events_evdev_init (CLUTTER_BACKEND (backend));
#endif
#if defined (CLUTTER_WINDOWING_X11) || defined (CLUTTER_WINDOWING_GDK)
/* Chain up to the X11 or GDK backend */
CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class)->
init_events (backend);
#endif
}
static void
@ -185,14 +95,6 @@ static void
clutter_backend_cogl_dispose (GObject *gobject)
{
ClutterBackend *backend = CLUTTER_BACKEND (gobject);
#ifdef HAVE_TSLIB
ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (gobject);
#endif
/* We chain up before disposing our CoglContext so that we will
* destroy all of the stages first. Otherwise the actors may try to
* make Cogl calls during destruction which would cause a crash */
G_OBJECT_CLASS (_clutter_backend_cogl_parent_class)->dispose (gobject);
if (backend->cogl_context)
{
@ -200,16 +102,7 @@ clutter_backend_cogl_dispose (GObject *gobject)
backend->cogl_context = NULL;
}
#ifdef HAVE_TSLIB
/* XXX: This should be renamed to _clutter_events_tslib_uninit */
_clutter_events_egl_uninit (backend_cogl);
if (backend_cogl->event_timer != NULL)
{
g_timer_destroy (backend_cogl->event_timer);
backend_cogl->event_timer = NULL;
}
#endif
G_OBJECT_CLASS (_clutter_backend_cogl_parent_class)->dispose (gobject);
}
static GObject *
@ -220,7 +113,7 @@ clutter_backend_cogl_constructor (GType gtype,
GObjectClass *parent_class;
GObject *retval;
if (!backend_singleton)
if (backend_singleton == NULL)
{
parent_class = G_OBJECT_CLASS (_clutter_backend_cogl_parent_class);
retval = parent_class->constructor (gtype, n_params, params);
@ -242,15 +135,6 @@ clutter_backend_cogl_get_features (ClutterBackend *backend)
ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend);
ClutterFeatureFlags flags = 0;
#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK)
{
ClutterBackendClass *parent_class;
parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class);
flags = parent_class->get_features (backend);
}
#endif
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN))
{
CLUTTER_NOTE (BACKEND, "Cogl supports multiple onscreen framebuffers");
@ -285,195 +169,6 @@ clutter_backend_cogl_get_features (ClutterBackend *backend)
return flags;
}
#ifdef CLUTTER_WINDOWING_X11
static XVisualInfo *
clutter_backend_cogl_get_visual_info (ClutterBackendX11 *backend_x11)
{
return cogl_clutter_winsys_xlib_get_visual_info ();
}
#endif
static gboolean
clutter_backend_cogl_create_context (ClutterBackend *backend,
GError **error)
{
#ifdef CLUTTER_WINDOWING_X11
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
#elif CLUTTER_WINDOWING_GDK
ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend);
#endif
CoglSwapChain *swap_chain = NULL;
CoglOnscreenTemplate *onscreen_template = NULL;
gboolean status;
if (backend->cogl_context)
return TRUE;
backend->cogl_renderer = cogl_renderer_new ();
#ifdef CLUTTER_WINDOWING_X11
cogl_xlib_renderer_set_foreign_display (backend->cogl_renderer,
backend_x11->xdpy);
#elif defined(CLUTTER_WINDOWING_GDK)
#if defined(COGL_HAS_XLIB_SUPPORT) && defined(GDK_WINDOWING_X11)
if (GDK_IS_X11_DISPLAY (backend_gdk->display))
{
cogl_xlib_renderer_set_foreign_display (backend->cogl_renderer,
gdk_x11_display_get_xdisplay (backend_gdk->display));
}
else
#endif
{
g_warning ("Unsupported GdkDisplay type %s", G_OBJECT_TYPE_NAME (backend_gdk->display));
goto error;
}
#endif /* GDK */
if (!cogl_renderer_connect (backend->cogl_renderer, error))
goto error;
swap_chain = cogl_swap_chain_new ();
#if defined(CLUTTER_WINDOWING_X11)
cogl_swap_chain_set_has_alpha (swap_chain,
clutter_x11_get_use_argb_visual ());
#elif defined(CLUTTER_WINDOWING_GDK)
cogl_swap_chain_set_has_alpha (swap_chain,
gdk_screen_get_rgba_visual (backend_gdk->screen) != NULL);
#endif
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
cogl_swap_chain_set_length (swap_chain, gdl_n_buffers);
#endif
onscreen_template = cogl_onscreen_template_new (swap_chain);
cogl_object_unref (swap_chain);
/* XXX: I have some doubts that this is a good design.
* Conceptually should we be able to check an onscreen_template
* without more details about the CoglDisplay configuration?
*/
status = cogl_renderer_check_onscreen_template (backend->cogl_renderer,
onscreen_template,
error);
#ifdef COGL_HAS_XLIB_SUPPORT
if (!status && clutter_x11_get_use_argb_visual ())
{
g_clear_error (error);
/* It's possible that the current renderer doesn't support transparency
* in a swap_chain so lets see if we can fallback to not having any
* transparency...
*
* XXX: It might be nice to have a CoglRenderer feature we could
* explicitly check for ahead of time.
*/
cogl_swap_chain_set_has_alpha (swap_chain, FALSE);
status = cogl_renderer_check_onscreen_template (backend->cogl_renderer,
onscreen_template,
error);
}
#endif
if (!status)
goto error;
backend->cogl_display = cogl_display_new (backend->cogl_renderer,
onscreen_template);
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
cogl_gdl_display_set_plane (backend->cogl_display, gdl_plane);
#endif
cogl_object_unref (backend->cogl_renderer);
cogl_object_unref (onscreen_template);
if (!cogl_display_setup (backend->cogl_display, error))
goto error;
backend->cogl_context = cogl_context_new (backend->cogl_display, error);
if (!backend->cogl_context)
goto error;
return TRUE;
error:
if (backend->cogl_display)
{
cogl_object_unref (backend->cogl_display);
backend->cogl_display = NULL;
}
if (onscreen_template)
cogl_object_unref (onscreen_template);
if (swap_chain)
cogl_object_unref (swap_chain);
if (backend->cogl_renderer)
{
cogl_object_unref (backend->cogl_renderer);
backend->cogl_renderer = NULL;
}
return FALSE;
}
static ClutterStageWindow *
clutter_backend_cogl_create_stage (ClutterBackend *backend,
ClutterStage *wrapper,
GError **error)
{
#if defined(CLUTTER_WINDOWING_X11)
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
ClutterEventTranslator *translator;
ClutterStageWindow *stage;
ClutterStageX11 *stage_x11;
stage = g_object_new (CLUTTER_TYPE_STAGE_COGL, NULL);
/* copy backend data into the stage */
stage_x11 = CLUTTER_STAGE_X11 (stage);
stage_x11->wrapper = wrapper;
stage_x11->backend = backend_x11;
translator = CLUTTER_EVENT_TRANSLATOR (stage_x11);
_clutter_backend_add_event_translator (backend, translator);
CLUTTER_NOTE (MISC, "Cogl stage created (display:%p, screen:%d, root:%u)",
backend_x11->xdpy,
backend_x11->xscreen_num,
(unsigned int) backend_x11->xwin_root);
return stage;
#elif defined(CLUTTER_WINDOWING_GDK)
return g_object_new (CLUTTER_TYPE_STAGE_COGL,
"wrapper", wrapper,
"backend", backend,
NULL);
#else
ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend);
ClutterStageWindow *stage;
ClutterStageCogl *stage_cogl;
if (G_UNLIKELY (backend_cogl->stage != NULL))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"The Cogl backend does not support multiple "
"onscreen windows");
return backend_cogl->stage;
}
stage = g_object_new (CLUTTER_TYPE_STAGE_COGL, NULL);
stage_cogl = CLUTTER_STAGE_COGL (stage);
stage_cogl->backend = backend_cogl;
stage_cogl->wrapper = wrapper;
backend_cogl->stage = stage;
return stage;
#endif /* CLUTTER_WINDOWING_X11 || CLUTTER_WINDOWING_GDK */
}
static void
clutter_backend_cogl_ensure_context (ClutterBackend *backend,
ClutterStage *stage)
@ -495,9 +190,6 @@ _clutter_backend_cogl_class_init (ClutterBackendCoglClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
#ifdef CLUTTER_WINDOWING_X11
ClutterBackendX11Class *backendx11_class = CLUTTER_BACKEND_X11_CLASS (klass);
#endif
gobject_class->constructor = clutter_backend_cogl_constructor;
gobject_class->dispose = clutter_backend_cogl_dispose;
@ -506,31 +198,13 @@ _clutter_backend_cogl_class_init (ClutterBackendCoglClass *klass)
backend_class->pre_parse = clutter_backend_cogl_pre_parse;
backend_class->post_parse = clutter_backend_cogl_post_parse;
backend_class->get_features = clutter_backend_cogl_get_features;
#if !(defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK))
backend_class->get_device_manager = clutter_backend_cogl_get_device_manager;
#endif
backend_class->init_events = clutter_backend_cogl_init_events;
backend_class->create_stage = clutter_backend_cogl_create_stage;
backend_class->create_context = clutter_backend_cogl_create_context;
backend_class->ensure_context = clutter_backend_cogl_ensure_context;
#ifdef CLUTTER_WINDOWING_X11
backendx11_class->get_visual_info = clutter_backend_cogl_get_visual_info;
#endif
}
static void
_clutter_backend_cogl_init (ClutterBackendCogl *backend_cogl)
{
#ifdef HAVE_TSLIB
backend_cogl->event_timer = g_timer_new ();
#endif
}
GType
_clutter_backend_impl_get_type (void)
{
return _clutter_backend_cogl_get_type ();
}
#ifdef COGL_HAS_EGL_SUPPORT
@ -559,22 +233,3 @@ clutter_egl_get_egl_display (void)
}
#endif
/* FIXME we should have a CLUTTER_ define for this */
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
void
clutter_cex100_set_plane (gdl_plane_id_t plane)
{
g_return_if_fail (plane >= GDL_PLANE_ID_UPP_A && plane <= GDL_PLANE_ID_UPP_E);
gdl_plane = plane;
}
void
clutter_cex100_set_buffering_mode (ClutterCex100BufferingMode mode)
{
g_return_if_fail (mode == CLUTTER_CEX100_DOUBLE_BUFFERING ||
mode == CLUTTER_CEX100_TRIPLE_BUFFERING);
gdl_n_buffers = mode;
}
#endif

View File

@ -37,13 +37,6 @@
#include "clutter-backend-private.h"
#ifdef CLUTTER_WINDOWING_X11
#include "../x11/clutter-backend-x11.h"
#endif
#ifdef CLUTTER_WINDOWING_GDK
#include "../gdk/clutter-backend-gdk.h"
#endif
G_BEGIN_DECLS
#define CLUTTER_TYPE_BACKEND_COGL (_clutter_backend_cogl_get_type ())
@ -58,52 +51,18 @@ typedef struct _ClutterBackendCoglClass ClutterBackendCoglClass;
struct _ClutterBackendCogl
{
#ifdef CLUTTER_WINDOWING_X11
ClutterBackendX11 parent_instance;
#elif defined(CLUTTER_WINDOWING_GDK)
ClutterBackendGdk parent_instance;
#else
ClutterBackend parent_instance;
/* main stage singleton */
ClutterStageWindow *stage;
/* device manager (ie evdev) */
ClutterDeviceManager *device_manager;
/* event source */
GSource *event_source;
/* event timer */
GTimer *event_timer;
#endif /* CLUTTER_WINDOWING_X11 || CLUTTER_WINDOWING_GDK */
CoglContext *cogl_context;
gboolean can_blit_sub_buffer;
};
struct _ClutterBackendCoglClass
{
#ifdef CLUTTER_WINDOWING_X11
ClutterBackendX11Class parent_class;
#elif defined(CLUTTER_WINDOWING_GDK)
ClutterBackendGdkClass parent_class;
#else
ClutterBackendClass parent_class;
#endif
};
GType _clutter_backend_cogl_get_type (void) G_GNUC_CONST;
#ifdef HAVE_TSLIB
void _clutter_events_tslib_init (ClutterBackendCogl *backend);
void _clutter_events_tslib_uninit (ClutterBackendCogl *backend);
#endif
const gchar *_clutter_backend_cogl_get_vblank (void);
G_END_DECLS

View File

@ -32,15 +32,6 @@
#include "clutter-config.h"
#ifdef CLUTTER_WINDOWING_GDK
#include <gdk/gdk.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#endif
#include "clutter-stage-cogl.h"
#include "clutter-backend-cogl.h"
@ -54,24 +45,26 @@
#include "clutter-stage-private.h"
#include "clutter-util.h"
#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK)
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
#ifdef CLUTTER_WINDOWING_X11
/* needed for a small check in redraw() */
#include "x11/clutter-stage-x11.h"
#endif
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterStageCogl,
_clutter_stage_cogl,
#if defined(CLUTTER_WINDOWING_X11)
CLUTTER_TYPE_STAGE_X11,
#elif defined(CLUTTER_WINDOWING_GDK)
CLUTTER_TYPE_STAGE_GDK,
#else
G_TYPE_OBJECT,
#endif
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init));
enum {
PROP_0,
PROP_WRAPPER,
PROP_BACKEND,
PROP_LAST
};
static void
clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window)
{
@ -79,11 +72,6 @@ clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window)
CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_cogl);
#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK)
/* chain up to the StageX11 implementation */
clutter_stage_window_parent_iface->unrealize (stage_window);
#endif
if (stage_cogl->onscreen != NULL)
{
cogl_object_unref (stage_cogl->onscreen);
@ -114,11 +102,6 @@ static gboolean
clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
#if defined(CLUTTER_WINDOWING_X11)
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
#elif defined(CLUTTER_WINDOWING_GDK)
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
#endif
ClutterBackend *backend;
CoglFramebuffer *framebuffer;
GError *error = NULL;
@ -130,52 +113,13 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
G_OBJECT_TYPE_NAME (stage_cogl),
stage_cogl);
#if defined(CLUTTER_WINDOWING_GDK)
/* we need to chain early to parent in the Gdk case, as the X window
must be created by GDK, not Cogl */
if (!clutter_stage_window_parent_iface->realize (stage_window))
return FALSE;
#endif
backend = clutter_get_default_backend ();
#if defined(CLUTTER_WINDOWING_X11)
clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height);
#elif defined(CLUTTER_WINDOWING_GDK)
clutter_actor_get_size (CLUTTER_ACTOR (stage_gdk->wrapper), &width, &height);
#endif
stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
width, height);
#if defined(CLUTTER_WINDOWING_X11)
if (stage_x11->xwin != None)
if (stage_cogl->onscreen == NULL)
{
cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen,
stage_x11->xwin,
_clutter_stage_x11_update_foreign_event_mask,
stage_x11);
stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
width, height);
}
#elif defined(CLUTTER_WINDOWING_GDK)
#if defined(COGL_HAS_XLIB_SUPPORT) && defined(GDK_WINDOWING_X11)
if (GDK_IS_X11_WINDOW (stage_gdk->window))
{
cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen,
gdk_x11_window_get_xid (stage_gdk->window),
_clutter_stage_gdk_update_foreign_event_mask,
stage_gdk);
}
else
#endif
{
g_warning ("Unsupported GdkWindow type %s", G_OBJECT_TYPE_NAME (stage_gdk->window));
cogl_object_unref (stage_cogl->onscreen);
stage_cogl->onscreen = NULL;
return FALSE;
}
#endif
clutter_vblank = _clutter_backend_cogl_get_vblank ();
if (clutter_vblank && strcmp (clutter_vblank, "none") == 0)
@ -191,7 +135,7 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
return FALSE;
}
/* FIXME: for fullscreen Cogl platforms then the size we gave above
/* FIXME: for fullscreen Cogl platforms then the size we gave
* will be ignored, so we need to make sure the stage size is
* updated to this size. */
@ -203,14 +147,7 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
stage_cogl);
}
#ifdef CLUTTER_WINDOWING_X11
if (stage_x11->xwin == None)
stage_x11->xwin = cogl_x11_onscreen_get_window_xid (stage_cogl->onscreen);
return clutter_stage_window_parent_iface->realize (stage_window);
#else
return TRUE;
#endif
}
static int
@ -221,8 +158,6 @@ clutter_stage_cogl_get_pending_swaps (ClutterStageWindow *stage_window)
return stage_cogl->pending_swaps;
}
#if !(defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK))
static ClutterActor *
clutter_stage_cogl_get_wrapper (ClutterStageWindow *stage_window)
{
@ -231,7 +166,7 @@ clutter_stage_cogl_get_wrapper (ClutterStageWindow *stage_window)
static void
clutter_stage_cogl_show (ClutterStageWindow *stage_window,
gboolean do_raise)
gboolean do_raise)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
@ -280,8 +215,6 @@ clutter_stage_cogl_resize (ClutterStageWindow *stage_window,
{
}
#endif /* X11 || GDK */
static gboolean
clutter_stage_cogl_has_redraw_clips (ClutterStageWindow *stage_window)
{
@ -410,17 +343,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
"The time spent in blit_sub_buffer",
0 /* no application private data */);
#if defined(CLUTTER_WINDOWING_X11)
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_cogl);
wrapper = CLUTTER_ACTOR (stage_x11->wrapper);
#elif defined(CLUTTER_WINDOWING_GDK)
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_cogl);
wrapper = CLUTTER_ACTOR (stage_gdk->wrapper);
#else
wrapper = CLUTTER_ACTOR (stage_cogl->wrapper);
#endif
if (!stage_cogl->onscreen)
return;
@ -440,7 +363,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
/* While resizing a window clipped redraws are disabled to avoid
* artefacts. See clutter-event-x11.c:event_translate for a
* detailed explanation */
&& G_LIKELY (stage_x11->clipped_redraws_cool_off == 0)
&& G_LIKELY (CLUTTER_STAGE_X11 (stage_cogl)->clipped_redraws_cool_off == 0)
#endif
)
{
@ -610,16 +533,6 @@ clutter_stage_cogl_get_active_framebuffer (ClutterStageWindow *stage_window)
static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
{
#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK)
clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
iface->realize = clutter_stage_cogl_realize;
iface->unrealize = clutter_stage_cogl_unrealize;
/* the rest is inherited from ClutterStageX11 */
#else /* COGL_HAS_X11_SUPPORT */
iface->realize = clutter_stage_cogl_realize;
iface->unrealize = clutter_stage_cogl_unrealize;
iface->get_wrapper = clutter_stage_cogl_get_wrapper;
@ -627,9 +540,6 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
iface->resize = clutter_stage_cogl_resize;
iface->show = clutter_stage_cogl_show;
iface->hide = clutter_stage_cogl_hide;
#endif /* COGL_HAS_X11_SUPPORT */
iface->get_pending_swaps = clutter_stage_cogl_get_pending_swaps;
iface->add_redraw_clip = clutter_stage_cogl_add_redraw_clip;
iface->has_redraw_clips = clutter_stage_cogl_has_redraw_clips;
@ -639,11 +549,28 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
iface->get_active_framebuffer = clutter_stage_cogl_get_active_framebuffer;
}
#ifdef COGL_HAS_X11_SUPPORT
static void
clutter_stage_cogl_dispose (GObject *gobject)
clutter_stage_cogl_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
G_OBJECT_CLASS (_clutter_stage_cogl_parent_class)->dispose (gobject);
ClutterStageCogl *self = CLUTTER_STAGE_COGL (gobject);
switch (prop_id)
{
case PROP_WRAPPER:
self->wrapper = CLUTTER_STAGE (g_value_get_object (value));
break;
case PROP_BACKEND:
self->backend = CLUTTER_BACKEND_COGL (g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
@ -651,14 +578,22 @@ _clutter_stage_cogl_class_init (ClutterStageCoglClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = clutter_stage_cogl_dispose;
gobject_class->set_property = clutter_stage_cogl_set_property;
g_object_class_install_property (gobject_class, PROP_WRAPPER,
g_param_spec_object ("wrapper",
"Wrapper",
"ClutterStage wrapping this native stage",
CLUTTER_TYPE_STAGE,
CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class, PROP_BACKEND,
g_param_spec_object ("backend",
"ClutterBackend",
"The Clutter backend singleton",
CLUTTER_TYPE_BACKEND_COGL,
CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
}
#else
static void
_clutter_stage_cogl_class_init (ClutterStageCoglClass *klass)
{
}
#endif /* COGL_HAS_X11_SUPPORT */
static void
_clutter_stage_cogl_init (ClutterStageCogl *stage)

View File

@ -15,13 +15,6 @@
#include <X11/Xutil.h>
#endif
#ifdef CLUTTER_WINDOWING_X11
#include "../x11/clutter-stage-x11.h"
#endif
#ifdef CLUTTER_WINDOWING_GDK
#include "../gdk/clutter-stage-gdk.h"
#endif
#include "clutter-backend-cogl.h"
G_BEGIN_DECLS
@ -38,13 +31,6 @@ typedef struct _ClutterStageCoglClass ClutterStageCoglClass;
struct _ClutterStageCogl
{
#ifdef CLUTTER_WINDOWING_X11
ClutterStageX11 parent_instance;
#elif defined(CLUTTER_WINDOWING_GDK)
ClutterStageGdk parent_instance;
#else
GObject parent_instance;
/* the stage wrapper */
@ -53,8 +39,6 @@ struct _ClutterStageCogl
/* back pointer to the backend */
ClutterBackendCogl *backend;
#endif
CoglOnscreen *onscreen;
gint pending_swaps;
@ -76,11 +60,7 @@ struct _ClutterStageCogl
struct _ClutterStageCoglClass
{
#ifdef CLUTTER_WINDOWING_X11
ClutterStageX11Class parent_class;
#elif defined(CLUTTER_WINDOWING_GDK)
GObjectClass parent_class;
#endif
};
GType _clutter_stage_cogl_get_type (void) G_GNUC_CONST;

View File

@ -0,0 +1,262 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2010,2011 Intel Corporation.
* 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
*
* 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/>.
* Authors:
* Matthew Allum
* Emmanuele Bassi
* Robert Bragg
* Neil Roberts
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "clutter-backend-eglnative.h"
/* This is a Cogl based backend */
#include "cogl/clutter-stage-cogl.h"
#ifdef HAVE_EVDEV
#include "clutter-device-manager-evdev.h"
#endif
#include "clutter-debug.h"
#include "clutter-private.h"
#include "clutter-main.h"
#include "clutter-stage-private.h"
#ifdef COGL_HAS_EGL_SUPPORT
#include "clutter-egl.h"
#endif
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
#include "clutter-cex100.h"
#endif
static gchar *clutter_vblank = NULL;
/* FIXME: We should have CLUTTER_ define for this... */
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
static gdl_plane_id_t gdl_plane = GDL_PLANE_ID_UPP_C;
static guint gdl_n_buffers = CLUTTER_CEX100_TRIPLE_BUFFERING;
#endif
G_DEFINE_TYPE (ClutterBackendEglNative, _clutter_backend_egl_native, CLUTTER_TYPE_BACKEND_COGL);
static ClutterDeviceManager *
clutter_backend_egl_native_get_device_manager (ClutterBackend *backend)
{
ClutterBackendEglNative *backend_egl_native = CLUTTER_BACKEND_EGL_NATIVE (backend);
if (G_UNLIKELY (backend_egl_native->device_manager == NULL))
{
#ifdef HAVE_EVDEV
backend_egl_native->device_manager =
g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_EVDEV,
"backend", backend_egl_native,
NULL);
#endif
}
return backend_egl_native->device_manager;
}
static void
clutter_backend_egl_native_init_events (ClutterBackend *backend)
{
#ifdef HAVE_TSLIB
_clutter_events_tslib_init (CLUTTER_BACKEND_EGL (backend));
#endif
#ifdef HAVE_EVDEV
_clutter_events_evdev_init (CLUTTER_BACKEND (backend));
#endif
}
static void
clutter_backend_cogl_dispose (GObject *gobject)
{
#ifdef HAVE_TSLIB
ClutterBackendEglNative *backend_egl_native = CLUTTER_BACKEND_EGL_NATIVE (gobject);
_clutter_events_tslib_uninit (backend_egl_native);
if (backend_egl_native->event_timer != NULL)
{
g_timer_destroy (backend_egl_native->event_timer);
backend_egl_native->event_timer = NULL;
}
#endif
G_OBJECT_CLASS (_clutter_backend_cogl_parent_class)->dispose (gobject);
}
static ClutterStageWindow *
clutter_backend_egl_native_create_stage (ClutterBackend *backend,
ClutterStage *wrapper,
GError **error)
{
ClutterBackendEglNative *backend_egl_native = CLUTTER_BACKEND_EGL_NATIVE (backend);
ClutterStageWindow *stage;
ClutterStageCogl *stage_cogl;
if (G_UNLIKELY (backend_egl_native->stage != NULL))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"The EglNative backend does not support multiple "
"onscreen windows");
return backend_egl_native->stage;
}
stage = g_object_new (CLUTTER_TYPE_STAGE_COGL,
"backend", backend,
"wrapper", wrapper,
NULL);
backend_egl_native->stage = stage;
return stage;
}
static gboolean
clutter_backend_egl_native_create_context (ClutterBackend *backend,
GError **error)
{
CoglSwapChain *swap_chain = NULL;
CoglOnscreenTemplate *onscreen_template = NULL;
if (backend->cogl_context != NULL)
return TRUE;
backend->cogl_renderer = cogl_renderer_new ();
if (!cogl_renderer_connect (backend->cogl_renderer, error))
goto error;
swap_chain = cogl_swap_chain_new ();
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
cogl_swap_chain_set_length (swap_chain, gdl_n_buffers);
#endif
onscreen_template = cogl_onscreen_template_new (swap_chain);
cogl_object_unref (swap_chain);
/* XXX: I have some doubts that this is a good design.
* Conceptually should we be able to check an onscreen_template
* without more details about the CoglDisplay configuration?
*/
if (!cogl_renderer_check_onscreen_template (backend->cogl_renderer,
onscreen_template,
error))
goto error;
backend->cogl_display = cogl_display_new (backend->cogl_renderer,
onscreen_template);
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
cogl_gdl_display_set_plane (backend->cogl_display, gdl_plane);
#endif
cogl_object_unref (backend->cogl_renderer);
cogl_object_unref (onscreen_template);
if (!cogl_display_setup (backend->cogl_display, error))
goto error;
backend->cogl_context = cogl_context_new (backend->cogl_display, error);
if (backend->cogl_context == NULL)
goto error;
return TRUE;
error:
if (backend->cogl_display != NULL)
{
cogl_object_unref (backend->cogl_display);
backend->cogl_display = NULL;
}
if (onscreen_template != NULL)
cogl_object_unref (onscreen_template);
if (swap_chain != NULL)
cogl_object_unref (swap_chain);
if (backend->cogl_renderer != NULL)
{
cogl_object_unref (backend->cogl_renderer);
backend->cogl_renderer = NULL;
}
return FALSE;
}
static void
_clutter_backend_egl_native_class_init (ClutterBackendEglNativeClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
gobject_class->dispose = clutter_backend_egl_native_dispose;
gobject_class->finalize = clutter_backend_egl_native_finalize;
backend_class->get_device_manager = clutter_backend_egl_native_get_device_manager;
backend_class->init_events = clutter_backend_egl_native_init_events;
backend_class->create_stage = clutter_backend_egl_native_create_stage;
backend_class->create_context = clutter_backend_egl_native_create_context;
}
static void
_clutter_backend_egl_native_init (ClutterBackendEglNative *backend_egl_native)
{
#ifdef HAVE_TSLIB
backend_egl_native->event_timer = g_timer_new ();
#endif
}
GType
_clutter_backend_impl_get_type (void)
{
return _clutter_backend_egl_native_get_type ();
}
/* FIXME we should have a CLUTTER_ define for this */
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
void
clutter_cex100_set_plane (gdl_plane_id_t plane)
{
g_return_if_fail (plane >= GDL_PLANE_ID_UPP_A && plane <= GDL_PLANE_ID_UPP_E);
gdl_plane = plane;
}
void
clutter_cex100_set_buffering_mode (ClutterCex100BufferingMode mode)
{
g_return_if_fail (mode == CLUTTER_CEX100_DOUBLE_BUFFERING ||
mode == CLUTTER_CEX100_TRIPLE_BUFFERING);
gdl_n_buffers = mode;
}
#endif

View File

@ -0,0 +1,80 @@
/* Clutter.
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2006, 2007 OpenedHand
* Copyright (C) 2010 Intel Corp
* 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
*
* 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/>.
*
* Authors:
* Matthew Allum
* Robert Bragg
*/
#ifndef __CLUTTER_BACKEND_EGL_NATIVE_H__
#define __CLUTTER_BACKEND_EGL_NATIVE_H__
#include <glib-object.h>
#include <clutter/clutter-event.h>
#include <clutter/clutter-backend.h>
#include <clutter/clutter-device-manager.h>
#include "clutter-backend-private.h"
#include "cogl/clutter-backend-cogl.h"
G_BEGIN_DECLS
#define CLUTTER_TYPE_BACKEND_EGL_NATIVE (_clutter_backend_egl_native_get_type ())
#define CLUTTER_BACKEND_EGL_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_EGL_NATIVE, ClutterBackendEglNative))
#define CLUTTER_IS_BACKEND_EGL_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_EGL_NATIVE))
#define CLUTTER_BACKEND_EGL_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_EGL_NATIVE, ClutterBackendEglNativeClass))
#define CLUTTER_IS_BACKEND_EGL_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_EGL_NATIVE))
#define CLUTTER_BACKEND_EGL_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_EGL_NATIVE, ClutterBackendEglNativeClass))
typedef struct _ClutterBackendEglNative ClutterBackendEglNative;
typedef struct _ClutterBackendEglNativeClass ClutterBackendEglNativeClass;
struct _ClutterBackendEglNative
{
ClutterBackendCogl parent_instance;
/* main stage singleton */
ClutterStageWindow *stage;
/* device manager (ie evdev) */
ClutterDeviceManager *device_manager;
/* event source */
GSource *event_source;
/* event timer */
GTimer *event_timer;
};
struct _ClutterBackendEglNativeClass
{
ClutterBackendCoglClass parent_class;
};
GType _clutter_backend_egl_native_get_type (void) G_GNUC_CONST;
#ifdef HAVE_TSLIB
void _clutter_events_tslib_init (ClutterBackendEglNative *backend);
void _clutter_events_tslib_uninit (ClutterBackendEglNative *backend);
#endif
G_END_DECLS
#endif /* __CLUTTER_BACKEND_EGL_NATIVE_H__ */

View File

@ -0,0 +1,91 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* 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/>.
*
* Authors:
* Damien Lespiau <damien.lespiau@intel.com>
*/
/**
* SECTION:clutter-cex100
* @short_description: Intel CE3100, CE4100 Specific API
*
* The CEX100 backend for Clutter provides some Intel CE3100/CE4100
* specific API
*
* You need to include
* <filename class="headerfile">&lt;clutter/egl/clutter-cex100.h&gt;</filename>
* to have access to the functions documented here.
*/
#ifndef __CLUTTER_CEX100_H__
#define __CLUTTER_CEX100_H__
#include <glib.h>
#include <libgdl.h>
G_BEGIN_DECLS
/**
* clutter_cex100_set_plane:
* @plane: a GDL plane
*
* Intel CE3100 and CE4100 have several planes (frame buffers) and a
* hardware blender to blend the planes togeteher and produce the final
* image.
*
* clutter_cex100_set_plane() let's you configure the GDL plane where
* the stage will be drawn. By default Clutter will pick UPP_C
* (GDL_PLANE_ID_UPP_C).
*
* <note>This function has to be called before clutter_init()</note>
*/
void clutter_cex100_set_plane (gdl_plane_id_t plane);
/**
* ClutterCex100BufferingMode:
* @CLUTTER_CEX100_DOUBLE_BUFFERING: The GDL plane will be double buffered
* @CLUTTER_CEX100_TRIPLE_BUFFERING: The GDL plane will be triple buffered
*
* Enum passed to clutter_cex100_set_buffering_mode().
*/
typedef enum /*< prefix=CLUTTER_CEX100 >*/
{
CLUTTER_CEX100_DOUBLE_BUFFERING = 2,
CLUTTER_CEX100_TRIPLE_BUFFERING = 3
} ClutterCex100BufferingMode;
/**
* clutter_cex100_set_buffering_mode:
* @mode: a #ClutterCex100BufferingMode
*
* Configure the buffering mode of the underlying GDL plane. The GDL
* surface used by Clutter to draw can be backed up by either one or two
* back buffers thus being double or triple buffered, respectively.
*
* Clutter defaults to %CLUTTER_CEX100_TRIPLE_BUFFERING.
*
* <note>This function has to be called before clutter_init()</note>
*/
void clutter_cex100_set_buffering_mode (ClutterCex100BufferingMode mode);
G_END_DECLS
#endif /* __CLUTTER_CEX100_H__ */

View File

@ -95,7 +95,7 @@ get_backend_time (void)
#endif
void
_clutter_events_tslib_init (ClutterBackendEGL *backend_egl)
_clutter_events_tslib_init (ClutterBackendEglNative *backend_egl)
{
#ifdef HAVE_TSLIB
ClutterEventSource *event_source;
@ -151,7 +151,7 @@ _clutter_events_tslib_init (ClutterBackendEGL *backend_egl)
}
void
_clutter_events_egl_uninit (ClutterBackendEGL *backend_egl)
_clutter_events_egl_uninit (ClutterBackendEglNative *backend_egl)
{
#ifdef HAVE_TSLIB
if (backend_egl->event_timer != NULL)

View File

@ -35,10 +35,16 @@
#include <gdk/gdk.h>
#include <cogl/cogl.h>
#include <cogl/cogl-xlib.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
/* other backends not yet supported */
#ifdef GDK_WINDOWING_WIN32
#include <gdk/gdkwin32.h>
#endif
#include "clutter-backend-gdk.h"
#include "clutter-device-manager-gdk.h"
@ -54,10 +60,7 @@
#include "clutter-private.h"
#define clutter_backend_gdk_get_type _clutter_backend_gdk_get_type
G_DEFINE_TYPE (ClutterBackendGdk, clutter_backend_gdk, CLUTTER_TYPE_BACKEND);
/* singleton object */
static ClutterBackendGdk *backend_singleton = NULL;
G_DEFINE_TYPE (ClutterBackendGdk, clutter_backend_gdk, CLUTTER_TYPE_BACKEND_COGL);
/* global for pre init setup calls */
static GdkDisplay *_foreign_dpy = NULL;
@ -131,21 +134,13 @@ cogl_gdk_filter (GdkXEvent *xevent,
#endif
}
static gboolean
_clutter_backend_gdk_pre_parse (ClutterBackend *backend,
GError **error)
{
/* nothing to do here */
return TRUE;
}
static gboolean
_clutter_backend_gdk_post_parse (ClutterBackend *backend,
GError **error)
{
ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend);
if (_foreign_dpy)
if (_foreign_dpy != NULL)
backend_gdk->display = _foreign_dpy;
/* Init Gdk, if outside code did not already */
@ -181,7 +176,8 @@ _clutter_backend_gdk_post_parse (ClutterBackend *backend,
"Gdk Display '%s' opened",
gdk_display_get_name (backend_gdk->display));
return TRUE;
return CLUTTER_BACKEND_CLASS (clutter_backend_gdk_parent_class)->post_parse (backend,
error);
}
@ -201,9 +197,6 @@ clutter_backend_gdk_finalize (GObject *gobject)
gdk_window_remove_filter (NULL, cogl_gdk_filter, NULL);
g_object_unref (backend_gdk->display);
if (backend_singleton)
backend_singleton = NULL;
G_OBJECT_CLASS (clutter_backend_gdk_parent_class)->finalize (gobject);
}
@ -224,34 +217,14 @@ clutter_backend_gdk_dispose (GObject *gobject)
G_OBJECT_CLASS (clutter_backend_gdk_parent_class)->dispose (gobject);
}
static GObject *
clutter_backend_gdk_constructor (GType gtype,
guint n_params,
GObjectConstructParam *params)
{
GObjectClass *parent_class;
GObject *retval;
if (backend_singleton == NULL)
{
parent_class = G_OBJECT_CLASS (clutter_backend_gdk_parent_class);
retval = parent_class->constructor (gtype, n_params, params);
backend_singleton = CLUTTER_BACKEND_GDK (retval);
return retval;
}
g_critical ("Attempting to create a new backend object. This should "
"never happen, so we return the singleton instance.");
return g_object_ref (backend_singleton);
}
static ClutterFeatureFlags
clutter_backend_gdk_get_features (ClutterBackend *backend)
{
return CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR;
ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR;
flags |= CLUTTER_BACKEND_CLASS (clutter_backend_gdk_parent_class)->get_features (backend);
return flags;
}
static void
@ -293,23 +266,128 @@ clutter_backend_gdk_get_device_manager (ClutterBackend *backend)
return backend_gdk->device_manager;
}
static gboolean
clutter_backend_gdk_create_context (ClutterBackend *backend,
GError **error)
{
ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend);
CoglSwapChain *swap_chain = NULL;
CoglOnscreenTemplate *onscreen_template = NULL;
GdkVisual *rgba_visual = NULL;
if (backend->cogl_context != NULL)
return TRUE;
backend->cogl_renderer = cogl_renderer_new ();
#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT)
if (GDK_IS_X11_DISPLAY (backend_gdk->display))
{
cogl_xlib_renderer_set_foreign_display (backend->cogl_renderer,
gdk_x11_display_get_xdisplay (backend_gdk->display));
}
else
#endif
#if defined(GDK_WINDOWING_WIN32)
if (GDK_IS_WIN32_DISPLAY (backend_gdk->display))
{
/* Force a WGL winsys on windows */
cogl_renderer_set_winsys_id (backend_cogl->cogl_renderer, COGL_WINSYS_ID_WGL);
}
else
#endif
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"Could not find a suitable CoglWinsys for"
"a GdkDisplay of type %s", G_OBJECT_TYPE_NAME (backend_gdk->display));
goto error;
}
if (!cogl_renderer_connect (backend->cogl_renderer, error))
goto error;
swap_chain = cogl_swap_chain_new ();
rgba_visual = gdk_screen_get_rgba_visual (backend_gdk->screen);
cogl_swap_chain_set_has_alpha (swap_chain, rgba_visual != NULL);
onscreen_template = cogl_onscreen_template_new (swap_chain);
cogl_object_unref (swap_chain);
/* XXX: I have some doubts that this is a good design.
* Conceptually should we be able to check an onscreen_template
* without more details about the CoglDisplay configuration?
*/
if (!cogl_renderer_check_onscreen_template (backend->cogl_renderer,
onscreen_template,
error))
goto error;
backend->cogl_display = cogl_display_new (backend->cogl_renderer,
onscreen_template);
cogl_object_unref (backend->cogl_renderer);
cogl_object_unref (onscreen_template);
if (!cogl_display_setup (backend->cogl_display, error))
goto error;
backend->cogl_context = cogl_context_new (backend->cogl_display, error);
if (backend->cogl_context == NULL)
goto error;
return TRUE;
error:
if (backend->cogl_display != NULL)
{
cogl_object_unref (backend->cogl_display);
backend->cogl_display = NULL;
}
if (onscreen_template != NULL)
cogl_object_unref (onscreen_template);
if (swap_chain != NULL)
cogl_object_unref (swap_chain);
if (backend->cogl_renderer != NULL)
{
cogl_object_unref (backend->cogl_renderer);
backend->cogl_renderer = NULL;
}
return FALSE;
}
static ClutterStageWindow *
clutter_backend_gdk_create_stage (ClutterBackend *backend,
ClutterStage *wrapper,
GError **error)
{
return g_object_new (CLUTTER_TYPE_STAGE_GDK,
"backend", backend,
"wrapper", wrapper,
NULL);
}
static void
clutter_backend_gdk_class_init (ClutterBackendGdkClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
gobject_class->constructor = clutter_backend_gdk_constructor;
gobject_class->dispose = clutter_backend_gdk_dispose;
gobject_class->finalize = clutter_backend_gdk_finalize;
backend_class->pre_parse = _clutter_backend_gdk_pre_parse;
backend_class->post_parse = _clutter_backend_gdk_post_parse;
backend_class->init_events = clutter_backend_gdk_init_events;
backend_class->get_features = clutter_backend_gdk_get_features;
backend_class->get_device_manager = clutter_backend_gdk_get_device_manager;
backend_class->copy_event_data = clutter_backend_gdk_copy_event_data;
backend_class->free_event_data = clutter_backend_gdk_free_event_data;
backend_class->create_context = clutter_backend_gdk_create_context;
backend_class->create_stage = clutter_backend_gdk_create_stage;
}
static void
@ -330,13 +408,15 @@ clutter_backend_gdk_init (ClutterBackendGdk *backend_gdk)
GdkDisplay *
clutter_gdk_get_default_display (void)
{
if (!backend_singleton)
ClutterBackend *backend = clutter_get_default_backend ();
if (!backend || !CLUTTER_IS_BACKEND_GDK (backend))
{
g_critical ("GDK backend has not been initialised");
return NULL;
}
return backend_singleton->display;
return CLUTTER_BACKEND_GDK (backend)->display;
}
/**
@ -366,3 +446,9 @@ clutter_gdk_set_display (GdkDisplay *display)
_foreign_dpy = g_object_ref (display);
}
GType
_clutter_backend_impl_get_type (void)
{
return _clutter_backend_gdk_get_type ();
}

View File

@ -30,6 +30,7 @@
#include "clutter-gdk.h"
#include "clutter-backend-private.h"
#include "cogl/clutter-backend-cogl.h"
G_BEGIN_DECLS
@ -45,7 +46,7 @@ typedef struct _ClutterBackendGdkClass ClutterBackendGdkClass;
struct _ClutterBackendGdk
{
ClutterBackend parent_instance;
ClutterBackendCogl parent_instance;
GdkDisplay *display;
GdkScreen *screen;
@ -55,7 +56,7 @@ struct _ClutterBackendGdk
struct _ClutterBackendGdkClass
{
ClutterBackendClass parent_class;
ClutterBackendCoglClass parent_class;
/* nothing here, for now */
};

View File

@ -27,6 +27,15 @@
#include <unistd.h>
#endif
#include <cogl/cogl.h>
#include <gdk/gdk.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#ifdef GDK_WINDOWING_WIN32
#include <gdk/gdkwin32.h>
#endif
#include "clutter-backend-gdk.h"
#include "clutter-stage-gdk.h"
#include "clutter-gdk.h"
@ -43,29 +52,22 @@
#include "clutter-private.h"
#include "clutter-stage-private.h"
#include "cogl/cogl.h"
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
#define clutter_stage_gdk_get_type _clutter_stage_gdk_get_type
G_DEFINE_TYPE_WITH_CODE (ClutterStageGdk,
clutter_stage_gdk,
G_TYPE_OBJECT,
CLUTTER_TYPE_STAGE_COGL,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init));
enum {
PROP_0,
PROP_WRAPPER,
PROP_BACKEND,
PROP_LAST
};
void
_clutter_stage_gdk_update_foreign_event_mask (CoglOnscreen *onscreen,
guint32 event_mask,
void *user_data)
static void
clutter_stage_gdk_update_foreign_event_mask (CoglOnscreen *onscreen,
guint32 event_mask,
void *user_data)
{
ClutterStageGdk *stage_gdk = user_data;
@ -79,7 +81,8 @@ static void
clutter_stage_gdk_set_gdk_geometry (ClutterStageGdk *stage)
{
GdkGeometry geometry;
gboolean resize = clutter_stage_get_user_resizable (stage->wrapper);
ClutterStage *wrapper = CLUTTER_STAGE_COGL (stage)->wrapper;
gboolean resize = clutter_stage_get_user_resizable (wrapper);
if (!resize)
{
@ -92,7 +95,7 @@ clutter_stage_gdk_set_gdk_geometry (ClutterStageGdk *stage)
}
else
{
clutter_stage_get_minimum_size (stage->wrapper,
clutter_stage_get_minimum_size (wrapper,
(guint *)&geometry.min_width,
(guint *)&geometry.min_height);
@ -108,7 +111,7 @@ clutter_stage_gdk_get_geometry (ClutterStageWindow *stage_window,
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
if (stage_gdk->window)
if (stage_gdk->window != NULL)
{
geometry->width = gdk_window_get_width (stage_gdk->window);
geometry->height = gdk_window_get_height (stage_gdk->window);
@ -139,7 +142,7 @@ clutter_stage_gdk_resize (ClutterStageWindow *stage_window,
CLUTTER_NOTE (BACKEND, "New size received: (%d, %d)", width, height);
CLUTTER_SET_PRIVATE_FLAGS (stage_gdk->wrapper,
CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_STAGE_COGL (stage_gdk)->wrapper,
CLUTTER_IN_RESIZE);
gdk_window_resize (stage_gdk->window, width, height);
@ -150,7 +153,7 @@ clutter_stage_gdk_unrealize (ClutterStageWindow *stage_window)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
if (stage_gdk->window)
if (stage_gdk->window != NULL)
{
g_object_set_data (G_OBJECT (stage_gdk->window),
"clutter-stage-window", NULL);
@ -166,20 +169,22 @@ static gboolean
clutter_stage_gdk_realize (ClutterStageWindow *stage_window)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
ClutterBackendGdk *backend_gdk = stage_gdk->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
ClutterBackend *backend = CLUTTER_BACKEND (stage_cogl->backend);
ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend);
GdkWindowAttr attributes;
gboolean cursor_visible;
gboolean use_alpha;
gfloat width, height;
if (stage_gdk->foreign_window &&
stage_gdk->window)
stage_gdk->window != NULL)
{
/* complete realizing the stage */
ClutterGeometry geometry;
clutter_stage_gdk_get_geometry (stage_window, &geometry);
clutter_actor_set_geometry (CLUTTER_ACTOR (stage_gdk->wrapper), &geometry);
clutter_actor_set_geometry (CLUTTER_ACTOR (stage_cogl->wrapper), &geometry);
gdk_window_ensure_native (stage_gdk->window);
gdk_window_set_events (stage_gdk->window,
@ -189,7 +194,7 @@ clutter_stage_gdk_realize (ClutterStageWindow *stage_window)
}
attributes.title = NULL;
g_object_get (stage_gdk->wrapper,
g_object_get (stage_cogl->wrapper,
"cursor-visible", &cursor_visible,
"title", &attributes.title,
"width", &width,
@ -212,14 +217,16 @@ clutter_stage_gdk_realize (ClutterStageWindow *stage_window)
attributes.cursor = stage_gdk->blank_cursor;
}
attributes.visual = NULL;
if (use_alpha)
{
attributes.visual = gdk_screen_get_rgba_visual (backend_gdk->screen);
if (attributes.visual == NULL)
clutter_stage_set_use_alpha (stage_gdk->wrapper, FALSE);
clutter_stage_set_use_alpha (stage_cogl->wrapper, FALSE);
}
else
if (attributes.visual == NULL)
{
/* This could still be an RGBA visual, although normally it's not */
attributes.visual = gdk_screen_get_system_visual (backend_gdk->screen);
@ -228,12 +235,8 @@ clutter_stage_gdk_realize (ClutterStageWindow *stage_window)
if (stage_gdk->window != NULL)
{
g_critical ("Stage realized more than once");
g_object_set_data (G_OBJECT (stage_gdk->window),
"clutter-stage-window", NULL);
if (stage_gdk->foreign_window)
g_object_unref (stage_gdk->window);
else
gdk_window_destroy (stage_gdk->window);
return FALSE;
}
stage_gdk->foreign_window = FALSE;
@ -248,9 +251,41 @@ clutter_stage_gdk_realize (ClutterStageWindow *stage_window)
g_free (attributes.title);
CLUTTER_NOTE (BACKEND, "Successfully realized stage");
stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
width, height);
return TRUE;
#if defined(GDK_WINDOWING_X11) && defined(COGL_HAS_XLIB_SUPPORT)
if (GDK_IS_X11_WINDOW (stage_gdk->window))
{
cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen,
GDK_WINDOW_XID (stage_gdk->window),
clutter_stage_gdk_update_foreign_event_mask,
stage_gdk);
}
else
#endif
#if defined(GDK_WINDOWING_WIN32) && defined(COGL_HAS_WIN32_SUPPORT)
if (GDK_IS_WIN32_WINDOW (stage_gdk->window))
{
cogl_win32_onscreen_set_foreign_window (stage_cogl->onscreen,
gdk_win32_window_get_handle (stage_gdk->window));
}
else
#endif
{
g_warning ("Cannot find an appropriate CoglWinsys for a "
"GdkWindow of type %s", G_OBJECT_TYPE_NAME (stage_gdk->window));
cogl_object_unref (stage_cogl->onscreen);
stage_cogl->onscreen = NULL;
gdk_window_destroy (stage_gdk->window);
stage_gdk->window = NULL;
return FALSE;
}
return clutter_stage_window_parent_iface->realize (stage_window);
}
static void
@ -258,7 +293,7 @@ clutter_stage_gdk_set_fullscreen (ClutterStageWindow *stage_window,
gboolean is_fullscreen)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window);
ClutterStage *stage = stage_gdk->wrapper;
ClutterStage *stage = CLUTTER_STAGE_COGL (stage_window)->wrapper;
if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
return;
@ -347,7 +382,7 @@ clutter_stage_gdk_show (ClutterStageWindow *stage_window,
g_return_if_fail (stage_gdk->window != NULL);
clutter_actor_map (CLUTTER_ACTOR (stage_gdk->wrapper));
clutter_actor_map (CLUTTER_ACTOR (CLUTTER_STAGE_COGL (stage_gdk)->wrapper));
if (do_raise)
gdk_window_show (stage_gdk->window);
@ -362,22 +397,16 @@ clutter_stage_gdk_hide (ClutterStageWindow *stage_window)
g_return_if_fail (stage_gdk->window != NULL);
clutter_actor_unmap (CLUTTER_ACTOR (stage_gdk->wrapper));
clutter_actor_unmap (CLUTTER_ACTOR (CLUTTER_STAGE_COGL (stage_gdk)->wrapper));
gdk_window_hide (stage_gdk->window);
}
static ClutterActor *
clutter_stage_gdk_get_wrapper (ClutterStageWindow *stage_window)
{
return CLUTTER_ACTOR (CLUTTER_STAGE_GDK (stage_window)->wrapper);
}
static void
clutter_stage_gdk_dispose (GObject *gobject)
{
ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (gobject);
if (stage_gdk->window)
if (stage_gdk->window != NULL)
{
g_object_set_data (G_OBJECT (stage_gdk->window),
"clutter-stage-window", NULL);
@ -388,7 +417,7 @@ clutter_stage_gdk_dispose (GObject *gobject)
stage_gdk->window = NULL;
}
if (stage_gdk->blank_cursor)
if (stage_gdk->blank_cursor != NULL)
{
g_object_unref (stage_gdk->blank_cursor);
stage_gdk->blank_cursor = NULL;
@ -397,51 +426,12 @@ clutter_stage_gdk_dispose (GObject *gobject)
G_OBJECT_CLASS (clutter_stage_gdk_parent_class)->dispose (gobject);
}
static void
clutter_stage_gdk_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterStageGdk *self = CLUTTER_STAGE_GDK (gobject);
switch (prop_id)
{
case PROP_WRAPPER:
self->wrapper = CLUTTER_STAGE (g_value_get_object (value));
break;
case PROP_BACKEND:
self->backend = CLUTTER_BACKEND_GDK (g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_stage_gdk_class_init (ClutterStageGdkClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = clutter_stage_gdk_dispose;
gobject_class->set_property = clutter_stage_gdk_set_property;
g_object_class_install_property (gobject_class, PROP_WRAPPER,
g_param_spec_object ("wrapper",
"Wrapper",
"ClutterStage wrapping this native stage",
CLUTTER_TYPE_STAGE,
CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class, PROP_BACKEND,
g_param_spec_object ("backend",
"ClutterBackend",
"The Clutter backend singleton",
CLUTTER_TYPE_BACKEND_GDK,
CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
}
static void
@ -453,7 +443,8 @@ clutter_stage_gdk_init (ClutterStageGdk *stage)
static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
{
iface->get_wrapper = clutter_stage_gdk_get_wrapper;
clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
iface->set_title = clutter_stage_gdk_set_title;
iface->set_fullscreen = clutter_stage_gdk_set_fullscreen;
iface->set_cursor_visible = clutter_stage_gdk_set_cursor_visible;
@ -507,7 +498,7 @@ clutter_gdk_get_stage_from_window (GdkWindow *window)
ClutterStageGdk *stage_gdk = g_object_get_data (G_OBJECT (window), "clutter-stage-window");
if (stage_gdk != NULL && CLUTTER_IS_STAGE_GDK (stage_gdk))
return stage_gdk->wrapper;
return CLUTTER_STAGE_COGL (stage_gdk)->wrapper;
return NULL;
}

View File

@ -28,6 +28,7 @@
#include <gdk/gdk.h>
#include "clutter-backend-gdk.h"
#include "cogl/clutter-stage-cogl.h"
G_BEGIN_DECLS
@ -43,21 +44,17 @@ typedef struct _ClutterStageGdkClass ClutterStageGdkClass;
struct _ClutterStageGdk
{
GObject parent_instance;
ClutterStageCogl parent_instance;
GdkWindow *window;
GdkCursor *blank_cursor;
/* backpointers */
ClutterStage *wrapper;
ClutterBackendGdk *backend;
gboolean foreign_window;
};
struct _ClutterStageGdkClass
{
GObjectClass parent_class;
ClutterStageCoglClass parent_class;
};
#define CLUTTER_STAGE_GDK_EVENT_MASK \

View File

@ -70,7 +70,7 @@
#define clutter_backend_x11_get_type _clutter_backend_x11_get_type
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND_COGL);
/* atoms; remember to add the code that assigns the atom value to
* the member of the ClutterBackendX11 structure if you add an
@ -92,9 +92,6 @@ static const gchar *atom_names[] = {
#define N_ATOM_NAMES G_N_ELEMENTS (atom_names)
/* singleton object */
static ClutterBackendX11 *backend_singleton = NULL;
/* various flags corresponding to pre init setup calls */
static gboolean _no_xevent_retrieval = FALSE;
static gboolean clutter_enable_xinput = FALSE;
@ -334,7 +331,8 @@ _clutter_backend_x11_pre_parse (ClutterBackend *backend,
env_string = NULL;
}
return TRUE;
return CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class)->pre_parse (backend,
error);
}
gboolean
@ -462,7 +460,8 @@ _clutter_backend_x11_post_parse (ClutterBackend *backend,
(unsigned int) backend_x11->xwin_root,
clutter_backend_get_resolution (backend));
return TRUE;
return CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class)->post_parse (backend,
error);
}
@ -526,9 +525,6 @@ clutter_backend_x11_finalize (GObject *gobject)
XCloseDisplay (backend_x11->xdpy);
if (backend_singleton)
backend_singleton = NULL;
G_OBJECT_CLASS (clutter_backend_x11_parent_class)->finalize (gobject);
}
@ -549,34 +545,14 @@ clutter_backend_x11_dispose (GObject *gobject)
G_OBJECT_CLASS (clutter_backend_x11_parent_class)->dispose (gobject);
}
static GObject *
clutter_backend_x11_constructor (GType gtype,
guint n_params,
GObjectConstructParam *params)
{
GObjectClass *parent_class;
GObject *retval;
if (backend_singleton == NULL)
{
parent_class = G_OBJECT_CLASS (clutter_backend_x11_parent_class);
retval = parent_class->constructor (gtype, n_params, params);
backend_singleton = CLUTTER_BACKEND_X11 (retval);
return retval;
}
g_warning ("Attempting to create a new backend object. This should "
"never happen, so we return the singleton instance.");
return g_object_ref (backend_singleton);
}
static ClutterFeatureFlags
clutter_backend_x11_get_features (ClutterBackend *backend)
{
return CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR;
ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR;
flags |= CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class)->get_features (backend);
return flags;
}
static void
@ -706,13 +682,124 @@ clutter_backend_x11_translate_event (ClutterBackend *backend,
return parent_class->translate_event (backend, native, event);
}
static gboolean
clutter_backend_x11_create_context (ClutterBackend *backend,
GError **error)
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
CoglOnscreenTemplate *onscreen_template = NULL;
CoglSwapChain *swap_chain = NULL;
gboolean status;
if (backend->cogl_context != NULL)
return TRUE;
backend->cogl_renderer = cogl_renderer_new ();
cogl_xlib_renderer_set_foreign_display (backend->cogl_renderer,
backend_x11->xdpy);
if (!cogl_renderer_connect (backend->cogl_renderer, error))
goto error;
swap_chain = cogl_swap_chain_new ();
cogl_swap_chain_set_has_alpha (swap_chain,
clutter_x11_get_use_argb_visual ());
onscreen_template = cogl_onscreen_template_new (swap_chain);
cogl_object_unref (swap_chain);
/* XXX: I have some doubts that this is a good design.
* Conceptually should we be able to check an onscreen_template
* without more details about the CoglDisplay configuration?
*/
status = cogl_renderer_check_onscreen_template (backend->cogl_renderer,
onscreen_template,
error);
if (!status && clutter_x11_get_use_argb_visual ())
{
g_clear_error (error);
/* It's possible that the current renderer doesn't support transparency
* in a swap_chain so lets see if we can fallback to not having any
* transparency...
*
* XXX: It might be nice to have a CoglRenderer feature we could
* explicitly check for ahead of time.
*/
cogl_swap_chain_set_has_alpha (swap_chain, FALSE);
status = cogl_renderer_check_onscreen_template (backend->cogl_renderer,
onscreen_template,
error);
}
if (!status)
goto error;
backend->cogl_display = cogl_display_new (backend->cogl_renderer,
onscreen_template);
cogl_object_unref (backend->cogl_renderer);
cogl_object_unref (onscreen_template);
if (!cogl_display_setup (backend->cogl_display, error))
goto error;
backend->cogl_context = cogl_context_new (backend->cogl_display, error);
if (backend->cogl_context == NULL)
goto error;
return TRUE;
error:
if (backend->cogl_display != NULL)
{
cogl_object_unref (backend->cogl_display);
backend->cogl_display = NULL;
}
if (onscreen_template != NULL)
cogl_object_unref (onscreen_template);
if (swap_chain != NULL)
cogl_object_unref (swap_chain);
if (backend->cogl_renderer != NULL)
{
cogl_object_unref (backend->cogl_renderer);
backend->cogl_renderer = NULL;
}
return FALSE;
}
static ClutterStageWindow *
clutter_backend_x11_create_stage (ClutterBackend *backend,
ClutterStage *wrapper,
GError **error)
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
ClutterEventTranslator *translator;
ClutterStageWindow *stage;
stage = g_object_new (CLUTTER_TYPE_STAGE_X11,
"backend", backend,
"wrapper", wrapper,
NULL);
translator = CLUTTER_EVENT_TRANSLATOR (stage);
_clutter_backend_add_event_translator (backend, translator);
CLUTTER_NOTE (MISC, "Cogl stage created (display:%p, screen:%d, root:%u)",
backend_x11->xdpy,
backend_x11->xscreen_num,
(unsigned int) backend_x11->xwin_root);
return stage;
}
static void
clutter_backend_x11_class_init (ClutterBackendX11Class *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
gobject_class->constructor = clutter_backend_x11_constructor;
gobject_class->dispose = clutter_backend_x11_dispose;
gobject_class->finalize = clutter_backend_x11_finalize;
@ -725,6 +812,8 @@ clutter_backend_x11_class_init (ClutterBackendX11Class *klass)
backend_class->copy_event_data = clutter_backend_x11_copy_event_data;
backend_class->free_event_data = clutter_backend_x11_free_event_data;
backend_class->translate_event = clutter_backend_x11_translate_event;
backend_class->create_context = clutter_backend_x11_create_context;
backend_class->create_stage = clutter_backend_x11_create_stage;
}
static void
@ -784,13 +873,15 @@ clutter_x11_untrap_x_errors (void)
Display *
clutter_x11_get_default_display (void)
{
if (!backend_singleton)
ClutterBackend *backend = clutter_get_default_backend ();
if (!backend || !CLUTTER_IS_BACKEND_X11 (backend))
{
g_critical ("X11 backend has not been initialised");
return NULL;
}
return backend_singleton->xdpy;
return CLUTTER_BACKEND_X11 (backend)->xdpy;
}
/**
@ -913,13 +1004,15 @@ clutter_x11_has_event_retrieval (void)
int
clutter_x11_get_default_screen (void)
{
if (!backend_singleton)
ClutterBackend *backend = clutter_get_default_backend ();
if (!backend || !CLUTTER_IS_BACKEND_X11 (backend))
{
g_critical ("X11 backend has not been initialised");
return 0;
}
return backend_singleton->xscreen_num;
return CLUTTER_BACKEND_X11 (backend)->xscreen_num;
}
/**
@ -934,13 +1027,15 @@ clutter_x11_get_default_screen (void)
Window
clutter_x11_get_root_window (void)
{
if (!backend_singleton)
ClutterBackend *backend = clutter_get_default_backend ();
if (!backend || !CLUTTER_IS_BACKEND_X11 (backend))
{
g_critical ("X11 backend has not been initialised");
return None;
}
return backend_singleton->xwin_root;
return CLUTTER_BACKEND_X11 (backend)->xwin_root;
}
/**
@ -957,21 +1052,25 @@ clutter_x11_add_filter (ClutterX11FilterFunc func,
gpointer data)
{
ClutterX11EventFilter *filter;
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
g_return_if_fail (func != NULL);
if (!backend_singleton)
if (!backend || !CLUTTER_IS_BACKEND_X11 (backend))
{
g_critical ("X11 backend has not been initialised");
return;
}
backend_x11 = CLUTTER_BACKEND_X11 (backend);
filter = g_new0 (ClutterX11EventFilter, 1);
filter->func = func;
filter->data = data;
backend_singleton->event_filters =
g_slist_append (backend_singleton->event_filters, filter);
backend_x11->event_filters =
g_slist_append (backend_x11->event_filters, filter);
return;
}
@ -991,10 +1090,20 @@ clutter_x11_remove_filter (ClutterX11FilterFunc func,
{
GSList *tmp_list, *this;
ClutterX11EventFilter *filter;
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendX11 *backend_x11;
g_return_if_fail (func != NULL);
tmp_list = backend_singleton->event_filters;
if (!backend || !CLUTTER_IS_BACKEND_X11 (backend))
{
g_critical ("X11 backend has not been initialised");
return;
}
backend_x11 = CLUTTER_BACKEND_X11 (backend);
tmp_list = backend_x11->event_filters;
while (tmp_list)
{
@ -1004,8 +1113,8 @@ clutter_x11_remove_filter (ClutterX11FilterFunc func,
if (filter->func == func && filter->data == data)
{
backend_singleton->event_filters =
g_slist_remove_link (backend_singleton->event_filters, this);
backend_x11->event_filters =
g_slist_remove_link (backend_x11->event_filters, this);
g_slist_free_1 (this);
g_free (filter);
@ -1052,10 +1161,15 @@ gboolean
clutter_x11_has_xinput (void)
{
#if defined(HAVE_XINPUT) || defined(HAVE_XINPUT_2)
if (backend_singleton != NULL)
return backend_singleton->has_xinput;
ClutterBackend *backend = clutter_get_default_backend ();
return FALSE;
if (!backend || !CLUTTER_IS_BACKEND_X11 (backend))
{
g_critical ("X11 backend has not been initialised");
return FALSE;
}
return CLUTTER_BACKEND_X11 (backend)->has_xinput;
#else
return FALSE;
#endif
@ -1159,15 +1273,7 @@ clutter_x11_get_use_argb_visual (void)
XVisualInfo *
_clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11)
{
ClutterBackendX11Class *klass;
g_return_val_if_fail (CLUTTER_IS_BACKEND_X11 (backend_x11), NULL);
klass = CLUTTER_BACKEND_X11_GET_CLASS (backend_x11);
if (klass->get_visual_info)
return klass->get_visual_info (backend_x11);
return NULL;
return cogl_clutter_winsys_xlib_get_visual_info ();
}
/**
@ -1242,3 +1348,9 @@ _clutter_x11_input_device_translate_screen_coord (ClutterInputDevice *device,
return TRUE;
}
GType
_clutter_backend_impl_get_type (void)
{
return _clutter_backend_x11_get_type ();
}

View File

@ -31,6 +31,7 @@
#include "clutter-backend-private.h"
#include "clutter-keymap-x11.h"
#include "cogl/clutter-backend-cogl.h"
#include "xsettings/xsettings-client.h"
@ -67,7 +68,7 @@ struct _ClutterEventX11
struct _ClutterBackendX11
{
ClutterBackend parent_instance;
ClutterBackendCogl parent_instance;
Display *xdpy;
gchar *display_name;
@ -112,14 +113,7 @@ struct _ClutterBackendX11
struct _ClutterBackendX11Class
{
ClutterBackendClass parent_class;
/*
* To support foreign stage windows the we need a way to ask for an
* XVisualInfo that may be used by toolkits to create an XWindow, and this
* may need to be handled differently for different backends.
*/
XVisualInfo *(* get_visual_info) (ClutterBackendX11 *backend);
ClutterBackendCoglClass parent_class;
};
void _clutter_backend_x11_events_init (ClutterBackend *backend);

View File

@ -27,6 +27,8 @@
#include <unistd.h>
#endif
#include <cogl/cogl.h>
#include "clutter-backend-x11.h"
#include "clutter-stage-x11.h"
#include "clutter-x11.h"
@ -43,14 +45,14 @@
#include "clutter-private.h"
#include "clutter-stage-private.h"
#include "cogl/cogl.h"
#ifdef HAVE_XFIXES
#include <X11/extensions/Xfixes.h>
#endif
#define STAGE_X11_IS_MAPPED(s) ((((ClutterStageX11 *) (s))->wm_state & STAGE_X11_WITHDRAWN) == 0)
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
@ -60,7 +62,7 @@ static GHashTable *clutter_stages_by_xid = NULL;
G_DEFINE_TYPE_WITH_CODE (ClutterStageX11,
clutter_stage_x11,
G_TYPE_OBJECT,
CLUTTER_TYPE_STAGE_COGL,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init)
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR,
@ -129,7 +131,8 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
gint new_width,
gint new_height)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
if (stage_x11->xwin != None && !stage_x11->is_foreign_xwin)
{
@ -137,11 +140,11 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
XSizeHints *size_hints;
gboolean resize;
resize = clutter_stage_get_user_resizable (stage_x11->wrapper);
resize = clutter_stage_get_user_resizable (stage_cogl->wrapper);
size_hints = XAllocSizeHints();
clutter_stage_get_minimum_size (stage_x11->wrapper,
clutter_stage_get_minimum_size (stage_cogl->wrapper,
&min_width,
&min_height);
@ -182,7 +185,8 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
static void
clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
Atom protocols[2];
int n = 0;
@ -197,7 +201,8 @@ clutter_stage_x11_get_geometry (ClutterStageWindow *stage_window,
cairo_rectangle_int_t *geometry)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
/* If we're fullscreen, return the size of the display. */
if ((stage_x11->state & CLUTTER_STAGE_STATE_FULLSCREEN) &&
@ -219,7 +224,8 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
gint height)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
if (stage_x11->is_foreign_xwin)
{
@ -229,7 +235,7 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
*/
stage_x11->xwin_width = width;
stage_x11->xwin_height = height;
clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_x11->wrapper));
clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_cogl->wrapper));
return;
}
@ -262,7 +268,7 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
width,
height);
CLUTTER_SET_PRIVATE_FLAGS (stage_x11->wrapper,
CLUTTER_SET_PRIVATE_FLAGS (stage_cogl->wrapper,
CLUTTER_IN_RESIZE);
/* XXX: in this case we can rely on a subsequent
@ -280,7 +286,8 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
static inline void
set_wm_pid (ClutterStageX11 *stage_x11)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
long pid;
if (stage_x11->xwin == None || stage_x11->is_foreign_xwin)
@ -304,7 +311,8 @@ set_wm_pid (ClutterStageX11 *stage_x11)
static inline void
set_wm_title (ClutterStageX11 *stage_x11)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
if (stage_x11->xwin == None || stage_x11->is_foreign_xwin)
return;
@ -331,7 +339,8 @@ set_wm_title (ClutterStageX11 *stage_x11)
static inline void
set_cursor_visible (ClutterStageX11 *stage_x11)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
if (stage_x11->xwin == None)
return;
@ -385,6 +394,8 @@ clutter_stage_x11_unrealize (ClutterStageWindow *stage_window)
g_hash_table_remove (clutter_stages_by_xid,
GINT_TO_POINTER (stage_x11->xwin));
}
clutter_stage_window_parent_iface->unrealize (stage_window);
}
void
@ -393,7 +404,8 @@ _clutter_stage_x11_update_foreign_event_mask (CoglOnscreen *onscreen,
void *user_data)
{
ClutterStageX11 *stage_x11 = user_data;
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = user_data;
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
XSetWindowAttributes attrs;
attrs.event_mask = event_mask | CLUTTER_STAGE_X11_EVENT_MASK;
@ -408,9 +420,36 @@ static gboolean
clutter_stage_x11_realize (ClutterStageWindow *stage_window)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
ClutterBackend *backend = CLUTTER_BACKEND (stage_cogl->backend);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
ClutterDeviceManager *device_manager;
int event_flags;
gfloat width, height;
clutter_actor_get_size (CLUTTER_ACTOR (stage_cogl->wrapper),
&width, &height);
stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
width, height);
if (stage_x11->xwin != None)
{
cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen,
stage_x11->xwin,
_clutter_stage_x11_update_foreign_event_mask,
stage_x11);
}
/* Chain to the parent class now. ClutterStageCogl will call cogl_framebuffer_allocate,
which will create the X Window we need */
if (!(clutter_stage_window_parent_iface->realize (stage_window)))
return FALSE;
if (stage_x11->xwin == None)
stage_x11->xwin = cogl_x11_onscreen_get_window_xid (stage_cogl->onscreen);
if (clutter_stages_by_xid == NULL)
clutter_stages_by_xid = g_hash_table_new (NULL, NULL);
@ -456,7 +495,7 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window)
*/
device_manager = clutter_device_manager_get_default ();
_clutter_device_manager_select_stage_events (device_manager,
stage_x11->wrapper,
stage_cogl->wrapper,
event_flags);
/* no user resize.. */
@ -475,8 +514,9 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
gboolean is_fullscreen)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStage *stage = stage_x11->wrapper;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
ClutterStage *stage = stage_cogl->wrapper;
gboolean was_fullscreen;
if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
@ -611,7 +651,8 @@ clutter_stage_x11_set_user_resizable (ClutterStageWindow *stage_window,
static inline void
update_wm_hints (ClutterStageX11 *stage_x11)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
XWMHints wm_hints;
if (stage_x11->wm_state & STAGE_X11_WITHDRAWN)
@ -661,7 +702,8 @@ clutter_stage_x11_show (ClutterStageWindow *stage_window,
gboolean do_raise)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
if (stage_x11->xwin != None)
{
@ -689,7 +731,7 @@ clutter_stage_x11_show (ClutterStageWindow *stage_window,
g_assert (STAGE_X11_IS_MAPPED (stage_x11));
clutter_actor_map (CLUTTER_ACTOR (stage_x11->wrapper));
clutter_actor_map (CLUTTER_ACTOR (stage_cogl->wrapper));
if (!stage_x11->is_foreign_xwin)
XMapWindow (backend_x11->xdpy, stage_x11->xwin);
@ -700,7 +742,8 @@ static void
clutter_stage_x11_hide (ClutterStageWindow *stage_window)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
if (stage_x11->xwin != None)
{
@ -709,19 +752,13 @@ clutter_stage_x11_hide (ClutterStageWindow *stage_window)
g_assert (!STAGE_X11_IS_MAPPED (stage_x11));
clutter_actor_unmap (CLUTTER_ACTOR (stage_x11->wrapper));
clutter_actor_unmap (CLUTTER_ACTOR (stage_cogl->wrapper));
if (!stage_x11->is_foreign_xwin)
XWithdrawWindow (backend_x11->xdpy, stage_x11->xwin, 0);
}
}
static ClutterActor *
clutter_stage_x11_get_wrapper (ClutterStageWindow *stage_window)
{
return CLUTTER_ACTOR (CLUTTER_STAGE_X11 (stage_window)->wrapper);
}
static void
clutter_stage_x11_finalize (GObject *gobject)
{
@ -736,7 +773,7 @@ static void
clutter_stage_x11_dispose (GObject *gobject)
{
ClutterEventTranslator *translator = CLUTTER_EVENT_TRANSLATOR (gobject);
ClutterBackendX11 *backend = CLUTTER_STAGE_X11 (gobject)->backend;
ClutterBackendCogl *backend = CLUTTER_STAGE_COGL (gobject)->backend;
_clutter_backend_remove_event_translator (CLUTTER_BACKEND (backend),
translator);
@ -768,14 +805,13 @@ clutter_stage_x11_init (ClutterStageX11 *stage)
stage->accept_focus = TRUE;
stage->title = NULL;
stage->wrapper = NULL;
}
static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
{
iface->get_wrapper = clutter_stage_x11_get_wrapper;
clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
iface->set_title = clutter_stage_x11_set_title;
iface->set_fullscreen = clutter_stage_x11_set_fullscreen;
iface->set_cursor_visible = clutter_stage_x11_set_cursor_visible;
@ -810,6 +846,7 @@ handle_wm_protocols_event (ClutterBackendX11 *backend_x11,
ClutterStageX11 *stage_x11,
XEvent *xevent)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
Atom atom = (Atom) xevent->xclient.data.l[0];
if (atom == backend_x11->atom_WM_DELETE_WINDOW &&
@ -821,8 +858,8 @@ handle_wm_protocols_event (ClutterBackendX11 *backend_x11,
* handle the request
*/
CLUTTER_NOTE (EVENT, "Delete stage %s[%p], win:0x%x",
_clutter_actor_get_debug_name (CLUTTER_ACTOR (stage_x11->wrapper)),
stage_x11->wrapper,
_clutter_actor_get_debug_name (CLUTTER_ACTOR (stage_cogl->wrapper)),
stage_cogl->wrapper,
(unsigned int) stage_x11->xwin);
set_user_time (backend_x11, stage_x11, xevent->xclient.data.l[1]);
@ -862,8 +899,9 @@ clutter_stage_x11_translate_event (ClutterEventTranslator *translator,
ClutterEvent *event)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (translator);
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (translator);
ClutterTranslateReturn res = CLUTTER_TRANSLATE_CONTINUE;
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
Window stage_xwindow = stage_x11->xwin;
XEvent *xevent = native;
ClutterStage *stage;
@ -901,7 +939,7 @@ clutter_stage_x11_translate_event (ClutterEventTranslator *translator,
xevent->xconfigure.width,
xevent->xconfigure.height);
CLUTTER_UNSET_PRIVATE_FLAGS (stage_x11->wrapper, CLUTTER_IN_RESIZE);
CLUTTER_UNSET_PRIVATE_FLAGS (stage_cogl->wrapper, CLUTTER_IN_RESIZE);
if (size_changed)
{
@ -1171,16 +1209,16 @@ clutter_x11_get_stage_window (ClutterStage *stage)
ClutterStage *
clutter_x11_get_stage_from_window (Window win)
{
ClutterStageX11 *stage_x11;
ClutterStageCogl *stage_cogl;
if (clutter_stages_by_xid == NULL)
return NULL;
stage_x11 = g_hash_table_lookup (clutter_stages_by_xid,
GINT_TO_POINTER (win));
stage_cogl = g_hash_table_lookup (clutter_stages_by_xid,
GINT_TO_POINTER (win));
if (stage_x11 != NULL)
return stage_x11->wrapper;
if (stage_cogl != NULL)
return stage_cogl->wrapper;
return NULL;
}
@ -1228,7 +1266,8 @@ set_foreign_window_callback (ClutterActor *actor,
void *data)
{
ForeignWindowData *fwd = data;
ClutterBackendX11 *backend_x11 = fwd->stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (fwd->stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
CLUTTER_NOTE (BACKEND, "Setting foreign window (0x%x)",
(unsigned int) fwd->xwindow);
@ -1279,6 +1318,7 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
{
ClutterBackendX11 *backend_x11;
ClutterStageX11 *stage_x11;
ClutterStageCogl *stage_cogl;
ClutterStageWindow *impl;
ClutterActor *actor;
gint x, y;
@ -1294,7 +1334,8 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
impl = _clutter_stage_get_window (stage);
stage_x11 = CLUTTER_STAGE_X11 (impl);
backend_x11 = stage_x11->backend;
stage_cogl = CLUTTER_STAGE_COGL (impl);
backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
xvisinfo = _clutter_backend_x11_get_visual_info (backend_x11);
g_return_val_if_fail (xvisinfo != NULL, FALSE);
@ -1369,7 +1410,10 @@ void
_clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11,
guint32 user_time)
{
set_user_time (stage_x11->backend, stage_x11, user_time);
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
set_user_time (backend_x11, stage_x11, user_time);
}
gboolean
@ -1377,7 +1421,8 @@ _clutter_stage_x11_get_root_coords (ClutterStageX11 *stage_x11,
gint *root_x,
gint *root_y)
{
ClutterBackendX11 *backend_x11 = stage_x11->backend;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
gint return_val;
Window child;
gint tx, ty;

View File

@ -28,6 +28,7 @@
#include <X11/Xatom.h>
#include "clutter-backend-x11.h"
#include "cogl/clutter-stage-cogl.h"
G_BEGIN_DECLS
@ -48,7 +49,7 @@ typedef enum
struct _ClutterStageX11
{
GObject parent_instance;
ClutterStageCogl parent_instance;
Window xwin;
gint xwin_width;
@ -62,10 +63,6 @@ struct _ClutterStageX11
ClutterStageX11State wm_state;
/* backpointers */
ClutterStage *wrapper;
ClutterBackendX11 *backend;
guint is_foreign_xwin : 1;
guint fullscreening : 1;
guint is_cursor_visible : 1;
@ -75,7 +72,7 @@ struct _ClutterStageX11
struct _ClutterStageX11Class
{
GObjectClass parent_class;
ClutterStageCoglClass parent_class;
};
#define CLUTTER_STAGE_X11_EVENT_MASK \

View File

@ -199,15 +199,14 @@ AS_CASE([$CLUTTER_FLAVOUR],
[glx],
[
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_GLX"
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_X11"
SUPPORT_X11=1
SUPPORT_XLIB=1
SUPPORT_GLX=1
CLUTTER_WINSYS=cogl
CLUTTER_WINSYS_BASE=x11
CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la"
CLUTTER_WINSYS=x11
CLUTTER_WINSYS_BASE=cogl
CLUTTER_SONAME_INFIX=glx
# Mesa 7.3 added a GL pkg-config file, finally
@ -228,15 +227,14 @@ AS_CASE([$CLUTTER_FLAVOUR],
[gdk],
[
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_COGL"
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_GDK"
# We don't claim to support X11 (even though that's the preferred
# GDK backend), to avoid building all the ClutterX11 stuff
SUPPORT_GDK=1
CLUTTER_WINSYS=cogl
CLUTTER_WINSYS_BASE=gdk
CLUTTER_WINSYS_BASE_LIB="gdk/libclutter-gdk.la"
CLUTTER_WINSYS=gdk
CLUTTER_WINSYS_BASE=cogl
CLUTTER_SONAME_INFIX=gdk
BACKEND_PC_FILES="$BACKEND_PC_FILES gdk-3.0"
@ -245,7 +243,7 @@ AS_CASE([$CLUTTER_FLAVOUR],
[opengl-egl-xlib],
[
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGL"
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_X11"
CLUTTER_EGL_BACKEND="generic"
SUPPORT_X11=1
@ -253,9 +251,8 @@ AS_CASE([$CLUTTER_FLAVOUR],
SUPPORT_EGL=1
SUPPORT_EGL_PLATFORM_POWERVR_X11=1
CLUTTER_WINSYS=cogl
CLUTTER_WINSYS_BASE=x11
CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la"
CLUTTER_WINSYS=x11
CLUTTER_WINSYS_BASE=cogl
# I think this winsys can be API and ABI compatible with the
# glx flavour so we can also be cheeky and use the same soname
CLUTTER_SONAME_INFIX=glx
@ -282,7 +279,7 @@ AS_CASE([$CLUTTER_FLAVOUR],
[eglx],
[
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGL"
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_X11"
CLUTTER_EGL_BACKEND="generic"
SUPPORT_X11=1
@ -290,9 +287,8 @@ AS_CASE([$CLUTTER_FLAVOUR],
SUPPORT_EGL=1
SUPPORT_EGL_PLATFORM_POWERVR_X11=1
CLUTTER_WINSYS=cogl
CLUTTER_WINSYS_BASE=x11
CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la"
CLUTTER_WINSYS=x11
CLUTTER_WINSYS_BASE=cogl
CLUTTER_SONAME_INFIX=eglx
],
@ -494,7 +490,6 @@ dnl === Clutter substitutions =================================================
AC_SUBST([CLUTTER_WINSYS])
# The same goes for the winsys-base...
AC_SUBST([CLUTTER_WINSYS_BASE])
AC_SUBST([CLUTTER_WINSYS_BASE_LIB])
AC_SUBST(CLUTTER_STAGE_TYPE)
AC_SUBST(CLUTTER_SONAME_INFIX)