From 610a9c17bacfe3106d59d3c450be6a07cd26490a Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Fri, 26 Aug 2011 03:09:18 +0200 Subject: [PATCH] Add a new GDK backend This commit introduces a new flavour for Clutter, that uses GDK for handling all window system specific interactions (except for creating the cogl context, as cogl does not know about GDK), including in particular events. This is not compatible with the X11 (glx) flavour, and this is reflected by the different soname (libclutter-gdk-1.0.so), as all X11 specific functions and classes are not available. If you wish to be compatible, you should check for CLUTTER_WINDOWING_X11. Other than that, this backend should be on feature parity with X11, including XInput 2, XSettings and EMWH (with much, much less code) https://bugzilla.gnome.org/show_bug.cgi?id=657434 --- clutter/Makefile.am | 28 + clutter/cogl/clutter-backend-cogl.c | 86 ++- clutter/cogl/clutter-backend-cogl.h | 18 +- clutter/cogl/clutter-stage-cogl.c | 70 ++- clutter/cogl/clutter-stage-cogl.h | 17 +- clutter/gdk/clutter-backend-gdk-private.h | 32 + clutter/gdk/clutter-backend-gdk.c | 368 ++++++++++++ clutter/gdk/clutter-backend-gdk.h | 72 +++ clutter/gdk/clutter-device-manager-gdk.c | 249 ++++++++ clutter/gdk/clutter-device-manager-gdk.h | 63 ++ clutter/gdk/clutter-event-gdk.c | 264 ++++++++ clutter/gdk/clutter-gdk.h | 55 ++ clutter/gdk/clutter-input-device-gdk.c | 160 +++++ clutter/gdk/clutter-input-device-gdk.h | 55 ++ clutter/gdk/clutter-settings-gdk.h | 28 + clutter/gdk/clutter-stage-gdk.c | 601 +++++++++++++++++++ clutter/gdk/clutter-stage-gdk.h | 84 +++ configure.ac | 21 + tests/conform/test-cogl-texture-pixmap-x11.c | 10 +- tests/conform/test-conform-common.c | 4 +- 20 files changed, 2232 insertions(+), 53 deletions(-) create mode 100644 clutter/gdk/clutter-backend-gdk-private.h create mode 100644 clutter/gdk/clutter-backend-gdk.c create mode 100644 clutter/gdk/clutter-backend-gdk.h create mode 100644 clutter/gdk/clutter-device-manager-gdk.c create mode 100644 clutter/gdk/clutter-device-manager-gdk.h create mode 100644 clutter/gdk/clutter-event-gdk.c create mode 100644 clutter/gdk/clutter-gdk.h create mode 100644 clutter/gdk/clutter-input-device-gdk.c create mode 100644 clutter/gdk/clutter-input-device-gdk.h create mode 100644 clutter/gdk/clutter-settings-gdk.h create mode 100644 clutter/gdk/clutter-stage-gdk.c create mode 100644 clutter/gdk/clutter-stage-gdk.h diff --git a/clutter/Makefile.am b/clutter/Makefile.am index b89349b7b..d28e7e969 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -416,6 +416,34 @@ backend_source_c += $(cogl_source_c) $(glx_source_c) backend_source_h_priv += $(cogl_source_h_priv) endif # SUPPORT_GLX +# GDK backend rules +gdk_source_c = \ + $(srcdir)/gdk/clutter-backend-gdk.c \ + $(srcdir)/gdk/clutter-device-manager-gdk.c \ + $(srcdir)/gdk/clutter-input-device-gdk.c \ + $(srcdir)/gdk/clutter-event-gdk.c \ + $(srcdir)/gdk/clutter-stage-gdk.c \ + $(NULL) + +gdk_source_h = \ + $(srcdir)/gdk/clutter-gdk.h \ + $(NULL) + +gdk_source_h_priv = \ + $(srcdir)/gdk/clutter-settings-gdk.h \ + $(srcdir)/gdk/clutter-backend-gdk.h \ + $(srcdir)/gdk/clutter-device-manager-gdk.h \ + $(srcdir)/gdk/clutter-input-device-gdk.h \ + $(srcdir)/gdk/clutter-event-gdk.h \ + $(srcdir)/gdk/clutter-stage-gdk.h \ + $(NULL) + +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) +endif # SUPPORT_GDK + # Windows backend rules win32_source_c = \ $(srcdir)/win32/clutter-backend-win32.c \ diff --git a/clutter/cogl/clutter-backend-cogl.c b/clutter/cogl/clutter-backend-cogl.c index f37ca197e..6741bdd87 100644 --- a/clutter/cogl/clutter-backend-cogl.c +++ b/clutter/cogl/clutter-backend-cogl.c @@ -36,6 +36,17 @@ #include +#include "clutter-config.h" + +#ifdef CLUTTER_WINDOWING_GDK +#include + +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#endif + #include "clutter-backend-cogl.h" #include "clutter-stage-cogl.h" @@ -67,8 +78,10 @@ static gdl_plane_id_t gdl_plane = GDL_PLANE_ID_UPP_C; static guint gdl_n_buffers = CLUTTER_CEX100_TRIPLE_BUFFERING; #endif -#ifdef COGL_HAS_X11_SUPPORT +#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 @@ -87,7 +100,7 @@ clutter_backend_cogl_pre_parse (ClutterBackend *backend, GError **error) { const gchar *env_string; -#ifdef COGL_HAS_X11_SUPPORT +#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK) ClutterBackendClass *parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class); @@ -109,7 +122,7 @@ static gboolean clutter_backend_cogl_post_parse (ClutterBackend *backend, GError **error) { -#ifdef COGL_HAS_X11_SUPPORT +#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK) ClutterBackendClass *parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class); @@ -122,7 +135,7 @@ clutter_backend_cogl_post_parse (ClutterBackend *backend, return TRUE; } -#ifndef COGL_HAS_XLIB_SUPPORT +#if !(defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK)) static ClutterDeviceManager * clutter_backend_cogl_get_device_manager (ClutterBackend *backend) { @@ -140,7 +153,7 @@ clutter_backend_cogl_get_device_manager (ClutterBackend *backend) return backend_cogl->device_manager; } -#endif +#endif /* !(X11 || GDK) */ static void clutter_backend_cogl_init_events (ClutterBackend *backend) @@ -152,8 +165,8 @@ clutter_backend_cogl_init_events (ClutterBackend *backend) #ifdef HAVE_EVDEV _clutter_events_evdev_init (CLUTTER_BACKEND (backend)); #endif -#ifdef COGL_HAS_X11_SUPPORT - /* Chain up to the X11 backend */ +#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 @@ -227,15 +240,15 @@ static ClutterFeatureFlags clutter_backend_cogl_get_features (ClutterBackend *backend) { ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend); -#ifdef COGL_HAS_XLIB_SUPPORT - ClutterBackendClass *parent_class; -#endif ClutterFeatureFlags flags = 0; -#ifdef COGL_HAS_XLIB_SUPPORT - parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class); +#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); + flags = parent_class->get_features (backend); + } #endif if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN)) @@ -272,7 +285,7 @@ clutter_backend_cogl_get_features (ClutterBackend *backend) return flags; } -#ifdef COGL_HAS_XLIB_SUPPORT +#ifdef CLUTTER_WINDOWING_X11 static XVisualInfo * clutter_backend_cogl_get_visual_info (ClutterBackendX11 *backend_x11) { @@ -284,8 +297,10 @@ static gboolean clutter_backend_cogl_create_context (ClutterBackend *backend, GError **error) { -#ifdef COGL_HAS_XLIB_SUPPORT +#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; @@ -295,17 +310,34 @@ clutter_backend_cogl_create_context (ClutterBackend *backend, return TRUE; backend->cogl_renderer = cogl_renderer_new (); -#ifdef COGL_HAS_XLIB_SUPPORT +#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 (); -#ifdef COGL_HAS_XLIB_SUPPORT +#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 @@ -387,7 +419,7 @@ clutter_backend_cogl_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error) { -#ifdef COGL_HAS_XLIB_SUPPORT +#if defined(CLUTTER_WINDOWING_X11) ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); ClutterEventTranslator *translator; ClutterStageWindow *stage; @@ -408,7 +440,14 @@ clutter_backend_cogl_create_stage (ClutterBackend *backend, backend_x11->xscreen_num, (unsigned int) backend_x11->xwin_root); -#else /* COGL_HAS_XLIB_SUPPORT */ + 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; @@ -431,9 +470,8 @@ clutter_backend_cogl_create_stage (ClutterBackend *backend, backend_cogl->stage = stage; -#endif /* COGL_HAS_XLIB_SUPPORT */ - return stage; +#endif /* CLUTTER_WINDOWING_X11 || CLUTTER_WINDOWING_GDK */ } static void @@ -457,7 +495,7 @@ _clutter_backend_cogl_class_init (ClutterBackendCoglClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); -#ifdef COGL_HAS_X11_SUPPORT +#ifdef CLUTTER_WINDOWING_X11 ClutterBackendX11Class *backendx11_class = CLUTTER_BACKEND_X11_CLASS (klass); #endif @@ -468,7 +506,7 @@ _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; -#ifndef COGL_HAS_XLIB_SUPPORT +#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; @@ -476,7 +514,7 @@ _clutter_backend_cogl_class_init (ClutterBackendCoglClass *klass) backend_class->create_context = clutter_backend_cogl_create_context; backend_class->ensure_context = clutter_backend_cogl_ensure_context; -#ifdef COGL_HAS_XLIB_SUPPORT +#ifdef CLUTTER_WINDOWING_X11 backendx11_class->get_visual_info = clutter_backend_cogl_get_visual_info; #endif } diff --git a/clutter/cogl/clutter-backend-cogl.h b/clutter/cogl/clutter-backend-cogl.h index c1563d390..68065591e 100644 --- a/clutter/cogl/clutter-backend-cogl.h +++ b/clutter/cogl/clutter-backend-cogl.h @@ -37,9 +37,12 @@ #include "clutter-backend-private.h" -#ifdef COGL_HAS_X11_SUPPORT +#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 @@ -55,10 +58,13 @@ typedef struct _ClutterBackendCoglClass ClutterBackendCoglClass; struct _ClutterBackendCogl { -#ifdef COGL_HAS_XLIB_SUPPORT +#ifdef CLUTTER_WINDOWING_X11 ClutterBackendX11 parent_instance; -#else /* COGL_HAS_X11_SUPPORT */ +#elif defined(CLUTTER_WINDOWING_GDK) + ClutterBackendGdk parent_instance; + +#else ClutterBackend parent_instance; /* main stage singleton */ @@ -73,7 +79,7 @@ struct _ClutterBackendCogl /* event timer */ GTimer *event_timer; -#endif /* COGL_HAS_X11_SUPPORT */ +#endif /* CLUTTER_WINDOWING_X11 || CLUTTER_WINDOWING_GDK */ CoglContext *cogl_context; @@ -82,8 +88,10 @@ struct _ClutterBackendCogl struct _ClutterBackendCoglClass { -#ifdef COGL_HAS_XLIB_SUPPORT +#ifdef CLUTTER_WINDOWING_X11 ClutterBackendX11Class parent_class; +#elif defined(CLUTTER_WINDOWING_GDK) + ClutterBackendGdkClass parent_class; #else ClutterBackendClass parent_class; #endif diff --git a/clutter/cogl/clutter-stage-cogl.c b/clutter/cogl/clutter-stage-cogl.c index 0acec4bef..9e9c0fd57 100644 --- a/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/cogl/clutter-stage-cogl.c @@ -30,6 +30,17 @@ #include "config.h" #endif +#include "clutter-config.h" + +#ifdef CLUTTER_WINDOWING_GDK +#include + +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#endif + #include "clutter-stage-cogl.h" #include "clutter-backend-cogl.h" @@ -43,7 +54,7 @@ #include "clutter-stage-private.h" #include "clutter-util.h" -#ifdef COGL_HAS_X11_SUPPORT +#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK) static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL; #endif @@ -51,8 +62,10 @@ static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); G_DEFINE_TYPE_WITH_CODE (ClutterStageCogl, _clutter_stage_cogl, -#ifdef COGL_HAS_X11_SUPPORT +#if defined(CLUTTER_WINDOWING_X11) CLUTTER_TYPE_STAGE_X11, +#elif defined(CLUTTER_WINDOWING_GDK) + CLUTTER_TYPE_STAGE_GDK, #else G_TYPE_OBJECT, #endif @@ -66,7 +79,7 @@ clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window) CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_cogl); -#ifdef COGL_HAS_XLIB_SUPPORT +#if defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK) /* chain up to the StageX11 implementation */ clutter_stage_window_parent_iface->unrealize (stage_window); #endif @@ -101,8 +114,10 @@ static gboolean clutter_stage_cogl_realize (ClutterStageWindow *stage_window) { ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); -#ifdef COGL_HAS_XLIB_SUPPORT +#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; @@ -115,16 +130,25 @@ 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 (); -#ifdef COGL_HAS_XLIB_SUPPORT +#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); -#ifdef COGL_HAS_XLIB_SUPPORT +#if defined(CLUTTER_WINDOWING_X11) if (stage_x11->xwin != None) { cogl_x11_onscreen_set_foreign_window_xid (stage_cogl->onscreen, @@ -133,6 +157,24 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window) stage_x11); } +#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 (); @@ -161,7 +203,7 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window) stage_cogl); } -#ifdef COGL_HAS_XLIB_SUPPORT +#ifdef CLUTTER_WINDOWING_X11 if (stage_x11->xwin == None) stage_x11->xwin = cogl_x11_onscreen_get_window_xid (stage_cogl->onscreen); @@ -179,7 +221,7 @@ clutter_stage_cogl_get_pending_swaps (ClutterStageWindow *stage_window) return stage_cogl->pending_swaps; } -#ifndef COGL_HAS_XLIB_SUPPORT +#if !(defined(CLUTTER_WINDOWING_X11) || defined(CLUTTER_WINDOWING_GDK)) static ClutterActor * clutter_stage_cogl_get_wrapper (ClutterStageWindow *stage_window) @@ -238,7 +280,7 @@ clutter_stage_cogl_resize (ClutterStageWindow *stage_window, { } -#endif /* COGL_HAS_XLIB_SUPPORT */ +#endif /* X11 || GDK */ static gboolean clutter_stage_cogl_has_redraw_clips (ClutterStageWindow *stage_window) @@ -368,10 +410,14 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) "The time spent in blit_sub_buffer", 0 /* no application private data */); -#ifdef COGL_HAS_X11_SUPPORT +#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 @@ -390,7 +436,7 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) /* some drivers struggle to get going and produce some junk * frames when starting up... */ G_LIKELY (stage_cogl->frame_count > 3) -#ifdef COGL_HAS_X11_SUPPORT +#if defined(CLUTTER_WINDOWING_X11) /* While resizing a window clipped redraws are disabled to avoid * artefacts. See clutter-event-x11.c:event_translate for a * detailed explanation */ @@ -564,7 +610,7 @@ clutter_stage_cogl_get_active_framebuffer (ClutterStageWindow *stage_window) static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface) { -#ifdef COGL_HAS_X11_SUPPORT +#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; diff --git a/clutter/cogl/clutter-stage-cogl.h b/clutter/cogl/clutter-stage-cogl.h index 73bfb06e0..ade2322cd 100644 --- a/clutter/cogl/clutter-stage-cogl.h +++ b/clutter/cogl/clutter-stage-cogl.h @@ -13,8 +13,14 @@ #include #include #include +#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" @@ -32,12 +38,13 @@ typedef struct _ClutterStageCoglClass ClutterStageCoglClass; struct _ClutterStageCogl { -#ifdef COGL_HAS_X11_SUPPORT - +#ifdef CLUTTER_WINDOWING_X11 ClutterStageX11 parent_instance; -#else +#elif defined(CLUTTER_WINDOWING_GDK) + ClutterStageGdk parent_instance; +#else GObject parent_instance; /* the stage wrapper */ @@ -69,9 +76,9 @@ struct _ClutterStageCogl struct _ClutterStageCoglClass { -#ifdef COGL_HAS_X11_SUPPORT +#ifdef CLUTTER_WINDOWING_X11 ClutterStageX11Class parent_class; -#else +#elif defined(CLUTTER_WINDOWING_GDK) GObjectClass parent_class; #endif }; diff --git a/clutter/gdk/clutter-backend-gdk-private.h b/clutter/gdk/clutter-backend-gdk-private.h new file mode 100644 index 000000000..18c53facd --- /dev/null +++ b/clutter/gdk/clutter-backend-gdk-private.h @@ -0,0 +1,32 @@ +/* An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_BACKEND_PRIVATE_X11_H__ +#define __CLUTTER_BACKEND_PRIVATE_X11_H__ + + +G_BEGIN_DECLS + +void _clutter_backend_x11_events_init (ClutterBackend *backend); +void _clutter_backend_x11_events_uninit (ClutterBackend *backend); + +G_END_DECLS + +#endif diff --git a/clutter/gdk/clutter-backend-gdk.c b/clutter/gdk/clutter-backend-gdk.c new file mode 100644 index 000000000..9286d85b8 --- /dev/null +++ b/clutter/gdk/clutter-backend-gdk.c @@ -0,0 +1,368 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * 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 . + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif +/* other backends not yet supported */ + +#include "clutter-backend-gdk.h" +#include "clutter-device-manager-gdk.h" +#include "clutter-settings-gdk.h" +#include "clutter-stage-gdk.h" +#include "clutter-gdk.h" + +#include "clutter-backend.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-event-private.h" +#include "clutter-main.h" +#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; + +/* global for pre init setup calls */ +static GdkDisplay *_foreign_dpy = NULL; + +static void +clutter_backend_gdk_init_settings (ClutterBackendGdk *backend_gdk) +{ + ClutterSettings *settings = clutter_settings_get_default (); + int i; + + for (i = 0; i < G_N_ELEMENTS (_clutter_settings_map); i++) + { + GValue val = G_VALUE_INIT; + + g_value_init (&val, CLUTTER_SETTING_TYPE(i)); + gdk_screen_get_setting (backend_gdk->screen, + CLUTTER_SETTING_GDK_NAME(i), + &val); + g_object_set_property (G_OBJECT (settings), + CLUTTER_SETTING_PROPERTY(i), + &val); + g_value_unset (&val); + } +} + +void +_clutter_backend_gdk_update_setting (ClutterBackendGdk *backend_gdk, + const gchar *setting_name) +{ + ClutterSettings *settings = clutter_settings_get_default (); + int i; + + for (i = 0; i < G_N_ELEMENTS (_clutter_settings_map); i++) + { + if (g_strcmp0 (CLUTTER_SETTING_GDK_NAME (i), setting_name) == 0) + { + GValue val = G_VALUE_INIT; + + g_value_init (&val, CLUTTER_SETTING_TYPE (i)); + gdk_screen_get_setting (backend_gdk->screen, + CLUTTER_SETTING_GDK_NAME (i), + &val); + g_object_set_property (G_OBJECT (settings), + CLUTTER_SETTING_PROPERTY (i), + &val); + g_value_unset (&val); + + break; + } + } +} + +static GdkFilterReturn +cogl_gdk_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer data) +{ +#ifdef GDK_WINDOWING_X11 + CoglFilterReturn ret; + + ret = cogl_xlib_handle_event ((XEvent*)xevent); + switch (ret) + { + case COGL_FILTER_REMOVE: + return GDK_FILTER_REMOVE; + + case COGL_FILTER_CONTINUE: + default: + return GDK_FILTER_CONTINUE; + } +#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) + backend_gdk->display = _foreign_dpy; + + /* Init Gdk, if outside code did not already */ + if (!gdk_init_check (NULL, NULL)) + return FALSE; + + /* + * Only open connection if not already set by prior call to + * clutter_gdk_set_display() + */ + if (backend_gdk->display == NULL) + backend_gdk->display = g_object_ref (gdk_display_get_default ()); + + g_assert (backend_gdk->display != NULL); + +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_DISPLAY (backend_gdk->display)) + { + /* Cogl needs to know the Xlib display connection for + CoglTexturePixmapX11 */ + cogl_xlib_set_display (gdk_x11_display_get_xdisplay (backend_gdk->display)); + } +#endif + + backend_gdk->screen = gdk_display_get_default_screen (backend_gdk->display); + + /* add event filter for Cogl events */ + gdk_window_add_filter (NULL, cogl_gdk_filter, NULL); + + clutter_backend_gdk_init_settings (backend_gdk); + + CLUTTER_NOTE (BACKEND, + "Gdk Display '%s' opened", + gdk_display_get_name (backend_gdk->display)); + + return TRUE; +} + + +static void +clutter_backend_gdk_init_events (ClutterBackend *backend) +{ + CLUTTER_NOTE (EVENT, "initialising the event loop"); + + _clutter_backend_gdk_events_init (backend); +} + +static void +clutter_backend_gdk_finalize (GObject *gobject) +{ + ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (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); +} + +static void +clutter_backend_gdk_dispose (GObject *gobject) +{ + ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (gobject); + ClutterStageManager *stage_manager; + + CLUTTER_NOTE (BACKEND, "Disposing the of stages"); + stage_manager = clutter_stage_manager_get_default (); + + g_object_unref (stage_manager); + + CLUTTER_NOTE (BACKEND, "Removing the event source"); + _clutter_backend_gdk_events_uninit (CLUTTER_BACKEND (backend_gdk)); + + 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; +} + +static void +clutter_backend_gdk_copy_event_data (ClutterBackend *backend, + const ClutterEvent *src, + ClutterEvent *dest) +{ + GdkEvent *gdk_event; + + gdk_event = _clutter_event_get_platform_data (src); + if (gdk_event != NULL) + _clutter_event_set_platform_data (dest, gdk_event_copy (gdk_event)); +} + +static void +clutter_backend_gdk_free_event_data (ClutterBackend *backend, + ClutterEvent *event) +{ + GdkEvent *gdk_event; + + gdk_event = _clutter_event_get_platform_data (event); + if (gdk_event != NULL) + gdk_event_free (gdk_event); +} + +static ClutterDeviceManager * +clutter_backend_gdk_get_device_manager (ClutterBackend *backend) +{ + ClutterBackendGdk *backend_gdk = CLUTTER_BACKEND_GDK (backend); + + if (G_UNLIKELY (backend_gdk->device_manager == NULL)) + { + backend_gdk->device_manager = g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_GDK, + "backend", backend_gdk, + "gdk-display", backend_gdk->display, + NULL); + } + + return backend_gdk->device_manager; +} + +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; +} + +static void +clutter_backend_gdk_init (ClutterBackendGdk *backend_gdk) +{ + /* nothing to do here */ +} + +/** + * clutter_gdk_get_default_display: + * + * Retrieves the pointer to the default display. + * + * Return value: (transfer none): the default display + * + * Since: 0.6 + */ +GdkDisplay * +clutter_gdk_get_default_display (void) +{ + if (!backend_singleton) + { + g_critical ("GDK backend has not been initialised"); + return NULL; + } + + return backend_singleton->display; +} + +/** + * clutter_gdk_set_display: + * @display: pointer to a GDK display connection. + * + * Sets the display connection Clutter should use; must be called + * before clutter_init(), clutter_init_with_args() or other functions + * pertaining Clutter's initialization process. + * + * If you are parsing the command line arguments by retrieving Clutter's + * #GOptionGroup with clutter_get_option_group() and calling + * g_option_context_parse() yourself, you should also call + * clutter_gdk_set_display() before g_option_context_parse(). + * + * Since: 0.8 + */ +void +clutter_gdk_set_display (GdkDisplay *display) +{ + if (_clutter_context_is_initialized ()) + { + g_warning ("%s() can only be used before calling clutter_init()", + G_STRFUNC); + return; + } + + _foreign_dpy = g_object_ref (display); +} diff --git a/clutter/gdk/clutter-backend-gdk.h b/clutter/gdk/clutter-backend-gdk.h new file mode 100644 index 000000000..effa6425d --- /dev/null +++ b/clutter/gdk/clutter-backend-gdk.h @@ -0,0 +1,72 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * 2011 Giovanni Campagna + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_BACKEND_GDK_H__ +#define __CLUTTER_BACKEND_GDK_H__ + +#include +#include +#include + +#include "clutter-gdk.h" + +#include "clutter-backend-private.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BACKEND_GDK (_clutter_backend_gdk_get_type ()) +#define CLUTTER_BACKEND_GDK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_GDK, ClutterBackendGdk)) +#define CLUTTER_IS_BACKEND_GDK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_GDK)) +#define CLUTTER_BACKEND_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_GDK, ClutterBackendGdkClass)) +#define CLUTTER_IS_BACKEND_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_GDK)) +#define CLUTTER_BACKEND_GDK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_GDK, ClutterBackendGdkClass)) + +typedef struct _ClutterBackendGdk ClutterBackendGdk; +typedef struct _ClutterBackendGdkClass ClutterBackendGdkClass; + +struct _ClutterBackendGdk +{ + ClutterBackend parent_instance; + + GdkDisplay *display; + GdkScreen *screen; + + ClutterDeviceManager *device_manager; +}; + +struct _ClutterBackendGdkClass +{ + ClutterBackendClass parent_class; + + /* nothing here, for now */ +}; + +GType _clutter_backend_gdk_get_type (void) G_GNUC_CONST; + +void _clutter_backend_gdk_events_init (ClutterBackend *backend); +void _clutter_backend_gdk_events_uninit (ClutterBackend *backend); + +void _clutter_backend_gdk_update_setting (ClutterBackendGdk *backend, const gchar *name); + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_GDK_H__ */ diff --git a/clutter/gdk/clutter-device-manager-gdk.c b/clutter/gdk/clutter-device-manager-gdk.c new file mode 100644 index 000000000..5175bbab5 --- /dev/null +++ b/clutter/gdk/clutter-device-manager-gdk.c @@ -0,0 +1,249 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2011 Intel Corp. + * 2011 Giovanni Campagna + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#include "config.h" + +#include + +#include "clutter-device-manager-gdk.h" + +#include "clutter-backend-gdk.h" +#include "clutter-input-device-gdk.h" +#include "clutter-stage-gdk.h" + +#include "clutter-backend.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-event-private.h" +#include "clutter-event-translator.h" +#include "clutter-stage-private.h" +#include "clutter-private.h" + +#define clutter_device_manager_gdk_get_type _clutter_device_manager_gdk_get_type + +G_DEFINE_TYPE (ClutterDeviceManagerGdk, clutter_device_manager_gdk, CLUTTER_TYPE_DEVICE_MANAGER) + +enum { + PROP_0, + PROP_GDK_DISPLAY, + PROP_LAST +}; + +ClutterInputDevice * +_clutter_device_manager_gdk_lookup_device (ClutterDeviceManager *manager, + GdkDevice *device) +{ + ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (manager); + ClutterInputDevice *clutter_device; + + clutter_device = g_object_get_data (G_OBJECT (device), "clutter-device"); + if (clutter_device != NULL) + return clutter_device; + + clutter_device = _clutter_input_device_gdk_new (manager, device); + g_object_set_data_full (G_OBJECT (device), "clutter-device", clutter_device, g_object_unref); + + manager_gdk->device_cache = g_slist_prepend (manager_gdk->device_cache, g_object_ref (clutter_device)); + g_hash_table_replace (manager_gdk->device_by_id, + GINT_TO_POINTER (clutter_input_device_get_device_id (clutter_device)), + g_object_ref (clutter_device)); + + return clutter_device; +} + +static void +clutter_device_manager_gdk_add_device (ClutterDeviceManager *manager, + ClutterInputDevice *device) +{ + /* XXX implement */ +} + +static void +clutter_device_manager_gdk_remove_device (ClutterDeviceManager *manager, + ClutterInputDevice *device) +{ + /* XXX implement */ +} + +static const GSList * +clutter_device_manager_gdk_get_devices (ClutterDeviceManager *manager) +{ + ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (manager); + + return manager_gdk->device_cache; +} + +static ClutterInputDevice * +clutter_device_manager_gdk_get_device (ClutterDeviceManager *manager, + gint id) +{ + ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (manager); + + return g_hash_table_lookup (manager_gdk->device_by_id, GINT_TO_POINTER (id)); +} + +static ClutterInputDevice * +clutter_device_manager_gdk_get_core_device (ClutterDeviceManager *manager, + ClutterInputDeviceType device_type) +{ + ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (manager); + GdkDevice *gdk_device; + + gdk_device = gdk_device_manager_get_client_pointer (manager_gdk->device_manager); + + g_assert (gdk_device != NULL); + + if (device_type == CLUTTER_KEYBOARD_DEVICE) + gdk_device = gdk_device_get_associated_device (gdk_device); + else if (device_type != CLUTTER_POINTER_DEVICE) + return NULL; + + return _clutter_device_manager_gdk_lookup_device (manager, gdk_device); +} + +static void +gdk_device_added (GdkDeviceManager *gdk_manager, + GdkDevice *device, + ClutterDeviceManager *self) +{ + /* this will do the right thing if the device is not there */ + ClutterInputDevice *clutter_device = _clutter_device_manager_gdk_lookup_device (self, device); + + _clutter_device_manager_add_device (self, clutter_device); +} + +static void +gdk_device_removed (GdkDeviceManager *gdk_manager, + GdkDevice *device, + ClutterDeviceManagerGdk *self) +{ + ClutterInputDevice *clutter_device = g_object_get_data (G_OBJECT (device), "clutter-device"); + + if (clutter_device == NULL) + return; + + self->device_cache = g_slist_remove (self->device_cache, clutter_device); + g_object_unref (clutter_device); + + g_hash_table_remove (self->device_by_id, + GINT_TO_POINTER (clutter_input_device_get_device_id (clutter_device))); + + _clutter_device_manager_remove_device (CLUTTER_DEVICE_MANAGER (self), clutter_device); +} + +static void +gdk_device_foreach_cb (gpointer data, + gpointer user_data) +{ + _clutter_device_manager_gdk_lookup_device (user_data, data); +} + +static void +clutter_device_manager_gdk_constructed (GObject *gobject) +{ + ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (gobject); + GList *all_devices; + + g_assert (manager_gdk->device_manager != NULL); + + all_devices = gdk_device_manager_list_devices (manager_gdk->device_manager, + GDK_DEVICE_TYPE_MASTER); + g_list_foreach (all_devices, gdk_device_foreach_cb, manager_gdk); + g_list_free (all_devices); + + all_devices = gdk_device_manager_list_devices (manager_gdk->device_manager, + GDK_DEVICE_TYPE_SLAVE); + g_list_foreach (all_devices, gdk_device_foreach_cb, manager_gdk); + g_list_free (all_devices); + + all_devices = gdk_device_manager_list_devices (manager_gdk->device_manager, + GDK_DEVICE_TYPE_FLOATING); + g_list_foreach (all_devices, gdk_device_foreach_cb, manager_gdk); + g_list_free (all_devices); + + g_object_connect (manager_gdk->device_manager, + "object-signal::device-added", gdk_device_added, gobject, + "object-signal::device-removed", gdk_device_removed, gobject, + NULL); + + if (G_OBJECT_CLASS (clutter_device_manager_gdk_parent_class)->constructed) + G_OBJECT_CLASS (clutter_device_manager_gdk_parent_class)->constructed (gobject); +} + +static void +clutter_device_manager_gdk_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterDeviceManagerGdk *manager_gdk = CLUTTER_DEVICE_MANAGER_GDK (gobject); + GdkDisplay *gdk_display; + + switch (prop_id) + { + case PROP_GDK_DISPLAY: + gdk_display = GDK_DISPLAY (g_value_get_object (value)); + manager_gdk->device_manager = gdk_display_get_device_manager (gdk_display); + g_object_ref (manager_gdk->device_manager); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_device_manager_gdk_class_init (ClutterDeviceManagerGdkClass *klass) +{ + ClutterDeviceManagerClass *manager_class; + GObjectClass *gobject_class; + GParamSpec *pspec; + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->constructed = clutter_device_manager_gdk_constructed; + gobject_class->set_property = clutter_device_manager_gdk_set_property; + + manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass); + manager_class->add_device = clutter_device_manager_gdk_add_device; + manager_class->remove_device = clutter_device_manager_gdk_remove_device; + manager_class->get_devices = clutter_device_manager_gdk_get_devices; + manager_class->get_core_device = clutter_device_manager_gdk_get_core_device; + manager_class->get_device = clutter_device_manager_gdk_get_device; + + pspec = g_param_spec_object ("gdk-display", + "GdkDisplay", + "The GDK display", + GDK_TYPE_DISPLAY, + CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (gobject_class, PROP_GDK_DISPLAY, pspec); +} + +static void +clutter_device_manager_gdk_init (ClutterDeviceManagerGdk *self) +{ + self->device_by_id = g_hash_table_new_full (NULL, NULL, + NULL, (GDestroyNotify) g_object_unref); +} diff --git a/clutter/gdk/clutter-device-manager-gdk.h b/clutter/gdk/clutter-device-manager-gdk.h new file mode 100644 index 000000000..ade24cd89 --- /dev/null +++ b/clutter/gdk/clutter-device-manager-gdk.h @@ -0,0 +1,63 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_DEVICE_MANAGER_GDK_H__ +#define __CLUTTER_DEVICE_MANAGER_GDK_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DEVICE_MANAGER_GDK (_clutter_device_manager_gdk_get_type ()) +#define CLUTTER_DEVICE_MANAGER_GDK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER_GDK, ClutterDeviceManagerGdk)) +#define CLUTTER_IS_DEVICE_MANAGER_GDK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER_GDK)) +#define CLUTTER_DEVICE_MANAGER_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER_GDK, ClutterDeviceManagerGdkClass)) +#define CLUTTER_IS_DEVICE_MANAGER_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER_GDK)) +#define CLUTTER_DEVICE_MANAGER_GDK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER_GDK, ClutterDeviceManagerGdkClass)) + +typedef struct _ClutterDeviceManagerGdk ClutterDeviceManagerGdk; +typedef struct _ClutterDeviceManagerGdkClass ClutterDeviceManagerGdkClass; + +struct _ClutterDeviceManagerGdk +{ + ClutterDeviceManager parent_instance; + + GdkDeviceManager *device_manager; + GSList *device_cache; + GHashTable *device_by_id; +}; + +struct _ClutterDeviceManagerGdkClass +{ + ClutterDeviceManagerClass parent_class; +}; + +GType _clutter_device_manager_gdk_get_type (void) G_GNUC_CONST; + +ClutterInputDevice * _clutter_device_manager_gdk_lookup_device (ClutterDeviceManager *manager, + GdkDevice *device); + +G_END_DECLS + +#endif /* __CLUTTER_DEVICE_MANAGER_GDK_H__ */ diff --git a/clutter/gdk/clutter-event-gdk.c b/clutter/gdk/clutter-event-gdk.c new file mode 100644 index 000000000..840250968 --- /dev/null +++ b/clutter/gdk/clutter-event-gdk.c @@ -0,0 +1,264 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd + * Copyright (C) 2009, 2010 Intel Corp. + * 2011 Giovanni Campagna + * + * 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 . + * + * + * + * Authored by: + * Matthew Allum + * Emmanuele Bassi + */ + +#include "config.h" + +#include "clutter-gdk.h" +#include "clutter-backend-gdk.h" +#include "clutter-device-manager-gdk.h" + +#include "clutter-debug.h" +#include "clutter-main.h" +#include "clutter-backend-private.h" +#include "clutter-event-private.h" +#include "clutter-stage-private.h" + +#include + +#include + +static void +gdk_event_handler (GdkEvent *event, + gpointer user_data) +{ + clutter_gdk_handle_event (event); +} + +void +_clutter_backend_gdk_events_init (ClutterBackend *backend) +{ + gdk_event_handler_set (gdk_event_handler, NULL, NULL); + + CLUTTER_NOTE (EVENT, "GDK event handler set"); +} + +void +_clutter_backend_gdk_events_uninit (ClutterBackend *backend) +{ + gdk_event_handler_set (NULL, NULL, NULL); +} + +/** + * clutter_gdk_handle_event: + * @event: a #GdkEvent + * + * This function processes a single GDK event; it can be used to hook + * into external event processing + * + * Return value: #GdkFilterReturn. %GDK_FILTER_REMOVE indicates that + * Clutter has internally handled the event and the caller should do + * no further processing. %GDK_FILTER_CONTINUE indicates that Clutter + * is either not interested in the event, or has used the event to + * update internal state without taking any exclusive action. + * %GDK_FILTER_TRANSLATE will not occur. + * + */ +GdkFilterReturn +clutter_gdk_handle_event (GdkEvent *gdk_event) +{ + ClutterDeviceManager *device_manager; + ClutterBackendGdk *backend_gdk; + ClutterStage *stage = NULL; + ClutterEvent *event = NULL; + gint spin = 0; + GdkFilterReturn result = GDK_FILTER_CONTINUE; + + if (gdk_event->any.window == NULL) + return GDK_FILTER_CONTINUE; + + clutter_threads_enter (); + + backend_gdk = CLUTTER_BACKEND_GDK (clutter_get_default_backend ()); + stage = clutter_gdk_get_stage_from_window (gdk_event->any.window); + device_manager = clutter_device_manager_get_default (); + + if (stage == NULL) + goto out; + + switch (gdk_event->type) { + case GDK_DELETE: + event = clutter_event_new (CLUTTER_DELETE); + break; + + case GDK_DESTROY: + event = clutter_event_new (CLUTTER_DESTROY_NOTIFY); + break; + + case GDK_EXPOSE: + clutter_redraw (stage); + break; + + case GDK_DAMAGE: + /* This is handled by cogl */ + goto out; + + case GDK_MOTION_NOTIFY: + event = clutter_event_new (CLUTTER_MOTION); + event->motion.time = gdk_event->motion.time; + event->motion.x = gdk_event->motion.x; + event->motion.y = gdk_event->motion.y; + event->motion.axes = NULL; + /* It's all X in the end, right? */ + event->motion.modifier_state = gdk_event->motion.state; + event->motion.device = _clutter_device_manager_gdk_lookup_device (device_manager, + gdk_event->motion.device); + break; + + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + event = clutter_event_new (gdk_event->type == GDK_BUTTON_PRESS ? + CLUTTER_BUTTON_PRESS : + CLUTTER_BUTTON_RELEASE); + event->button.time = gdk_event->button.time; + event->button.x = gdk_event->button.x; + event->button.y = gdk_event->button.y; + event->button.axes = NULL; + event->button.modifier_state = gdk_event->button.state; + event->button.button = gdk_event->button.button; + event->button.click_count = 1; + event->button.device = _clutter_device_manager_gdk_lookup_device (device_manager, + gdk_event->button.device); + break; + + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + /* these are handled by clutter-main.c updating click_count */ + goto out; + + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: + event = clutter_event_new (gdk_event->type == GDK_KEY_PRESS ? + CLUTTER_KEY_PRESS : + CLUTTER_KEY_RELEASE); + event->key.time = gdk_event->key.time; + event->key.modifier_state = gdk_event->key.state; + event->key.keyval = gdk_event->key.keyval; + event->key.hardware_keycode = gdk_event->key.hardware_keycode; + event->key.unicode_value = g_utf8_get_char (gdk_event->key.string); + break; + + case GDK_ENTER_NOTIFY: + case GDK_LEAVE_NOTIFY: + event = clutter_event_new (gdk_event->type == GDK_ENTER_NOTIFY ? + CLUTTER_ENTER : + CLUTTER_LEAVE); + event->crossing.source = CLUTTER_ACTOR (stage); + event->crossing.time = gdk_event->crossing.time; + event->crossing.x = gdk_event->crossing.x; + event->crossing.y = gdk_event->crossing.y; + + /* XXX: no better fallback here? */ + event->crossing.device = clutter_device_manager_get_core_device (device_manager, + CLUTTER_POINTER_DEVICE); + + if (gdk_event->type == GDK_ENTER_NOTIFY) + _clutter_stage_add_device (stage, event->crossing.device); + else + _clutter_stage_remove_device (stage, event->crossing.device); + break; + + case GDK_FOCUS_CHANGE: + event = clutter_event_new (CLUTTER_STAGE_STATE); + event->stage_state.time = 0; /* XXX: there is no timestamp in this GdkEvent */ + event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED; + event->stage_state.new_state = gdk_event->focus_change.in ? CLUTTER_STAGE_STATE_ACTIVATED : 0; + break; + + case GDK_CONFIGURE: + clutter_actor_set_size (CLUTTER_ACTOR (stage), + gdk_event->configure.width, + gdk_event->configure.height); + break; + + case GDK_SCROLL: + event = clutter_event_new (CLUTTER_SCROLL); + event->scroll.time = gdk_event->scroll.time; + event->scroll.x = gdk_event->scroll.x; + event->scroll.y = gdk_event->scroll.y; + event->scroll.modifier_state = gdk_event->scroll.state; + event->scroll.axes = NULL; + event->scroll.direction = gdk_event->scroll.direction; + event->scroll.device = _clutter_device_manager_gdk_lookup_device (device_manager, + gdk_event->scroll.device); + + case GDK_WINDOW_STATE: + event = clutter_event_new (CLUTTER_STAGE_STATE); + event->stage_state.changed_mask = 0; + event->stage_state.new_state = 0; + if (gdk_event->window_state.changed_mask & GDK_WINDOW_STATE_WITHDRAWN) + { + event->stage_state.changed_mask |= CLUTTER_STAGE_STATE_OFFSCREEN; + event->stage_state.new_state |= (gdk_event->window_state.new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ? + CLUTTER_STAGE_STATE_OFFSCREEN : 0; + } + if (gdk_event->window_state.changed_mask & GDK_WINDOW_STATE_FULLSCREEN) + { + event->stage_state.changed_mask |= CLUTTER_STAGE_STATE_FULLSCREEN; + event->stage_state.new_state |= (gdk_event->window_state.new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ? + CLUTTER_STAGE_STATE_FULLSCREEN : 0; + } + break; + + case GDK_SETTING: + _clutter_backend_gdk_update_setting (backend_gdk, gdk_event->setting.name); + break; + + default: + break; + } + + if (event != NULL) + { + event->any.stage = stage; + if (gdk_event->any.send_event) + event->any.flags = CLUTTER_EVENT_FLAG_SYNTHETIC; + + _clutter_event_push (event, FALSE); + spin = 1; + + CLUTTER_NOTE (EVENT, "Translated one event from Gdk"); + + /* handle also synthetic enter/leave events */ + if (event->type == CLUTTER_MOTION) + spin += 2; + + while (spin > 0 && (event = clutter_event_get ())) + { + /* forward the event into clutter for emission etc. */ + clutter_do_event (event); + clutter_event_free (event); + --spin; + } + + result = GDK_FILTER_REMOVE; + } + + out: + + clutter_threads_leave (); + return result; +} diff --git a/clutter/gdk/clutter-gdk.h b/clutter/gdk/clutter-gdk.h new file mode 100644 index 000000000..6aa825bba --- /dev/null +++ b/clutter/gdk/clutter-gdk.h @@ -0,0 +1,55 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * 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 . + * + * + */ + +/** + * SECTION:clutter-gdk + * @short_description: GDK specific API + * + * The GDK backend for Clutter provides some specific API, allowing + * integration with the GDK API for manipulating the stage window and + * handling events outside of Clutter. + */ + +#ifndef __CLUTTER_GDK_H__ +#define __CLUTTER_GDK_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +void clutter_gdk_set_display (GdkDisplay *display); +GdkWindow *clutter_gdk_get_stage_window (ClutterStage *stage); +gboolean clutter_gdk_set_stage_foreign (ClutterStage *stage, + GdkWindow *window); + +GdkFilterReturn clutter_gdk_handle_event (GdkEvent *event); + +ClutterStage *clutter_gdk_get_stage_from_window (GdkWindow *window); + +G_END_DECLS + +#endif /* __CLUTTER_GDK_H__ */ diff --git a/clutter/gdk/clutter-input-device-gdk.c b/clutter/gdk/clutter-input-device-gdk.c new file mode 100644 index 000000000..9d37dbc40 --- /dev/null +++ b/clutter/gdk/clutter-input-device-gdk.c @@ -0,0 +1,160 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2011 Intel Corp. + * 2011 Giovanni Campagna + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#include "config.h" + +#include "clutter-input-device-gdk.h" + +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" + +#include "clutter-backend-gdk.h" +#include "clutter-stage-gdk.h" + +typedef struct _ClutterInputDeviceClass ClutterInputDeviceGdkClass; + +#define clutter_input_device_gdk_get_type _clutter_input_device_gdk_get_type + +G_DEFINE_TYPE (ClutterInputDeviceGdk, + clutter_input_device_gdk, + CLUTTER_TYPE_INPUT_DEVICE); + +static int device_int_counter; + +enum { + PROP_0, + PROP_GDK_DEVICE, + PROP_LAST +}; + +static void +clutter_input_device_gdk_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterInputDeviceGdk *self = CLUTTER_INPUT_DEVICE_GDK (gobject); + + switch (prop_id) + { + case PROP_GDK_DEVICE: + self->gdk_device = GDK_DEVICE (g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_input_device_gdk_class_init (ClutterInputDeviceGdkClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = clutter_input_device_gdk_set_property; + + g_object_class_install_property (gobject_class, PROP_GDK_DEVICE, + g_param_spec_object ("gdk-device", + "GdkDevice", + "The GDK device", + GDK_TYPE_DEVICE, + CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +clutter_input_device_gdk_init (ClutterInputDeviceGdk *self) +{ +} + +ClutterInputDevice* +_clutter_input_device_gdk_new (ClutterDeviceManager *manager, + GdkDevice *device) +{ + ClutterBackend *backend; + ClutterInputDevice *clutter_device; + ClutterInputMode input_mode = CLUTTER_INPUT_MODE_FLOATING; + ClutterInputDeviceType device_type = CLUTTER_EXTENSION_DEVICE; + gboolean has_cursor = FALSE; + const gchar *name; + gboolean is_enabled = FALSE; + + g_object_get (manager, "backend", &backend, NULL); + + /* yay for name consistency */ + switch (gdk_device_get_device_type (device)) + { + case GDK_DEVICE_TYPE_MASTER: + input_mode = CLUTTER_INPUT_MODE_MASTER; + is_enabled = TRUE; + break; + case GDK_DEVICE_TYPE_SLAVE: + input_mode = CLUTTER_INPUT_MODE_SLAVE; + is_enabled = FALSE; + break; + case GDK_DEVICE_TYPE_FLOATING: + input_mode = CLUTTER_INPUT_MODE_FLOATING; + is_enabled = FALSE; + break; + } + + switch (gdk_device_get_source (device)) + { + case GDK_SOURCE_MOUSE: + device_type = CLUTTER_POINTER_DEVICE; + break; + case GDK_SOURCE_PEN: + device_type = CLUTTER_PEN_DEVICE; + break; + case GDK_SOURCE_ERASER: + device_type = CLUTTER_ERASER_DEVICE; + break; + case GDK_SOURCE_CURSOR: + device_type = CLUTTER_CURSOR_DEVICE; + break; + case GDK_SOURCE_KEYBOARD: + device_type = CLUTTER_KEYBOARD_DEVICE; + break; + } + + if (device_type != CLUTTER_KEYBOARD_DEVICE) + /* why Gdk asserts if passed a GDK_SOURCE_KEYBOARD device? */ + has_cursor = gdk_device_get_has_cursor (device); + name = gdk_device_get_name (device); + + clutter_device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_GDK, + "backend", backend, + "device-manager", manager, + "device-mode", input_mode, + "device-type", device_type, + "has-cursor", has_cursor, + "gdk-device", device, + "id", device_int_counter++, + "name", name, + "enabled", is_enabled, + NULL); + return clutter_device; +} diff --git a/clutter/gdk/clutter-input-device-gdk.h b/clutter/gdk/clutter-input-device-gdk.h new file mode 100644 index 000000000..bcc57183a --- /dev/null +++ b/clutter/gdk/clutter-input-device-gdk.h @@ -0,0 +1,55 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2011 Intel Corp. + * + * 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 . + * + * Author: Emmanuele Bassi + */ + +#ifndef __CLUTTER_INPUT_DEVICE_GDK_H__ +#define __CLUTTER_INPUT_DEVICE_GDK_H__ + +#include +#include + +#include "clutter-backend.h" +#include "clutter-device-manager-private.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_INPUT_DEVICE_GDK (_clutter_input_device_gdk_get_type ()) +#define CLUTTER_INPUT_DEVICE_GDK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_GDK, ClutterInputDeviceGdk)) +#define CLUTTER_IS_INPUT_DEVICE_GDK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_GDK)) + +typedef struct _ClutterInputDeviceGdk ClutterInputDeviceGdk; + +struct _ClutterInputDeviceGdk +{ + ClutterInputDevice parent; + + GdkDevice *gdk_device; +}; + +GType _clutter_input_device_gdk_get_type (void) G_GNUC_CONST; + +ClutterInputDevice * _clutter_input_device_gdk_new (ClutterDeviceManager *manager, + GdkDevice *device); + +G_END_DECLS + +#endif /* __CLUTTER_INPUT_DEVICE_GDK_H__ */ diff --git a/clutter/gdk/clutter-settings-gdk.h b/clutter/gdk/clutter-settings-gdk.h new file mode 100644 index 000000000..c2b576e01 --- /dev/null +++ b/clutter/gdk/clutter-settings-gdk.h @@ -0,0 +1,28 @@ +#ifndef __CLUTTER_SETTINGS_GDK_H__ +#define __CLUTTER_SETTINGS_GDK_H__ + +/* XSETTINGS key names to ClutterSettings properties */ +static const struct { + const char *gdk_setting_name; + const char *settings_property; + GType type; +} _clutter_settings_map[] = { + { "gtk-double-click-time", "double-click-time", G_TYPE_INT }, + { "gtk-double-click-distance", "double-click-distance", G_TYPE_INT }, + { "gtk-dnd-drag-threshold", "dnd-drag-threshold", G_TYPE_INT }, + { "gtk-font-name", "font-name", G_TYPE_STRING }, + { "gtk-xft-antialias", "font-antialias", G_TYPE_INT }, + { "gtk-xft-dpi", "font-dpi", G_TYPE_INT }, + { "gtk-xft-hinting", "font-hinting", G_TYPE_INT }, + { "gtk-xft-hintstyle", "font-hint-style", G_TYPE_STRING }, + { "gtk-xft-rgba", "font-subpixel-order", G_TYPE_STRING }, + { "gtk-fontconfig-timestamp", "fontconfig-timestamp", G_TYPE_UINT }, +}; + +static const gint _n_clutter_settings_map = G_N_ELEMENTS (_clutter_settings_map); + +#define CLUTTER_SETTING_TYPE(id) (_clutter_settings_map[(id)].type) +#define CLUTTER_SETTING_GDK_NAME(id) (_clutter_settings_map[(id)].gdk_setting_name) +#define CLUTTER_SETTING_PROPERTY(id) (_clutter_settings_map[(id)].settings_property) + +#endif /* __CLUTTER_SETTINGS_GDK_H__ */ diff --git a/clutter/gdk/clutter-stage-gdk.c b/clutter/gdk/clutter-stage-gdk.c new file mode 100644 index 000000000..600da646e --- /dev/null +++ b/clutter/gdk/clutter-stage-gdk.c @@ -0,0 +1,601 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * 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 . + * + * + */ + +#include "config.h" + +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "clutter-backend-gdk.h" +#include "clutter-stage-gdk.h" +#include "clutter-gdk.h" + +#include "clutter-actor-private.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-enum-types.h" +#include "clutter-event-translator.h" +#include "clutter-event-private.h" +#include "clutter-feature.h" +#include "clutter-main.h" +#include "clutter-paint-volume-private.h" +#include "clutter-private.h" +#include "clutter-stage-private.h" + +#include "cogl/cogl.h" + +static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); + +#define clutter_stage_gdk_get_type _clutter_stage_gdk_get_type + +G_DEFINE_TYPE_WITH_CODE (ClutterStageGdk, + clutter_stage_gdk, + G_TYPE_OBJECT, + 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) +{ + ClutterStageGdk *stage_gdk = user_data; + + /* we assume that a GDK event mask is bitwise compatible with X11 + event masks */ + gdk_window_set_events (stage_gdk->window, event_mask | CLUTTER_STAGE_GDK_EVENT_MASK); +} + + +static void +clutter_stage_gdk_set_gdk_geometry (ClutterStageGdk *stage) +{ + GdkGeometry geometry; + gboolean resize = clutter_stage_get_user_resizable (stage->wrapper); + + if (!resize) + { + geometry.min_width = geometry.max_width = gdk_window_get_width (stage->window); + geometry.min_height = geometry.max_height = gdk_window_get_height (stage->window); + + gdk_window_set_geometry_hints (stage->window, + &geometry, + GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE); + } + else + { + clutter_stage_get_minimum_size (stage->wrapper, + (guint *)&geometry.min_width, + (guint *)&geometry.min_height); + + gdk_window_set_geometry_hints (stage->window, + &geometry, + GDK_HINT_MIN_SIZE); + } +} + +static void +clutter_stage_gdk_get_geometry (ClutterStageWindow *stage_window, + ClutterGeometry *geometry) +{ + ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); + + if (stage_gdk->window) + { + geometry->width = gdk_window_get_width (stage_gdk->window); + geometry->height = gdk_window_get_height (stage_gdk->window); + } + else + { + geometry->width = 640; + geometry->height = 480; + } +} + +static void +clutter_stage_gdk_resize (ClutterStageWindow *stage_window, + gint width, + gint height) +{ + ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); + + if (width == 0 || height == 0) + { + /* Should not happen, if this turns up we need to debug it and + * determine the cleanest way to fix. + */ + g_warning ("GDK stage not allowed to have 0 width or height"); + width = 1; + height = 1; + } + + CLUTTER_NOTE (BACKEND, "New size received: (%d, %d)", width, height); + + CLUTTER_SET_PRIVATE_FLAGS (stage_gdk->wrapper, + CLUTTER_IN_RESIZE); + + gdk_window_resize (stage_gdk->window, width, height); +} + +static void +clutter_stage_gdk_unrealize (ClutterStageWindow *stage_window) +{ + ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); + + if (stage_gdk->window) + { + 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); + stage_gdk->window = NULL; + } +} + +static gboolean +clutter_stage_gdk_realize (ClutterStageWindow *stage_window) +{ + ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); + ClutterBackendGdk *backend_gdk = stage_gdk->backend; + GdkWindowAttr attributes; + gboolean cursor_visible; + gboolean use_alpha; + gfloat width, height; + + if (stage_gdk->foreign_window && + stage_gdk->window) + { + /* complete realizing the stage */ + ClutterGeometry geometry; + + clutter_stage_gdk_get_geometry (stage_window, &geometry); + clutter_actor_set_geometry (CLUTTER_ACTOR (stage_gdk->wrapper), &geometry); + + gdk_window_ensure_native (stage_gdk->window); + gdk_window_set_events (stage_gdk->window, + CLUTTER_STAGE_GDK_EVENT_MASK); + + return TRUE; + } + + attributes.title = NULL; + g_object_get (stage_gdk->wrapper, + "cursor-visible", &cursor_visible, + "title", &attributes.title, + "width", &width, + "height", &height, + "use-alpha", &use_alpha, + NULL); + + attributes.width = width; + attributes.height = height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_TOPLEVEL; + attributes.event_mask = CLUTTER_STAGE_GDK_EVENT_MASK; + + attributes.cursor = NULL; + if (!cursor_visible) + { + if (stage_gdk->blank_cursor == NULL) + stage_gdk->blank_cursor = gdk_cursor_new (GDK_BLANK_CURSOR); + + attributes.cursor = stage_gdk->blank_cursor; + } + + 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); + } + else + { + /* This could still be an RGBA visual, although normally it's not */ + attributes.visual = gdk_screen_get_system_visual (backend_gdk->screen); + } + + 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); + } + + stage_gdk->foreign_window = FALSE; + stage_gdk->window = gdk_window_new (NULL, &attributes, + GDK_WA_TITLE | GDK_WA_CURSOR | GDK_WA_VISUAL); + gdk_window_ensure_native (stage_gdk->window); + + clutter_stage_gdk_set_gdk_geometry (stage_gdk); + + g_object_set_data (G_OBJECT (stage_gdk->window), + "clutter-stage-window", stage_gdk); + + g_free (attributes.title); + + CLUTTER_NOTE (BACKEND, "Successfully realized stage"); + + return TRUE; +} + +static void +clutter_stage_gdk_set_fullscreen (ClutterStageWindow *stage_window, + gboolean is_fullscreen) +{ + ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); + ClutterStage *stage = stage_gdk->wrapper; + + if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage)) + return; + + if (stage_gdk->window == NULL) + return; + + CLUTTER_NOTE (BACKEND, "%ssetting fullscreen", is_fullscreen ? "" : "un"); + + if (is_fullscreen) + gdk_window_fullscreen (stage_gdk->window); + else + gdk_window_unfullscreen (stage_gdk->window); +} + +static void +clutter_stage_gdk_set_cursor_visible (ClutterStageWindow *stage_window, + gboolean cursor_visible) +{ + ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); + + if (stage_gdk->window == NULL) + return; + + if (cursor_visible) + { + gdk_window_set_cursor (stage_gdk->window, NULL); + } + else + { + if (stage_gdk->blank_cursor == NULL) + stage_gdk->blank_cursor = gdk_cursor_new (GDK_BLANK_CURSOR); + + gdk_window_set_cursor (stage_gdk->window, stage_gdk->blank_cursor); + } +} + +static void +clutter_stage_gdk_set_title (ClutterStageWindow *stage_window, + const gchar *title) +{ + ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); + + if (stage_gdk->window == NULL) + return; + + gdk_window_set_title (stage_gdk->window, title); +} + +static void +clutter_stage_gdk_set_user_resizable (ClutterStageWindow *stage_window, + gboolean is_resizable) +{ + ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); + GdkWMFunction function; + + if (stage_gdk->window == NULL) + return; + + function = GDK_FUNC_MOVE | GDK_FUNC_MINIMIZE | GDK_FUNC_CLOSE; + if (is_resizable) + function |= GDK_FUNC_RESIZE | GDK_FUNC_MAXIMIZE; + + gdk_window_set_functions (stage_gdk->window, function); + + clutter_stage_gdk_set_gdk_geometry (stage_gdk); +} + +static void +clutter_stage_gdk_set_accept_focus (ClutterStageWindow *stage_window, + gboolean accept_focus) +{ + ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); + + if (stage_gdk->window == NULL) + return; + + gdk_window_set_accept_focus (stage_gdk->window, accept_focus); +} + +static void +clutter_stage_gdk_show (ClutterStageWindow *stage_window, + gboolean do_raise) +{ + ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); + + g_return_if_fail (stage_gdk->window != NULL); + + clutter_actor_map (CLUTTER_ACTOR (stage_gdk->wrapper)); + + if (do_raise) + gdk_window_show (stage_gdk->window); + else + gdk_window_show_unraised (stage_gdk->window); +} + +static void +clutter_stage_gdk_hide (ClutterStageWindow *stage_window) +{ + ClutterStageGdk *stage_gdk = CLUTTER_STAGE_GDK (stage_window); + + g_return_if_fail (stage_gdk->window != NULL); + + clutter_actor_unmap (CLUTTER_ACTOR (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) + { + 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); + stage_gdk->window = NULL; + } + + if (stage_gdk->blank_cursor) + { + g_object_unref (stage_gdk->blank_cursor); + stage_gdk->blank_cursor = NULL; + } + + 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 +clutter_stage_gdk_init (ClutterStageGdk *stage) +{ + /* nothing to do here */ +} + +static void +clutter_stage_window_iface_init (ClutterStageWindowIface *iface) +{ + iface->get_wrapper = clutter_stage_gdk_get_wrapper; + 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; + iface->set_user_resizable = clutter_stage_gdk_set_user_resizable; + iface->set_accept_focus = clutter_stage_gdk_set_accept_focus; + iface->show = clutter_stage_gdk_show; + iface->hide = clutter_stage_gdk_hide; + iface->resize = clutter_stage_gdk_resize; + iface->get_geometry = clutter_stage_gdk_get_geometry; + iface->realize = clutter_stage_gdk_realize; + iface->unrealize = clutter_stage_gdk_unrealize; +} + +/** + * clutter_gdk_get_stage_window: + * @stage: a #ClutterStage + * + * Gets the stages GdkWindow. + * + * Return value: (transfer none): A GdkWindow* for the stage window. + * + * Since: 0.4 + */ +GdkWindow* +clutter_gdk_get_stage_window (ClutterStage *stage) +{ + ClutterStageWindow *impl; + + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), None); + + impl = _clutter_stage_get_window (stage); + g_assert (CLUTTER_IS_STAGE_GDK (impl)); + + return CLUTTER_STAGE_GDK (impl)->window; +} + +/** + * clutter_gdk_get_stage_from_window: + * @window: a #GtkWindow + * + * Gets the stage for a particular X window. + * + * Return value: (transfer none): A #ClutterStage, or% NULL if a stage + * does not exist for the window + * + * Since: 0.8 + */ +ClutterStage * +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 NULL; +} + +typedef struct +{ + ClutterStageGdk *stage_gdk; + GdkWindow *window; +} ForeignWindowClosure; + +static void +set_foreign_window_callback (ClutterActor *actor, + void *data) +{ + ForeignWindowClosure *closure = data; + ClutterStageGdk *stage_gdk = closure->stage_gdk; + + stage_gdk->window = closure->window; + stage_gdk->foreign_window = TRUE; + + /* calling this with the stage unrealized will unset the stage + * from the GL context; once the stage is realized the GL context + * will be set again + */ + clutter_stage_ensure_current (CLUTTER_STAGE (actor)); +} + +/** + * clutter_gdk_set_stage_foreign: + * @stage: a #ClutterStage + * @window: an existing #GdkWindow + * + * Target the #ClutterStage to use an existing external #GdkWindow + * + * Return value: %TRUE if foreign window is valid + * + * Since: 0.4 + */ +gboolean +clutter_gdk_set_stage_foreign (ClutterStage *stage, + GdkWindow *window) +{ + ForeignWindowClosure closure; + ClutterStageGdk *stage_gdk; + ClutterStageWindow *impl; + ClutterActor *actor; + gpointer gtk_data = NULL; + + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + g_return_val_if_fail (!CLUTTER_ACTOR_IN_DESTRUCTION (stage), FALSE); + g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE); + + impl = _clutter_stage_get_window (stage); + stage_gdk = CLUTTER_STAGE_GDK (impl); + + if (g_object_get_data (G_OBJECT (window), "clutter-stage-window") != NULL) + { + g_critical ("The provided GdkWindow is already in use by another ClutterStage"); + return FALSE; + } + + gdk_window_get_user_data (window, >k_data); + if (gtk_data != NULL) + { + g_critical ("The provided GdkWindow is already in use by a GtkWidget. " + "Use a child GdkWindow for embedding instead"); + return FALSE; + } + + closure.stage_gdk = stage_gdk; + closure.window = g_object_ref (window); + + actor = CLUTTER_ACTOR (stage); + + _clutter_actor_rerealize (actor, + set_foreign_window_callback, + &closure); + + /* Queue a relayout - so the stage will be allocated the new + * window size. + * + * Note also that when the stage gets allocated the new + * window size that will result in the stage's + * priv->viewport being changed, which will in turn result + * in the Cogl viewport changing when _clutter_do_redraw + * calls _clutter_stage_maybe_setup_viewport(). + */ + clutter_actor_queue_relayout (actor); + + return TRUE; +} diff --git a/clutter/gdk/clutter-stage-gdk.h b/clutter/gdk/clutter-stage-gdk.h new file mode 100644 index 000000000..38cf39980 --- /dev/null +++ b/clutter/gdk/clutter-stage-gdk.h @@ -0,0 +1,84 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * 2011 Giovanni Campagna + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __CLUTTER_STAGE_GDK_H__ +#define __CLUTTER_STAGE_GDK_H__ + +#include +#include +#include + +#include "clutter-backend-gdk.h" + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_STAGE_GDK (_clutter_stage_gdk_get_type ()) +#define CLUTTER_STAGE_GDK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_GDK, ClutterStageGdk)) +#define CLUTTER_IS_STAGE_GDK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_GDK)) +#define CLUTTER_STAGE_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_GDK, ClutterStageGdkClass)) +#define CLUTTER_IS_STAGE_GDK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_GDK)) +#define CLUTTER_STAGE_GDK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_GDK, ClutterStageGdkClass)) + +typedef struct _ClutterStageGdk ClutterStageGdk; +typedef struct _ClutterStageGdkClass ClutterStageGdkClass; + +struct _ClutterStageGdk +{ + GObject parent_instance; + + GdkWindow *window; + GdkCursor *blank_cursor; + + /* backpointers */ + ClutterStage *wrapper; + ClutterBackendGdk *backend; + + gboolean foreign_window; +}; + +struct _ClutterStageGdkClass +{ + GObjectClass parent_class; +}; + +#define CLUTTER_STAGE_GDK_EVENT_MASK \ + (GDK_STRUCTURE_MASK | \ + GDK_FOCUS_CHANGE_MASK | \ + GDK_EXPOSURE_MASK | \ + GDK_PROPERTY_CHANGE_MASK | \ + GDK_ENTER_NOTIFY_MASK | \ + GDK_LEAVE_NOTIFY_MASK | \ + GDK_KEY_PRESS_MASK | \ + GDK_KEY_RELEASE_MASK | \ + GDK_BUTTON_PRESS_MASK | \ + GDK_BUTTON_RELEASE_MASK | \ + GDK_POINTER_MOTION_MASK) + +GType _clutter_stage_gdk_get_type (void) G_GNUC_CONST; + +void _clutter_stage_gdk_update_foreign_event_mask (CoglOnscreen *onscreen, + guint32 event_mask, + void *user_data); + +G_END_DECLS + +#endif /* __CLUTTER_STAGE_H__ */ diff --git a/configure.ac b/configure.ac index 966626bbd..bf12228a8 100644 --- a/configure.ac +++ b/configure.ac @@ -226,6 +226,23 @@ AS_CASE([$CLUTTER_FLAVOUR], []) ], + [gdk], + [ + CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_COGL" + + # 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_SONAME_INFIX=gdk + + BACKEND_PC_FILES="$BACKEND_PC_FILES gdk-3.0" + PKG_CHECK_EXISTS([gl], [BACKEND_PC_FILES="$BACKEND_PC_FILES gl"], []) + ], + [opengl-egl-xlib], [ CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGL" @@ -419,6 +436,7 @@ AS_IF([test "x$CLUTTER_EGL_BACKEND" = "xcex100"], AM_CONDITIONAL(SUPPORT_GLX, [test "x$SUPPORT_GLX" = "x1"]) AM_CONDITIONAL(SUPPORT_X11, [test "x$SUPPORT_X11" = "x1"]) AM_CONDITIONAL(SUPPORT_XLIB, [test "x$SUPPORT_XLIB" = "x1"]) +AM_CONDITIONAL(SUPPORT_GDK, [test "x$SUPPORT_GDK" = "x1"]) AM_CONDITIONAL(SUPPORT_EGL, [test "x$SUPPORT_EGL" = "x1"]) AM_CONDITIONAL(SUPPORT_OSX, [test "x$CLUTTER_WINSYS" = "xosx"]) AM_CONDITIONAL(SUPPORT_WIN32, [test "x$CLUTTER_WINSYS" = "xwin32"]) @@ -446,6 +464,9 @@ CLUTTER_CONFIG_DEFINES= AS_IF([test "x$SUPPORT_XLIB" = "x1"], [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES #define CLUTTER_WINDOWING_X11 1"]) +AS_IF([test "x$SUPPORT_GDK" = "x1"], + [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_WINDOWING_GDK 1"]) AS_IF([test "x$SUPPORT_GLX" = "x1"], [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES #define CLUTTER_WINDOWING_GLX 1"]) diff --git a/tests/conform/test-cogl-texture-pixmap-x11.c b/tests/conform/test-cogl-texture-pixmap-x11.c index abdef1298..36f86d458 100644 --- a/tests/conform/test-cogl-texture-pixmap-x11.c +++ b/tests/conform/test-cogl-texture-pixmap-x11.c @@ -4,7 +4,7 @@ static const ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xff }; -#ifdef COGL_HAS_XLIB +#ifdef CLUTTER_WINDOWING_X11 #include #include @@ -195,13 +195,13 @@ queue_redraw (gpointer stage) return TRUE; } -#endif /* COGL_HAS_XLIB */ +#endif /* CLUTTER_WINDOWING_X11 */ void test_cogl_texture_pixmap_x11 (TestConformSimpleFixture *fixture, gconstpointer data) { -#ifdef COGL_HAS_XLIB +#ifdef CLUTTER_WINDOWING_X11 TestState state; guint idle_handler; @@ -235,11 +235,11 @@ test_cogl_texture_pixmap_x11 (TestConformSimpleFixture *fixture, if (g_test_verbose ()) g_print ("OK\n"); -#else /* COGL_HAS_XLIB */ +#else /* CLUTTER_WINDOWING_X11 */ if (g_test_verbose ()) g_print ("Skipping\n"); -#endif /* COGL_HAS_XLIB */ +#endif /* CLUTTER_WINDOWING_X11 */ } diff --git a/tests/conform/test-conform-common.c b/tests/conform/test-conform-common.c index 484c010bb..e7cd42bc4 100644 --- a/tests/conform/test-conform-common.c +++ b/tests/conform/test-conform-common.c @@ -3,7 +3,7 @@ #include #include -#ifdef COGL_HAS_XLIB +#ifdef CLUTTER_WINDOWING_X11 #include #include #endif @@ -48,7 +48,7 @@ test_conform_simple_fixture_setup (TestConformSimpleFixture *fixture, g_assert (clutter_init (shared_state->argc_addr, shared_state->argv_addr) == CLUTTER_INIT_SUCCESS); -#ifdef COGL_HAS_XLIB +#ifdef CLUTTER_WINDOWING_X11 /* A lot of the tests depend on a specific stage / framebuffer size * when they read pixels back to verify the results of the test. *