[gtk+/wip/mir] Stub Mir module



commit 260b30a4d47499ca05dc61b7a9a8d090e22f1b40
Author: Robert Ancell <robert ancell canonical com>
Date:   Tue May 20 10:03:30 2014 +1200

    Stub Mir module

 Makefile.am                      |    4 +-
 configure.ac                     |   32 +-
 docs/reference/gtk/Makefile.am   |    1 +
 docs/reference/gtk/building.sgml |   11 +-
 docs/reference/gtk/gtk-docs.sgml |    1 +
 docs/reference/gtk/mir.xml       |   35 +
 docs/reference/gtk/running.sgml  |    5 +
 gdk/Makefile.am                  |    6 +-
 gdk/gdkdisplaymanager.c          |    7 +
 gdk/mir/Makefile.am              |   36 +
 gdk/mir/gdkmir-private.h         |   61 ++
 gdk/mir/gdkmir.h                 |   37 +
 gdk/mir/gdkmircursor.c           |   73 ++
 gdk/mir/gdkmirdevice.c           |  168 +++++
 gdk/mir/gdkmirdevicemanager.c    |  103 +++
 gdk/mir/gdkmirdisplay.c          |  550 ++++++++++++++
 gdk/mir/gdkmirkeymap.c           |  174 +++++
 gdk/mir/gdkmirscreen.c           |  561 +++++++++++++++
 gdk/mir/gdkmirwindow.c           |   52 ++
 gdk/mir/gdkmirwindowimpl.c       | 1472 ++++++++++++++++++++++++++++++++++++++
 20 files changed, 3383 insertions(+), 6 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 4da3fd0..3a9f474 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,11 +33,11 @@ MAINTAINERCLEANFILES = \
 
 
 ## Copy .pc files to target-specific names
-gtk+-x11-3.0.pc gtk+-win32-3.0.pc gtk+-quartz-3.0.pc gtk+-broadway-3.0.pc gtk+-wayland-3.0.pc: gtk+-3.0.pc
+gtk+-x11-3.0.pc gtk+-win32-3.0.pc gtk+-quartz-3.0.pc gtk+-broadway-3.0.pc gtk+-wayland-3.0.pc 
gtk+-mir-3.0.pc: gtk+-3.0.pc
        rm -f $@ && \
        cp gtk+-3.0.pc $@
 
-gdk-x11-3.0.pc gdk-win32-3.0.pc gdk-quartz-3.0.pc gdk-broadway-3.0.pc gdk-wayland-3.0.pc: gdk-3.0.pc
+gdk-x11-3.0.pc gdk-win32-3.0.pc gdk-quartz-3.0.pc gdk-broadway-3.0.pc gdk-wayland-3.0.pc gdk-mir-3.0.pc: 
gdk-3.0.pc
        rm -f $@ && \
        cp gdk-3.0.pc $@
 
diff --git a/configure.ac b/configure.ac
index 3222efe..bea2b16 100644
--- a/configure.ac
+++ b/configure.ac
@@ -308,6 +308,10 @@ AC_ARG_ENABLE(wayland-backend,
               [AS_HELP_STRING([--enable-wayland-backend],
                               [enable the wayland gdk backend])],
                              [backend_set=yes])
+AC_ARG_ENABLE(mir-backend,
+              [AS_HELP_STRING([--enable-mir-backend],
+                              [enable the Mir gdk backend])],
+                             [backend_set=yes])
 
 if test -z "$backend_set"; then
   if test "$platform_win32" = yes; then
@@ -315,6 +319,7 @@ if test -z "$backend_set"; then
   else
     enable_x11_backend=yes
     enable_wayland_backend=maybe
+    enable_mir_backend=maybe
   fi
 fi
 
@@ -430,6 +435,30 @@ else
 fi
 AC_SUBST(DISABLE_ON_WAYLAND)
 
+MIR_DEPENDENCIES="mirclient"
+if test "$enable_mir_backend" = "maybe" ; then
+  PKG_CHECK_EXISTS($MIR_DEPENDENCIES, [have_mir_deps=yes], [have_mir_deps=no])
+  AC_MSG_CHECKING([for MIR_DEPENDENCIES])
+  if test "$have_mir_deps" = "no" ; then
+    enable_mir_backend=no
+  else
+    enable_mir_backend=yes
+  fi
+  AC_MSG_RESULT($enable_mir_backend)
+fi
+
+if test "$enable_mir_backend" = "yes"; then
+  cairo_backends="$cairo_backends cairo"
+  GDK_BACKENDS="$GDK_BACKENDS mir"
+  GDK_WINDOWING="$GDK_WINDOWING
+#define GDK_WINDOWING_MIR"
+  MIR_PACKAGES="$MIR_DEPENDENCIES"
+
+  AM_CONDITIONAL(USE_MIR, true)
+else
+  AM_CONDITIONAL(USE_MIR, false)
+fi
+
 # strip leading space
 GDK_BACKENDS=${GDK_BACKENDS#* }
 
@@ -1300,7 +1329,7 @@ CFLAGS="$saved_cflags"
 LDFLAGS="$saved_ldflags"
 
 GDK_PACKAGES="$PANGO_PACKAGES gdk-pixbuf-2.0 cairo cairo-gobject"
-GDK_PRIVATE_PACKAGES="$GDK_GIO_PACKAGE $X_PACKAGES $WAYLAND_PACKAGES $cairo_backends"
+GDK_PRIVATE_PACKAGES="$GDK_GIO_PACKAGE $X_PACKAGES $WAYLAND_PACKAGES $MIR_PACKAGES $cairo_backends"
 if test "x$enable_x11_backend" = xyes; then
   GDK_PRIVATE_PACKAGES="$GDK_PRIVATE_PACKAGES pangoft2"
 fi
@@ -1859,6 +1888,7 @@ gdk/win32/rc/Makefile
 gdk/win32/rc/gdk.rc
 gdk/quartz/Makefile
 gdk/wayland/Makefile
+gdk/mir/Makefile
 gdk/gdkversionmacros.h
 gtk/Makefile
 gtk/makefile.msc
diff --git a/docs/reference/gtk/Makefile.am b/docs/reference/gtk/Makefile.am
index 1c60e59..4e899c9 100644
--- a/docs/reference/gtk/Makefile.am
+++ b/docs/reference/gtk/Makefile.am
@@ -144,6 +144,7 @@ content_files =                                     \
        osx.sgml                                \
        broadway.xml                            \
        wayland.xml                             \
+       mir.xml                                 \
        question_index.sgml                     \
        resources.sgml                          \
        text_widget.sgml                        \
diff --git a/docs/reference/gtk/building.sgml b/docs/reference/gtk/building.sgml
index a945982..c7787a4 100644
--- a/docs/reference/gtk/building.sgml
+++ b/docs/reference/gtk/building.sgml
@@ -395,6 +395,11 @@ How to compile GTK+ itself
           </group>
           <sbr/>
           <group>
+            <arg choice="plain">--enable-mir-backend</arg>
+            <arg choice="plain">--disable-mir-backend</arg>
+          </group>
+          <sbr/>
+          <group>
             <arg choice="plain">--enable-introspection=[no/auto/yes]</arg>
           </group>
           <sbr/>
@@ -595,8 +600,10 @@ How to compile GTK+ itself
           <systemitem>--disable-quartz-backend</systemitem>,
           <systemitem>--enable-broadway-backend</systemitem>,
           <systemitem>--disable-broadway-backend</systemitem>,
-          <systemitem>--enable-wayland-backend</systemitem>, and
-          <systemitem>--disable-wayland-backend</systemitem></title>
+          <systemitem>--enable-wayland-backend</systemitem>,
+          <systemitem>--disable-wayland-backend</systemitem>
+          <systemitem>--enable-mir-backend</systemitem>, and
+          <systemitem>--disable-mir-backend</systemitem></title>
 
         <para>
           Enables specific backends for GDK.  If none of these options
diff --git a/docs/reference/gtk/gtk-docs.sgml b/docs/reference/gtk/gtk-docs.sgml
index 9099510..f93b3c4 100644
--- a/docs/reference/gtk/gtk-docs.sgml
+++ b/docs/reference/gtk/gtk-docs.sgml
@@ -391,6 +391,7 @@
     <xi:include href="osx.sgml" />
     <xi:include href="broadway.xml" />
     <xi:include href="wayland.xml" />
+    <xi:include href="mir.xml" />
   </part>
 
   <xi:include href="glossary.xml" />
diff --git a/docs/reference/gtk/mir.xml b/docs/reference/gtk/mir.xml
new file mode 100644
index 0000000..3a0a52e
--- /dev/null
+++ b/docs/reference/gtk/mir.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"; [
+]>
+<refentry id="gtk-mir">
+<refmeta>
+<refentrytitle>Using GTK+ with Mir</refentrytitle>
+<manvolnum>3</manvolnum>
+<refmiscinfo>GTK Library</refmiscinfo>
+</refmeta>
+
+<refnamediv>
+<refname>Using GTK+ with Mir</refname>
+<refpurpose>
+Mir-specific aspects of using GTK+
+</refpurpose>
+</refnamediv>
+
+<refsect1>
+<title>Using GTK+ with Mir</title>
+
+<para>
+The GDK Mir backend provides support for running GTK+ applications
+under Mir based display servers. To run your application in this way,
+select the Mir backend by setting <literal>GDK_BACKEND=mir</literal>.
+</para>
+
+<para>
+Currently, the Mir backend does not use any additional commandline
+options or environment variables.
+</para>
+
+</refsect1>
+
+</refentry>
diff --git a/docs/reference/gtk/running.sgml b/docs/reference/gtk/running.sgml
index 71fb7b3..9d2382c 100644
--- a/docs/reference/gtk/running.sgml
+++ b/docs/reference/gtk/running.sgml
@@ -460,6 +460,11 @@ nevertheless.
         <listitem><para>Selects the Wayland backend for connecting to Wayland display 
servers</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term>mir</term>
+        <listitem><para>Selects the Mir backend for connecting to Mir display servers</para></listitem>
+      </varlistentry>
+
     </variablelist>
     Since 3.10, this environment variable can contain a comma-separated list
     of backend names, which are tried in order. The list may also contain
diff --git a/gdk/Makefile.am b/gdk/Makefile.am
index 8cba7c0..589c5da 100644
--- a/gdk/Makefile.am
+++ b/gdk/Makefile.am
@@ -11,7 +11,7 @@ INTROSPECTION_COMPILER_ARGS = \
 
 SUBDIRS = $(GDK_BACKENDS) .
 
-DIST_SUBDIRS = win32 x11 quartz broadway wayland
+DIST_SUBDIRS = win32 x11 quartz broadway wayland mir
 
 CLEANFILES =
 
@@ -191,6 +191,10 @@ if USE_WAYLAND
 libgdk_3_la_LIBADD += wayland/libgdk-wayland.la
 endif
 
+if USE_MIR
+libgdk_3_la_LIBADD += mir/libgdk-mir.la
+endif
+
 if HAVE_INTROSPECTION
 
 introspection_files =          \
diff --git a/gdk/gdkdisplaymanager.c b/gdk/gdkdisplaymanager.c
index 94f857e..fb0f93a 100644
--- a/gdk/gdkdisplaymanager.c
+++ b/gdk/gdkdisplaymanager.c
@@ -60,6 +60,10 @@
 #include "wayland/gdkprivate-wayland.h"
 #endif
 
+#ifdef GDK_WINDOWING_MIR
+#include "mir/gdkmir-private.h"
+#endif
+
 /**
  * SECTION:gdkdisplaymanager
  * @Short_description: Maintains a list of all open GdkDisplays
@@ -273,6 +277,9 @@ static GdkBackend gdk_backends[] = {
 #ifdef GDK_WINDOWING_WAYLAND
   { "wayland",  _gdk_wayland_display_open },
 #endif
+#ifdef GDK_WINDOWING_MIR
+  { "mir",  _gdk_mir_display_open },
+#endif
 #ifdef GDK_WINDOWING_BROADWAY
   { "broadway", _gdk_broadway_display_open },
 #endif
diff --git a/gdk/mir/Makefile.am b/gdk/mir/Makefile.am
new file mode 100644
index 0000000..aff5e27
--- /dev/null
+++ b/gdk/mir/Makefile.am
@@ -0,0 +1,36 @@
+## Process this file with automake to produce Makefile.in
+include $(top_srcdir)/Makefile.decl
+
+libgdkincludedir = $(includedir)/gtk-3.0/gdk
+libgdkmirincludedir = $(includedir)/gtk-3.0/gdk/mir
+
+AM_CPPFLAGS = \
+       -DG_LOG_DOMAIN=\"Gdk\" \
+       -DGDK_COMPILATION \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/gdk \
+       -I$(top_builddir)/gdk \
+       $(GDK_HIDDEN_VISIBILITY_CFLAGS) \
+       $(GTK_DEBUG_FLAGS) \
+       $(GDK_DEP_CFLAGS)
+
+LDADDS = $(GDK_DEP_LIBS)
+
+noinst_LTLIBRARIES = \
+       libgdk-mir.la
+
+libgdk_mir_la_SOURCES =        \
+       gdkmircursor.c \
+       gdkmirdevice.c \
+       gdkmirdevicemanager.c \
+       gdkmirdisplay.c \
+       gdkmirkeymap.c \
+       gdkmirscreen.c  \
+       gdkmirwindow.c  \
+       gdkmirwindowimpl.c      \
+       gdkmir.h
+
+libgdkinclude_HEADERS = \
+       gdkmir.h
+
+-include $(top_srcdir)/git.mk
diff --git a/gdk/mir/gdkmir-private.h b/gdk/mir/gdkmir-private.h
new file mode 100644
index 0000000..744f5a9
--- /dev/null
+++ b/gdk/mir/gdkmir-private.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2014 Canonical Ltd
+ *
+ * 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/>.
+ */
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * 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 __GDK_PRIVATE_MIR_H__
+#define __GDK_PRIVATE_MIR_H__
+
+#include "config.h"
+
+#include "gdkdisplay.h"
+#include "gdkscreen.h"
+#include "gdkdevicemanager.h"
+#include "gdkkeys.h"
+#include "gdkwindowimpl.h"
+
+GdkDisplay *_gdk_mir_display_open (const gchar *display_name);
+
+GdkScreen *_gdk_mir_screen_new (GdkDisplay *display);
+
+GdkDeviceManager *_gdk_mir_device_manager_new (GdkDisplay *display);
+
+GdkDevice *_gdk_mir_device_manager_get_keyboard (GdkDeviceManager *device_manager);
+
+GdkKeymap *_gdk_mir_keymap_new (void);
+
+GdkDevice *_gdk_mir_device_new (GdkDeviceManager *device_manager, const gchar *name, GdkInputSource 
input_source, gboolean has_cursor);
+
+GdkCursor *_gdk_mir_cursor_new (GdkDisplay *display, GdkCursorType type);
+
+GdkWindowImpl *_gdk_mir_window_impl_new (int width, int height);
+
+#endif /* __GDK_PRIVATE_MIR_H__ */
diff --git a/gdk/mir/gdkmir.h b/gdk/mir/gdkmir.h
new file mode 100644
index 0000000..8ce99b7
--- /dev/null
+++ b/gdk/mir/gdkmir.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2014 Canonical Ltd
+ *
+ * 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 __GDK_MIR_H__
+#define __GDK_MIR_H__
+
+#include <gdk/gdk.h>
+#include <mir_toolkit/mir_client_library.h>
+
+#define GDK_TYPE_MIR_DISPLAY              (gdk_mir_display_get_type ())
+#define GDK_IS_MIR_DISPLAY(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MIR_DISPLAY))
+
+#define GDK_TYPE_MIR_WINDOW              (gdk_mir_window_get_type ())
+#define GDK_IS_WINDOW_MIR(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WINDOW_MIR))
+
+GType gdk_mir_display_get_type (void);
+
+GDK_AVAILABLE_IN_ALL
+struct MirConnection *gdk_mir_display_get_mir_connection (GdkDisplay *display);
+
+GType gdk_mir_window_get_type (void);
+
+#endif /* __GDK_MIR_H__ */
diff --git a/gdk/mir/gdkmircursor.c b/gdk/mir/gdkmircursor.c
new file mode 100644
index 0000000..bdbce5e
--- /dev/null
+++ b/gdk/mir/gdkmircursor.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2014 Canonical Ltd
+ *
+ * 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 "gdkcursorprivate.h"
+
+#include "gdkmir.h"
+#include "gdkmir-private.h"
+
+typedef struct GdkMirCursor      GdkMirCursor;
+typedef struct GdkMirCursorClass GdkMirCursorClass;
+
+#define GDK_TYPE_MIR_CURSOR              (gdk_mir_cursor_get_type ())
+#define GDK_MIR_CURSOR(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MIR_CURSOR, 
GdkMirCursor))
+#define GDK_MIR_CURSOR_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MIR_CURSOR, 
GdkMirCursorClass))
+#define GDK_IS_MIR_CURSOR(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MIR_CURSOR))
+#define GDK_IS_MIR_CURSOR_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MIR_CURSOR))
+#define GDK_MIR_CURSOR_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MIR_CURSOR, 
GdkMirCursorClass))
+
+struct GdkMirCursor
+{
+  GdkCursor parent_instance;
+};
+
+struct GdkMirCursorClass
+{
+  GdkCursorClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMirCursor, gdk_mir_cursor, GDK_TYPE_CURSOR)
+
+GdkCursor *
+_gdk_mir_cursor_new (GdkDisplay *display, GdkCursorType type)
+{
+  return g_object_new (GDK_TYPE_MIR_CURSOR, "display", display, "cursor-type", type, NULL);
+}
+
+cairo_surface_t *
+gdk_mir_cursor_get_surface (GdkCursor *cursor,
+                            gdouble   *x_hot,
+                            gdouble   *y_hot)
+{
+  g_printerr ("gdk_mir_cursor_get_surface\n");
+  return NULL;
+}
+
+static void
+gdk_mir_cursor_init (GdkMirCursor *cursor)
+{
+}
+
+static void
+gdk_mir_cursor_class_init (GdkMirCursorClass *klass)
+{
+  GdkCursorClass *cursor_class = GDK_CURSOR_CLASS (klass);
+
+  cursor_class->get_surface = gdk_mir_cursor_get_surface;
+}
diff --git a/gdk/mir/gdkmirdevice.c b/gdk/mir/gdkmirdevice.c
new file mode 100644
index 0000000..c0ccfa1
--- /dev/null
+++ b/gdk/mir/gdkmirdevice.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright © 2014 Canonical Ltd
+ *
+ * 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 "gdkdeviceprivate.h"
+
+typedef struct GdkMirDevice      GdkMirDevice;
+typedef struct GdkMirDeviceClass GdkMirDeviceClass;
+
+#define GDK_TYPE_MIR_DEVICE              (gdk_mir_device_get_type ())
+#define GDK_MIR_DEVICE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MIR_DEVICE, 
GdkMirDevice))
+#define GDK_MIR_DEVICE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MIR_DEVICE, 
GdkMirDeviceClass))
+#define GDK_IS_MIR_DEVICE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MIR_DEVICE))
+#define GDK_IS_MIR_DEVICE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MIR_DEVICE))
+#define GDK_MIR_DEVICE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MIR_DEVICE, 
GdkMirDeviceClass))
+
+struct GdkMirDevice
+{
+  GdkDevice parent_instance;
+};
+
+struct GdkMirDeviceClass
+{
+  GdkDeviceClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMirDevice, gdk_mir_device, GDK_TYPE_DEVICE)
+
+GdkDevice *
+_gdk_mir_device_new (GdkDeviceManager *device_manager, const gchar *name, GdkInputSource input_source, 
gboolean has_cursor)
+{
+  return g_object_new (GDK_TYPE_MIR_DEVICE,
+                       "display", gdk_device_manager_get_display (device_manager),
+                       "device-manager", device_manager,
+                       "name", name,
+                       "type", GDK_DEVICE_TYPE_MASTER,
+                       "input-source", input_source,
+                       "input-mode", GDK_MODE_SCREEN,
+                       "has-cursor", has_cursor,
+                       NULL);
+}
+
+static gboolean
+gdk_mir_device_get_history (GdkDevice      *device,
+                            GdkWindow      *window,
+                            guint32         start,
+                            guint32         stop,
+                            GdkTimeCoord ***events,
+                            gint           *n_events)
+{
+  g_printerr ("gdk_mir_device_get_history\n");
+  return FALSE;
+}
+
+static void
+gdk_mir_device_get_state (GdkDevice       *device,
+                          GdkWindow       *window,
+                          gdouble         *axes,
+                          GdkModifierType *mask)
+{
+  g_printerr ("gdk_mir_device_get_state\n");
+}
+
+static void
+gdk_mir_device_set_window_cursor (GdkDevice *device,
+                                  GdkWindow *window,
+                                  GdkCursor *cursor)
+{
+  g_printerr ("gdk_mir_device_set_window_cursor\n");
+}
+
+static void
+gdk_mir_device_warp (GdkDevice *device,
+                     GdkScreen *screen,
+                     gdouble    x,
+                     gdouble    y)
+{
+  g_printerr ("gdk_mir_device_warp\n");
+}
+
+static void
+gdk_mir_device_query_state (GdkDevice        *device,
+                            GdkWindow        *window,
+                            GdkWindow       **root_window,
+                            GdkWindow       **child_window,
+                            gdouble          *root_x,
+                            gdouble          *root_y,
+                            gdouble          *win_x,
+                            gdouble          *win_y,
+                            GdkModifierType  *mask)
+{
+  g_printerr ("gdk_mir_device_query_state\n");
+}
+
+static GdkGrabStatus
+gdk_mir_device_grab (GdkDevice    *device,
+                     GdkWindow    *window,
+                     gboolean      owner_events,
+                     GdkEventMask  event_mask,
+                     GdkWindow    *confine_to,
+                     GdkCursor    *cursor,
+                     guint32       time_)
+{
+  g_printerr ("gdk_mir_device_grab\n");
+  return GDK_GRAB_SUCCESS;
+}
+
+static void
+gdk_mir_device_ungrab (GdkDevice *device,
+                       guint32    time_)
+{
+  g_printerr ("gdk_mir_device_ungrab\n");
+}
+
+static GdkWindow *
+gdk_mir_device_window_at_position (GdkDevice       *device,
+                                   gdouble         *win_x,
+                                   gdouble         *win_y,
+                                   GdkModifierType *mask,
+                                   gboolean         get_toplevel)
+{
+  g_printerr ("gdk_mir_device_window_at_position (%f, %f)\n", *win_x, *win_y);
+  return NULL;
+}
+
+static void
+gdk_mir_device_select_window_events (GdkDevice    *device,
+                                     GdkWindow    *window,
+                                     GdkEventMask  event_mask)
+{
+  g_printerr ("gdk_mir_device_select_window_events\n");
+}
+
+static void
+gdk_mir_device_init (GdkMirDevice *device)
+{
+}
+
+static void
+gdk_mir_device_class_init (GdkMirDeviceClass *klass)
+{
+  GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
+
+  device_class->get_history = gdk_mir_device_get_history;
+  device_class->get_state = gdk_mir_device_get_state;
+  device_class->set_window_cursor = gdk_mir_device_set_window_cursor;
+  device_class->warp = gdk_mir_device_warp;
+  device_class->query_state = gdk_mir_device_query_state;
+  device_class->grab = gdk_mir_device_grab;
+  device_class->ungrab = gdk_mir_device_ungrab;
+  device_class->window_at_position = gdk_mir_device_window_at_position;
+  device_class->select_window_events = gdk_mir_device_select_window_events;
+}
diff --git a/gdk/mir/gdkmirdevicemanager.c b/gdk/mir/gdkmirdevicemanager.c
new file mode 100644
index 0000000..7c8fa43
--- /dev/null
+++ b/gdk/mir/gdkmirdevicemanager.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright © 2014 Canonical Ltd
+ *
+ * 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 "gdkdevicemanagerprivate.h"
+
+#include "gdkmir.h"
+#include "gdkmir-private.h"
+
+typedef struct GdkMirDeviceManager      GdkMirDeviceManager;
+typedef struct GdkMirDeviceManagerClass GdkMirDeviceManagerClass;
+
+#define GDK_TYPE_MIR_DEVICE_MANAGER              (gdk_mir_device_manager_get_type ())
+#define GDK_MIR_DEVICE_MANAGER(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), 
GDK_TYPE_MIR_DEVICE_MANAGER, GdkMirDeviceManager))
+#define GDK_MIR_DEVICE_MANAGER_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), 
GDK_TYPE_MIR_DEVICE_MANAGER, GdkMirDeviceManagerClass))
+#define GDK_IS_MIR_DEVICE_MANAGER(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), 
GDK_TYPE_MIR_DEVICE_MANAGER))
+#define GDK_IS_MIR_DEVICE_MANAGER_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), 
GDK_TYPE_MIR_DEVICE_MANAGER))
+#define GDK_MIR_DEVICE_MANAGER_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GDK_TYPE_MIR_DEVICE_MANAGER, GdkMirDeviceManagerClass))
+
+struct GdkMirDeviceManager
+{
+  GdkDeviceManager parent_instance;
+
+  GdkDevice *pointer;
+  GdkDevice *keyboard;
+};
+
+struct GdkMirDeviceManagerClass
+{
+  GdkDeviceManagerClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMirDeviceManager, gdk_mir_device_manager, GDK_TYPE_DEVICE_MANAGER)
+
+GdkDeviceManager *
+_gdk_mir_device_manager_new (GdkDisplay *display)
+{
+  return g_object_new (GDK_TYPE_MIR_DEVICE_MANAGER, "display", display, NULL);
+}
+
+static GList *
+gdk_mir_device_manager_list_devices (GdkDeviceManager *device_manager,
+                                     GdkDeviceType     type)
+{
+  //g_printerr ("gdk_mir_device_manager_list_devices (%u)\n", type);
+  GdkMirDeviceManager *dm = GDK_MIR_DEVICE_MANAGER (device_manager);
+
+  if (type == GDK_DEVICE_TYPE_MASTER)
+    {
+      GList *devices;
+
+      devices = g_list_append (NULL, dm->keyboard);
+      devices = g_list_append (devices, dm->pointer);
+
+      return devices;
+    }
+
+  return NULL;
+}
+
+static GdkDevice *
+gdk_mir_device_manager_get_client_pointer (GdkDeviceManager *device_manager)
+{
+  //g_printerr ("gdk_mir_device_manager_get_client_pointer\n");
+  return GDK_MIR_DEVICE_MANAGER (device_manager)->pointer;
+}
+
+GdkDevice *
+_gdk_mir_device_manager_get_keyboard (GdkDeviceManager *device_manager)
+{
+  return GDK_MIR_DEVICE_MANAGER (device_manager)->keyboard;
+}
+
+static void
+gdk_mir_device_manager_init (GdkMirDeviceManager *device_manager)
+{
+  device_manager->keyboard = _gdk_mir_device_new (GDK_DEVICE_MANAGER (device_manager), "Mir Keyboard", 
GDK_SOURCE_KEYBOARD, FALSE);
+  device_manager->pointer = _gdk_mir_device_new (GDK_DEVICE_MANAGER (device_manager), "Mir Pointer", 
GDK_SOURCE_MOUSE, TRUE);
+}
+
+static void
+gdk_mir_device_manager_class_init (GdkMirDeviceManagerClass *klass)
+{
+  GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
+
+  device_manager_class->list_devices = gdk_mir_device_manager_list_devices;
+  device_manager_class->get_client_pointer = gdk_mir_device_manager_get_client_pointer;
+}
diff --git a/gdk/mir/gdkmirdisplay.c b/gdk/mir/gdkmirdisplay.c
new file mode 100644
index 0000000..7d606fe
--- /dev/null
+++ b/gdk/mir/gdkmirdisplay.c
@@ -0,0 +1,550 @@
+/*
+ * Copyright © 2014 Canonical Ltd
+ *
+ * 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 "gdkdisplayprivate.h"
+#include "gdkinternals.h"
+
+#include "gdkmir.h"
+#include "gdkmir-private.h"
+
+#define GDK_MIR_DISPLAY(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DISPLAY_MIR, 
GdkMirDisplay))
+#define GDK_MIR_DISPLAY_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DISPLAY_MIR, 
GdkMirDisplayClass))
+#define GDK_IS_MIR_DISPLAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MIR_DISPLAY))
+#define GDK_MIR_DISPLAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MIR_DISPLAY, 
GdkMirDisplayImplClass))
+
+typedef struct GdkMirDisplay
+{
+  GdkDisplay parent_instance;
+
+  /* Connection to Mir server */
+  MirConnection *connection;
+
+  /* Serial number? */
+  gulong serial;
+
+  /* Screen information */
+  GdkScreen *screen;
+
+  GdkCursor *cursor;
+
+  GdkKeymap *keymap;
+} GdkMirDisplay;
+
+typedef struct GdkMirDisplayClass
+{
+  GdkDisplayClass parent_class;
+} GdkMirDisplayClass;
+
+/**
+ * SECTION:mir_interaction
+ * @Short_description: Mir backend-specific functions
+ * @Title: Mir Interaction
+ *
+ * The functions in this section are specific to the GDK Mir backend.
+ * To use them, you need to include the <literal>&lt;gdk/gdkmir.h&gt;</literal>
+ * header and use the Mir-specific pkg-config files to build your
+ * application (either <literal>gdk-mir-3.0</literal> or
+ * <literal>gtk+-mir-3.0</literal>).
+ *
+ * To make your code compile with other GDK backends, guard backend-specific
+ * calls by an ifdef as follows. Since GDK may be built with multiple
+ * backends, you should also check for the backend that is in use (e.g. by
+ * using the GDK_IS_MIR_DISPLAY() macro).
+ * |[
+ * #ifdef GDK_WINDOWING_MIR
+ *   if (GDK_IS_MIR_DISPLAY (display))
+ *     {
+ *       /&ast; make Mir-specific calls here &ast;/
+ *     }
+ *   else
+ * #endif
+ * #ifdef GDK_WINDOWING_X11
+ *   if (GDK_IS_X11_DISPLAY (display))
+ *     {
+ *       /&ast; make X11-specific calls here &ast;/
+ *     }
+ *   else
+ * #endif
+ *   g_error ("Unsupported GDK backend");
+ * ]|
+ */
+
+G_DEFINE_TYPE (GdkMirDisplay, gdk_mir_display, GDK_TYPE_DISPLAY)
+
+GdkDisplay *
+_gdk_mir_display_open (const gchar *display_name)
+{
+  MirConnection *connection;
+  GdkMirDisplay *display;
+
+  g_printerr ("gdk_mir_display_open\n");
+
+  connection = mir_connect_sync (NULL, "GDK-Mir");
+  if (!connection)
+     return NULL;
+  if (!mir_connection_is_valid (connection))
+    {
+      g_printerr ("Failed to connect to Mir: %s\n", mir_connection_get_error_message (connection));
+      mir_connection_release (connection);
+      return NULL;
+    }
+
+  display = g_object_new (GDK_TYPE_MIR_DISPLAY, NULL);
+
+  display->connection = connection;
+  GDK_DISPLAY (display)->device_manager = _gdk_mir_device_manager_new (GDK_DISPLAY (display));
+  display->screen = _gdk_mir_screen_new (GDK_DISPLAY (display));
+
+  g_signal_emit_by_name (display, "opened");
+
+  return GDK_DISPLAY (display);
+}
+
+/**
+ * gdk_mir_display_get_mir_connection
+ * @display: (type GdkMirDisplay): a #GdkDisplay
+ *
+ * Returns the #MirConnection for a #GdkDisplay
+ *
+ * Returns: (transfer none): a #MirConnection
+ *
+ * Since: 3.14
+ */
+struct MirConnection *
+gdk_mir_display_get_mir_connection (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_MIR_DISPLAY (display), NULL);
+  return GDK_MIR_DISPLAY (display)->connection;
+}
+
+static void
+gdk_mir_display_dispose (GObject *object)
+{
+  GdkMirDisplay *display = GDK_MIR_DISPLAY (object);
+
+  g_object_unref (display->screen);
+  display->screen = NULL;
+
+  G_OBJECT_CLASS (gdk_mir_display_parent_class)->dispose (object);
+}
+
+static void
+gdk_mir_display_finalize (GObject *object)
+{
+  GdkMirDisplay *display = GDK_MIR_DISPLAY (object);
+
+  mir_connection_release (display->connection);
+
+  G_OBJECT_CLASS (gdk_mir_display_parent_class)->finalize (object);
+}
+
+static const gchar *
+gdk_mir_display_get_name (GdkDisplay *display)
+{
+  //g_printerr ("gdk_mir_display_get_name\n");
+  return "Mir";
+}
+
+static GdkScreen *
+gdk_mir_display_get_default_screen (GdkDisplay *display)
+{
+  //g_printerr ("gdk_mir_display_get_default_screen\n");
+  return GDK_MIR_DISPLAY (display)->screen;
+}
+
+static void
+gdk_mir_display_beep (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_beep\n");
+  /* No system level beep... */
+}
+
+static void
+gdk_mir_display_sync (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_sync\n");
+}
+
+static void
+gdk_mir_display_flush (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_flush\n");
+}
+
+static gboolean
+gdk_mir_display_has_pending (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_has_pending\n");
+  return FALSE;
+}
+
+static void
+gdk_mir_display_queue_events (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_queue_events\n");
+}
+
+static void
+gdk_mir_display_make_default (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_make_default\n");
+}
+
+static GdkWindow *
+gdk_mir_display_get_default_group (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_get_default_group\n");
+  return NULL;
+}
+
+static gboolean
+gdk_mir_display_supports_shapes (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_supports_shapes\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_display_supports_input_shapes (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_supports_input_shapes\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_display_supports_composite (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_supports_composite\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_display_supports_clipboard_persistence (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_supports_clipboard_persistence\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_display_supports_cursor_alpha (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_supports_cursor_alpha\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_display_supports_cursor_color (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_supports_cursor_color\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_display_supports_selection_notification (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_supports_selection_notification\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_display_request_selection_notification (GdkDisplay *display,
+                                                GdkAtom     selection)
+{
+  g_printerr ("gdk_mir_display_request_selection_notification\n");
+  return FALSE;
+}
+
+static void
+gdk_mir_display_store_clipboard (GdkDisplay    *display,
+                                 GdkWindow     *clipboard_window,
+                                 guint32        time_,
+                                 const GdkAtom *targets,
+                                 gint           n_targets)
+{
+  g_printerr ("gdk_mir_display_store_clipboard\n");
+}
+
+static void
+gdk_mir_display_get_default_cursor_size (GdkDisplay *display,
+                                         guint      *width,
+                                         guint      *height)
+{
+  g_printerr ("gdk_mir_display_get_default_cursor_size\n");
+  *width = *height = 32; // FIXME: Random value
+}
+
+static void
+gdk_mir_display_get_maximal_cursor_size (GdkDisplay *display,
+                                         guint      *width,
+                                         guint      *height)
+{
+  g_printerr ("gdk_mir_display_get_maximal_cursor_size\n");
+  *width = *height = 32; // FIXME: Random value
+}
+
+static GdkCursor *
+gdk_mir_display_get_cursor_for_type (GdkDisplay    *display,
+                                     GdkCursorType  cursor_type)
+{
+  //g_printerr ("gdk_mir_display_get_cursor_for_type (%u)\n", cursor_type);
+  /* We don't support configurable cursors */
+  return g_object_ref (GDK_MIR_DISPLAY (display)->cursor);
+}
+
+static GdkCursor *
+gdk_mir_display_get_cursor_for_name (GdkDisplay  *display,
+                                     const gchar *name)
+{
+  g_printerr ("gdk_mir_display_get_cursor_for_name (\"%s\")\n", name);
+  /* We don't support configurable cursors */
+  return g_object_ref (GDK_MIR_DISPLAY (display)->cursor);
+}
+
+static GdkCursor *
+gdk_mir_display_get_cursor_for_surface (GdkDisplay      *display,
+                                        cairo_surface_t *surface,
+                                        gdouble          x,
+                                        gdouble          y)
+{
+  g_printerr ("gdk_mir_display_get_cursor_for_surface (%f, %f)\n", x, y);
+  return NULL;
+}
+
+static GList *
+gdk_mir_display_list_devices (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_list_devices\n");
+  // FIXME: Should this access the device manager?
+  return NULL;
+}
+
+static GdkAppLaunchContext *
+gdk_mir_display_get_app_launch_context (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_get_app_launch_context\n");
+  return NULL;
+}
+
+static void
+gdk_mir_display_before_process_all_updates (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_before_process_all_updates\n");
+}
+
+static void
+gdk_mir_display_after_process_all_updates (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_after_process_all_updates\n");
+}
+
+static gulong
+gdk_mir_display_get_next_serial (GdkDisplay *display)
+{
+  //g_printerr ("gdk_mir_display_get_next_serial\n");
+  return GDK_MIR_DISPLAY (display)->serial++;
+}
+
+static void
+gdk_mir_display_notify_startup_complete (GdkDisplay  *display,
+                                         const gchar *startup_id)
+{
+  g_printerr ("gdk_mir_display_notify_startup_complete\n");
+}
+
+static void
+gdk_mir_display_event_data_copy (GdkDisplay     *display,
+                                 const GdkEvent *src,
+                                 GdkEvent       *dst)
+{
+  g_printerr ("gdk_mir_display_event_data_copy\n");
+}
+
+static void
+gdk_mir_display_event_data_free (GdkDisplay *display,
+                                 GdkEvent   *event)
+{
+  //g_printerr ("gdk_mir_display_event_data_free\n");
+}
+
+static void
+gdk_mir_display_create_window_impl (GdkDisplay    *display,
+                                    GdkWindow     *window,
+                                    GdkWindow     *real_parent,
+                                    GdkScreen     *screen,
+                                    GdkEventMask   event_mask,
+                                    GdkWindowAttr *attributes,
+                                    gint           attributes_mask)
+{
+  g_printerr ("gdk_mir_display_create_window_impl (%d, %d, %d, %d)\n", window->x, window->y, window->width, 
window->height);
+  window->impl = _gdk_mir_window_impl_new (window->width, window->height);
+}
+
+static GdkKeymap *
+gdk_mir_display_get_keymap (GdkDisplay *display)
+{
+  //g_printerr ("gdk_mir_display_get_keymap\n");
+  return GDK_MIR_DISPLAY (display)->keymap;
+}
+
+static void
+gdk_mir_display_push_error_trap (GdkDisplay *display)
+{
+  g_printerr ("gdk_mir_display_push_error_trap\n");
+}
+
+static gint
+gdk_mir_display_pop_error_trap (GdkDisplay *display,
+                                gboolean    ignored)
+{
+  g_printerr ("gdk_mir_display_pop_error_trap\n");
+  return 0;
+}
+
+static GdkWindow *
+gdk_mir_display_get_selection_owner (GdkDisplay *display,
+                                     GdkAtom     selection)
+{
+  g_printerr ("gdk_mir_display_get_selection_owner\n");
+  return NULL;
+}
+
+static gboolean
+gdk_mir_display_set_selection_owner (GdkDisplay *display,
+                                     GdkWindow  *owner,
+                                     GdkAtom     selection,
+                                     guint32     time,
+                                     gboolean    send_event)
+{
+  g_printerr ("gdk_mir_display_set_selection_owner\n");
+  return FALSE;
+}
+
+static void
+gdk_mir_display_send_selection_notify (GdkDisplay *display,
+                                       GdkWindow  *requestor,
+                                       GdkAtom     selection,
+                                       GdkAtom     target,
+                                       GdkAtom     property,
+                                       guint32     time)
+{
+  g_printerr ("gdk_mir_display_send_selection_notify\n");
+}
+
+static gint
+gdk_mir_display_get_selection_property (GdkDisplay  *display,
+                                            GdkWindow   *requestor,
+                                            guchar     **data,
+                                            GdkAtom     *ret_type,
+                                            gint        *ret_format)
+{
+  g_printerr ("gdk_mir_display_get_selection_property\n");
+  return 0;
+}
+
+static void
+gdk_mir_display_convert_selection (GdkDisplay *display,
+                                   GdkWindow  *requestor,
+                                   GdkAtom     selection,
+                                   GdkAtom     target,
+                                   guint32     time)
+{
+  g_printerr ("gdk_mir_display_convert_selection\n");
+}
+
+static gint
+gdk_mir_display_text_property_to_utf8_list (GdkDisplay    *display,
+                                            GdkAtom        encoding,
+                                            gint           format,
+                                            const guchar  *text,
+                                            gint           length,
+                                            gchar       ***list)
+{
+  g_printerr ("gdk_mir_display_text_property_to_utf8_list\n");
+  return 0;
+}
+
+static gchar *
+gdk_mir_display_utf8_to_string_target (GdkDisplay  *display,
+                                       const gchar *str)
+{
+  g_printerr ("gdk_mir_display_utf8_to_string_target\n");
+  return NULL;
+}
+
+static void
+gdk_mir_display_init (GdkMirDisplay *display)
+{
+  display->cursor = _gdk_mir_cursor_new (GDK_DISPLAY (display), GDK_ARROW);
+  display->keymap = _gdk_mir_keymap_new ();
+}
+
+static void
+gdk_mir_display_class_init (GdkMirDisplayClass * class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (class);
+
+  object_class->dispose = gdk_mir_display_dispose;
+  object_class->finalize = gdk_mir_display_finalize;
+
+  display_class->window_type = gdk_mir_window_get_type ();
+
+  display_class->get_name = gdk_mir_display_get_name;
+  display_class->get_default_screen = gdk_mir_display_get_default_screen;
+  display_class->beep = gdk_mir_display_beep;
+  display_class->sync = gdk_mir_display_sync;
+  display_class->flush = gdk_mir_display_flush;
+  display_class->has_pending = gdk_mir_display_has_pending;
+  display_class->queue_events = gdk_mir_display_queue_events;
+  display_class->make_default = gdk_mir_display_make_default;
+  display_class->get_default_group = gdk_mir_display_get_default_group;
+  display_class->supports_shapes = gdk_mir_display_supports_shapes;
+  display_class->supports_input_shapes = gdk_mir_display_supports_input_shapes;
+  display_class->supports_composite = gdk_mir_display_supports_composite;
+  display_class->supports_clipboard_persistence = gdk_mir_display_supports_clipboard_persistence;
+  display_class->supports_cursor_alpha = gdk_mir_display_supports_cursor_alpha;
+  display_class->supports_cursor_color = gdk_mir_display_supports_cursor_color;
+  display_class->supports_selection_notification = gdk_mir_display_supports_selection_notification;
+  display_class->request_selection_notification = gdk_mir_display_request_selection_notification;
+  display_class->store_clipboard = gdk_mir_display_store_clipboard;
+  display_class->get_default_cursor_size = gdk_mir_display_get_default_cursor_size;
+  display_class->get_maximal_cursor_size = gdk_mir_display_get_maximal_cursor_size;
+  display_class->get_cursor_for_type = gdk_mir_display_get_cursor_for_type;
+  display_class->get_cursor_for_name = gdk_mir_display_get_cursor_for_name;
+  display_class->get_cursor_for_surface = gdk_mir_display_get_cursor_for_surface;
+  display_class->list_devices = gdk_mir_display_list_devices;
+  display_class->get_app_launch_context = gdk_mir_display_get_app_launch_context;
+  display_class->before_process_all_updates = gdk_mir_display_before_process_all_updates;
+  display_class->after_process_all_updates = gdk_mir_display_after_process_all_updates;
+  display_class->get_next_serial = gdk_mir_display_get_next_serial;
+  display_class->notify_startup_complete = gdk_mir_display_notify_startup_complete;
+  display_class->event_data_copy = gdk_mir_display_event_data_copy;
+  display_class->event_data_free = gdk_mir_display_event_data_free;
+  display_class->create_window_impl = gdk_mir_display_create_window_impl;
+  display_class->get_keymap = gdk_mir_display_get_keymap;
+  display_class->push_error_trap = gdk_mir_display_push_error_trap;
+  display_class->pop_error_trap = gdk_mir_display_pop_error_trap;
+  display_class->get_selection_owner = gdk_mir_display_get_selection_owner;
+  display_class->set_selection_owner = gdk_mir_display_set_selection_owner;
+  display_class->send_selection_notify = gdk_mir_display_send_selection_notify;
+  display_class->get_selection_property = gdk_mir_display_get_selection_property;
+  display_class->convert_selection = gdk_mir_display_convert_selection;
+  display_class->text_property_to_utf8_list = gdk_mir_display_text_property_to_utf8_list;
+  display_class->utf8_to_string_target = gdk_mir_display_utf8_to_string_target;
+}
diff --git a/gdk/mir/gdkmirkeymap.c b/gdk/mir/gdkmirkeymap.c
new file mode 100644
index 0000000..0a247fb
--- /dev/null
+++ b/gdk/mir/gdkmirkeymap.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright © 2014 Canonical Ltd
+ *
+ * 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 "gdkkeysprivate.h"
+
+typedef struct GdkMirKeymap      GdkMirKeymap;
+typedef struct GdkMirKeymapClass GdkMirKeymapClass;
+
+#define GDK_TYPE_MIR_KEYMAP              (gdk_mir_keymap_get_type ())
+#define GDK_MIR_KEYMAP(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MIR_KEYMAP, 
GdkMirKeymap))
+#define GDK_MIR_KEYMAP_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MIR_KEYMAP, 
GdkMirKeymapClass))
+#define GDK_IS_MIR_KEYMAP(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MIR_KEYMAP))
+#define GDK_IS_MIR_KEYMAP_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MIR_KEYMAP))
+#define GDK_MIR_KEYMAP_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MIR_KEYMAP, 
GdkMirKeymapClass))
+
+struct GdkMirKeymap
+{
+  GdkKeymap parent_instance;
+};
+
+struct GdkMirKeymapClass
+{
+  GdkKeymapClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMirKeymap, gdk_mir_keymap, GDK_TYPE_KEYMAP)
+
+GdkKeymap *
+_gdk_mir_keymap_new (void)
+{
+  return g_object_new (GDK_TYPE_MIR_KEYMAP, NULL);
+}
+
+static PangoDirection
+gdk_mir_keymap_get_direction (GdkKeymap *keymap)
+{
+  g_printerr ("gdk_mir_keymap_get_direction\n");
+  return PANGO_DIRECTION_LTR;
+}
+
+static gboolean
+gdk_mir_keymap_have_bidi_layouts (GdkKeymap *keymap)
+{
+  g_printerr ("gdk_mir_keymap_have_bidi_layouts\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_keymap_get_caps_lock_state (GdkKeymap *keymap)
+{
+  g_printerr ("gdk_mir_keymap_get_caps_lock_state\n");
+  return FALSE; // FIXME
+}
+
+static gboolean
+gdk_mir_keymap_get_num_lock_state (GdkKeymap *keymap)
+{
+  g_printerr ("gdk_mir_keymap_get_num_lock_state\n");
+  return FALSE; // FIXME
+}
+
+static gboolean
+gdk_mir_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
+                                       guint          keyval,
+                                       GdkKeymapKey **keys,
+                                       gint          *n_keys)
+{
+  g_printerr ("gdk_mir_keymap_get_entries_for_keyval\n");
+  return FALSE; // FIXME
+}
+
+static gboolean
+gdk_mir_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
+                                        guint          hardware_keycode,
+                                        GdkKeymapKey **keys,
+                                        guint        **keyvals,
+                                        gint          *n_entries)
+{
+  g_printerr ("gdk_mir_keymap_get_entries_for_keycode\n");
+  return FALSE; // FIXME
+}
+
+static guint
+gdk_mir_keymap_lookup_key (GdkKeymap          *keymap,
+                           const GdkKeymapKey *key)
+{
+  g_printerr ("gdk_mir_keymap_lookup_key\n");
+  return 0; // FIXME
+}
+
+static gboolean
+gdk_mir_keymap_translate_keyboard_state (GdkKeymap       *keymap,
+                                         guint            hardware_keycode,
+                                         GdkModifierType  state,
+                                         gint             group,
+                                         guint           *keyval,
+                                         gint            *effective_group,
+                                         gint            *level,
+                                         GdkModifierType *consumed_modifiers)
+{
+  g_printerr ("gdk_mir_keymap_translate_keyboard_state\n");
+  return FALSE; // FIXME
+}
+
+static void
+gdk_mir_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
+                                      GdkModifierType *state)
+{
+  g_printerr ("gdk_mir_keymap_add_virtual_modifiers\n");
+  // FIXME
+}
+
+static gboolean
+gdk_mir_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
+                                      GdkModifierType *state)
+{
+  g_printerr ("gdk_mir_keymap_map_virtual_modifiers\n");
+  return FALSE; // FIXME
+}
+
+static GdkModifierType
+gdk_mir_keymap_get_modifier_mask (GdkKeymap         *keymap,
+                                  GdkModifierIntent  intent)
+{
+  g_printerr ("gdk_mir_keymap_get_modifier_mask\n");
+  return 0; // FIXME GDK_MODIFIER_TYPE_
+}
+
+static guint
+gdk_mir_keymap_get_modifier_state (GdkKeymap *keymap)
+{
+  g_printerr ("gdk_mir_keymap_get_modifier_state\n");
+  return 0; // FIXME
+}
+
+static void
+gdk_mir_keymap_init (GdkMirKeymap *keymap)
+{
+}
+
+static void
+gdk_mir_keymap_class_init (GdkMirKeymapClass *klass)
+{
+  GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
+
+  keymap_class->get_direction = gdk_mir_keymap_get_direction;
+  keymap_class->have_bidi_layouts = gdk_mir_keymap_have_bidi_layouts;
+  keymap_class->get_caps_lock_state = gdk_mir_keymap_get_caps_lock_state;
+  keymap_class->get_num_lock_state = gdk_mir_keymap_get_num_lock_state;
+  keymap_class->get_entries_for_keyval = gdk_mir_keymap_get_entries_for_keyval;
+  keymap_class->get_entries_for_keycode = gdk_mir_keymap_get_entries_for_keycode;
+  keymap_class->lookup_key = gdk_mir_keymap_lookup_key;
+  keymap_class->translate_keyboard_state = gdk_mir_keymap_translate_keyboard_state;
+  keymap_class->add_virtual_modifiers = gdk_mir_keymap_add_virtual_modifiers;
+  keymap_class->map_virtual_modifiers = gdk_mir_keymap_map_virtual_modifiers;
+  keymap_class->get_modifier_mask = gdk_mir_keymap_get_modifier_mask;
+  keymap_class->get_modifier_state = gdk_mir_keymap_get_modifier_state;
+}
diff --git a/gdk/mir/gdkmirscreen.c b/gdk/mir/gdkmirscreen.c
new file mode 100644
index 0000000..fc6cd65
--- /dev/null
+++ b/gdk/mir/gdkmirscreen.c
@@ -0,0 +1,561 @@
+/*
+ * Copyright © 2014 Canonical Ltd
+ *
+ * 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 <string.h>
+
+#include "gdkscreenprivate.h"
+#include "gdkdisplayprivate.h"
+#include "gdkvisualprivate.h"
+#include "gdkinternals.h"
+
+#include "gdkmir.h"
+#include "gdkmir-private.h"
+
+#define VISUAL_TYPE GDK_VISUAL_TRUE_COLOR
+#define VISUAL_DEPTH 32
+
+typedef struct GdkMirScreen      GdkMirScreen;
+typedef struct GdkMirScreenClass GdkMirScreenClass;
+
+#define GDK_TYPE_MIR_SCREEN              (gdk_mir_screen_get_type ())
+#define GDK_MIR_SCREEN(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MIR_SCREEN, 
GdkMirScreen))
+#define GDK_MIR_SCREEN_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MIR_SCREEN, 
GdkMirScreenClass))
+#define GDK_IS_MIR_SCREEN(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MIR_SCREEN))
+#define GDK_IS_MIR_SCREEN_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MIR_SCREEN))
+#define GDK_MIR_SCREEN_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MIR_SCREEN, 
GdkMirScreenClass))
+
+struct GdkMirScreen
+{
+  GdkScreen parent_instance;
+
+  /* Display this screen is running on */
+  GdkDisplay *display;
+
+  /* Current monitor configuration */
+  MirDisplayConfiguration *display_config;
+
+  GdkVisual *visual;
+
+  GdkWindow *root_window;
+};
+
+struct GdkMirScreenClass
+{
+  GdkScreenClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMirScreen, gdk_mir_screen, GDK_TYPE_SCREEN)
+
+static MirConnection *
+get_connection (GdkMirScreen *screen)
+{
+  return gdk_mir_display_get_mir_connection (GDK_DISPLAY (screen->display));
+}
+
+static void
+get_screen_size (MirDisplayConfiguration *config, gint *width, gint *height)
+{
+  uint32_t i;
+
+  *width = 0;
+  *height = 0;
+
+  if (!config)
+    return;
+
+  for (i = 0; i < config->num_outputs; i++)
+    {
+      MirDisplayOutput *o = &config->outputs[i];
+      gint w, h;
+
+      if (!o->used)
+        continue;
+
+      w = o->position_x + o->modes[o->current_mode].horizontal_resolution;
+      if (w > *width)
+        *width = w;
+      h = o->position_y + o->modes[o->current_mode].vertical_resolution;
+      if (h > *height)
+        *height = h;
+    }
+}
+
+static void
+update_display_config (GdkMirScreen *screen)
+{
+  gdk_mir_display_get_mir_connection (GDK_DISPLAY (screen->display));
+  mir_display_config_destroy (screen->display_config);
+  screen->display_config = mir_connection_create_display_config (get_connection (screen));
+}
+
+static void
+config_changed_cb (MirConnection *connection, void *data)
+{
+  GdkMirScreen *screen = data;
+  gint old_width, old_height, new_width, new_height;
+
+  get_screen_size (screen->display_config, &old_width, &old_height);
+  update_display_config (screen);
+  get_screen_size (screen->display_config, &new_width, &new_height);
+
+  g_signal_emit_by_name (screen, "monitors-changed");
+  if (old_width > 0 && (old_width != new_width || old_height != new_height))
+    g_signal_emit_by_name (screen, "size-changed");
+}
+
+GdkScreen *
+_gdk_mir_screen_new (GdkDisplay *display)
+{
+  GdkMirScreen *screen;
+
+  screen = g_object_new (GDK_TYPE_MIR_SCREEN, NULL);
+  screen->display = display;
+  mir_connection_set_display_config_change_callback (get_connection (screen), config_changed_cb, display);
+  update_display_config (screen);
+
+  return GDK_SCREEN (screen);
+}
+
+static void
+gdk_mir_screen_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (gdk_mir_screen_parent_class)->dispose (object);
+}
+
+static void
+gdk_mir_screen_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gdk_mir_screen_parent_class)->finalize (object);
+}
+
+static GdkDisplay *
+gdk_mir_screen_get_display (GdkScreen *screen)
+{
+  //g_printerr ("gdk_mir_screen_get_display\n");
+  return GDK_DISPLAY (GDK_MIR_SCREEN (screen)->display);
+}
+
+static MirDisplayOutput *
+get_output (GdkScreen *screen, gint monitor_num)
+{
+  MirDisplayConfiguration *config;
+  uint32_t i, j;
+
+  config = GDK_MIR_SCREEN (screen)->display_config;
+
+  for (i = 0, j = 0; i < config->num_outputs; i++)
+    {
+      if (!config->outputs[i].used)
+        continue;
+
+      if (j == monitor_num)
+        return &config->outputs[i];
+      j++;
+    }
+
+  return NULL;
+}
+
+static gint
+gdk_mir_screen_get_width (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_get_width\n");
+  gint width, height;
+  get_screen_size (GDK_MIR_SCREEN (screen)->display_config, &width, &height);
+  return width;
+}
+
+static gint
+gdk_mir_screen_get_height (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_get_height\n");
+  gint width, height;
+  get_screen_size (GDK_MIR_SCREEN (screen)->display_config, &width, &height);
+  return height;
+}
+
+static gint
+gdk_mir_screen_get_width_mm (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_get_width_mm\n");
+  // FIXME: A combination of all screens?
+  return get_output (screen, 0)->physical_width_mm;
+}
+
+static gint
+gdk_mir_screen_get_height_mm (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_get_height_mm\n");
+  // FIXME: A combination of all screens?
+  return get_output (screen, 0)->physical_height_mm;
+}
+
+static gint
+gdk_mir_screen_get_number (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_get_number\n");
+  return 0; //?
+}
+
+static GdkWindow *
+gdk_mir_screen_get_root_window (GdkScreen *screen)
+{
+  //g_printerr ("gdk_mir_screen_get_root_window\n");
+  GdkMirScreen *s = GDK_MIR_SCREEN (screen);
+  gint width, height;
+
+  if (s->root_window)
+     return s->root_window;
+
+  get_screen_size (GDK_MIR_SCREEN (screen)->display_config, &width, &height);
+
+  s->root_window = _gdk_display_create_window (s->display);
+  s->root_window->impl = _gdk_mir_window_impl_new (width, height);
+  s->root_window->impl_window = s->root_window;
+  s->root_window->visual = s->visual;
+  s->root_window->window_type = GDK_WINDOW_ROOT;
+  s->root_window->depth = VISUAL_DEPTH;
+  s->root_window->x = 0;
+  s->root_window->y = 0;
+  s->root_window->abs_x = 0;
+  s->root_window->abs_y = 0;
+  s->root_window->width = width;
+  s->root_window->height = height;
+  s->root_window->viewable = TRUE;
+
+  return s->root_window;
+}
+
+static gint
+gdk_mir_screen_get_n_monitors (GdkScreen *screen)
+{
+  //g_printerr ("gdk_mir_screen_get_n_monitors\n");
+  MirDisplayConfiguration *config;
+  uint32_t i;
+  gint count = 0;
+
+  config = GDK_MIR_SCREEN (screen)->display_config;
+
+  for (i = 0; i < config->num_outputs; i++)
+    if (config->outputs[i].used)
+      count++;
+
+  return count;
+}
+
+static gint
+gdk_mir_screen_get_primary_monitor (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_get_primary_monitor\n");
+  return 0; //?
+}
+
+static gint
+gdk_mir_screen_get_monitor_width_mm    (GdkScreen *screen,
+                                     gint       monitor_num)
+{
+  g_printerr ("gdk_mir_screen_get_monitor_width_mm (%d)\n", monitor_num);
+  return get_output (screen, monitor_num)->physical_width_mm;
+}
+
+static gint
+gdk_mir_screen_get_monitor_height_mm (GdkScreen *screen,
+                                      gint       monitor_num)
+{
+  g_printerr ("gdk_mir_screen_get_monitor_height_mm (%d)\n", monitor_num);
+  return get_output (screen, monitor_num)->physical_height_mm;
+}
+
+static gchar *
+gdk_mir_screen_get_monitor_plug_name (GdkScreen *screen,
+                                      gint       monitor_num)
+{
+  g_printerr ("gdk_mir_screen_get_monitor_plug_name (%d)\n", monitor_num);
+  return NULL; //?
+}
+
+static void
+gdk_mir_screen_get_monitor_geometry (GdkScreen    *screen,
+                                     gint          monitor_num,
+                                     GdkRectangle *dest)
+{
+  g_printerr ("gdk_mir_screen_get_monitor_geometry (%d)\n", monitor_num);
+  MirDisplayOutput *output;
+  MirDisplayMode *mode;
+
+  output = get_output (screen, monitor_num);
+  mode = &output->modes[output->current_mode];
+  dest->x = output->position_x;
+  dest->y = output->position_y;
+  dest->width = mode->horizontal_resolution;
+  dest->height = mode->vertical_resolution;
+}
+
+static void
+gdk_mir_screen_get_monitor_workarea (GdkScreen    *screen,
+                                     gint          monitor_num,
+                                     GdkRectangle *dest)
+{
+  g_printerr ("gdk_mir_screen_get_monitor_workarea (%d)\n", monitor_num);
+  // FIXME: Don't know what this is
+  gdk_mir_screen_get_monitor_geometry (screen, monitor_num, dest);
+}
+
+static GList *
+gdk_mir_screen_list_visuals (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_list_visuals\n");
+  return g_list_append (NULL, GDK_MIR_SCREEN (screen)->visual);
+}
+
+static GdkVisual *
+gdk_mir_screen_get_system_visual (GdkScreen *screen)
+{
+  //g_printerr ("gdk_mir_screen_get_system_visual\n");
+  return GDK_MIR_SCREEN (screen)->visual;
+}
+
+static GdkVisual *
+gdk_mir_screen_get_rgba_visual (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_get_rgba_visual\n");
+  return GDK_MIR_SCREEN (screen)->visual;
+}
+
+static gboolean
+gdk_mir_screen_is_composited (GdkScreen *screen)
+{
+  //g_printerr ("gdk_mir_screen_is_composited\n");
+  /* We're always composited */
+  return TRUE;
+}
+
+static gchar *
+gdk_mir_screen_make_display_name (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_make_display_name\n");
+  return NULL; // FIXME
+}
+
+static GdkWindow *
+gdk_mir_screen_get_active_window (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_get_active_window\n");
+  return NULL; // FIXME
+}
+
+static GList *
+gdk_mir_screen_get_window_stack (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_get_window_stack\n");
+  return NULL; // FIXME
+}
+
+static void
+gdk_mir_screen_broadcast_client_message (GdkScreen *screen,
+                                         GdkEvent  *event)
+{
+  g_printerr ("gdk_mir_screen_broadcast_client_message\n");
+  // FIXME
+}
+
+static gboolean
+gdk_mir_screen_get_setting (GdkScreen   *screen,
+                            const gchar *name,
+                            GValue      *value)
+{
+  //g_printerr ("gdk_mir_screen_get_setting (\"%s\")\n", name);
+
+  if (strcmp (name, "gtk-theme-name") == 0)
+    {
+      g_value_set_string (value, "Ambience");
+      return TRUE;
+    }
+
+  if (strcmp (name, "gtk-font-name") == 0)
+    {
+      g_value_set_string (value, "Ubuntu");
+      return TRUE;
+    }
+
+  if (strcmp (name, "gtk-enable-animations") == 0)
+    {
+      g_value_set_boolean (value, TRUE);
+      return TRUE;
+    }
+
+  if (strcmp (name, "gtk-xft-dpi") == 0)
+    {
+      g_value_set_int (value, 96 * 1024);
+      return TRUE;
+    }
+
+  if (strcmp (name, "gtk-xft-antialias") == 0)
+    {
+      g_value_set_int (value, TRUE);
+      return TRUE;
+    }
+
+  if (strcmp (name, "gtk-xft-hinting") == 0)
+    {
+      g_value_set_int (value, TRUE);
+      return TRUE;
+    }
+
+  if (strcmp (name, "gtk-xft-hintstyle") == 0)
+    {
+      g_value_set_static_string (value, "hintfull");
+      return TRUE;
+    }
+
+  if (strcmp (name, "gtk-xft-rgba") == 0)
+    {
+      g_value_set_static_string (value, "rgba");
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gint
+gdk_mir_screen_visual_get_best_depth (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_visual_get_best_depth\n");
+  return VISUAL_DEPTH;
+}
+
+static GdkVisualType
+gdk_mir_screen_visual_get_best_type (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_visual_get_best_type\n");
+  return VISUAL_TYPE;
+}
+
+static GdkVisual*
+gdk_mir_screen_visual_get_best (GdkScreen *screen)
+{
+  g_printerr ("gdk_mir_screen_visual_get_best\n");
+  return GDK_MIR_SCREEN (screen)->visual;
+}
+
+static GdkVisual*
+gdk_mir_screen_visual_get_best_with_depth (GdkScreen *screen,
+                                           gint       depth)
+{
+  g_printerr ("gdk_mir_screen_visual_get_best_with_depth (%d)\n", depth);
+  return GDK_MIR_SCREEN (screen)->visual;
+}
+
+static GdkVisual*
+gdk_mir_screen_visual_get_best_with_type (GdkScreen     *screen,
+                                          GdkVisualType  visual_type)
+{
+  g_printerr ("gdk_mir_screen_visual_get_best_with_type (%d)\n", visual_type);
+  return GDK_MIR_SCREEN (screen)->visual;
+}
+
+static GdkVisual*
+gdk_mir_screen_visual_get_best_with_both (GdkScreen     *screen,
+                                          gint           depth,
+                                          GdkVisualType  visual_type)
+{
+  g_printerr ("gdk_mir_screen_visual_get_best_with_both\n");
+  return GDK_MIR_SCREEN (screen)->visual;
+}
+
+static void
+gdk_mir_screen_query_depths (GdkScreen  *screen,
+                             gint      **depths,
+                             gint       *count)
+{
+  g_printerr ("gdk_mir_screen_query_depths\n");
+  static gint supported_depths[] = { VISUAL_DEPTH };
+  *depths = supported_depths;
+  *count = 1;
+}
+
+static void
+gdk_mir_screen_query_visual_types (GdkScreen      *screen,
+                                   GdkVisualType **visual_types,
+                                   gint           *count)
+{
+  g_printerr ("gdk_mir_screen_query_visual_types\n");
+  static GdkVisualType supported_visual_types[] = { VISUAL_TYPE };
+  *visual_types = supported_visual_types;
+  *count = 1;
+}
+
+static gint
+gdk_mir_screen_get_monitor_scale_factor (GdkScreen *screen,
+                                         gint       monitor_num)
+{
+  //g_printerr ("gdk_mir_screen_get_monitor_scale_factor (%d)\n", monitor_num);
+  /* Don't support monitor scaling */
+  return 1;
+}
+
+static void
+gdk_mir_screen_init (GdkMirScreen *screen)
+{
+  screen->visual = g_object_new (GDK_TYPE_VISUAL, NULL);
+  screen->visual->screen = GDK_SCREEN (screen);
+  screen->visual->type = VISUAL_TYPE;
+  screen->visual->depth = VISUAL_DEPTH;
+}
+
+static void
+gdk_mir_screen_class_init (GdkMirScreenClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkScreenClass *screen_class = GDK_SCREEN_CLASS (klass);
+
+  object_class->dispose = gdk_mir_screen_dispose;
+  object_class->finalize = gdk_mir_screen_finalize;
+
+  screen_class->get_display = gdk_mir_screen_get_display;
+  screen_class->get_width = gdk_mir_screen_get_width;
+  screen_class->get_height = gdk_mir_screen_get_height;
+  screen_class->get_width_mm = gdk_mir_screen_get_width_mm;
+  screen_class->get_height_mm = gdk_mir_screen_get_height_mm;
+  screen_class->get_number = gdk_mir_screen_get_number;
+  screen_class->get_root_window = gdk_mir_screen_get_root_window;
+  screen_class->get_n_monitors = gdk_mir_screen_get_n_monitors;
+  screen_class->get_primary_monitor = gdk_mir_screen_get_primary_monitor;
+  screen_class->get_monitor_width_mm = gdk_mir_screen_get_monitor_width_mm;
+  screen_class->get_monitor_height_mm = gdk_mir_screen_get_monitor_height_mm;
+  screen_class->get_monitor_plug_name = gdk_mir_screen_get_monitor_plug_name;
+  screen_class->get_monitor_geometry = gdk_mir_screen_get_monitor_geometry;
+  screen_class->get_monitor_workarea = gdk_mir_screen_get_monitor_workarea;
+  screen_class->list_visuals = gdk_mir_screen_list_visuals;
+  screen_class->get_system_visual = gdk_mir_screen_get_system_visual;
+  screen_class->get_rgba_visual = gdk_mir_screen_get_rgba_visual;
+  screen_class->is_composited = gdk_mir_screen_is_composited;
+  screen_class->make_display_name = gdk_mir_screen_make_display_name;
+  screen_class->get_active_window = gdk_mir_screen_get_active_window;
+  screen_class->get_window_stack = gdk_mir_screen_get_window_stack;
+  screen_class->broadcast_client_message = gdk_mir_screen_broadcast_client_message;
+  screen_class->get_setting = gdk_mir_screen_get_setting;
+  screen_class->visual_get_best_depth = gdk_mir_screen_visual_get_best_depth;
+  screen_class->visual_get_best_type = gdk_mir_screen_visual_get_best_type;
+  screen_class->visual_get_best = gdk_mir_screen_visual_get_best;
+  screen_class->visual_get_best_with_depth = gdk_mir_screen_visual_get_best_with_depth;
+  screen_class->visual_get_best_with_type = gdk_mir_screen_visual_get_best_with_type;
+  screen_class->visual_get_best_with_both = gdk_mir_screen_visual_get_best_with_both;
+  screen_class->query_depths = gdk_mir_screen_query_depths;
+  screen_class->query_visual_types = gdk_mir_screen_query_visual_types;
+  screen_class->get_monitor_scale_factor = gdk_mir_screen_get_monitor_scale_factor;
+}
diff --git a/gdk/mir/gdkmirwindow.c b/gdk/mir/gdkmirwindow.c
new file mode 100644
index 0000000..03da7e0
--- /dev/null
+++ b/gdk/mir/gdkmirwindow.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2014 Canonical Ltd
+ *
+ * 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 "gdkinternals.h"
+
+#include "gdkmir.h"
+
+#define GDK_MIR_WINDOW(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WINDOW_MIR, 
GdkMirWindow))
+#define GDK_MIR_WINDOW_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_MIR, 
GdkMirWindowClass))
+#define GDK_IS_WINDOW_MIR_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_MIR))
+#define GDK_MIR_WINDOW_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW_MIR, 
GdkMirWindowClass))
+
+typedef struct _GdkMirWindow GdkMirWindow;
+typedef struct _GdkMirWindowClass GdkMirWindowClass;
+
+struct _GdkMirWindow
+{
+  GdkWindow parent_instance;
+};
+
+struct _GdkMirWindowClass
+{
+  GdkWindowClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMirWindow, gdk_mir_window, GDK_TYPE_WINDOW)
+
+static void
+gdk_mir_window_init (GdkMirWindow *impl)
+{
+}
+
+static void
+gdk_mir_window_class_init (GdkMirWindowClass *klass)
+{
+}
diff --git a/gdk/mir/gdkmirwindowimpl.c b/gdk/mir/gdkmirwindowimpl.c
new file mode 100644
index 0000000..19c9383
--- /dev/null
+++ b/gdk/mir/gdkmirwindowimpl.c
@@ -0,0 +1,1472 @@
+/*
+ * Copyright © 2014 Canonical Ltd
+ *
+ * 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 <inttypes.h>
+
+#include "config.h"
+
+#include "gdk.h"
+#include "gdkmir.h"
+#include "gdkmir-private.h"
+
+#include "gdkwindowimpl.h"
+#include "gdkinternals.h"
+#include "gdkdisplayprivate.h"
+
+#define GDK_TYPE_MIR_WINDOW_IMPL              (gdk_mir_window_impl_get_type ())
+#define GDK_MIR_WINDOW_IMPL(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), 
GDK_TYPE_WINDOW_IMPL_MIR, GdkMirWindowImpl))
+#define GDK_MIR_WINDOW_IMPL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL_MIR, 
GdkMirWindowImplClass))
+#define GDK_IS_WINDOW_IMPL_MIR(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), 
GDK_TYPE_WINDOW_IMPL_MIR))
+#define GDK_IS_WINDOW_IMPL_MIR_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_MIR))
+#define GDK_MIR_WINDOW_IMPL_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW_IMPL_MIR, 
GdkMirWindowImplClass))
+
+typedef struct _GdkMirWindowImpl GdkMirWindowImpl;
+typedef struct _GdkMirWindowImplClass GdkMirWindowImplClass;
+
+struct _GdkMirWindowImpl
+{
+  GdkWindowImpl parent_instance;
+
+  /* Events to report */
+  GdkEventMask event_mask;
+
+  /* Desired surface attributes */
+  int width;
+  int height;
+  MirSurfaceType surface_type; // FIXME
+  MirSurfaceState surface_state;
+
+  /* Pattern for background */
+  cairo_pattern_t *background;
+
+  /* Current button state for checking which buttons are being pressed / released */
+  MirMotionButton button_state;
+
+  /* Surface being rendered to (only exists when window visible) */
+  MirSurface *surface;
+
+  /* Cairo context for current frame */
+  cairo_surface_t *cairo_surface;
+};
+
+struct _GdkMirWindowImplClass
+{
+  GdkWindowImplClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMirWindowImpl, gdk_mir_window_impl, GDK_TYPE_WINDOW_IMPL)
+
+GdkWindowImpl *
+_gdk_mir_window_impl_new (int width, int height)
+{
+  GdkMirWindowImpl *impl = g_object_new (GDK_TYPE_MIR_WINDOW_IMPL, NULL);
+
+  impl->width = width;
+  impl->height = height;
+
+  return GDK_WINDOW_IMPL (impl);
+}
+
+static void
+gdk_mir_window_impl_init (GdkMirWindowImpl *impl)
+{
+}
+
+static MirConnection *
+get_connection (GdkWindow *window)
+{
+  return gdk_mir_display_get_mir_connection (gdk_window_get_display (window));
+}
+
+static void
+set_surface_state (GdkMirWindowImpl *impl, MirSurfaceState state)
+{
+  impl->surface_state = state;
+  if (impl->surface)
+    mir_surface_set_state (impl->surface, state);
+}
+
+static void
+print_modifiers (unsigned int modifiers)
+{
+  g_printerr (" Modifiers");
+  if ((modifiers & mir_key_modifier_alt) != 0)
+    g_printerr (" alt");
+  if ((modifiers & mir_key_modifier_alt_left) != 0)
+    g_printerr (" alt-left");
+  if ((modifiers & mir_key_modifier_alt_right) != 0)
+    g_printerr (" alt-right");
+  if ((modifiers & mir_key_modifier_shift) != 0)
+    g_printerr (" shift");
+  if ((modifiers & mir_key_modifier_shift_left) != 0)
+    g_printerr (" shift-left");
+  if ((modifiers & mir_key_modifier_shift_right) != 0)
+    g_printerr (" shift-right");
+  if ((modifiers & mir_key_modifier_sym) != 0)
+    g_printerr (" sym");
+  if ((modifiers & mir_key_modifier_function) != 0)
+    g_printerr (" function");
+  if ((modifiers & mir_key_modifier_ctrl) != 0)
+    g_printerr (" ctrl");
+  if ((modifiers & mir_key_modifier_ctrl_left) != 0)
+    g_printerr (" ctrl-left");
+  if ((modifiers & mir_key_modifier_ctrl_right) != 0)
+    g_printerr (" ctrl-right");
+  if ((modifiers & mir_key_modifier_meta) != 0)
+    g_printerr (" meta");
+  if ((modifiers & mir_key_modifier_meta_left) != 0)
+    g_printerr (" meta-left");
+  if ((modifiers & mir_key_modifier_meta_right) != 0)
+    g_printerr (" meta-right");
+  if ((modifiers & mir_key_modifier_caps_lock) != 0)
+    g_printerr (" caps-lock");
+  if ((modifiers & mir_key_modifier_num_lock) != 0)
+    g_printerr (" num-lock");
+  if ((modifiers & mir_key_modifier_scroll_lock) != 0)
+    g_printerr (" scroll-lock");
+  g_printerr ("\n");
+}
+
+static void
+print_key_event (const MirKeyEvent *event)
+{
+  g_printerr ("KEY\n");
+  g_printerr (" Device %i\n", event->device_id);
+  g_printerr (" Source %i\n", event->source_id);
+  g_printerr (" Action ");
+  switch (event->action)
+    {
+    case mir_key_action_down:
+      g_printerr ("down");
+      break;
+    case mir_key_action_up:
+      g_printerr ("up");
+      break;
+    case mir_key_action_multiple:
+      g_printerr ("multiple");
+      break;
+    default:
+      g_printerr ("%u", event->action);
+      break;
+    }
+  g_printerr ("\n");
+  g_printerr (" Flags");
+  if ((event->flags & mir_key_flag_woke_here) != 0)
+    g_printerr (" woke-here");
+  if ((event->flags & mir_key_flag_soft_keyboard) != 0)
+    g_printerr (" soft-keyboard");
+  if ((event->flags & mir_key_flag_keep_touch_mode) != 0)
+    g_printerr (" keep-touch-mode");
+  if ((event->flags & mir_key_flag_from_system) != 0)
+    g_printerr (" from-system");
+  if ((event->flags & mir_key_flag_editor_action) != 0)
+    g_printerr (" editor-action");
+  if ((event->flags & mir_key_flag_canceled) != 0)
+    g_printerr (" canceled");
+  if ((event->flags & mir_key_flag_virtual_hard_key) != 0)
+    g_printerr (" virtual-hard-key");
+  if ((event->flags & mir_key_flag_long_press) != 0)
+    g_printerr (" long-press");
+  if ((event->flags & mir_key_flag_canceled_long_press) != 0)
+    g_printerr (" canceled-long-press");
+  if ((event->flags & mir_key_flag_tracking) != 0)
+    g_printerr (" tracking");
+  if ((event->flags & mir_key_flag_fallback) != 0)
+    g_printerr (" fallback");
+  g_printerr ("\n");
+  print_modifiers (event->modifiers);
+  g_printerr (" Key Code %i\n", event->key_code);
+  g_printerr (" Scan Code %i\n", event->scan_code);
+  g_printerr (" Repeat Count %i\n", event->repeat_count);
+  g_printerr (" Down Time %lli\n", (long long int) event->down_time);
+  g_printerr (" Event Time %lli\n", (long long int) event->event_time);
+  g_printerr (" Is System Key %s\n", event->is_system_key ? "true" : "false");
+}
+
+static void
+print_motion_event (const MirMotionEvent *event)
+{
+  size_t i;
+
+  g_printerr ("MOTION\n");
+  g_printerr (" Device %i\n", event->device_id);
+  g_printerr (" Source %i\n", event->source_id);
+  g_printerr (" Action ");
+  switch (event->action)
+    {
+    case mir_motion_action_down:
+      g_printerr ("down");
+      break;
+    case mir_motion_action_up:
+      g_printerr ("up");
+      break;
+    case mir_motion_action_move:
+      g_printerr ("move");
+      break;
+    case mir_motion_action_cancel:
+      g_printerr ("cancel");
+      break;
+    case mir_motion_action_outside:
+      g_printerr ("outside");
+      break;
+    case mir_motion_action_pointer_down:
+      g_printerr ("pointer-down");
+      break;
+    case mir_motion_action_pointer_up:
+      g_printerr ("pointer-up");
+      break;
+    case mir_motion_action_hover_move:
+      g_printerr ("hover-move");
+      break;
+    case mir_motion_action_scroll:
+      g_printerr ("scroll");
+      break;
+    case mir_motion_action_hover_enter:
+      g_printerr ("hover-enter");
+      break;
+    case mir_motion_action_hover_exit:
+      g_printerr ("hover-exit");
+      break;
+    default:
+      g_printerr ("%u", event->action);
+    }
+  g_printerr ("\n");
+  g_printerr (" Flags");
+  switch (event->flags)
+    {
+    case mir_motion_flag_window_is_obscured:
+      g_printerr (" window-is-obscured");
+      break;
+    }
+  g_printerr ("\n");
+  print_modifiers (event->modifiers);
+  g_printerr (" Edge Flags %i\n", event->edge_flags);
+  g_printerr (" Button State");
+  switch (event->button_state)
+    {
+    case mir_motion_button_primary:
+      g_printerr (" primary");
+      break;
+    case mir_motion_button_secondary:
+      g_printerr (" secondary");
+      break;
+    case mir_motion_button_tertiary:
+      g_printerr (" tertiary");
+      break;
+    case mir_motion_button_back:
+      g_printerr (" back");
+      break;
+    case mir_motion_button_forward:
+      g_printerr (" forward");
+      break;
+    }
+  g_printerr ("\n");
+  g_printerr (" Offset (%f, %f)\n", event->x_offset, event->y_offset);
+  g_printerr (" Precision (%f, %f)\n", event->x_precision, event->y_precision);
+  g_printerr (" Down Time %lli\n", (long long int) event->down_time);
+  g_printerr (" Event Time %lli\n", (long long int) event->event_time);
+  g_printerr (" Pointer Coordinates\n");
+  for (i = 0; i < event->pointer_count; i++)
+    {
+      g_printerr ("  ID=%i location=(%f, %f) raw=(%f, %f) touch=(%f, %f) size=%f pressure=%f orientation=%f 
scroll=(%f, %f) tool=",
+                  event->pointer_coordinates[i].id,
+                  event->pointer_coordinates[i].x, event->pointer_coordinates[i].y,
+                  event->pointer_coordinates[i].raw_x, event->pointer_coordinates[i].raw_y,
+                  event->pointer_coordinates[i].touch_major, event->pointer_coordinates[i].touch_minor,
+                  event->pointer_coordinates[i].size,
+                  event->pointer_coordinates[i].pressure,
+                  event->pointer_coordinates[i].orientation,
+                  event->pointer_coordinates[i].hscroll, event->pointer_coordinates[i].vscroll);
+      switch (event->pointer_coordinates[i].tool_type)
+        {
+        case mir_motion_tool_type_unknown:
+          g_printerr ("unknown");
+          break;
+        case mir_motion_tool_type_finger:
+          g_printerr ("finger");
+          break;
+        case mir_motion_tool_type_stylus:
+          g_printerr ("stylus");
+          break;
+        case mir_motion_tool_type_mouse:
+          g_printerr ("mouse");
+          break;
+        case mir_motion_tool_type_eraser:
+          g_printerr ("eraser");
+          break;
+        default:
+          g_printerr ("%u", event->pointer_coordinates[i].tool_type);
+          break;
+        }
+      g_printerr ("\n");
+    }
+}
+
+static void
+print_surface_event (const MirSurfaceEvent *event)
+{
+  g_printerr ("SURFACE\n");
+  g_printerr (" Surface %i\n", event->id);
+  g_printerr (" Attribute ");
+  switch (event->attrib)
+    {
+    case mir_surface_attrib_type:
+      g_printerr ("type");
+      break;
+    case mir_surface_attrib_state:
+      g_printerr ("state");
+      break;
+    case mir_surface_attrib_swapinterval:
+      g_printerr ("swapinterval");
+      break;
+    case mir_surface_attrib_focus:
+      g_printerr ("focus");
+      break;
+    default:
+      g_printerr ("%u", event->attrib);
+      break;
+    }
+  g_printerr ("\n");
+  g_printerr (" Value %i\n", event->value);
+}
+
+static void
+print_resize_event (const MirResizeEvent *event)
+{
+  g_printerr ("RESIZE\n");
+  g_printerr (" Surface %i\n", event->surface_id);
+  g_printerr (" Size (%i, %i)\n", event->width, event->height);
+}
+
+static void
+print_event (const MirEvent *event)
+{
+  switch (event->type)
+    {
+    case mir_event_type_key:
+      print_key_event (&event->key);
+      break;
+    case mir_event_type_motion:
+      print_motion_event (&event->motion);
+      break;
+    case mir_event_type_surface:
+      print_surface_event (&event->surface);
+      break;
+    case mir_event_type_resize:
+      print_resize_event (&event->resize);
+      break;
+    default:
+      g_printerr ("EVENT %u\n", event->type);
+      break;
+    }
+}
+
+static void
+send_event (GdkWindow *window, GdkDevice *device, GdkEvent *event)
+{
+  GdkDisplay *display;
+  GList *node;
+
+  gdk_event_set_device (event, device);
+  event->any.window = g_object_ref (window);
+  event->any.send_event = FALSE; // FIXME: What is this?
+
+  display = gdk_window_get_display (window);
+  node = _gdk_event_queue_append (display, event);
+  _gdk_windowing_got_event (display, node, event, _gdk_display_get_next_serial (display));
+}
+
+static void
+generate_key_event (GdkWindow *window, GdkEventType type, guint state, guint keyval, guint16 keycode, 
gboolean is_modifier)
+{
+  GdkEvent *event;
+
+  event = gdk_event_new (type);
+  event->key.time = 0; // FIXME
+  event->key.state = state;
+  event->key.keyval = keyval;
+  event->key.length = 0;
+  event->key.string = NULL; // FIXME: Is this still needed?
+  event->key.hardware_keycode = keycode;
+  event->key.group = 0; // FIXME
+  event->key.is_modifier = is_modifier;
+
+  send_event (window, _gdk_mir_device_manager_get_keyboard (gdk_display_get_device_manager 
(gdk_window_get_display (window))), event);
+}
+
+static void
+generate_button_event (GdkWindow *window, GdkEventType type, gdouble x, gdouble y, guint button, guint state)
+{
+  GdkEvent *event;
+
+  event = gdk_event_new (type);
+  event->button.time = 0; // FIXME
+  event->button.x = x;
+  event->button.y = y;
+  event->button.state = state;
+  event->button.button = button;
+  event->button.x_root = x; // FIXME
+  event->button.y_root = y; // FIXME
+
+  send_event (window, gdk_device_manager_get_client_pointer (gdk_display_get_device_manager 
(gdk_window_get_display (window))), event);
+}
+
+static void
+generate_scroll_event (GdkWindow *window, gdouble x, gdouble y, gdouble delta_x, gdouble delta_y, guint 
state)
+{
+  GdkEvent *event;
+
+  event = gdk_event_new (GDK_SCROLL);
+  event->scroll.time = 0; // FIXME
+  event->scroll.x = x;
+  event->scroll.y = y;
+  event->scroll.state = state;
+  event->scroll.direction = GDK_SCROLL_SMOOTH;
+  event->scroll.x_root = x; // FIXME
+  event->scroll.y_root = y; // FIXME
+  event->scroll.delta_x = delta_x;
+  event->scroll.delta_y = delta_y;
+
+  send_event (window, gdk_device_manager_get_client_pointer (gdk_display_get_device_manager 
(gdk_window_get_display (window))), event);
+}
+
+static void
+generate_motion_event (GdkWindow *window, gdouble x, gdouble y, guint state)
+{
+  GdkEvent *event;
+
+  event = gdk_event_new (GDK_MOTION_NOTIFY);
+  event->motion.time = 0; // FIXME
+  event->motion.x = x;
+  event->motion.y = y;
+  event->motion.axes = NULL;
+  event->motion.state = state;
+  event->motion.is_hint = FALSE;
+  event->motion.x_root = x; // FIXME
+  event->motion.y_root = y; // FIXME
+
+  send_event (window, gdk_device_manager_get_client_pointer (gdk_display_get_device_manager 
(gdk_window_get_display (window))), event);
+}
+
+static guint
+get_modifier_state (unsigned int modifiers, unsigned int button_state)
+{
+  guint modifier_state = 0;
+
+  if ((modifiers & mir_key_modifier_alt) != 0)
+    modifier_state |= GDK_MOD1_MASK;
+  if ((modifiers & mir_key_modifier_shift) != 0)
+    modifier_state |= GDK_SHIFT_MASK;
+  if ((modifiers & mir_key_modifier_ctrl) != 0)
+    modifier_state |= GDK_CONTROL_MASK;
+  if ((modifiers & mir_key_modifier_meta) != 0)
+    modifier_state |= GDK_SUPER_MASK;
+  if ((modifiers & mir_key_modifier_caps_lock) != 0)
+    modifier_state |= GDK_LOCK_MASK;
+  if ((button_state & mir_motion_button_primary) != 0)
+    modifier_state |= GDK_BUTTON1_MASK;
+  if ((button_state & mir_motion_button_secondary) != 0)
+    modifier_state |= GDK_BUTTON3_MASK;
+  if ((button_state & mir_motion_button_tertiary) != 0)
+    modifier_state |= GDK_BUTTON2_MASK;
+
+  return modifier_state;
+}
+
+static void
+event_cb (MirSurface *surface, const MirEvent *event, void *context)
+{
+  GdkWindow *window = context;
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+  MirMotionButton changed_button_state;
+  GdkEventType event_type;
+  gdouble x, y;
+  guint modifier_state;
+  gboolean is_modifier = FALSE;
+
+  if (g_getenv ("GDK_MIR_LOG_EVENTS"))
+    print_event (event);
+
+  // FIXME: Only generate events if the window wanted them?
+  switch (event->type)
+    {
+    case mir_event_type_key:
+      modifier_state = get_modifier_state (event->key.modifiers, 0); // FIXME: Need to track button state
+
+      switch (event->key.action)
+        {
+        case mir_key_action_down:
+        case mir_key_action_up:
+          // FIXME: Convert keycode
+          // FIXME: is_modifier
+          generate_key_event (window,
+                              event->key.action == mir_key_action_down ? GDK_KEY_PRESS : GDK_KEY_RELEASE,
+                              modifier_state,
+                              event->key.key_code,
+                              event->key.scan_code,
+                              is_modifier);
+          break;
+        default:
+        //case mir_key_action_multiple:
+          // FIXME
+          break;
+        }
+      break;
+    case mir_event_type_motion:
+      if (event->motion.pointer_count < 1)
+        return;
+      x = event->motion.pointer_coordinates[0].x;
+      y = event->motion.pointer_coordinates[0].y;
+      modifier_state = get_modifier_state (event->motion.modifiers, event->motion.button_state);
+
+      switch (event->motion.action)
+        {
+        case mir_motion_action_down:
+        case mir_motion_action_up:
+          event_type = event->motion.action == mir_motion_action_down ? GDK_BUTTON_PRESS : 
GDK_BUTTON_RELEASE;
+          changed_button_state = impl->button_state ^ event->motion.button_state;
+          if ((event_type == GDK_BUTTON_PRESS && (impl->event_mask & GDK_BUTTON_PRESS_MASK) != 0) ||
+              (event_type == GDK_BUTTON_RELEASE && (impl->event_mask & GDK_BUTTON_RELEASE_MASK) != 0))
+            {
+              if ((changed_button_state & mir_motion_button_primary) != 0)
+                generate_button_event (window, event_type, x, y, GDK_BUTTON_PRIMARY, modifier_state);
+              if ((changed_button_state & mir_motion_button_secondary) != 0)
+                generate_button_event (window, event_type, x, y, GDK_BUTTON_SECONDARY, modifier_state);
+              if ((changed_button_state & mir_motion_button_tertiary) != 0)
+                generate_button_event (window, event_type, x, y, GDK_BUTTON_MIDDLE, modifier_state);
+            }
+            impl->button_state = event->motion.button_state;
+          break;
+        case mir_motion_action_scroll:
+          if ((impl->event_mask & GDK_SMOOTH_SCROLL_MASK) != 0)
+            generate_scroll_event (window, x, y, event->motion.pointer_coordinates[0].hscroll, 
event->motion.pointer_coordinates[0].vscroll, modifier_state);
+          break;
+        case mir_motion_action_move: // move with button
+        case mir_motion_action_hover_move: // move without button
+          if ((impl->event_mask & GDK_POINTER_MOTION_MASK) != 0 ||
+              ((impl->event_mask & (GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK)) != 0 && 
(modifier_state & GDK_BUTTON1_MASK)) != 0 ||
+              ((impl->event_mask & (GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK)) != 0 && 
(modifier_state & GDK_BUTTON2_MASK)) != 0 ||
+              ((impl->event_mask & (GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK)) != 0 && 
(modifier_state & GDK_BUTTON3_MASK)) != 0)
+            generate_motion_event (window, x, y, modifier_state);
+          break;
+        }
+      break;
+    case mir_event_type_surface:
+      switch (event->surface.attrib)
+        {
+        case mir_surface_attrib_type:
+          break;
+        case mir_surface_attrib_state:
+          impl->surface_state = event->surface.value;
+          // FIXME: notify
+          break;
+        case mir_surface_attrib_swapinterval:
+          break;
+        case mir_surface_attrib_focus:
+          if (event->surface.value)
+            gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FOCUSED);
+          else
+            gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FOCUSED, 0);
+          break;
+        default:
+          break;
+        }
+      break;
+    case mir_event_type_resize:
+      // FIXME: Generate configure event
+      break;
+    default:
+      // FIXME?
+      break;
+    }
+}
+
+static void
+ensure_surface (GdkWindow *window)
+{
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+  MirPixelFormat formats[100], pixel_format = mir_pixel_format_invalid;
+  unsigned int n_formats, i;
+  MirSurfaceParameters parameters;
+  MirEventDelegate event_delegate = { event_cb, window };
+
+  if (impl->surface)
+    return;
+
+  // Should probably calculate this once?
+  // Should prefer certain formats over others
+  mir_connection_get_available_surface_formats (get_connection (window), formats, 100, &n_formats);
+  for (i = 0; i < n_formats; i++)
+    if (formats[i] == mir_pixel_format_argb_8888)
+      {
+        pixel_format = formats[i];
+        break;
+      }
+
+  parameters.name = "GTK+ Mir";
+  parameters.width = impl->width;
+  parameters.height = impl->height;
+  parameters.pixel_format = pixel_format;
+  parameters.buffer_usage = mir_buffer_usage_software;
+  parameters.output_id = mir_display_output_id_invalid;
+  impl->surface = mir_connection_create_surface_sync (get_connection (window), &parameters);
+  mir_surface_set_event_handler (impl->surface, &event_delegate); // FIXME: Ignore some events until shown
+  set_surface_state (impl, impl->surface_state);
+}
+
+static void
+send_buffer (GdkWindow *window)
+{
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+
+  /* Send the completed buffer to Mir */
+  mir_surface_swap_buffers_sync (impl->surface);
+
+  /* The Cairo context is no longer valid */
+  if (impl->cairo_surface)
+    {
+      cairo_surface_destroy (impl->cairo_surface);
+      impl->cairo_surface = NULL;
+    }
+}
+
+static cairo_surface_t *
+gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_ref_cairo_surface\n");
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+  MirGraphicsRegion region;
+  cairo_format_t pixel_format = CAIRO_FORMAT_INVALID;
+  cairo_surface_t *cairo_surface;
+  cairo_t *c;
+
+  if (impl->cairo_surface)
+    {
+      cairo_surface_reference (impl->cairo_surface);
+      return impl->cairo_surface;
+    }
+
+  ensure_surface (window);
+
+  mir_surface_get_graphics_region (impl->surface, &region);
+
+  // FIXME: Should calculate this once
+  switch (region.pixel_format)
+    {
+    case mir_pixel_format_argb_8888:
+      pixel_format = CAIRO_FORMAT_ARGB32;
+      break;
+    default:
+    case mir_pixel_format_abgr_8888:
+    case mir_pixel_format_xbgr_8888:
+    case mir_pixel_format_xrgb_8888:
+    case mir_pixel_format_bgr_888:
+        // uh-oh...
+        g_printerr ("Unsupported pixel format %d\n", region.pixel_format);
+        break;
+    }
+
+  cairo_surface = cairo_image_surface_create_for_data ((unsigned char *) region.vaddr,
+                                                       pixel_format,
+                                                       region.width,
+                                                       region.height,
+                                                       region.stride);
+  impl->cairo_surface = cairo_surface_reference (cairo_surface);
+
+  /* Draw background */
+  c = cairo_create (impl->cairo_surface);
+  if (impl->background)
+    cairo_set_source (c, impl->background);
+  else
+    cairo_set_source_rgb (c, 1.0, 0.0, 0.0);
+  cairo_paint (c);
+  cairo_destroy (c);
+
+  return cairo_surface;
+}
+
+static cairo_surface_t *
+gdk_mir_window_impl_create_similar_image_surface (GdkWindow      *window,
+                                                  cairo_format_t  format,
+                                                  int             width,
+                                                  int             height)
+{
+  g_printerr ("gdk_mir_window_impl_create_similar_image_surface\n");
+  return cairo_image_surface_create (format, width, height);
+}
+
+static void
+gdk_mir_window_impl_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gdk_mir_window_impl_parent_class)->finalize (object);
+}
+
+static void
+gdk_mir_window_impl_show (GdkWindow *window,
+                          gboolean   already_mapped)
+{
+  cairo_surface_t *s;
+
+  g_printerr ("gdk_mir_window_impl_show\n");
+
+  /* Make sure there's a surface to see */
+  ensure_surface (window);
+
+  /* Make sure something is rendered and then show first frame */
+  s = gdk_mir_window_impl_ref_cairo_surface (window);
+  send_buffer (window);
+  cairo_surface_destroy (s);
+}
+
+static void
+gdk_mir_window_impl_hide (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_hide\n");
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+
+  if (impl->surface)
+    {
+      mir_surface_release_sync (impl->surface);
+      impl->surface = NULL;
+    }
+}
+
+static void
+gdk_mir_window_impl_withdraw (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_withdraw\n");
+}
+
+static void
+gdk_mir_window_impl_raise (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_raise\n");
+  /* We don't support client window stacking */
+}
+
+static void
+gdk_mir_window_impl_lower (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_lower\n");
+  /* We don't support client window stacking */
+}
+
+static void
+gdk_mir_window_impl_restack_under (GdkWindow *window,
+                                   GList     *native_siblings)
+{
+  //g_printerr ("gdk_mir_window_impl_restack_under\n");
+  /* We don't support client window stacking */
+}
+
+static void
+gdk_mir_window_impl_restack_toplevel (GdkWindow *window,
+                                      GdkWindow *sibling,
+                                      gboolean   above)
+{
+  //g_printerr ("gdk_mir_window_impl_restack_toplevel\n");
+  /* We don't support client window stacking */
+}
+
+static void
+gdk_mir_window_impl_move_resize (GdkWindow *window,
+                                 gboolean   with_move,
+                                 gint       x,
+                                 gint       y,
+                                 gint       width,
+                                 gint       height)
+{
+  g_printerr ("gdk_mir_window_impl_move_resize\n");
+}
+
+static void
+gdk_mir_window_impl_set_background (GdkWindow       *window,
+                                    cairo_pattern_t *pattern)
+{
+  g_printerr ("gdk_mir_window_impl_set_background\n");
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+
+  if (impl->background)
+    cairo_pattern_destroy (impl->background);
+  impl->background = cairo_pattern_reference (pattern);
+}
+
+static GdkEventMask
+gdk_mir_window_impl_get_events (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_get_events\n");
+  return GDK_MIR_WINDOW_IMPL (window)->event_mask;
+}
+
+static void
+gdk_mir_window_impl_set_events (GdkWindow    *window,
+                                GdkEventMask  event_mask)
+{
+  //g_printerr ("gdk_mir_window_impl_set_events\n");
+  GDK_MIR_WINDOW_IMPL (window->impl)->event_mask = event_mask;
+}
+
+static gboolean
+gdk_mir_window_impl_reparent (GdkWindow *window,
+                              GdkWindow *new_parent,
+                              gint       x,
+                              gint       y)
+{
+  g_printerr ("gdk_mir_window_impl_reparent\n");
+  return FALSE;
+}
+
+static void
+gdk_mir_window_impl_set_device_cursor (GdkWindow *window,
+                                       GdkDevice *device,
+                                       GdkCursor *cursor)
+{
+  g_printerr ("gdk_mir_window_impl_set_device_cursor\n");
+}
+
+static void
+gdk_mir_window_impl_get_geometry (GdkWindow *window,
+                                  gint      *x,
+                                  gint      *y,
+                                  gint      *width,
+                                  gint      *height)
+{
+  g_printerr ("gdk_mir_window_impl_get_geometry\n");
+}
+
+static gint
+gdk_mir_window_impl_get_root_coords (GdkWindow *window,
+                                     gint       x,
+                                     gint       y,
+                                     gint      *root_x,
+                                     gint      *root_y)
+{
+  g_printerr ("gdk_mir_window_impl_get_root_coords\n");
+  return 0;
+}
+
+static gboolean
+gdk_mir_window_impl_get_device_state (GdkWindow       *window,
+                                      GdkDevice       *device,
+                                      gdouble         *x,
+                                      gdouble         *y,
+                                      GdkModifierType *mask)
+{
+  g_printerr ("gdk_mir_window_impl_get_device_state\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_window_impl_begin_paint_region (GdkWindow            *window,
+                                        const cairo_region_t *region)
+{
+  g_printerr ("gdk_mir_window_impl_begin_paint_region\n");
+  /* Indicate we are ready to be drawn onto directly? */
+  return FALSE;
+}
+
+static void
+gdk_mir_window_impl_end_paint (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_end_paint\n");
+  send_buffer (window);
+}
+
+static cairo_region_t *
+gdk_mir_window_impl_get_shape (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_get_shape\n");
+  return NULL;
+}
+
+static cairo_region_t *
+gdk_mir_window_impl_get_input_shape (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_get_input_shape\n");
+  return NULL;
+}
+
+static void
+gdk_mir_window_impl_shape_combine_region (GdkWindow            *window,
+                                          const cairo_region_t *shape_region,
+                                          gint                  offset_x,
+                                          gint                  offset_y)
+{
+  g_printerr ("gdk_mir_window_impl_shape_combine_region\n");
+}
+
+static void
+gdk_mir_window_impl_input_shape_combine_region (GdkWindow            *window,
+                                                const cairo_region_t *shape_region,
+                                                gint                  offset_x,
+                                                gint                  offset_y)
+{
+  g_printerr ("gdk_mir_window_impl_input_shape_combine_region\n");
+}
+
+static gboolean
+gdk_mir_window_impl_set_static_gravities (GdkWindow *window,
+                                          gboolean   use_static)
+{
+  g_printerr ("gdk_mir_window_impl_set_static_gravities\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_window_impl_queue_antiexpose (GdkWindow      *window,
+                                      cairo_region_t *area)
+{
+  g_printerr ("gdk_mir_window_impl_queue_antiexpose\n");
+  return FALSE;
+}
+
+static void
+gdk_mir_window_impl_destroy (GdkWindow *window,
+                             gboolean   recursing,
+                             gboolean   foreign_destroy)
+{
+  g_printerr ("gdk_mir_window_impl_destroy\n");
+}
+
+static void
+gdk_mir_window_impl_destroy_foreign (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_destroy_foreign\n");
+}
+
+static cairo_surface_t *
+gdk_mir_window_impl_resize_cairo_surface (GdkWindow       *window,
+                                          cairo_surface_t *surface,
+                                          gint             width,
+                                          gint             height)
+{
+  g_printerr ("gdk_mir_window_impl_resize_cairo_surface\n");
+  return surface;
+}
+
+static void
+gdk_mir_window_impl_focus (GdkWindow *window,
+                      guint32    timestamp)
+{
+  g_printerr ("gdk_mir_window_impl_focus\n");
+}
+
+static void
+gdk_mir_window_impl_set_type_hint (GdkWindow         *window,
+                                   GdkWindowTypeHint  hint)
+{
+  g_printerr ("gdk_mir_window_impl_set_type_hint\n");
+}
+
+static GdkWindowTypeHint
+gdk_mir_window_impl_get_type_hint (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_get_type_hint\n");
+  return GDK_WINDOW_TYPE_HINT_NORMAL;
+}
+
+void
+gdk_mir_window_impl_set_modal_hint (GdkWindow *window,
+                                    gboolean   modal)
+{
+  g_printerr ("gdk_mir_window_impl_set_modal_hint\n");
+}
+
+static void
+gdk_mir_window_impl_set_skip_taskbar_hint (GdkWindow *window,
+                                           gboolean   skips_taskbar)
+{
+  g_printerr ("gdk_mir_window_impl_set_skip_taskbar_hint\n");
+}
+
+static void
+gdk_mir_window_impl_set_skip_pager_hint (GdkWindow *window,
+                                         gboolean   skips_pager)
+{
+  g_printerr ("gdk_mir_window_impl_set_skip_pager_hint\n");
+}
+
+static void
+gdk_mir_window_impl_set_urgency_hint (GdkWindow *window,
+                                      gboolean   urgent)
+{
+  g_printerr ("gdk_mir_window_impl_set_urgency_hint\n");
+}
+
+static void
+gdk_mir_window_impl_set_geometry_hints (GdkWindow         *window,
+                                        const GdkGeometry *geometry,
+                                        GdkWindowHints     geom_mask)
+{
+  g_printerr ("gdk_mir_window_impl_set_geometry_hints\n");
+}
+
+static void
+gdk_mir_window_impl_set_title (GdkWindow   *window,
+                               const gchar *title)
+{
+  g_printerr ("gdk_mir_window_impl_set_title\n");
+}
+
+static void
+gdk_mir_window_impl_set_role (GdkWindow   *window,
+                              const gchar *role)
+{
+  g_printerr ("gdk_mir_window_impl_set_role\n");
+}
+
+static void
+gdk_mir_window_impl_set_startup_id (GdkWindow   *window,
+                                    const gchar *startup_id)
+{
+  g_printerr ("gdk_mir_window_impl_set_startup_id\n");
+}
+
+static void
+gdk_mir_window_impl_set_transient_for (GdkWindow *window,
+                                       GdkWindow *parent)
+{
+  g_printerr ("gdk_mir_window_impl_set_transient_for\n");
+}
+
+static void
+gdk_mir_window_impl_get_root_origin (GdkWindow *window,
+                                     gint      *x,
+                                     gint      *y)
+{
+  g_printerr ("gdk_mir_window_impl_get_root_origin\n");
+}
+
+static void
+gdk_mir_window_impl_get_frame_extents (GdkWindow    *window,
+                                       GdkRectangle *rect)
+{
+  g_printerr ("gdk_mir_window_impl_get_frame_extents\n");
+}
+
+static void
+gdk_mir_window_impl_set_override_redirect (GdkWindow *window,
+                                           gboolean   override_redirect)
+{
+  g_printerr ("gdk_mir_window_impl_set_override_redirect\n");
+}
+
+static void
+gdk_mir_window_impl_set_accept_focus (GdkWindow *window,
+                                      gboolean   accept_focus)
+{
+  g_printerr ("gdk_mir_window_impl_set_accept_focus\n");
+}
+
+static void
+gdk_mir_window_impl_set_focus_on_map (GdkWindow *window,
+                                      gboolean focus_on_map)
+{
+  g_printerr ("gdk_mir_window_impl_set_focus_on_map\n");
+}
+
+static void
+gdk_mir_window_impl_set_icon_list (GdkWindow *window,
+                                   GList     *pixbufs)
+{
+  g_printerr ("gdk_mir_window_impl_set_icon_list\n");
+}
+
+static void
+gdk_mir_window_impl_set_icon_name (GdkWindow   *window,
+                                   const gchar *name)
+{
+  g_printerr ("gdk_mir_window_impl_set_icon_name\n");
+}
+
+static void
+gdk_mir_window_impl_iconify (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_iconify\n");
+  /* We don't support iconification */
+}
+
+static void
+gdk_mir_window_impl_deiconify (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_deiconify\n");
+  /* We don't support iconification */
+}
+
+static void
+gdk_mir_window_impl_stick (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_stick\n");
+  /* We do not support stick/unstick in Mir */
+}
+
+static void
+gdk_mir_window_impl_unstick (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_unstick\n");
+  /* We do not support stick/unstick in Mir */
+}
+
+static void
+gdk_mir_window_impl_maximize (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_maximize\n");
+  set_surface_state (GDK_MIR_WINDOW_IMPL (window->impl), mir_surface_state_maximized);
+}
+
+static void
+gdk_mir_window_impl_unmaximize (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_unmaximize\n");
+  set_surface_state (GDK_MIR_WINDOW_IMPL (window->impl), mir_surface_state_restored);
+}
+
+static void
+gdk_mir_window_impl_fullscreen (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_fullscreen\n");
+  set_surface_state (GDK_MIR_WINDOW_IMPL (window->impl), mir_surface_state_fullscreen);
+}
+
+static void
+gdk_mir_window_impl_unfullscreen (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_unfullscreen\n");
+  set_surface_state (GDK_MIR_WINDOW_IMPL (window->impl), mir_surface_state_restored);
+}
+
+static void
+gdk_mir_window_impl_set_keep_above (GdkWindow *window,
+                                    gboolean   setting)
+{
+  //g_printerr ("gdk_mir_window_impl_set_keep_above\n");
+  /* We do not support keep above/below in Mir */
+}
+
+static void
+gdk_mir_window_impl_set_keep_below (GdkWindow *window,
+                                    gboolean setting)
+{
+  //g_printerr ("gdk_mir_window_impl_set_keep_below\n");
+  /* We do not support keep above/below in Mir */
+}
+
+static GdkWindow *
+gdk_mir_window_impl_get_group (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_get_group\n");
+  return NULL;
+}
+
+static void
+gdk_mir_window_impl_set_group (GdkWindow *window,
+                               GdkWindow *leader)
+{
+  g_printerr ("gdk_mir_window_impl_set_group\n");
+}
+
+static void
+gdk_mir_window_impl_set_decorations (GdkWindow       *window,
+                                     GdkWMDecoration  decorations)
+{
+  g_printerr ("gdk_mir_window_impl_set_decorations (%u)\n", decorations);
+}
+
+static gboolean
+gdk_mir_window_impl_get_decorations (GdkWindow       *window,
+                                     GdkWMDecoration *decorations)
+{
+  g_printerr ("gdk_mir_window_impl_get_decorations\n");
+  return FALSE;
+}
+
+static void
+gdk_mir_window_impl_set_functions (GdkWindow     *window,
+                                   GdkWMFunction  functions)
+{
+  g_printerr ("gdk_mir_window_impl_set_functions\n");
+}
+
+static void
+gdk_mir_window_impl_begin_resize_drag (GdkWindow     *window,
+                                       GdkWindowEdge  edge,
+                                       GdkDevice     *device,
+                                       gint           button,
+                                       gint           root_x,
+                                       gint           root_y,
+                                       guint32        timestamp)
+{
+  g_printerr ("gdk_mir_window_impl_begin_resize_drag\n");
+}
+
+static void
+gdk_mir_window_impl_begin_move_drag (GdkWindow *window,
+                                     GdkDevice *device,
+                                     gint       button,
+                                     gint       root_x,
+                                     gint       root_y,
+                                     guint32    timestamp)
+{
+  g_printerr ("gdk_mir_window_impl_begin_move_drag\n");
+}
+
+static void
+gdk_mir_window_impl_enable_synchronized_configure (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_enable_synchronized_configure\n");
+}
+
+static void
+gdk_mir_window_impl_configure_finished (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_configure_finished\n");
+}
+
+static void
+gdk_mir_window_impl_set_opacity (GdkWindow *window,
+                                 gdouble    opacity)
+{
+  g_printerr ("gdk_mir_window_impl_set_opacity\n");
+}
+
+static void
+gdk_mir_window_impl_set_composited (GdkWindow *window,
+                                    gboolean   composited)
+{
+  g_printerr ("gdk_mir_window_impl_set_composited\n");
+}
+
+static void
+gdk_mir_window_impl_destroy_notify (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_destroy_notify\n");
+}
+
+static GdkDragProtocol
+gdk_mir_window_impl_get_drag_protocol (GdkWindow *window,
+                                       GdkWindow **target)
+{
+  g_printerr ("gdk_mir_window_impl_get_drag_protocol\n");
+  return 0;
+}
+
+static void
+gdk_mir_window_impl_register_dnd (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_register_dnd\n");
+}
+
+static GdkDragContext *
+gdk_mir_window_impl_drag_begin (GdkWindow *window,
+                                GdkDevice *device,
+                                GList     *targets)
+{
+  g_printerr ("gdk_mir_window_impl_drag_begin\n");
+  return NULL;
+}
+
+static void
+gdk_mir_window_impl_process_updates_recurse (GdkWindow      *window,
+                                             cairo_region_t *region)
+{
+  g_printerr ("gdk_mir_window_impl_process_updates_recurse\n");
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+  cairo_rectangle_int_t rectangle;
+
+  /* We redraw the whole region, but we should track the buffers and only redraw what has changed since we 
sent this buffer */
+  rectangle.x = 0;
+  rectangle.y = 0;
+  rectangle.width = impl->width;
+  rectangle.height = impl->height;
+  cairo_region_union_rectangle (region, &rectangle);
+
+  _gdk_window_process_updates_recurse (window, region);
+}
+
+static void
+gdk_mir_window_impl_sync_rendering (GdkWindow *window)
+{
+  g_printerr ("gdk_mir_window_impl_sync_rendering\n");
+  // FIXME: Only used for benchmarking
+}
+
+static gboolean
+gdk_mir_window_impl_simulate_key (GdkWindow       *window,
+                                  gint             x,
+                                  gint             y,
+                                  guint            keyval,
+                                  GdkModifierType  modifiers,
+                                  GdkEventType     key_pressrelease)
+{
+  g_printerr ("gdk_mir_window_impl_simulate_key\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_window_impl_simulate_button (GdkWindow       *window,
+                                     gint             x,
+                                     gint             y,
+                                     guint            button,
+                                     GdkModifierType  modifiers,
+                                     GdkEventType     button_pressrelease)
+{
+  g_printerr ("gdk_mir_window_impl_simulate_button\n");
+  return FALSE;
+}
+
+static gboolean
+gdk_mir_window_impl_get_property (GdkWindow   *window,
+                                  GdkAtom      property,
+                                  GdkAtom      type,
+                                  gulong       offset,
+                                  gulong       length,
+                                  gint         pdelete,
+                                  GdkAtom     *actual_property_type,
+                                  gint        *actual_format_type,
+                                  gint        *actual_length,
+                                  guchar     **data)
+{
+  g_printerr ("gdk_mir_window_impl_get_property\n");
+  return FALSE;
+}
+
+static void
+gdk_mir_window_impl_change_property (GdkWindow    *window,
+                                     GdkAtom       property,
+                                     GdkAtom       type,
+                                     gint          format,
+                                     GdkPropMode   mode,
+                                     const guchar *data,
+                                     gint          nelements)
+{
+  g_printerr ("gdk_mir_window_impl_change_property\n");
+}
+
+static void
+gdk_mir_window_impl_delete_property (GdkWindow *window,
+                                     GdkAtom    property)
+{
+  g_printerr ("gdk_mir_window_impl_delete_property\n");
+}
+
+static gint
+gdk_mir_window_impl_get_scale_factor (GdkWindow *window)
+{
+  //g_printerr ("gdk_mir_window_impl_get_scale_factor\n");
+  /* Don't support monitor scaling */
+  return 1;
+}
+
+static void
+gdk_mir_window_impl_set_opaque_region (GdkWindow      *window,
+                                       cairo_region_t *region)
+{
+  //g_printerr ("gdk_mir_window_impl_set_opaque_region\n");
+  /* FIXME: An optimisation to tell the compositor which regions of the window are fully transparent */
+}
+
+static void
+gdk_mir_window_impl_class_init (GdkMirWindowImplClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
+
+  object_class->finalize = gdk_mir_window_impl_finalize;
+
+  impl_class->ref_cairo_surface = gdk_mir_window_impl_ref_cairo_surface;
+  impl_class->create_similar_image_surface = gdk_mir_window_impl_create_similar_image_surface;
+  impl_class->show = gdk_mir_window_impl_show;
+  impl_class->hide = gdk_mir_window_impl_hide;
+  impl_class->withdraw = gdk_mir_window_impl_withdraw;
+  impl_class->raise = gdk_mir_window_impl_raise;
+  impl_class->lower = gdk_mir_window_impl_lower;
+  impl_class->restack_under = gdk_mir_window_impl_restack_under;
+  impl_class->restack_toplevel = gdk_mir_window_impl_restack_toplevel;
+  impl_class->move_resize = gdk_mir_window_impl_move_resize;
+  impl_class->set_background = gdk_mir_window_impl_set_background;
+  impl_class->get_events = gdk_mir_window_impl_get_events;
+  impl_class->set_events = gdk_mir_window_impl_set_events;
+  impl_class->reparent = gdk_mir_window_impl_reparent;
+  impl_class->set_device_cursor = gdk_mir_window_impl_set_device_cursor;
+  impl_class->get_geometry = gdk_mir_window_impl_get_geometry;
+  impl_class->get_root_coords = gdk_mir_window_impl_get_root_coords;
+  impl_class->get_device_state = gdk_mir_window_impl_get_device_state;
+  impl_class->begin_paint_region = gdk_mir_window_impl_begin_paint_region;
+  impl_class->end_paint = gdk_mir_window_impl_end_paint;
+  impl_class->get_shape = gdk_mir_window_impl_get_shape;
+  impl_class->get_input_shape = gdk_mir_window_impl_get_input_shape;
+  impl_class->shape_combine_region = gdk_mir_window_impl_shape_combine_region;
+  impl_class->input_shape_combine_region = gdk_mir_window_impl_input_shape_combine_region;
+  impl_class->set_static_gravities = gdk_mir_window_impl_set_static_gravities;
+  impl_class->queue_antiexpose = gdk_mir_window_impl_queue_antiexpose;
+  impl_class->destroy = gdk_mir_window_impl_destroy;
+  impl_class->destroy_foreign = gdk_mir_window_impl_destroy_foreign;
+  impl_class->resize_cairo_surface = gdk_mir_window_impl_resize_cairo_surface;
+  impl_class->focus = gdk_mir_window_impl_focus;
+  impl_class->set_type_hint = gdk_mir_window_impl_set_type_hint;
+  impl_class->get_type_hint = gdk_mir_window_impl_get_type_hint;
+  impl_class->set_modal_hint = gdk_mir_window_impl_set_modal_hint;
+  impl_class->set_skip_taskbar_hint = gdk_mir_window_impl_set_skip_taskbar_hint;
+  impl_class->set_skip_pager_hint = gdk_mir_window_impl_set_skip_pager_hint;
+  impl_class->set_urgency_hint = gdk_mir_window_impl_set_urgency_hint;
+  impl_class->set_geometry_hints = gdk_mir_window_impl_set_geometry_hints;
+  impl_class->set_title = gdk_mir_window_impl_set_title;
+  impl_class->set_role = gdk_mir_window_impl_set_role;
+  impl_class->set_startup_id = gdk_mir_window_impl_set_startup_id;
+  impl_class->set_transient_for = gdk_mir_window_impl_set_transient_for;
+  impl_class->get_root_origin = gdk_mir_window_impl_get_root_origin;
+  impl_class->get_frame_extents = gdk_mir_window_impl_get_frame_extents;
+  impl_class->set_override_redirect = gdk_mir_window_impl_set_override_redirect;
+  impl_class->set_accept_focus = gdk_mir_window_impl_set_accept_focus;
+  impl_class->set_focus_on_map = gdk_mir_window_impl_set_focus_on_map;
+  impl_class->set_icon_list = gdk_mir_window_impl_set_icon_list;
+  impl_class->set_icon_name = gdk_mir_window_impl_set_icon_name;
+  impl_class->iconify = gdk_mir_window_impl_iconify;
+  impl_class->deiconify = gdk_mir_window_impl_deiconify;
+  impl_class->stick = gdk_mir_window_impl_stick;
+  impl_class->unstick = gdk_mir_window_impl_unstick;
+  impl_class->maximize = gdk_mir_window_impl_maximize;
+  impl_class->unmaximize = gdk_mir_window_impl_unmaximize;
+  impl_class->fullscreen = gdk_mir_window_impl_fullscreen;
+  impl_class->unfullscreen = gdk_mir_window_impl_unfullscreen;
+  impl_class->set_keep_above = gdk_mir_window_impl_set_keep_above;
+  impl_class->set_keep_below = gdk_mir_window_impl_set_keep_below;
+  impl_class->get_group = gdk_mir_window_impl_get_group;
+  impl_class->set_group = gdk_mir_window_impl_set_group;
+  impl_class->set_decorations = gdk_mir_window_impl_set_decorations;
+  impl_class->get_decorations = gdk_mir_window_impl_get_decorations;
+  impl_class->set_functions = gdk_mir_window_impl_set_functions;
+  impl_class->begin_resize_drag = gdk_mir_window_impl_begin_resize_drag;
+  impl_class->begin_move_drag = gdk_mir_window_impl_begin_move_drag;
+  impl_class->enable_synchronized_configure = gdk_mir_window_impl_enable_synchronized_configure;
+  impl_class->configure_finished = gdk_mir_window_impl_configure_finished;
+  impl_class->set_opacity = gdk_mir_window_impl_set_opacity;
+  impl_class->set_composited = gdk_mir_window_impl_set_composited;
+  impl_class->destroy_notify = gdk_mir_window_impl_destroy_notify;
+  impl_class->get_drag_protocol = gdk_mir_window_impl_get_drag_protocol;
+  impl_class->register_dnd = gdk_mir_window_impl_register_dnd;
+  impl_class->drag_begin = gdk_mir_window_impl_drag_begin;
+  impl_class->process_updates_recurse = gdk_mir_window_impl_process_updates_recurse;
+  impl_class->sync_rendering = gdk_mir_window_impl_sync_rendering;
+  impl_class->simulate_key = gdk_mir_window_impl_simulate_key;
+  impl_class->simulate_button = gdk_mir_window_impl_simulate_button;
+  impl_class->get_property = gdk_mir_window_impl_get_property;
+  impl_class->change_property = gdk_mir_window_impl_change_property;
+  impl_class->delete_property = gdk_mir_window_impl_delete_property;
+  impl_class->get_scale_factor = gdk_mir_window_impl_get_scale_factor;
+  impl_class->set_opaque_region = gdk_mir_window_impl_set_opaque_region;
+}


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