[clutter/multi-backend: 1/22] Add a new GDK backend



commit 18269e48172d4bb63bde0e78eb6e462158f2512a
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Fri Aug 26 03:09:18 2011 +0200

    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(-)
---
diff --git a/clutter/Makefile.am b/clutter/Makefile.am
index 461e7d1..ce0fb69 100644
--- a/clutter/Makefile.am
+++ b/clutter/Makefile.am
@@ -413,6 +413,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 1ca8850..134ae94 100644
--- a/clutter/cogl/clutter-backend-cogl.c
+++ b/clutter/cogl/clutter-backend-cogl.c
@@ -36,6 +36,17 @@
 
 #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"
 
@@ -65,8 +76,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
@@ -92,7 +105,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);
 
@@ -114,7 +127,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);
 
@@ -129,7 +142,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)
 {
@@ -147,7 +160,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)
@@ -159,8 +172,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
@@ -234,15 +247,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))
@@ -279,7 +292,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)
 {
@@ -291,8 +304,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;
@@ -301,17 +316,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
@@ -374,7 +406,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;
@@ -395,7 +427,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;
@@ -418,9 +457,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
@@ -444,7 +482,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
 
@@ -455,7 +493,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;
@@ -463,7 +501,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 c1563d3..6806559 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 0acec4b..9e9c0fd 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 <gdk/gdk.h>
+
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#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 73bfb06..ade2322 100644
--- a/clutter/cogl/clutter-stage-cogl.h
+++ b/clutter/cogl/clutter-stage-cogl.h
@@ -13,8 +13,14 @@
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
 #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"
 
@@ -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 0000000..18c53fa
--- /dev/null
+++ b/clutter/gdk/clutter-backend-gdk-private.h
@@ -0,0 +1,32 @@
+/* An OpenGL based 'interactive canvas' library.
+ * Authored By Matthew Allum  <mallum openedhand com>
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#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 0000000..9286d85
--- /dev/null
+++ b/clutter/gdk/clutter-backend-gdk.c
@@ -0,0 +1,368 @@
+/* Clutter.
+ * An OpenGL based 'interactive canvas' library.
+ * Authored By Matthew Allum  <mallum openedhand com>
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n-lib.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <gdk/gdk.h>
+#include <cogl/cogl.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#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 0000000..effa642
--- /dev/null
+++ b/clutter/gdk/clutter-backend-gdk.h
@@ -0,0 +1,72 @@
+/* Clutter.
+ * An OpenGL based 'interactive canvas' library.
+ * Authored By Matthew Allum  <mallum openedhand com>
+ * Copyright (C) 2006-2007 OpenedHand
+ *               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/>.
+ *
+ *
+ */
+
+#ifndef __CLUTTER_BACKEND_GDK_H__
+#define __CLUTTER_BACKEND_GDK_H__
+
+#include <glib-object.h>
+#include <clutter/clutter-event.h>
+#include <gdk/gdk.h>
+
+#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 0000000..5175bba
--- /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 <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/>.
+ *
+ * Author: Emmanuele Bassi <ebassi linux intel com>
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+
+#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 0000000..ade24cd
--- /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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Emmanuele Bassi <ebassi linux intel com>
+ */
+
+#ifndef __CLUTTER_DEVICE_MANAGER_GDK_H__
+#define __CLUTTER_DEVICE_MANAGER_GDK_H__
+
+#include <clutter/clutter-device-manager.h>
+#include <gdk/gdk.h>
+
+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 0000000..8402509
--- /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 <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/>.
+ *
+ *
+ *
+ * Authored by:
+ *      Matthew Allum <mallum openedhand com>
+ *      Emmanuele Bassi <ebassi linux intel com>
+ */
+
+#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 <string.h>
+
+#include <glib.h>
+
+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 0000000..6aa825b
--- /dev/null
+++ b/clutter/gdk/clutter-gdk.h
@@ -0,0 +1,55 @@
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Authored By Matthew Allum  <mallum openedhand com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+/**
+ * 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 <glib.h>
+#include <gdk/gdk.h>
+#include <clutter/clutter.h>
+
+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 0000000..9d37dbc
--- /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 <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/>.
+ *
+ * Author: Emmanuele Bassi <ebassi linux intel com>
+ */
+
+#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 0000000..bcc5718
--- /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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Emmanuele Bassi <ebassi linux intel com>
+ */
+
+#ifndef __CLUTTER_INPUT_DEVICE_GDK_H__
+#define __CLUTTER_INPUT_DEVICE_GDK_H__
+
+#include <clutter/clutter-input-device.h>
+#include <gdk/gdk.h>
+
+#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 0000000..c2b576e
--- /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 0000000..600da64
--- /dev/null
+++ b/clutter/gdk/clutter-stage-gdk.c
@@ -0,0 +1,601 @@
+/* Clutter.
+ * An OpenGL based 'interactive canvas' library.
+ * Authored By Matthew Allum  <mallum openedhand com>
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#include "config.h"
+
+#include <math.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#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, &gtk_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 0000000..38cf399
--- /dev/null
+++ b/clutter/gdk/clutter-stage-gdk.h
@@ -0,0 +1,84 @@
+/* Clutter.
+ * An OpenGL based 'interactive canvas' library.
+ * Authored By Matthew Allum  <mallum openedhand com>
+ * Copyright (C) 2006-2007 OpenedHand
+ *               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/>.
+ *
+ *
+ */
+
+#ifndef __CLUTTER_STAGE_GDK_H__
+#define __CLUTTER_STAGE_GDK_H__
+
+#include <clutter/clutter-group.h>
+#include <clutter/clutter-stage.h>
+#include <gdk/gdk.h>
+
+#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 8545dbb..b73d001 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 abdef12..36f86d4 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 <clutter/x11/clutter-x11.h>
 #include <cogl/cogl-texture-pixmap-x11.h>
@@ -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 484c010..e7cd42b 100644
--- a/tests/conform/test-conform-common.c
+++ b/tests/conform/test-conform-common.c
@@ -3,7 +3,7 @@
 #include <clutter/clutter.h>
 #include <stdlib.h>
 
-#ifdef COGL_HAS_XLIB
+#ifdef CLUTTER_WINDOWING_X11
 #include <X11/Xlib.h>
 #include <clutter/x11/clutter-x11.h>
 #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.
    *



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]