GdkWindow -> GdkSurface: File renames
authorAlexander Larsson <alexl@redhat.com>
Tue, 20 Mar 2018 10:46:11 +0000 (11:46 +0100)
committerAlexander Larsson <alexl@redhat.com>
Tue, 20 Mar 2018 10:46:11 +0000 (11:46 +0100)
Rename all *window.[ch] source files.

This is an automatic operation, done by the following commands:

for i in $(git ls-files gdk | grep window); do
    git mv $i $(echo $i | sed s/window/surface/);
    git sed -f g $(basename $i) $(basename $i | sed s/window/surface/) ;
done

git checkout NEWS* po-properties po

95 files changed:
demos/gtk-demo/list_store.c
gdk/broadway/gdkbroadway.h
gdk/broadway/gdkbroadwaysurface.h [new file with mode: 0644]
gdk/broadway/gdkbroadwaywindow.h [deleted file]
gdk/broadway/gdkdevice-broadway.c
gdk/broadway/gdkdisplay-broadway.h
gdk/broadway/gdkprivate-broadway.h
gdk/broadway/gdksurface-broadway.c [new file with mode: 0644]
gdk/broadway/gdksurface-broadway.h [new file with mode: 0644]
gdk/broadway/gdkwindow-broadway.c [deleted file]
gdk/broadway/gdkwindow-broadway.h [deleted file]
gdk/broadway/meson.build
gdk/gdk.h
gdk/gdkdisplay.c
gdk/gdkdisplayprivate.h
gdk/gdkdnd.c
gdk/gdkdrawingcontext.c
gdk/gdkinternals.h
gdk/gdkpixbuf-drawable.c
gdk/gdkseat.h
gdk/gdksurface.c [new file with mode: 0644]
gdk/gdksurface.h [new file with mode: 0644]
gdk/gdksurfaceimpl.c [new file with mode: 0644]
gdk/gdksurfaceimpl.h [new file with mode: 0644]
gdk/gdkwindow.c [deleted file]
gdk/gdkwindow.h [deleted file]
gdk/gdkwindowimpl.c [deleted file]
gdk/gdkwindowimpl.h [deleted file]
gdk/meson.build
gdk/quartz/GdkQuartzNSWindow.c
gdk/quartz/GdkQuartzView.c
gdk/quartz/gdkdevice-core-quartz.c
gdk/quartz/gdkdisplay-quartz.c
gdk/quartz/gdkdisplay-quartz.h
gdk/quartz/gdkevents-quartz.c
gdk/quartz/gdkglcontext-quartz.h
gdk/quartz/gdkprivate-quartz.h
gdk/quartz/gdkquartz.h
gdk/quartz/gdkquartzsurface.h [new file with mode: 0644]
gdk/quartz/gdkquartzwindow.h [deleted file]
gdk/quartz/gdkscreen-quartz.c
gdk/quartz/gdksurface-quartz.c [new file with mode: 0644]
gdk/quartz/gdksurface-quartz.h [new file with mode: 0644]
gdk/quartz/gdkwindow-quartz.c [deleted file]
gdk/quartz/gdkwindow-quartz.h [deleted file]
gdk/quartz/meson.build
gdk/wayland/gdkdevice-wayland.c
gdk/wayland/gdkdisplay-wayland.h
gdk/wayland/gdkglcontext-wayland.c
gdk/wayland/gdkglcontext-wayland.h
gdk/wayland/gdksurface-wayland.c [new file with mode: 0644]
gdk/wayland/gdkvulkancontext-wayland.c
gdk/wayland/gdkwayland.h
gdk/wayland/gdkwaylandsurface.h [new file with mode: 0644]
gdk/wayland/gdkwaylandwindow.h [deleted file]
gdk/wayland/gdkwindow-wayland.c [deleted file]
gdk/wayland/meson.build
gdk/win32/gdkcursor-win32.c
gdk/win32/gdkdevice-virtual.c
gdk/win32/gdkdevice-win32.c
gdk/win32/gdkdevice-wintab.c
gdk/win32/gdkdisplay-win32.c
gdk/win32/gdkglcontext-win32.c
gdk/win32/gdkglcontext-win32.h
gdk/win32/gdkprivate-win32.h
gdk/win32/gdksurface-win32.c [new file with mode: 0644]
gdk/win32/gdksurface-win32.h [new file with mode: 0644]
gdk/win32/gdkwin32.h
gdk/win32/gdkwin32surface.h [new file with mode: 0644]
gdk/win32/gdkwin32window.h [deleted file]
gdk/win32/gdkwindow-win32.c [deleted file]
gdk/win32/gdkwindow-win32.h [deleted file]
gdk/win32/meson.build
gdk/x11/gdkdevice-core-x11.c
gdk/x11/gdkdisplay-x11.h
gdk/x11/gdkeventsource.c
gdk/x11/gdkeventtranslator.c
gdk/x11/gdkgeometry-x11.c
gdk/x11/gdkglcontext-x11.c
gdk/x11/gdkglcontext-x11.h
gdk/x11/gdkprivate-x11.h
gdk/x11/gdkselectioninputstream-x11.c
gdk/x11/gdkselectionoutputstream-x11.c
gdk/x11/gdksurface-x11.c [new file with mode: 0644]
gdk/x11/gdksurface-x11.h [new file with mode: 0644]
gdk/x11/gdkvulkancontext-x11.c
gdk/x11/gdkwindow-x11.c [deleted file]
gdk/x11/gdkwindow-x11.h [deleted file]
gdk/x11/gdkx.h
gdk/x11/gdkx11surface.h [new file with mode: 0644]
gdk/x11/gdkx11window.h [deleted file]
gdk/x11/meson.build
gdk/x11/xsettings-client.c
gtk/gtkdnd-quartz.c
gtk/gtkwindow.c

index 0662fd1979cbe3fbbfb57285a4b778b1511457cf..53c30a2b7238538867e3f24df2fafa76fd820258 100644 (file)
@@ -37,7 +37,7 @@ enum
 static Bug data[] =
 {
   { FALSE, 60482, "Normal",     "scrollable notebooks and hidden tabs" },
-  { FALSE, 60620, "Critical",   "gdk_surface_clear_area (gdkwindow-win32.c) is not thread-safe" },
+  { FALSE, 60620, "Critical",   "gdk_surface_clear_area (gdksurface-win32.c) is not thread-safe" },
   { FALSE, 50214, "Major",      "Xft support does not clean up correctly" },
   { TRUE,  52877, "Major",      "GtkFileSelection needs a refresh method. " },
   { FALSE, 56070, "Normal",     "Can't click button after setting in sensitive" },
index 3e72be0f3b9f3d332f22721768153fec8bdd17fb..33a7bff89d3b97fad4cf66b05b6af3d381d61b04 100644 (file)
@@ -30,7 +30,7 @@
 #define __GDKBROADWAY_H_INSIDE__
 
 #include <gdk/broadway/gdkbroadwaydisplay.h>
-#include <gdk/broadway/gdkbroadwaywindow.h>
+#include <gdk/broadway/gdkbroadwaysurface.h>
 #include <gdk/broadway/gdkbroadwaycursor.h>
 #include <gdk/broadway/gdkbroadwaymonitor.h>
 
diff --git a/gdk/broadway/gdkbroadwaysurface.h b/gdk/broadway/gdkbroadwaysurface.h
new file mode 100644 (file)
index 0000000..12ce448
--- /dev/null
@@ -0,0 +1,54 @@
+/* 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GDK_BROADWAY_SURFACE_H__
+#define __GDK_BROADWAY_SURFACE_H__
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_BROADWAY_SURFACE              (gdk_broadway_surface_get_type ())
+#define GDK_BROADWAY_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_BROADWAY_SURFACE, GdkBroadwaySurface))
+#define GDK_BROADWAY_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_BROADWAY_SURFACE, GdkBroadwaySurfaceClass))
+#define GDK_IS_BROADWAY_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_BROADWAY_SURFACE))
+#define GDK_IS_BROADWAY_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_BROADWAY_SURFACE))
+#define GDK_BROADWAY_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_BROADWAY_SURFACE, GdkBroadwaySurfaceClass))
+
+#ifdef GDK_COMPILATION
+typedef struct _GdkBroadwaySurface GdkBroadwaySurface;
+#else
+typedef GdkSurface GdkBroadwaySurface;
+#endif
+typedef struct _GdkBroadwaySurfaceClass GdkBroadwaySurfaceClass;
+
+GDK_AVAILABLE_IN_ALL
+GType    gdk_broadway_surface_get_type          (void);
+
+GDK_AVAILABLE_IN_ALL
+guint32  gdk_broadway_get_last_seen_time (GdkSurface       *window);
+
+G_END_DECLS
+
+#endif /* __GDK_BROADWAY_SURFACE_H__ */
diff --git a/gdk/broadway/gdkbroadwaywindow.h b/gdk/broadway/gdkbroadwaywindow.h
deleted file mode 100644 (file)
index 12ce448..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-#ifndef __GDK_BROADWAY_SURFACE_H__
-#define __GDK_BROADWAY_SURFACE_H__
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_BROADWAY_SURFACE              (gdk_broadway_surface_get_type ())
-#define GDK_BROADWAY_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_BROADWAY_SURFACE, GdkBroadwaySurface))
-#define GDK_BROADWAY_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_BROADWAY_SURFACE, GdkBroadwaySurfaceClass))
-#define GDK_IS_BROADWAY_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_BROADWAY_SURFACE))
-#define GDK_IS_BROADWAY_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_BROADWAY_SURFACE))
-#define GDK_BROADWAY_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_BROADWAY_SURFACE, GdkBroadwaySurfaceClass))
-
-#ifdef GDK_COMPILATION
-typedef struct _GdkBroadwaySurface GdkBroadwaySurface;
-#else
-typedef GdkSurface GdkBroadwaySurface;
-#endif
-typedef struct _GdkBroadwaySurfaceClass GdkBroadwaySurfaceClass;
-
-GDK_AVAILABLE_IN_ALL
-GType    gdk_broadway_surface_get_type          (void);
-
-GDK_AVAILABLE_IN_ALL
-guint32  gdk_broadway_get_last_seen_time (GdkSurface       *window);
-
-G_END_DECLS
-
-#endif /* __GDK_BROADWAY_SURFACE_H__ */
index fda10591ac3b28f96df126051599b920a291946e..8158871b6402ed829e9dd299596f5f9033593d7c 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "gdkdevice-broadway.h"
 
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkprivate-broadway.h"
 
 static gboolean gdk_broadway_device_get_history (GdkDevice      *device,
index 51d59ae077bbd5f99da91a8f2643b90d3b73f0bf..25a962ac66fc09a0c901d8692adaf355fd2fd021 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "gdkdisplayprivate.h"
 #include "gdkkeys.h"
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkinternals.h"
 #include "gdkbroadway-server.h"
 #include "gdkmonitorprivate.h"
index abbdaadce922f889c257c7396341ab265e6e1a2f..8f1a9237eb6595bf5375ea17d5aacbb6bd518294 100644 (file)
 
 #include <gdk/gdkcursor.h>
 #include <gdk/gdkinternals.h>
-#include "gdkwindow-broadway.h"
+#include "gdksurface-broadway.h"
 #include "gdkdisplay-broadway.h"
 
 #include "gdkbroadwaycursor.h"
-#include "gdkbroadwaywindow.h"
+#include "gdkbroadwaysurface.h"
 
 void _gdk_broadway_resync_windows (void);
 
diff --git a/gdk/broadway/gdksurface-broadway.c b/gdk/broadway/gdksurface-broadway.c
new file mode 100644 (file)
index 0000000..30777d8
--- /dev/null
@@ -0,0 +1,1428 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
+ * Josh MacDonald, Ryan Lortie
+ *
+ * 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include "config.h"
+
+#include "gdksurface-broadway.h"
+
+#include "gdkbroadwaydisplay.h"
+#include "gdkdisplay.h"
+#include "gdksurface.h"
+#include "gdksurfaceimpl.h"
+#include "gdkdisplay-broadway.h"
+#include "gdkprivate-broadway.h"
+#include "gdkinternals.h"
+#include "gdkdeviceprivate.h"
+#include "gdkeventsource.h"
+#include <gdk/gdktextureprivate.h>
+#include <gdk/gdkframeclockprivate.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Forward declarations */
+static void        gdk_surface_impl_broadway_finalize   (GObject            *object);
+
+#define WINDOW_IS_TOPLEVEL(window) \
+  (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD)
+
+struct _GdkBroadwaySurface {
+  GdkSurface parent;
+};
+
+struct _GdkBroadwaySurfaceClass {
+  GdkSurfaceClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkBroadwaySurface, gdk_broadway_surface, GDK_TYPE_SURFACE)
+
+static void
+gdk_broadway_surface_class_init (GdkBroadwaySurfaceClass *broadway_surface_class)
+{
+}
+
+static void
+gdk_broadway_surface_init (GdkBroadwaySurface *broadway_surface)
+{
+}
+
+G_DEFINE_TYPE (GdkSurfaceImplBroadway,
+               gdk_surface_impl_broadway,
+               GDK_TYPE_SURFACE_IMPL)
+
+static GdkDisplay *
+find_broadway_display (void)
+{
+  GdkDisplay *display;
+  GSList *list, *l;
+
+  display = NULL;
+
+  list = gdk_display_manager_list_displays (gdk_display_manager_get ());
+  for (l = list; l; l = l->next)
+    {
+      if (GDK_IS_BROADWAY_DISPLAY (l->data))
+        {
+          display = l->data;
+          break; 
+        }
+    }
+  g_slist_free (list);
+
+  return display;
+}
+
+static guint flush_id = 0;
+
+static gboolean
+flush_idle (gpointer data)
+{
+  flush_id = 0;
+
+  gdk_display_flush (find_broadway_display ());
+
+  return FALSE;
+}
+
+/* We need to flush in an idle rather than AFTER_PAINT, as the clock
+   is frozen during e.g. window resizes so the paint will not happen
+   and the window resize request is never flushed. */
+static void
+queue_flush (GdkSurface *window)
+{
+  if (flush_id == 0)
+    {
+      flush_id = g_idle_add (flush_idle, NULL);
+      g_source_set_name_by_id (flush_id, "[gtk+] flush_idle");
+    }
+}
+
+static void
+gdk_surface_impl_broadway_init (GdkSurfaceImplBroadway *impl)
+{
+  impl->toplevel_window_type = -1;
+}
+
+static void
+gdk_surface_impl_broadway_finalize (GObject *object)
+{
+  GdkSurface *wrapper;
+  GdkSurfaceImplBroadway *impl;
+  GdkBroadwayDisplay *broadway_display;
+
+  g_return_if_fail (GDK_IS_SURFACE_IMPL_BROADWAY (object));
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (object);
+
+  wrapper = impl->wrapper;
+
+  _gdk_broadway_surface_grab_check_destroy (wrapper);
+
+  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (impl->wrapper));
+
+  g_hash_table_remove (broadway_display->id_ht, GINT_TO_POINTER(impl->id));
+
+  if (impl->cursor)
+    g_object_unref (impl->cursor);
+
+  broadway_display->toplevels = g_list_remove (broadway_display->toplevels, impl);
+
+  G_OBJECT_CLASS (gdk_surface_impl_broadway_parent_class)->finalize (object);
+}
+
+static gboolean
+thaw_clock_cb (GdkFrameClock *clock)
+{
+  _gdk_frame_clock_thaw (clock);
+  g_object_unref (clock);
+  return G_SOURCE_REMOVE;
+}
+
+void
+_gdk_broadway_roundtrip_notify (GdkSurface  *window,
+                                guint32 tag,
+                                gboolean local_reply)
+{
+  GdkFrameClock *clock = gdk_surface_get_frame_clock (window);
+
+  /* If there is no remove web client, rate limit update to once a second */
+  if (local_reply)
+    g_timeout_add_seconds (1, (GSourceFunc)thaw_clock_cb, g_object_ref (clock));
+  else
+    _gdk_frame_clock_thaw (clock);
+}
+
+static void
+on_frame_clock_after_paint (GdkFrameClock *clock,
+                            GdkSurface     *window)
+{
+  GdkDisplay *display = gdk_surface_get_display (window);
+  GdkSurfaceImplBroadway *impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+  GdkBroadwayDisplay *broadway_display;
+
+  _gdk_frame_clock_freeze (gdk_surface_get_frame_clock (window));
+
+  broadway_display = GDK_BROADWAY_DISPLAY (display);
+
+  _gdk_broadway_server_roundtrip (broadway_display->server, impl->id, _gdk_display_get_next_serial (display));
+
+  gdk_display_flush (display);
+}
+
+static void
+connect_frame_clock (GdkSurface *window)
+{
+  if (WINDOW_IS_TOPLEVEL (window))
+    {
+      GdkFrameClock *frame_clock = gdk_surface_get_frame_clock (window);
+
+      g_signal_connect (frame_clock, "after-paint",
+                        G_CALLBACK (on_frame_clock_after_paint), window);
+    }
+}
+
+void
+_gdk_broadway_display_create_window_impl (GdkDisplay    *display,
+                                          GdkSurface     *window,
+                                          GdkSurface     *real_parent,
+                                          GdkEventMask   event_mask,
+                                          GdkSurfaceAttr *attributes)
+{
+  GdkSurfaceImplBroadway *impl;
+  GdkBroadwayDisplay *broadway_display;
+
+  broadway_display = GDK_BROADWAY_DISPLAY (display);
+
+  impl = g_object_new (GDK_TYPE_SURFACE_IMPL_BROADWAY, NULL);
+  window->impl = (GdkSurfaceImpl *)impl;
+  impl->id = _gdk_broadway_server_new_surface (broadway_display->server,
+                                               window->x,
+                                               window->y,
+                                               window->width,
+                                               window->height,
+                                               window->window_type == GDK_SURFACE_TEMP);
+  g_hash_table_insert (broadway_display->id_ht, GINT_TO_POINTER(impl->id), window);
+  impl->wrapper = window;
+
+  g_assert (window->window_type == GDK_SURFACE_TOPLEVEL ||
+            window->window_type == GDK_SURFACE_TEMP);
+  g_assert (window->parent == NULL);
+
+  broadway_display->toplevels = g_list_prepend (broadway_display->toplevels, impl);
+
+  connect_frame_clock (window);
+}
+
+static cairo_surface_t *
+gdk_surface_broadway_ref_cairo_surface (GdkSurface *window)
+{
+  GdkSurfaceImplBroadway *impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+
+  if (GDK_IS_SURFACE_IMPL_BROADWAY (window) &&
+      GDK_SURFACE_DESTROYED (impl->wrapper))
+    return NULL;
+
+  return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+}
+
+static void
+_gdk_broadway_surface_destroy (GdkSurface *window,
+                              gboolean   recursing,
+                              gboolean   foreign_destroy)
+{
+  GdkSurfaceImplBroadway *impl;
+  GdkBroadwayDisplay *broadway_display;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+
+  if (impl->node_data)
+    g_array_unref (impl->node_data);
+  if (impl->node_data_textures)
+    g_ptr_array_unref (impl->node_data_textures);
+
+  _gdk_broadway_surface_grab_check_destroy (window);
+
+  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
+  g_hash_table_remove (broadway_display->id_ht, GINT_TO_POINTER (impl->id));
+
+  _gdk_broadway_server_destroy_surface (broadway_display->server, impl->id);
+
+}
+
+void
+gdk_broadway_surface_set_nodes (GdkSurface *window,
+                               GArray *nodes,
+                               GPtrArray *node_textures)
+{
+  GdkSurfaceImplBroadway *impl;
+  GdkBroadwayDisplay *broadway_display;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+
+  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
+
+  if (nodes)
+    g_array_ref (nodes);
+  if (impl->node_data)
+    g_array_unref (impl->node_data);
+  impl->node_data = nodes;
+
+  if (node_textures)
+    g_ptr_array_ref (node_textures);
+  if (impl->node_data_textures)
+    g_ptr_array_unref (impl->node_data_textures);
+  impl->node_data_textures = node_textures;
+
+  gdk_broadway_server_surface_set_nodes (broadway_display->server, impl->id, impl->node_data);
+}
+
+/* This function is called when the XWindow is really gone.
+ */
+static void
+gdk_broadway_surface_destroy_notify (GdkSurface *window)
+{
+  if (!GDK_SURFACE_DESTROYED (window))
+    _gdk_surface_destroy (window, TRUE);
+
+  g_object_unref (window);
+}
+
+static void
+gdk_surface_broadway_show (GdkSurface *window, gboolean already_mapped)
+{
+  GdkSurfaceImplBroadway *impl;
+  GdkBroadwayDisplay *broadway_display;
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+  impl->visible = TRUE;
+
+  if (window->event_mask & GDK_STRUCTURE_MASK)
+    _gdk_make_event (GDK_SURFACE (window), GDK_MAP, NULL, FALSE);
+
+  if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+    _gdk_make_event (GDK_SURFACE (window), GDK_MAP, NULL, FALSE);
+
+  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
+  if (_gdk_broadway_server_surface_show (broadway_display->server, impl->id))
+    queue_flush (window);
+
+}
+
+static void
+gdk_surface_broadway_hide (GdkSurface *window)
+{
+  GdkSurfaceImplBroadway *impl;
+  GdkBroadwayDisplay *broadway_display;
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+  impl->visible = FALSE;
+
+  if (window->event_mask & GDK_STRUCTURE_MASK)
+    _gdk_make_event (GDK_SURFACE (window), GDK_UNMAP, NULL, FALSE);
+
+  if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+    _gdk_make_event (GDK_SURFACE (window), GDK_UNMAP, NULL, FALSE);
+
+  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
+
+  _gdk_broadway_surface_grab_check_unmap (window,
+                                         _gdk_broadway_server_get_next_serial (broadway_display->server));
+
+  if (_gdk_broadway_server_surface_hide (broadway_display->server, impl->id))
+    queue_flush (window);
+
+  _gdk_surface_clear_update_area (window);
+}
+
+static void
+gdk_surface_broadway_withdraw (GdkSurface *window)
+{
+  gdk_surface_broadway_hide (window);
+}
+
+static void
+gdk_surface_broadway_move_resize (GdkSurface *window,
+                                 gboolean   with_move,
+                                 gint       x,
+                                 gint       y,
+                                 gint       width,
+                                 gint       height)
+{
+  GdkSurfaceImplBroadway *impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+  GdkBroadwayDisplay *broadway_display;
+  gboolean size_changed;
+
+  size_changed = FALSE;
+
+  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
+
+  if (width > 0 || height > 0)
+    {
+      if (width < 1)
+        width = 1;
+
+      if (height < 1)
+        height = 1;
+
+      if (width != window->width ||
+          height != window->height)
+        {
+          size_changed = TRUE;
+
+          /* Resize clears the content */
+          impl->dirty = TRUE;
+          impl->last_synced = FALSE;
+
+          window->width = width;
+          window->height = height;
+        }
+    }
+
+  _gdk_broadway_server_surface_move_resize (broadway_display->server,
+                                            impl->id,
+                                            with_move,
+                                            x, y,
+                                            window->width, window->height);
+  queue_flush (window);
+  if (size_changed)
+    window->resize_count++;
+}
+
+static void
+gdk_surface_broadway_raise (GdkSurface *window)
+{
+}
+
+static void
+gdk_surface_broadway_restack_toplevel (GdkSurface *window,
+                                      GdkSurface *sibling,
+                                      gboolean   above)
+{
+}
+
+static void
+gdk_surface_broadway_lower (GdkSurface *window)
+{
+}
+
+
+static void
+gdk_broadway_surface_focus (GdkSurface *window,
+                           guint32    timestamp)
+{
+  GdkSurfaceImplBroadway *impl;
+  GdkBroadwayDisplay *broadway_display;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !window->accept_focus)
+    return;
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
+  _gdk_broadway_server_surface_focus (broadway_display->server,
+                                      impl->id);
+}
+
+static void
+gdk_broadway_surface_set_type_hint (GdkSurface        *window,
+                                   GdkSurfaceTypeHint hint)
+{
+}
+
+static GdkSurfaceTypeHint
+gdk_broadway_surface_get_type_hint (GdkSurface *window)
+{
+  return GDK_SURFACE_TYPE_HINT_NORMAL;
+}
+
+static void
+gdk_broadway_surface_set_modal_hint (GdkSurface *window,
+                                    gboolean   modal)
+{
+}
+
+static void
+gdk_broadway_surface_set_skip_taskbar_hint (GdkSurface *window,
+                                           gboolean   skips_taskbar)
+{
+}
+
+static void
+gdk_broadway_surface_set_skip_pager_hint (GdkSurface *window,
+                                         gboolean   skips_pager)
+{
+}
+
+static void
+gdk_broadway_surface_set_urgency_hint (GdkSurface *window,
+                                      gboolean   urgent)
+{
+}
+
+static void
+gdk_broadway_surface_set_geometry_hints (GdkSurface         *window,
+                                        const GdkGeometry *geometry,
+                                        GdkSurfaceHints     geom_mask)
+{
+  GdkSurfaceImplBroadway *impl;
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+
+  impl->geometry_hints = *geometry;
+  impl->geometry_hints_mask = geom_mask;
+}
+
+static void
+gdk_broadway_surface_set_title (GdkSurface   *window,
+                               const gchar *title)
+{
+}
+
+static void
+gdk_broadway_surface_set_role (GdkSurface   *window,
+                              const gchar *role)
+{
+}
+
+static void
+gdk_broadway_surface_set_startup_id (GdkSurface   *window,
+                                    const gchar *startup_id)
+{
+}
+
+static void
+gdk_broadway_surface_set_transient_for (GdkSurface *window,
+                                       GdkSurface *parent)
+{
+  GdkBroadwayDisplay *display;
+  GdkSurfaceImplBroadway *impl;
+  int parent_id;
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+
+  parent_id = 0;
+  if (parent)
+    parent_id = GDK_SURFACE_IMPL_BROADWAY (parent->impl)->id;
+
+  impl->transient_for = parent_id;
+
+  display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (impl->wrapper));
+  _gdk_broadway_server_surface_set_transient_for (display->server, impl->id, impl->transient_for);
+}
+
+static void
+gdk_surface_broadway_get_geometry (GdkSurface *window,
+                                  gint      *x,
+                                  gint      *y,
+                                  gint      *width,
+                                  gint      *height)
+{
+  GdkSurfaceImplBroadway *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+
+  /* TODO: These should really roundtrip to the client to get the current data */
+
+  if (x)
+    *x = impl->wrapper->x;
+  if (y)
+    *y = impl->wrapper->y;
+  if (width)
+    *width = impl->wrapper->width;
+  if (height)
+    *height = impl->wrapper->height;
+
+}
+
+static void
+gdk_surface_broadway_get_root_coords (GdkSurface *window,
+                                     gint       x,
+                                     gint       y,
+                                     gint      *root_x,
+                                     gint      *root_y)
+{
+  GdkSurfaceImplBroadway *impl;
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+
+  if (root_x)
+    *root_x = x + impl->wrapper->x;
+  if (root_y)
+    *root_y = y + impl->wrapper->y;
+}
+
+static void
+gdk_broadway_surface_get_frame_extents (GdkSurface    *window,
+                                       GdkRectangle *rect)
+{
+  g_return_if_fail (rect != NULL);
+
+  /* TODO: This should take wm frame into account */
+
+  rect->x = window->x;
+  rect->y = window->y;
+  rect->width = window->width;
+  rect->height = window->height;
+}
+
+static gboolean
+gdk_surface_broadway_get_device_state (GdkSurface       *window,
+                                      GdkDevice       *device,
+                                      gdouble         *x,
+                                      gdouble         *y,
+                                      GdkModifierType *mask)
+{
+  GdkSurface *child;
+
+  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), FALSE);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return FALSE;
+
+  GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
+                                              &child,
+                                              NULL, NULL,
+                                              x, y, mask);
+  return child != NULL;
+}
+
+static GdkEventMask
+gdk_surface_broadway_get_events (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window))
+    return 0;
+
+  return 0;
+}
+
+static void
+gdk_surface_broadway_set_events (GdkSurface    *window,
+                                GdkEventMask  event_mask)
+{
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+    }
+}
+
+static void
+gdk_surface_broadway_shape_combine_region (GdkSurface       *window,
+                                          const cairo_region_t *shape_region,
+                                          gint             offset_x,
+                                          gint             offset_y)
+{
+}
+
+static void
+gdk_surface_broadway_input_shape_combine_region (GdkSurface       *window,
+                                                const cairo_region_t *shape_region,
+                                                gint             offset_x,
+                                                gint             offset_y)
+{
+}
+
+static void
+gdk_broadway_surface_set_accept_focus (GdkSurface *window,
+                                      gboolean accept_focus)
+{
+  accept_focus = accept_focus != FALSE;
+
+  if (window->accept_focus != accept_focus)
+    {
+      window->accept_focus = accept_focus;
+    }
+}
+
+static void
+gdk_broadway_surface_set_focus_on_map (GdkSurface *window,
+                                      gboolean focus_on_map)
+{
+  focus_on_map = focus_on_map != FALSE;
+
+  if (window->focus_on_map != focus_on_map)
+    {
+      window->focus_on_map = focus_on_map;
+    }
+}
+
+
+static void
+gdk_broadway_surface_set_icon_list (GdkSurface *window,
+                                   GList     *surfaces)
+{
+}
+
+static void
+gdk_broadway_surface_set_icon_name (GdkSurface   *window,
+                                   const gchar *name)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
+                      GUINT_TO_POINTER (name != NULL));
+}
+
+static void
+gdk_broadway_surface_iconify (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+}
+
+static void
+gdk_broadway_surface_deiconify (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+}
+
+static void
+gdk_broadway_surface_stick (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+}
+
+static void
+gdk_broadway_surface_unstick (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+}
+
+static void
+gdk_broadway_surface_maximize (GdkSurface *window)
+{
+  GdkSurfaceImplBroadway *impl;
+  GdkDisplay *display;
+  GdkMonitor *monitor;
+  GdkRectangle geom;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+
+  if (impl->maximized)
+    return;
+
+  impl->maximized = TRUE;
+
+  gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_MAXIMIZED);
+
+  impl->pre_maximize_x = window->x;
+  impl->pre_maximize_y = window->y;
+  impl->pre_maximize_width = window->width;
+  impl->pre_maximize_height = window->height;
+
+  display = gdk_surface_get_display (window);
+  monitor = gdk_display_get_primary_monitor (display);
+  gdk_monitor_get_geometry (monitor, &geom);
+
+  gdk_surface_move_resize (window,
+                          geom.x, geom.y,
+                          geom.width, geom.height);
+}
+
+static void
+gdk_broadway_surface_unmaximize (GdkSurface *window)
+{
+  GdkSurfaceImplBroadway *impl;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+
+  if (!impl->maximized)
+    return;
+
+  impl->maximized = FALSE;
+
+  gdk_synthesize_window_state (window, GDK_SURFACE_STATE_MAXIMIZED, 0);
+
+  gdk_surface_move_resize (window,
+                          impl->pre_maximize_x,
+                          impl->pre_maximize_y,
+                          impl->pre_maximize_width,
+                          impl->pre_maximize_height);
+}
+
+static void
+gdk_broadway_surface_fullscreen (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+}
+
+static void
+gdk_broadway_surface_unfullscreen (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+}
+
+static void
+gdk_broadway_surface_set_keep_above (GdkSurface *window,
+                                    gboolean   setting)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+}
+
+static void
+gdk_broadway_surface_set_keep_below (GdkSurface *window, gboolean setting)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+}
+
+static GdkSurface *
+gdk_broadway_surface_get_group (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return NULL;
+
+  return window;
+}
+
+static void
+gdk_broadway_surface_set_group (GdkSurface *window,
+                               GdkSurface *leader)
+{
+}
+
+static void
+gdk_broadway_surface_set_decorations (GdkSurface      *window,
+                                     GdkWMDecoration decorations)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+}
+
+static gboolean
+gdk_broadway_surface_get_decorations (GdkSurface       *window,
+                                     GdkWMDecoration *decorations)
+{
+  gboolean result = FALSE;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return FALSE;
+
+  return result;
+}
+
+static void
+gdk_broadway_surface_set_functions (GdkSurface    *window,
+                                   GdkWMFunction functions)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+}
+
+static void
+gdk_broadway_surface_end_paint (GdkSurface *window)
+{
+  GdkSurfaceImplBroadway *impl;
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+  impl->dirty = TRUE;
+}
+
+typedef struct _MoveResizeData MoveResizeData;
+
+struct _MoveResizeData
+{
+  GdkDisplay *display;
+
+  GdkSurface *moveresize_window;
+  GdkSurface *moveresize_emulation_window;
+  gboolean is_resize;
+  GdkSurfaceEdge resize_edge;
+  gint moveresize_button;
+  gint moveresize_x;
+  gint moveresize_y;
+  gint moveresize_orig_x;
+  gint moveresize_orig_y;
+  gint moveresize_orig_width;
+  gint moveresize_orig_height;
+  long moveresize_process_time;
+  GdkSurfaceHints moveresize_geom_mask;
+  GdkGeometry moveresize_geometry;
+  BroadwayInputMsg *moveresize_pending_event;
+};
+
+static MoveResizeData *
+get_move_resize_data (GdkDisplay *display,
+                      gboolean    create)
+{
+  GdkBroadwayDisplay *broadway_display;
+  MoveResizeData *mv_resize;
+
+  broadway_display = GDK_BROADWAY_DISPLAY (display);
+
+  mv_resize = broadway_display->move_resize_data;
+
+  if (!mv_resize && create)
+    {
+      mv_resize = g_new0 (MoveResizeData, 1);
+      mv_resize->display = display;
+
+      broadway_display->move_resize_data = mv_resize;
+    }
+
+  return mv_resize;
+}
+
+static void
+update_pos (MoveResizeData *mv_resize,
+            gint            new_root_x,
+            gint            new_root_y)
+{
+  gint dx, dy;
+
+  dx = new_root_x - mv_resize->moveresize_x;
+  dy = new_root_y - mv_resize->moveresize_y;
+
+  if (mv_resize->is_resize)
+    {
+      gint x, y, w, h;
+
+      x = mv_resize->moveresize_orig_x;
+      y = mv_resize->moveresize_orig_y;
+
+      w = mv_resize->moveresize_orig_width;
+      h = mv_resize->moveresize_orig_height;
+
+      switch (mv_resize->resize_edge)
+        {
+        case GDK_SURFACE_EDGE_NORTH_WEST:
+          x += dx;
+          y += dy;
+          w -= dx;
+          h -= dy;
+          break;
+        case GDK_SURFACE_EDGE_NORTH:
+          y += dy;
+          h -= dy;
+          break;
+        case GDK_SURFACE_EDGE_NORTH_EAST:
+          y += dy;
+          h -= dy;
+          w += dx;
+          break;
+        case GDK_SURFACE_EDGE_SOUTH_WEST:
+          h += dy;
+          x += dx;
+          w -= dx;
+          break;
+        case GDK_SURFACE_EDGE_SOUTH_EAST:
+          w += dx;
+          h += dy;
+          break;
+        case GDK_SURFACE_EDGE_SOUTH:
+          h += dy;
+          break;
+        case GDK_SURFACE_EDGE_EAST:
+          w += dx;
+          break;
+        case GDK_SURFACE_EDGE_WEST:
+          x += dx;
+          w -= dx;
+          break;
+        default:
+          break;
+        }
+
+      x = MAX (x, 0);
+      y = MAX (y, 0);
+      w = MAX (w, 1);
+      h = MAX (h, 1);
+
+      if (mv_resize->moveresize_geom_mask)
+        {
+          gdk_surface_constrain_size (&mv_resize->moveresize_geometry,
+                                     mv_resize->moveresize_geom_mask,
+                                     w, h, &w, &h);
+        }
+
+      gdk_surface_move_resize (mv_resize->moveresize_window, x, y, w, h);
+    }
+  else
+    {
+      gint x, y;
+
+      x = mv_resize->moveresize_orig_x + dx;
+      y = mv_resize->moveresize_orig_y + dy;
+
+      gdk_surface_move (mv_resize->moveresize_window, x, y);
+    }
+}
+
+static void
+finish_drag (MoveResizeData *mv_resize)
+{
+  gdk_surface_destroy (mv_resize->moveresize_emulation_window);
+  mv_resize->moveresize_emulation_window = NULL;
+  g_object_unref (mv_resize->moveresize_window);
+  mv_resize->moveresize_window = NULL;
+  g_clear_pointer (&mv_resize->moveresize_pending_event, g_free);
+}
+
+static gboolean
+moveresize_lookahead (GdkDisplay *display,
+                      MoveResizeData *mv_resize,
+                      BroadwayInputMsg *event)
+{
+  GdkBroadwayDisplay *broadway_display;
+
+  broadway_display = GDK_BROADWAY_DISPLAY (display);
+
+  return !_gdk_broadway_server_lookahead_event (broadway_display->server, "mb");
+}
+
+gboolean
+_gdk_broadway_moveresize_handle_event (GdkDisplay *display,
+                                       BroadwayInputMsg *event)
+{
+  guint button_mask = 0;
+  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
+
+  if (!mv_resize || !mv_resize->moveresize_window)
+    return FALSE;
+
+  button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
+
+  switch (event->base.type)
+    {
+    case BROADWAY_EVENT_TOUCH:
+      if (event->touch.touch_type == 2) /* END */
+        {
+          update_pos (mv_resize,
+                      event->touch.root_x,
+                      event->touch.root_y);
+
+          finish_drag (mv_resize);
+        }
+      else if (event->touch.touch_type == 1) /* UPDATE */
+        {
+          if (mv_resize->moveresize_window->resize_count > 0)
+            {
+              if (mv_resize->moveresize_pending_event)
+                *mv_resize->moveresize_pending_event = *event;
+              else
+                mv_resize->moveresize_pending_event =
+                  g_memdup (event, sizeof (BroadwayInputMsg));
+
+              break;
+            }
+          update_pos (mv_resize,
+                      event->touch.root_x,
+                      event->touch.root_y);
+        }
+
+      break;
+
+    case BROADWAY_EVENT_POINTER_MOVE:
+      if (mv_resize->moveresize_window->resize_count > 0)
+        {
+          if (mv_resize->moveresize_pending_event)
+            *mv_resize->moveresize_pending_event = *event;
+          else
+            mv_resize->moveresize_pending_event =
+              g_memdup (event, sizeof (BroadwayInputMsg));
+
+          break;
+        }
+      if (!moveresize_lookahead (display, mv_resize, event))
+        break;
+
+      update_pos (mv_resize,
+                  event->pointer.root_x,
+                  event->pointer.root_y);
+
+      /* This should never be triggered in normal cases, but in the
+       * case where the drag started without an implicit grab being
+       * in effect, we could miss the release if it occurs before
+       * we grab the pointer; this ensures that we will never
+       * get a permanently stuck grab.
+       */
+      if ((event->pointer.state & button_mask) == 0)
+        finish_drag (mv_resize);
+      break;
+
+    case BROADWAY_EVENT_BUTTON_RELEASE:
+      update_pos (mv_resize,
+                  event->pointer.root_x,
+                  event->pointer.root_y);
+
+      if (event->button.button == mv_resize->moveresize_button)
+        finish_drag (mv_resize);
+      break;
+    default:
+      break;
+    }
+  return TRUE;
+}
+
+gboolean
+_gdk_broadway_moveresize_configure_done (GdkDisplay *display,
+                                         GdkSurface  *window)
+{
+  BroadwayInputMsg *tmp_event;
+  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
+
+  if (!mv_resize || window != mv_resize->moveresize_window)
+    return FALSE;
+
+  if (mv_resize->moveresize_pending_event)
+    {
+      tmp_event = mv_resize->moveresize_pending_event;
+      mv_resize->moveresize_pending_event = NULL;
+      _gdk_broadway_moveresize_handle_event (display, tmp_event);
+      g_free (tmp_event);
+    }
+
+  return TRUE;
+}
+
+static void
+create_moveresize_window (MoveResizeData *mv_resize,
+                          guint32         timestamp)
+{
+  GdkGrabStatus status;
+  GdkSeat *seat;
+  GdkDevice *pointer;
+
+  g_assert (mv_resize->moveresize_emulation_window == NULL);
+
+  mv_resize->moveresize_emulation_window = gdk_surface_new_temp (mv_resize->display);
+
+  gdk_surface_show (mv_resize->moveresize_emulation_window);
+
+  seat = gdk_display_get_default_seat (mv_resize->display);
+  pointer = gdk_seat_get_pointer (seat);
+
+  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+  status = gdk_device_grab (pointer,
+                             mv_resize->moveresize_emulation_window,
+                             GDK_OWNERSHIP_APPLICATION,
+                             FALSE,
+                             GDK_BUTTON_RELEASE_MASK |
+                             GDK_POINTER_MOTION_MASK,
+                             NULL,
+                             timestamp);
+  G_GNUC_END_IGNORE_DEPRECATIONS;
+
+  if (status != GDK_GRAB_SUCCESS)
+    {
+      /* If this fails, some other client has grabbed the window
+       * already.
+       */
+      finish_drag (mv_resize);
+    }
+
+  mv_resize->moveresize_process_time = 0;
+}
+
+static void
+calculate_unmoving_origin (MoveResizeData *mv_resize)
+{
+  GdkRectangle rect;
+  gint width, height;
+
+  if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
+      mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
+    {
+      gdk_surface_get_origin (mv_resize->moveresize_window,
+                             &mv_resize->moveresize_orig_x,
+                             &mv_resize->moveresize_orig_y);
+    }
+  else
+    {
+      gdk_surface_get_frame_extents (mv_resize->moveresize_window, &rect);
+      gdk_surface_get_geometry (mv_resize->moveresize_window,
+                               NULL, NULL, &width, &height);
+
+      switch (mv_resize->moveresize_geometry.win_gravity)
+        {
+        case GDK_GRAVITY_NORTH_WEST:
+          mv_resize->moveresize_orig_x = rect.x;
+          mv_resize->moveresize_orig_y = rect.y;
+          break;
+        case GDK_GRAVITY_NORTH:
+          mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
+          mv_resize->moveresize_orig_y = rect.y;
+          break;
+        case GDK_GRAVITY_NORTH_EAST:
+          mv_resize->moveresize_orig_x = rect.x + rect.width - width;
+          mv_resize->moveresize_orig_y = rect.y;
+          break;
+        case GDK_GRAVITY_WEST:
+          mv_resize->moveresize_orig_x = rect.x;
+          mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
+          break;
+        case GDK_GRAVITY_CENTER:
+          mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
+          mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
+          break;
+        case GDK_GRAVITY_EAST:
+          mv_resize->moveresize_orig_x = rect.x + rect.width - width;
+          mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
+          break;
+        case GDK_GRAVITY_SOUTH_WEST:
+          mv_resize->moveresize_orig_x = rect.x;
+          mv_resize->moveresize_orig_y = rect.y + rect.height - height;
+          break;
+        case GDK_GRAVITY_SOUTH:
+          mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
+          mv_resize->moveresize_orig_y = rect.y + rect.height - height;
+          break;
+        case GDK_GRAVITY_SOUTH_EAST:
+          mv_resize->moveresize_orig_x = rect.x + rect.width - width;
+          mv_resize->moveresize_orig_y = rect.y + rect.height - height;
+          break;
+        case GDK_GRAVITY_STATIC:
+        default:
+          mv_resize->moveresize_orig_x = rect.x;
+          mv_resize->moveresize_orig_y = rect.y;
+          break;
+        }
+    }
+}
+
+static void
+gdk_broadway_surface_begin_resize_drag (GdkSurface     *window,
+                                       GdkSurfaceEdge  edge,
+                                       GdkDevice     *device,
+                                       gint           button,
+                                       gint           root_x,
+                                       gint           root_y,
+                                       guint32        timestamp)
+{
+  MoveResizeData *mv_resize;
+  GdkSurfaceImplBroadway *impl;
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  if (impl->maximized)
+    return;
+
+  mv_resize = get_move_resize_data (gdk_surface_get_display (window), TRUE);
+
+  mv_resize->is_resize = TRUE;
+  mv_resize->moveresize_button = button;
+  mv_resize->resize_edge = edge;
+  mv_resize->moveresize_x = root_x;
+  mv_resize->moveresize_y = root_y;
+  mv_resize->moveresize_window = g_object_ref (window);
+
+  mv_resize->moveresize_orig_width = gdk_surface_get_width (window);
+  mv_resize->moveresize_orig_height = gdk_surface_get_height (window);
+
+  mv_resize->moveresize_geom_mask = impl->geometry_hints_mask;
+  mv_resize->moveresize_geometry = impl->geometry_hints;
+
+  calculate_unmoving_origin (mv_resize);
+
+  create_moveresize_window (mv_resize, timestamp);
+}
+
+static void
+gdk_broadway_surface_begin_move_drag (GdkSurface *window,
+                                     GdkDevice *device,
+                                     gint       button,
+                                     gint       root_x,
+                                     gint       root_y,
+                                     guint32    timestamp)
+{
+  MoveResizeData *mv_resize;
+  GdkSurfaceImplBroadway *impl;
+
+  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  if (impl->maximized)
+    return;
+
+  mv_resize = get_move_resize_data (gdk_surface_get_display (window), TRUE);
+
+  mv_resize->is_resize = FALSE;
+  mv_resize->moveresize_button = button;
+  mv_resize->moveresize_x = root_x;
+  mv_resize->moveresize_y = root_y;
+  mv_resize->moveresize_window = g_object_ref (window);
+
+  mv_resize->moveresize_orig_width = gdk_surface_get_width (window);
+  mv_resize->moveresize_orig_height = gdk_surface_get_height (window);
+
+  mv_resize->moveresize_geom_mask = impl->geometry_hints_mask;
+  mv_resize->moveresize_geometry = impl->geometry_hints;
+
+  calculate_unmoving_origin (mv_resize);
+
+  create_moveresize_window (mv_resize, timestamp);
+}
+
+static gboolean
+gdk_broadway_surface_beep (GdkSurface *window)
+{
+  return FALSE;
+}
+
+static void
+gdk_broadway_surface_set_opacity (GdkSurface *window,
+                                 gdouble    opacity)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  if (opacity < 0)
+    opacity = 0;
+  else if (opacity > 1)
+    opacity = 1;
+}
+
+guint32
+gdk_broadway_get_last_seen_time (GdkSurface  *window)
+{
+  GdkDisplay *display;
+
+  display = gdk_surface_get_display (window);
+  return _gdk_broadway_server_get_last_seen_time (GDK_BROADWAY_DISPLAY (display)->server);
+}
+
+static void
+gdk_surface_impl_broadway_class_init (GdkSurfaceImplBroadwayClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_CLASS (klass);
+
+  object_class->finalize = gdk_surface_impl_broadway_finalize;
+
+  impl_class->ref_cairo_surface = gdk_surface_broadway_ref_cairo_surface;
+  impl_class->show = gdk_surface_broadway_show;
+  impl_class->hide = gdk_surface_broadway_hide;
+  impl_class->withdraw = gdk_surface_broadway_withdraw;
+  impl_class->set_events = gdk_surface_broadway_set_events;
+  impl_class->get_events = gdk_surface_broadway_get_events;
+  impl_class->raise = gdk_surface_broadway_raise;
+  impl_class->lower = gdk_surface_broadway_lower;
+  impl_class->restack_toplevel = gdk_surface_broadway_restack_toplevel;
+  impl_class->move_resize = gdk_surface_broadway_move_resize;
+  impl_class->get_geometry = gdk_surface_broadway_get_geometry;
+  impl_class->get_root_coords = gdk_surface_broadway_get_root_coords;
+  impl_class->get_device_state = gdk_surface_broadway_get_device_state;
+  impl_class->shape_combine_region = gdk_surface_broadway_shape_combine_region;
+  impl_class->input_shape_combine_region = gdk_surface_broadway_input_shape_combine_region;
+  impl_class->destroy = _gdk_broadway_surface_destroy;
+  impl_class->end_paint = gdk_broadway_surface_end_paint;
+  impl_class->beep = gdk_broadway_surface_beep;
+
+  impl_class->focus = gdk_broadway_surface_focus;
+  impl_class->set_type_hint = gdk_broadway_surface_set_type_hint;
+  impl_class->get_type_hint = gdk_broadway_surface_get_type_hint;
+  impl_class->set_modal_hint = gdk_broadway_surface_set_modal_hint;
+  impl_class->set_skip_taskbar_hint = gdk_broadway_surface_set_skip_taskbar_hint;
+  impl_class->set_skip_pager_hint = gdk_broadway_surface_set_skip_pager_hint;
+  impl_class->set_urgency_hint = gdk_broadway_surface_set_urgency_hint;
+  impl_class->set_geometry_hints = gdk_broadway_surface_set_geometry_hints;
+  impl_class->set_title = gdk_broadway_surface_set_title;
+  impl_class->set_role = gdk_broadway_surface_set_role;
+  impl_class->set_startup_id = gdk_broadway_surface_set_startup_id;
+  impl_class->set_transient_for = gdk_broadway_surface_set_transient_for;
+  impl_class->get_frame_extents = gdk_broadway_surface_get_frame_extents;
+  impl_class->set_accept_focus = gdk_broadway_surface_set_accept_focus;
+  impl_class->set_focus_on_map = gdk_broadway_surface_set_focus_on_map;
+  impl_class->set_icon_list = gdk_broadway_surface_set_icon_list;
+  impl_class->set_icon_name = gdk_broadway_surface_set_icon_name;
+  impl_class->iconify = gdk_broadway_surface_iconify;
+  impl_class->deiconify = gdk_broadway_surface_deiconify;
+  impl_class->stick = gdk_broadway_surface_stick;
+  impl_class->unstick = gdk_broadway_surface_unstick;
+  impl_class->maximize = gdk_broadway_surface_maximize;
+  impl_class->unmaximize = gdk_broadway_surface_unmaximize;
+  impl_class->fullscreen = gdk_broadway_surface_fullscreen;
+  impl_class->unfullscreen = gdk_broadway_surface_unfullscreen;
+  impl_class->set_keep_above = gdk_broadway_surface_set_keep_above;
+  impl_class->set_keep_below = gdk_broadway_surface_set_keep_below;
+  impl_class->get_group = gdk_broadway_surface_get_group;
+  impl_class->set_group = gdk_broadway_surface_set_group;
+  impl_class->set_decorations = gdk_broadway_surface_set_decorations;
+  impl_class->get_decorations = gdk_broadway_surface_get_decorations;
+  impl_class->set_functions = gdk_broadway_surface_set_functions;
+  impl_class->begin_resize_drag = gdk_broadway_surface_begin_resize_drag;
+  impl_class->begin_move_drag = gdk_broadway_surface_begin_move_drag;
+  impl_class->set_opacity = gdk_broadway_surface_set_opacity;
+  impl_class->destroy_notify = gdk_broadway_surface_destroy_notify;
+  impl_class->register_dnd = _gdk_broadway_surface_register_dnd;
+  impl_class->drag_begin = _gdk_broadway_surface_drag_begin;
+}
diff --git a/gdk/broadway/gdksurface-broadway.h b/gdk/broadway/gdksurface-broadway.h
new file mode 100644 (file)
index 0000000..00fa539
--- /dev/null
@@ -0,0 +1,84 @@
+/* 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GDK_SURFACE_BROADWAY_H__
+#define __GDK_SURFACE_BROADWAY_H__
+
+#include <gdk/gdksurfaceimpl.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdkSurfaceImplBroadway GdkSurfaceImplBroadway;
+typedef struct _GdkSurfaceImplBroadwayClass GdkSurfaceImplBroadwayClass;
+
+/* Window implementation for Broadway
+ */
+
+#define GDK_TYPE_SURFACE_IMPL_BROADWAY              (gdk_surface_impl_broadway_get_type ())
+#define GDK_SURFACE_IMPL_BROADWAY(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_BROADWAY, GdkSurfaceImplBroadway))
+#define GDK_SURFACE_IMPL_BROADWAY_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_BROADWAY, GdkSurfaceImplBroadwayClass))
+#define GDK_IS_SURFACE_IMPL_BROADWAY(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_BROADWAY))
+#define GDK_IS_SURFACE_IMPL_BROADWAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_BROADWAY))
+#define GDK_SURFACE_IMPL_BROADWAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_BROADWAY, GdkSurfaceImplBroadwayClass))
+
+struct _GdkSurfaceImplBroadway
+{
+  GdkSurfaceImpl parent_instance;
+
+  GdkSurface *wrapper;
+
+  GdkCursor *cursor;
+
+  int id;
+
+  gboolean visible;
+  gboolean maximized;
+  int transient_for;
+
+  int pre_maximize_x;
+  int pre_maximize_y;
+  int pre_maximize_width;
+  int pre_maximize_height;
+
+  gint8 toplevel_window_type;
+  gboolean dirty;
+  gboolean last_synced;
+
+  GdkGeometry geometry_hints;
+  GdkSurfaceHints geometry_hints_mask;
+
+  GArray *node_data;
+  GPtrArray *node_data_textures;
+};
+
+struct _GdkSurfaceImplBroadwayClass
+{
+  GdkSurfaceImplClass parent_class;
+};
+
+GType gdk_surface_impl_broadway_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDK_SURFACE_BROADWAY_H__ */
diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c
deleted file mode 100644 (file)
index 9b7dbcf..0000000
+++ /dev/null
@@ -1,1428 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
- * Josh MacDonald, Ryan Lortie
- *
- * 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-#include "config.h"
-
-#include "gdkwindow-broadway.h"
-
-#include "gdkbroadwaydisplay.h"
-#include "gdkdisplay.h"
-#include "gdkwindow.h"
-#include "gdkwindowimpl.h"
-#include "gdkdisplay-broadway.h"
-#include "gdkprivate-broadway.h"
-#include "gdkinternals.h"
-#include "gdkdeviceprivate.h"
-#include "gdkeventsource.h"
-#include <gdk/gdktextureprivate.h>
-#include <gdk/gdkframeclockprivate.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-/* Forward declarations */
-static void        gdk_surface_impl_broadway_finalize   (GObject            *object);
-
-#define WINDOW_IS_TOPLEVEL(window) \
-  (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD)
-
-struct _GdkBroadwaySurface {
-  GdkSurface parent;
-};
-
-struct _GdkBroadwaySurfaceClass {
-  GdkSurfaceClass parent_class;
-};
-
-G_DEFINE_TYPE (GdkBroadwaySurface, gdk_broadway_surface, GDK_TYPE_SURFACE)
-
-static void
-gdk_broadway_surface_class_init (GdkBroadwaySurfaceClass *broadway_surface_class)
-{
-}
-
-static void
-gdk_broadway_surface_init (GdkBroadwaySurface *broadway_surface)
-{
-}
-
-G_DEFINE_TYPE (GdkSurfaceImplBroadway,
-               gdk_surface_impl_broadway,
-               GDK_TYPE_SURFACE_IMPL)
-
-static GdkDisplay *
-find_broadway_display (void)
-{
-  GdkDisplay *display;
-  GSList *list, *l;
-
-  display = NULL;
-
-  list = gdk_display_manager_list_displays (gdk_display_manager_get ());
-  for (l = list; l; l = l->next)
-    {
-      if (GDK_IS_BROADWAY_DISPLAY (l->data))
-        {
-          display = l->data;
-          break; 
-        }
-    }
-  g_slist_free (list);
-
-  return display;
-}
-
-static guint flush_id = 0;
-
-static gboolean
-flush_idle (gpointer data)
-{
-  flush_id = 0;
-
-  gdk_display_flush (find_broadway_display ());
-
-  return FALSE;
-}
-
-/* We need to flush in an idle rather than AFTER_PAINT, as the clock
-   is frozen during e.g. window resizes so the paint will not happen
-   and the window resize request is never flushed. */
-static void
-queue_flush (GdkSurface *window)
-{
-  if (flush_id == 0)
-    {
-      flush_id = g_idle_add (flush_idle, NULL);
-      g_source_set_name_by_id (flush_id, "[gtk+] flush_idle");
-    }
-}
-
-static void
-gdk_surface_impl_broadway_init (GdkSurfaceImplBroadway *impl)
-{
-  impl->toplevel_window_type = -1;
-}
-
-static void
-gdk_surface_impl_broadway_finalize (GObject *object)
-{
-  GdkSurface *wrapper;
-  GdkSurfaceImplBroadway *impl;
-  GdkBroadwayDisplay *broadway_display;
-
-  g_return_if_fail (GDK_IS_SURFACE_IMPL_BROADWAY (object));
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (object);
-
-  wrapper = impl->wrapper;
-
-  _gdk_broadway_surface_grab_check_destroy (wrapper);
-
-  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (impl->wrapper));
-
-  g_hash_table_remove (broadway_display->id_ht, GINT_TO_POINTER(impl->id));
-
-  if (impl->cursor)
-    g_object_unref (impl->cursor);
-
-  broadway_display->toplevels = g_list_remove (broadway_display->toplevels, impl);
-
-  G_OBJECT_CLASS (gdk_surface_impl_broadway_parent_class)->finalize (object);
-}
-
-static gboolean
-thaw_clock_cb (GdkFrameClock *clock)
-{
-  _gdk_frame_clock_thaw (clock);
-  g_object_unref (clock);
-  return G_SOURCE_REMOVE;
-}
-
-void
-_gdk_broadway_roundtrip_notify (GdkSurface  *window,
-                                guint32 tag,
-                                gboolean local_reply)
-{
-  GdkFrameClock *clock = gdk_surface_get_frame_clock (window);
-
-  /* If there is no remove web client, rate limit update to once a second */
-  if (local_reply)
-    g_timeout_add_seconds (1, (GSourceFunc)thaw_clock_cb, g_object_ref (clock));
-  else
-    _gdk_frame_clock_thaw (clock);
-}
-
-static void
-on_frame_clock_after_paint (GdkFrameClock *clock,
-                            GdkSurface     *window)
-{
-  GdkDisplay *display = gdk_surface_get_display (window);
-  GdkSurfaceImplBroadway *impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-  GdkBroadwayDisplay *broadway_display;
-
-  _gdk_frame_clock_freeze (gdk_surface_get_frame_clock (window));
-
-  broadway_display = GDK_BROADWAY_DISPLAY (display);
-
-  _gdk_broadway_server_roundtrip (broadway_display->server, impl->id, _gdk_display_get_next_serial (display));
-
-  gdk_display_flush (display);
-}
-
-static void
-connect_frame_clock (GdkSurface *window)
-{
-  if (WINDOW_IS_TOPLEVEL (window))
-    {
-      GdkFrameClock *frame_clock = gdk_surface_get_frame_clock (window);
-
-      g_signal_connect (frame_clock, "after-paint",
-                        G_CALLBACK (on_frame_clock_after_paint), window);
-    }
-}
-
-void
-_gdk_broadway_display_create_window_impl (GdkDisplay    *display,
-                                          GdkSurface     *window,
-                                          GdkSurface     *real_parent,
-                                          GdkEventMask   event_mask,
-                                          GdkSurfaceAttr *attributes)
-{
-  GdkSurfaceImplBroadway *impl;
-  GdkBroadwayDisplay *broadway_display;
-
-  broadway_display = GDK_BROADWAY_DISPLAY (display);
-
-  impl = g_object_new (GDK_TYPE_SURFACE_IMPL_BROADWAY, NULL);
-  window->impl = (GdkSurfaceImpl *)impl;
-  impl->id = _gdk_broadway_server_new_surface (broadway_display->server,
-                                               window->x,
-                                               window->y,
-                                               window->width,
-                                               window->height,
-                                               window->window_type == GDK_SURFACE_TEMP);
-  g_hash_table_insert (broadway_display->id_ht, GINT_TO_POINTER(impl->id), window);
-  impl->wrapper = window;
-
-  g_assert (window->window_type == GDK_SURFACE_TOPLEVEL ||
-            window->window_type == GDK_SURFACE_TEMP);
-  g_assert (window->parent == NULL);
-
-  broadway_display->toplevels = g_list_prepend (broadway_display->toplevels, impl);
-
-  connect_frame_clock (window);
-}
-
-static cairo_surface_t *
-gdk_surface_broadway_ref_cairo_surface (GdkSurface *window)
-{
-  GdkSurfaceImplBroadway *impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-
-  if (GDK_IS_SURFACE_IMPL_BROADWAY (window) &&
-      GDK_SURFACE_DESTROYED (impl->wrapper))
-    return NULL;
-
-  return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
-}
-
-static void
-_gdk_broadway_surface_destroy (GdkSurface *window,
-                              gboolean   recursing,
-                              gboolean   foreign_destroy)
-{
-  GdkSurfaceImplBroadway *impl;
-  GdkBroadwayDisplay *broadway_display;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-
-  if (impl->node_data)
-    g_array_unref (impl->node_data);
-  if (impl->node_data_textures)
-    g_ptr_array_unref (impl->node_data_textures);
-
-  _gdk_broadway_surface_grab_check_destroy (window);
-
-  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
-  g_hash_table_remove (broadway_display->id_ht, GINT_TO_POINTER (impl->id));
-
-  _gdk_broadway_server_destroy_surface (broadway_display->server, impl->id);
-
-}
-
-void
-gdk_broadway_surface_set_nodes (GdkSurface *window,
-                               GArray *nodes,
-                               GPtrArray *node_textures)
-{
-  GdkSurfaceImplBroadway *impl;
-  GdkBroadwayDisplay *broadway_display;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-
-  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
-
-  if (nodes)
-    g_array_ref (nodes);
-  if (impl->node_data)
-    g_array_unref (impl->node_data);
-  impl->node_data = nodes;
-
-  if (node_textures)
-    g_ptr_array_ref (node_textures);
-  if (impl->node_data_textures)
-    g_ptr_array_unref (impl->node_data_textures);
-  impl->node_data_textures = node_textures;
-
-  gdk_broadway_server_surface_set_nodes (broadway_display->server, impl->id, impl->node_data);
-}
-
-/* This function is called when the XWindow is really gone.
- */
-static void
-gdk_broadway_surface_destroy_notify (GdkSurface *window)
-{
-  if (!GDK_SURFACE_DESTROYED (window))
-    _gdk_surface_destroy (window, TRUE);
-
-  g_object_unref (window);
-}
-
-static void
-gdk_surface_broadway_show (GdkSurface *window, gboolean already_mapped)
-{
-  GdkSurfaceImplBroadway *impl;
-  GdkBroadwayDisplay *broadway_display;
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-  impl->visible = TRUE;
-
-  if (window->event_mask & GDK_STRUCTURE_MASK)
-    _gdk_make_event (GDK_SURFACE (window), GDK_MAP, NULL, FALSE);
-
-  if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
-    _gdk_make_event (GDK_SURFACE (window), GDK_MAP, NULL, FALSE);
-
-  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
-  if (_gdk_broadway_server_surface_show (broadway_display->server, impl->id))
-    queue_flush (window);
-
-}
-
-static void
-gdk_surface_broadway_hide (GdkSurface *window)
-{
-  GdkSurfaceImplBroadway *impl;
-  GdkBroadwayDisplay *broadway_display;
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-  impl->visible = FALSE;
-
-  if (window->event_mask & GDK_STRUCTURE_MASK)
-    _gdk_make_event (GDK_SURFACE (window), GDK_UNMAP, NULL, FALSE);
-
-  if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
-    _gdk_make_event (GDK_SURFACE (window), GDK_UNMAP, NULL, FALSE);
-
-  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
-
-  _gdk_broadway_surface_grab_check_unmap (window,
-                                         _gdk_broadway_server_get_next_serial (broadway_display->server));
-
-  if (_gdk_broadway_server_surface_hide (broadway_display->server, impl->id))
-    queue_flush (window);
-
-  _gdk_surface_clear_update_area (window);
-}
-
-static void
-gdk_surface_broadway_withdraw (GdkSurface *window)
-{
-  gdk_surface_broadway_hide (window);
-}
-
-static void
-gdk_surface_broadway_move_resize (GdkSurface *window,
-                                 gboolean   with_move,
-                                 gint       x,
-                                 gint       y,
-                                 gint       width,
-                                 gint       height)
-{
-  GdkSurfaceImplBroadway *impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-  GdkBroadwayDisplay *broadway_display;
-  gboolean size_changed;
-
-  size_changed = FALSE;
-
-  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
-
-  if (width > 0 || height > 0)
-    {
-      if (width < 1)
-        width = 1;
-
-      if (height < 1)
-        height = 1;
-
-      if (width != window->width ||
-          height != window->height)
-        {
-          size_changed = TRUE;
-
-          /* Resize clears the content */
-          impl->dirty = TRUE;
-          impl->last_synced = FALSE;
-
-          window->width = width;
-          window->height = height;
-        }
-    }
-
-  _gdk_broadway_server_surface_move_resize (broadway_display->server,
-                                            impl->id,
-                                            with_move,
-                                            x, y,
-                                            window->width, window->height);
-  queue_flush (window);
-  if (size_changed)
-    window->resize_count++;
-}
-
-static void
-gdk_surface_broadway_raise (GdkSurface *window)
-{
-}
-
-static void
-gdk_surface_broadway_restack_toplevel (GdkSurface *window,
-                                      GdkSurface *sibling,
-                                      gboolean   above)
-{
-}
-
-static void
-gdk_surface_broadway_lower (GdkSurface *window)
-{
-}
-
-
-static void
-gdk_broadway_surface_focus (GdkSurface *window,
-                           guint32    timestamp)
-{
-  GdkSurfaceImplBroadway *impl;
-  GdkBroadwayDisplay *broadway_display;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !window->accept_focus)
-    return;
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-  broadway_display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (window));
-  _gdk_broadway_server_surface_focus (broadway_display->server,
-                                      impl->id);
-}
-
-static void
-gdk_broadway_surface_set_type_hint (GdkSurface        *window,
-                                   GdkSurfaceTypeHint hint)
-{
-}
-
-static GdkSurfaceTypeHint
-gdk_broadway_surface_get_type_hint (GdkSurface *window)
-{
-  return GDK_SURFACE_TYPE_HINT_NORMAL;
-}
-
-static void
-gdk_broadway_surface_set_modal_hint (GdkSurface *window,
-                                    gboolean   modal)
-{
-}
-
-static void
-gdk_broadway_surface_set_skip_taskbar_hint (GdkSurface *window,
-                                           gboolean   skips_taskbar)
-{
-}
-
-static void
-gdk_broadway_surface_set_skip_pager_hint (GdkSurface *window,
-                                         gboolean   skips_pager)
-{
-}
-
-static void
-gdk_broadway_surface_set_urgency_hint (GdkSurface *window,
-                                      gboolean   urgent)
-{
-}
-
-static void
-gdk_broadway_surface_set_geometry_hints (GdkSurface         *window,
-                                        const GdkGeometry *geometry,
-                                        GdkSurfaceHints     geom_mask)
-{
-  GdkSurfaceImplBroadway *impl;
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-
-  impl->geometry_hints = *geometry;
-  impl->geometry_hints_mask = geom_mask;
-}
-
-static void
-gdk_broadway_surface_set_title (GdkSurface   *window,
-                               const gchar *title)
-{
-}
-
-static void
-gdk_broadway_surface_set_role (GdkSurface   *window,
-                              const gchar *role)
-{
-}
-
-static void
-gdk_broadway_surface_set_startup_id (GdkSurface   *window,
-                                    const gchar *startup_id)
-{
-}
-
-static void
-gdk_broadway_surface_set_transient_for (GdkSurface *window,
-                                       GdkSurface *parent)
-{
-  GdkBroadwayDisplay *display;
-  GdkSurfaceImplBroadway *impl;
-  int parent_id;
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-
-  parent_id = 0;
-  if (parent)
-    parent_id = GDK_SURFACE_IMPL_BROADWAY (parent->impl)->id;
-
-  impl->transient_for = parent_id;
-
-  display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (impl->wrapper));
-  _gdk_broadway_server_surface_set_transient_for (display->server, impl->id, impl->transient_for);
-}
-
-static void
-gdk_surface_broadway_get_geometry (GdkSurface *window,
-                                  gint      *x,
-                                  gint      *y,
-                                  gint      *width,
-                                  gint      *height)
-{
-  GdkSurfaceImplBroadway *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-
-  /* TODO: These should really roundtrip to the client to get the current data */
-
-  if (x)
-    *x = impl->wrapper->x;
-  if (y)
-    *y = impl->wrapper->y;
-  if (width)
-    *width = impl->wrapper->width;
-  if (height)
-    *height = impl->wrapper->height;
-
-}
-
-static void
-gdk_surface_broadway_get_root_coords (GdkSurface *window,
-                                     gint       x,
-                                     gint       y,
-                                     gint      *root_x,
-                                     gint      *root_y)
-{
-  GdkSurfaceImplBroadway *impl;
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-
-  if (root_x)
-    *root_x = x + impl->wrapper->x;
-  if (root_y)
-    *root_y = y + impl->wrapper->y;
-}
-
-static void
-gdk_broadway_surface_get_frame_extents (GdkSurface    *window,
-                                       GdkRectangle *rect)
-{
-  g_return_if_fail (rect != NULL);
-
-  /* TODO: This should take wm frame into account */
-
-  rect->x = window->x;
-  rect->y = window->y;
-  rect->width = window->width;
-  rect->height = window->height;
-}
-
-static gboolean
-gdk_surface_broadway_get_device_state (GdkSurface       *window,
-                                      GdkDevice       *device,
-                                      gdouble         *x,
-                                      gdouble         *y,
-                                      GdkModifierType *mask)
-{
-  GdkSurface *child;
-
-  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), FALSE);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return FALSE;
-
-  GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
-                                              &child,
-                                              NULL, NULL,
-                                              x, y, mask);
-  return child != NULL;
-}
-
-static GdkEventMask
-gdk_surface_broadway_get_events (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return 0;
-
-  return 0;
-}
-
-static void
-gdk_surface_broadway_set_events (GdkSurface    *window,
-                                GdkEventMask  event_mask)
-{
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-    }
-}
-
-static void
-gdk_surface_broadway_shape_combine_region (GdkSurface       *window,
-                                          const cairo_region_t *shape_region,
-                                          gint             offset_x,
-                                          gint             offset_y)
-{
-}
-
-static void
-gdk_surface_broadway_input_shape_combine_region (GdkSurface       *window,
-                                                const cairo_region_t *shape_region,
-                                                gint             offset_x,
-                                                gint             offset_y)
-{
-}
-
-static void
-gdk_broadway_surface_set_accept_focus (GdkSurface *window,
-                                      gboolean accept_focus)
-{
-  accept_focus = accept_focus != FALSE;
-
-  if (window->accept_focus != accept_focus)
-    {
-      window->accept_focus = accept_focus;
-    }
-}
-
-static void
-gdk_broadway_surface_set_focus_on_map (GdkSurface *window,
-                                      gboolean focus_on_map)
-{
-  focus_on_map = focus_on_map != FALSE;
-
-  if (window->focus_on_map != focus_on_map)
-    {
-      window->focus_on_map = focus_on_map;
-    }
-}
-
-
-static void
-gdk_broadway_surface_set_icon_list (GdkSurface *window,
-                                   GList     *surfaces)
-{
-}
-
-static void
-gdk_broadway_surface_set_icon_name (GdkSurface   *window,
-                                   const gchar *name)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
-                      GUINT_TO_POINTER (name != NULL));
-}
-
-static void
-gdk_broadway_surface_iconify (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-}
-
-static void
-gdk_broadway_surface_deiconify (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-}
-
-static void
-gdk_broadway_surface_stick (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-}
-
-static void
-gdk_broadway_surface_unstick (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-}
-
-static void
-gdk_broadway_surface_maximize (GdkSurface *window)
-{
-  GdkSurfaceImplBroadway *impl;
-  GdkDisplay *display;
-  GdkMonitor *monitor;
-  GdkRectangle geom;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-
-  if (impl->maximized)
-    return;
-
-  impl->maximized = TRUE;
-
-  gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_MAXIMIZED);
-
-  impl->pre_maximize_x = window->x;
-  impl->pre_maximize_y = window->y;
-  impl->pre_maximize_width = window->width;
-  impl->pre_maximize_height = window->height;
-
-  display = gdk_surface_get_display (window);
-  monitor = gdk_display_get_primary_monitor (display);
-  gdk_monitor_get_geometry (monitor, &geom);
-
-  gdk_surface_move_resize (window,
-                          geom.x, geom.y,
-                          geom.width, geom.height);
-}
-
-static void
-gdk_broadway_surface_unmaximize (GdkSurface *window)
-{
-  GdkSurfaceImplBroadway *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-
-  if (!impl->maximized)
-    return;
-
-  impl->maximized = FALSE;
-
-  gdk_synthesize_window_state (window, GDK_SURFACE_STATE_MAXIMIZED, 0);
-
-  gdk_surface_move_resize (window,
-                          impl->pre_maximize_x,
-                          impl->pre_maximize_y,
-                          impl->pre_maximize_width,
-                          impl->pre_maximize_height);
-}
-
-static void
-gdk_broadway_surface_fullscreen (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-}
-
-static void
-gdk_broadway_surface_unfullscreen (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-}
-
-static void
-gdk_broadway_surface_set_keep_above (GdkSurface *window,
-                                    gboolean   setting)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-}
-
-static void
-gdk_broadway_surface_set_keep_below (GdkSurface *window, gboolean setting)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-}
-
-static GdkSurface *
-gdk_broadway_surface_get_group (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return NULL;
-
-  return window;
-}
-
-static void
-gdk_broadway_surface_set_group (GdkSurface *window,
-                               GdkSurface *leader)
-{
-}
-
-static void
-gdk_broadway_surface_set_decorations (GdkSurface      *window,
-                                     GdkWMDecoration decorations)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-}
-
-static gboolean
-gdk_broadway_surface_get_decorations (GdkSurface       *window,
-                                     GdkWMDecoration *decorations)
-{
-  gboolean result = FALSE;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return FALSE;
-
-  return result;
-}
-
-static void
-gdk_broadway_surface_set_functions (GdkSurface    *window,
-                                   GdkWMFunction functions)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-}
-
-static void
-gdk_broadway_surface_end_paint (GdkSurface *window)
-{
-  GdkSurfaceImplBroadway *impl;
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-  impl->dirty = TRUE;
-}
-
-typedef struct _MoveResizeData MoveResizeData;
-
-struct _MoveResizeData
-{
-  GdkDisplay *display;
-
-  GdkSurface *moveresize_window;
-  GdkSurface *moveresize_emulation_window;
-  gboolean is_resize;
-  GdkSurfaceEdge resize_edge;
-  gint moveresize_button;
-  gint moveresize_x;
-  gint moveresize_y;
-  gint moveresize_orig_x;
-  gint moveresize_orig_y;
-  gint moveresize_orig_width;
-  gint moveresize_orig_height;
-  long moveresize_process_time;
-  GdkSurfaceHints moveresize_geom_mask;
-  GdkGeometry moveresize_geometry;
-  BroadwayInputMsg *moveresize_pending_event;
-};
-
-static MoveResizeData *
-get_move_resize_data (GdkDisplay *display,
-                      gboolean    create)
-{
-  GdkBroadwayDisplay *broadway_display;
-  MoveResizeData *mv_resize;
-
-  broadway_display = GDK_BROADWAY_DISPLAY (display);
-
-  mv_resize = broadway_display->move_resize_data;
-
-  if (!mv_resize && create)
-    {
-      mv_resize = g_new0 (MoveResizeData, 1);
-      mv_resize->display = display;
-
-      broadway_display->move_resize_data = mv_resize;
-    }
-
-  return mv_resize;
-}
-
-static void
-update_pos (MoveResizeData *mv_resize,
-            gint            new_root_x,
-            gint            new_root_y)
-{
-  gint dx, dy;
-
-  dx = new_root_x - mv_resize->moveresize_x;
-  dy = new_root_y - mv_resize->moveresize_y;
-
-  if (mv_resize->is_resize)
-    {
-      gint x, y, w, h;
-
-      x = mv_resize->moveresize_orig_x;
-      y = mv_resize->moveresize_orig_y;
-
-      w = mv_resize->moveresize_orig_width;
-      h = mv_resize->moveresize_orig_height;
-
-      switch (mv_resize->resize_edge)
-        {
-        case GDK_SURFACE_EDGE_NORTH_WEST:
-          x += dx;
-          y += dy;
-          w -= dx;
-          h -= dy;
-          break;
-        case GDK_SURFACE_EDGE_NORTH:
-          y += dy;
-          h -= dy;
-          break;
-        case GDK_SURFACE_EDGE_NORTH_EAST:
-          y += dy;
-          h -= dy;
-          w += dx;
-          break;
-        case GDK_SURFACE_EDGE_SOUTH_WEST:
-          h += dy;
-          x += dx;
-          w -= dx;
-          break;
-        case GDK_SURFACE_EDGE_SOUTH_EAST:
-          w += dx;
-          h += dy;
-          break;
-        case GDK_SURFACE_EDGE_SOUTH:
-          h += dy;
-          break;
-        case GDK_SURFACE_EDGE_EAST:
-          w += dx;
-          break;
-        case GDK_SURFACE_EDGE_WEST:
-          x += dx;
-          w -= dx;
-          break;
-        default:
-          break;
-        }
-
-      x = MAX (x, 0);
-      y = MAX (y, 0);
-      w = MAX (w, 1);
-      h = MAX (h, 1);
-
-      if (mv_resize->moveresize_geom_mask)
-        {
-          gdk_surface_constrain_size (&mv_resize->moveresize_geometry,
-                                     mv_resize->moveresize_geom_mask,
-                                     w, h, &w, &h);
-        }
-
-      gdk_surface_move_resize (mv_resize->moveresize_window, x, y, w, h);
-    }
-  else
-    {
-      gint x, y;
-
-      x = mv_resize->moveresize_orig_x + dx;
-      y = mv_resize->moveresize_orig_y + dy;
-
-      gdk_surface_move (mv_resize->moveresize_window, x, y);
-    }
-}
-
-static void
-finish_drag (MoveResizeData *mv_resize)
-{
-  gdk_surface_destroy (mv_resize->moveresize_emulation_window);
-  mv_resize->moveresize_emulation_window = NULL;
-  g_object_unref (mv_resize->moveresize_window);
-  mv_resize->moveresize_window = NULL;
-  g_clear_pointer (&mv_resize->moveresize_pending_event, g_free);
-}
-
-static gboolean
-moveresize_lookahead (GdkDisplay *display,
-                      MoveResizeData *mv_resize,
-                      BroadwayInputMsg *event)
-{
-  GdkBroadwayDisplay *broadway_display;
-
-  broadway_display = GDK_BROADWAY_DISPLAY (display);
-
-  return !_gdk_broadway_server_lookahead_event (broadway_display->server, "mb");
-}
-
-gboolean
-_gdk_broadway_moveresize_handle_event (GdkDisplay *display,
-                                       BroadwayInputMsg *event)
-{
-  guint button_mask = 0;
-  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
-
-  if (!mv_resize || !mv_resize->moveresize_window)
-    return FALSE;
-
-  button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
-
-  switch (event->base.type)
-    {
-    case BROADWAY_EVENT_TOUCH:
-      if (event->touch.touch_type == 2) /* END */
-        {
-          update_pos (mv_resize,
-                      event->touch.root_x,
-                      event->touch.root_y);
-
-          finish_drag (mv_resize);
-        }
-      else if (event->touch.touch_type == 1) /* UPDATE */
-        {
-          if (mv_resize->moveresize_window->resize_count > 0)
-            {
-              if (mv_resize->moveresize_pending_event)
-                *mv_resize->moveresize_pending_event = *event;
-              else
-                mv_resize->moveresize_pending_event =
-                  g_memdup (event, sizeof (BroadwayInputMsg));
-
-              break;
-            }
-          update_pos (mv_resize,
-                      event->touch.root_x,
-                      event->touch.root_y);
-        }
-
-      break;
-
-    case BROADWAY_EVENT_POINTER_MOVE:
-      if (mv_resize->moveresize_window->resize_count > 0)
-        {
-          if (mv_resize->moveresize_pending_event)
-            *mv_resize->moveresize_pending_event = *event;
-          else
-            mv_resize->moveresize_pending_event =
-              g_memdup (event, sizeof (BroadwayInputMsg));
-
-          break;
-        }
-      if (!moveresize_lookahead (display, mv_resize, event))
-        break;
-
-      update_pos (mv_resize,
-                  event->pointer.root_x,
-                  event->pointer.root_y);
-
-      /* This should never be triggered in normal cases, but in the
-       * case where the drag started without an implicit grab being
-       * in effect, we could miss the release if it occurs before
-       * we grab the pointer; this ensures that we will never
-       * get a permanently stuck grab.
-       */
-      if ((event->pointer.state & button_mask) == 0)
-        finish_drag (mv_resize);
-      break;
-
-    case BROADWAY_EVENT_BUTTON_RELEASE:
-      update_pos (mv_resize,
-                  event->pointer.root_x,
-                  event->pointer.root_y);
-
-      if (event->button.button == mv_resize->moveresize_button)
-        finish_drag (mv_resize);
-      break;
-    default:
-      break;
-    }
-  return TRUE;
-}
-
-gboolean
-_gdk_broadway_moveresize_configure_done (GdkDisplay *display,
-                                         GdkSurface  *window)
-{
-  BroadwayInputMsg *tmp_event;
-  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
-
-  if (!mv_resize || window != mv_resize->moveresize_window)
-    return FALSE;
-
-  if (mv_resize->moveresize_pending_event)
-    {
-      tmp_event = mv_resize->moveresize_pending_event;
-      mv_resize->moveresize_pending_event = NULL;
-      _gdk_broadway_moveresize_handle_event (display, tmp_event);
-      g_free (tmp_event);
-    }
-
-  return TRUE;
-}
-
-static void
-create_moveresize_window (MoveResizeData *mv_resize,
-                          guint32         timestamp)
-{
-  GdkGrabStatus status;
-  GdkSeat *seat;
-  GdkDevice *pointer;
-
-  g_assert (mv_resize->moveresize_emulation_window == NULL);
-
-  mv_resize->moveresize_emulation_window = gdk_surface_new_temp (mv_resize->display);
-
-  gdk_surface_show (mv_resize->moveresize_emulation_window);
-
-  seat = gdk_display_get_default_seat (mv_resize->display);
-  pointer = gdk_seat_get_pointer (seat);
-
-  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
-  status = gdk_device_grab (pointer,
-                             mv_resize->moveresize_emulation_window,
-                             GDK_OWNERSHIP_APPLICATION,
-                             FALSE,
-                             GDK_BUTTON_RELEASE_MASK |
-                             GDK_POINTER_MOTION_MASK,
-                             NULL,
-                             timestamp);
-  G_GNUC_END_IGNORE_DEPRECATIONS;
-
-  if (status != GDK_GRAB_SUCCESS)
-    {
-      /* If this fails, some other client has grabbed the window
-       * already.
-       */
-      finish_drag (mv_resize);
-    }
-
-  mv_resize->moveresize_process_time = 0;
-}
-
-static void
-calculate_unmoving_origin (MoveResizeData *mv_resize)
-{
-  GdkRectangle rect;
-  gint width, height;
-
-  if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
-      mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
-    {
-      gdk_surface_get_origin (mv_resize->moveresize_window,
-                             &mv_resize->moveresize_orig_x,
-                             &mv_resize->moveresize_orig_y);
-    }
-  else
-    {
-      gdk_surface_get_frame_extents (mv_resize->moveresize_window, &rect);
-      gdk_surface_get_geometry (mv_resize->moveresize_window,
-                               NULL, NULL, &width, &height);
-
-      switch (mv_resize->moveresize_geometry.win_gravity)
-        {
-        case GDK_GRAVITY_NORTH_WEST:
-          mv_resize->moveresize_orig_x = rect.x;
-          mv_resize->moveresize_orig_y = rect.y;
-          break;
-        case GDK_GRAVITY_NORTH:
-          mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
-          mv_resize->moveresize_orig_y = rect.y;
-          break;
-        case GDK_GRAVITY_NORTH_EAST:
-          mv_resize->moveresize_orig_x = rect.x + rect.width - width;
-          mv_resize->moveresize_orig_y = rect.y;
-          break;
-        case GDK_GRAVITY_WEST:
-          mv_resize->moveresize_orig_x = rect.x;
-          mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
-          break;
-        case GDK_GRAVITY_CENTER:
-          mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
-          mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
-          break;
-        case GDK_GRAVITY_EAST:
-          mv_resize->moveresize_orig_x = rect.x + rect.width - width;
-          mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
-          break;
-        case GDK_GRAVITY_SOUTH_WEST:
-          mv_resize->moveresize_orig_x = rect.x;
-          mv_resize->moveresize_orig_y = rect.y + rect.height - height;
-          break;
-        case GDK_GRAVITY_SOUTH:
-          mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
-          mv_resize->moveresize_orig_y = rect.y + rect.height - height;
-          break;
-        case GDK_GRAVITY_SOUTH_EAST:
-          mv_resize->moveresize_orig_x = rect.x + rect.width - width;
-          mv_resize->moveresize_orig_y = rect.y + rect.height - height;
-          break;
-        case GDK_GRAVITY_STATIC:
-        default:
-          mv_resize->moveresize_orig_x = rect.x;
-          mv_resize->moveresize_orig_y = rect.y;
-          break;
-        }
-    }
-}
-
-static void
-gdk_broadway_surface_begin_resize_drag (GdkSurface     *window,
-                                       GdkSurfaceEdge  edge,
-                                       GdkDevice     *device,
-                                       gint           button,
-                                       gint           root_x,
-                                       gint           root_y,
-                                       guint32        timestamp)
-{
-  MoveResizeData *mv_resize;
-  GdkSurfaceImplBroadway *impl;
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  if (impl->maximized)
-    return;
-
-  mv_resize = get_move_resize_data (gdk_surface_get_display (window), TRUE);
-
-  mv_resize->is_resize = TRUE;
-  mv_resize->moveresize_button = button;
-  mv_resize->resize_edge = edge;
-  mv_resize->moveresize_x = root_x;
-  mv_resize->moveresize_y = root_y;
-  mv_resize->moveresize_window = g_object_ref (window);
-
-  mv_resize->moveresize_orig_width = gdk_surface_get_width (window);
-  mv_resize->moveresize_orig_height = gdk_surface_get_height (window);
-
-  mv_resize->moveresize_geom_mask = impl->geometry_hints_mask;
-  mv_resize->moveresize_geometry = impl->geometry_hints;
-
-  calculate_unmoving_origin (mv_resize);
-
-  create_moveresize_window (mv_resize, timestamp);
-}
-
-static void
-gdk_broadway_surface_begin_move_drag (GdkSurface *window,
-                                     GdkDevice *device,
-                                     gint       button,
-                                     gint       root_x,
-                                     gint       root_y,
-                                     guint32    timestamp)
-{
-  MoveResizeData *mv_resize;
-  GdkSurfaceImplBroadway *impl;
-
-  impl = GDK_SURFACE_IMPL_BROADWAY (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  if (impl->maximized)
-    return;
-
-  mv_resize = get_move_resize_data (gdk_surface_get_display (window), TRUE);
-
-  mv_resize->is_resize = FALSE;
-  mv_resize->moveresize_button = button;
-  mv_resize->moveresize_x = root_x;
-  mv_resize->moveresize_y = root_y;
-  mv_resize->moveresize_window = g_object_ref (window);
-
-  mv_resize->moveresize_orig_width = gdk_surface_get_width (window);
-  mv_resize->moveresize_orig_height = gdk_surface_get_height (window);
-
-  mv_resize->moveresize_geom_mask = impl->geometry_hints_mask;
-  mv_resize->moveresize_geometry = impl->geometry_hints;
-
-  calculate_unmoving_origin (mv_resize);
-
-  create_moveresize_window (mv_resize, timestamp);
-}
-
-static gboolean
-gdk_broadway_surface_beep (GdkSurface *window)
-{
-  return FALSE;
-}
-
-static void
-gdk_broadway_surface_set_opacity (GdkSurface *window,
-                                 gdouble    opacity)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  if (opacity < 0)
-    opacity = 0;
-  else if (opacity > 1)
-    opacity = 1;
-}
-
-guint32
-gdk_broadway_get_last_seen_time (GdkSurface  *window)
-{
-  GdkDisplay *display;
-
-  display = gdk_surface_get_display (window);
-  return _gdk_broadway_server_get_last_seen_time (GDK_BROADWAY_DISPLAY (display)->server);
-}
-
-static void
-gdk_surface_impl_broadway_class_init (GdkSurfaceImplBroadwayClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_CLASS (klass);
-
-  object_class->finalize = gdk_surface_impl_broadway_finalize;
-
-  impl_class->ref_cairo_surface = gdk_surface_broadway_ref_cairo_surface;
-  impl_class->show = gdk_surface_broadway_show;
-  impl_class->hide = gdk_surface_broadway_hide;
-  impl_class->withdraw = gdk_surface_broadway_withdraw;
-  impl_class->set_events = gdk_surface_broadway_set_events;
-  impl_class->get_events = gdk_surface_broadway_get_events;
-  impl_class->raise = gdk_surface_broadway_raise;
-  impl_class->lower = gdk_surface_broadway_lower;
-  impl_class->restack_toplevel = gdk_surface_broadway_restack_toplevel;
-  impl_class->move_resize = gdk_surface_broadway_move_resize;
-  impl_class->get_geometry = gdk_surface_broadway_get_geometry;
-  impl_class->get_root_coords = gdk_surface_broadway_get_root_coords;
-  impl_class->get_device_state = gdk_surface_broadway_get_device_state;
-  impl_class->shape_combine_region = gdk_surface_broadway_shape_combine_region;
-  impl_class->input_shape_combine_region = gdk_surface_broadway_input_shape_combine_region;
-  impl_class->destroy = _gdk_broadway_surface_destroy;
-  impl_class->end_paint = gdk_broadway_surface_end_paint;
-  impl_class->beep = gdk_broadway_surface_beep;
-
-  impl_class->focus = gdk_broadway_surface_focus;
-  impl_class->set_type_hint = gdk_broadway_surface_set_type_hint;
-  impl_class->get_type_hint = gdk_broadway_surface_get_type_hint;
-  impl_class->set_modal_hint = gdk_broadway_surface_set_modal_hint;
-  impl_class->set_skip_taskbar_hint = gdk_broadway_surface_set_skip_taskbar_hint;
-  impl_class->set_skip_pager_hint = gdk_broadway_surface_set_skip_pager_hint;
-  impl_class->set_urgency_hint = gdk_broadway_surface_set_urgency_hint;
-  impl_class->set_geometry_hints = gdk_broadway_surface_set_geometry_hints;
-  impl_class->set_title = gdk_broadway_surface_set_title;
-  impl_class->set_role = gdk_broadway_surface_set_role;
-  impl_class->set_startup_id = gdk_broadway_surface_set_startup_id;
-  impl_class->set_transient_for = gdk_broadway_surface_set_transient_for;
-  impl_class->get_frame_extents = gdk_broadway_surface_get_frame_extents;
-  impl_class->set_accept_focus = gdk_broadway_surface_set_accept_focus;
-  impl_class->set_focus_on_map = gdk_broadway_surface_set_focus_on_map;
-  impl_class->set_icon_list = gdk_broadway_surface_set_icon_list;
-  impl_class->set_icon_name = gdk_broadway_surface_set_icon_name;
-  impl_class->iconify = gdk_broadway_surface_iconify;
-  impl_class->deiconify = gdk_broadway_surface_deiconify;
-  impl_class->stick = gdk_broadway_surface_stick;
-  impl_class->unstick = gdk_broadway_surface_unstick;
-  impl_class->maximize = gdk_broadway_surface_maximize;
-  impl_class->unmaximize = gdk_broadway_surface_unmaximize;
-  impl_class->fullscreen = gdk_broadway_surface_fullscreen;
-  impl_class->unfullscreen = gdk_broadway_surface_unfullscreen;
-  impl_class->set_keep_above = gdk_broadway_surface_set_keep_above;
-  impl_class->set_keep_below = gdk_broadway_surface_set_keep_below;
-  impl_class->get_group = gdk_broadway_surface_get_group;
-  impl_class->set_group = gdk_broadway_surface_set_group;
-  impl_class->set_decorations = gdk_broadway_surface_set_decorations;
-  impl_class->get_decorations = gdk_broadway_surface_get_decorations;
-  impl_class->set_functions = gdk_broadway_surface_set_functions;
-  impl_class->begin_resize_drag = gdk_broadway_surface_begin_resize_drag;
-  impl_class->begin_move_drag = gdk_broadway_surface_begin_move_drag;
-  impl_class->set_opacity = gdk_broadway_surface_set_opacity;
-  impl_class->destroy_notify = gdk_broadway_surface_destroy_notify;
-  impl_class->register_dnd = _gdk_broadway_surface_register_dnd;
-  impl_class->drag_begin = _gdk_broadway_surface_drag_begin;
-}
diff --git a/gdk/broadway/gdkwindow-broadway.h b/gdk/broadway/gdkwindow-broadway.h
deleted file mode 100644 (file)
index d623931..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-#ifndef __GDK_SURFACE_BROADWAY_H__
-#define __GDK_SURFACE_BROADWAY_H__
-
-#include <gdk/gdkwindowimpl.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GdkSurfaceImplBroadway GdkSurfaceImplBroadway;
-typedef struct _GdkSurfaceImplBroadwayClass GdkSurfaceImplBroadwayClass;
-
-/* Window implementation for Broadway
- */
-
-#define GDK_TYPE_SURFACE_IMPL_BROADWAY              (gdk_surface_impl_broadway_get_type ())
-#define GDK_SURFACE_IMPL_BROADWAY(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_BROADWAY, GdkSurfaceImplBroadway))
-#define GDK_SURFACE_IMPL_BROADWAY_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_BROADWAY, GdkSurfaceImplBroadwayClass))
-#define GDK_IS_SURFACE_IMPL_BROADWAY(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_BROADWAY))
-#define GDK_IS_SURFACE_IMPL_BROADWAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_BROADWAY))
-#define GDK_SURFACE_IMPL_BROADWAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_BROADWAY, GdkSurfaceImplBroadwayClass))
-
-struct _GdkSurfaceImplBroadway
-{
-  GdkSurfaceImpl parent_instance;
-
-  GdkSurface *wrapper;
-
-  GdkCursor *cursor;
-
-  int id;
-
-  gboolean visible;
-  gboolean maximized;
-  int transient_for;
-
-  int pre_maximize_x;
-  int pre_maximize_y;
-  int pre_maximize_width;
-  int pre_maximize_height;
-
-  gint8 toplevel_window_type;
-  gboolean dirty;
-  gboolean last_synced;
-
-  GdkGeometry geometry_hints;
-  GdkSurfaceHints geometry_hints_mask;
-
-  GArray *node_data;
-  GPtrArray *node_data_textures;
-};
-
-struct _GdkSurfaceImplBroadwayClass
-{
-  GdkSurfaceImplClass parent_class;
-};
-
-GType gdk_surface_impl_broadway_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GDK_SURFACE_BROADWAY_H__ */
index 970b6c8e6c9691c0f3f16e3449416a0611acb520..81e29cc9c1cbcb6dbac7e4524fb98addb18d25a0 100644 (file)
@@ -12,12 +12,12 @@ gdk_broadway_sources = files([
   'gdkkeys-broadway.c',
   'gdkmonitor-broadway.c',
   'gdkselection-broadway.c',
-  'gdkwindow-broadway.c',
+  'gdksurface-broadway.c',
 ])
 
 gdk_broadway_public_headers = [
   'gdkbroadwaydisplay.h',
-  'gdkbroadwaywindow.h',
+  'gdkbroadwaysurface.h',
   'gdkbroadwaycursor.h',
   'gdkbroadwaymonitor.h',
 ]
index 6bb48e004a89bd855b472209e9be1f2fa6891fb8..921e93690d34aaf0ec7d7d169f21d51693fc3336 100644 (file)
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -67,7 +67,7 @@
 #include <gdk/gdktexture.h>
 #include <gdk/gdktypes.h>
 #include <gdk/gdkvulkancontext.h>
-#include <gdk/gdkwindow.h>
+#include <gdk/gdksurface.h>
 
 #include <gdk/gdk-autocleanup.h>
 
index cfcffcec6a2ab9d2f9ca3f5bbfd6589949a7d612..2e9f0abd230fdadecd8e57f800eedb9b6bb5c5ee 100644 (file)
@@ -31,7 +31,7 @@
 #include "gdkdeviceprivate.h"
 #include "gdkdisplaymanagerprivate.h"
 #include "gdkevents.h"
-#include "gdkwindowimpl.h"
+#include "gdksurfaceimpl.h"
 #include "gdkinternals.h"
 #include "gdkmonitorprivate.h"
 
index dc206b9070f3ac1dff873f5573efefd016e21d25..db52472a3c1a33062019d2cf4ac87255a99c76ec 100644 (file)
@@ -19,7 +19,7 @@
 #define __GDK_DISPLAY_PRIVATE_H__
 
 #include "gdkdisplay.h"
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkcursor.h"
 #include "gdkmonitor.h"
 #include "gdkinternals.h"
index f3197e6d75b8bee4d61d32302a26655c3d62ba43..7d6d453d2f873950ce6d687ab2e5a70f24684b3a 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "gdkdndprivate.h"
 #include "gdkdisplay.h"
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkintl.h"
 #include "gdkcontentformats.h"
 #include "gdkcontentprovider.h"
index eecf58a23ae38ec358aa4c54f48fb7a80ed0338c..b47aaf35a471a0e23fad1fcffc6a4022ac0ae4e5 100644 (file)
@@ -49,7 +49,7 @@
 #include "gdkinternals.h"
 #include "gdkintl.h"
 #include "gdkframeclockidle.h"
-#include "gdkwindowimpl.h"
+#include "gdksurfaceimpl.h"
 #include "gdkglcontextprivate.h"
 #include "gdk-private.h"
 
index 97c54b01e24fc59db581089bccd37acdda7afbae..c55353448a7c5873459c67d004b5dd87de7e5b74 100644 (file)
@@ -28,7 +28,7 @@
 #define __GDK_INTERNALS_H__
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
-#include "gdkwindowimpl.h"
+#include "gdksurfaceimpl.h"
 #include "gdkdisplay.h"
 #include "gdkeventsprivate.h"
 #include "gdkenumtypes.h"
index c8a2c20376e6eff67ed6ea502c7c03d016d7c16a..fd4fa5a97a063c1d5b787575d7fdfbec3668ceb4 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "gdkpixbuf.h"
 
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkinternals.h"
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
index f5e6a0336eaa009fb9ad93bcfa679631492943a0..c9a0a4c220fd45a25399246ea5fba28666faad99 100644 (file)
@@ -25,7 +25,7 @@
 #endif
 
 #include <glib-object.h>
-#include <gdk/gdkwindow.h>
+#include <gdk/gdksurface.h>
 #include <gdk/gdkevents.h>
 #include <gdk/gdktypes.h>
 
diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c
new file mode 100644 (file)
index 0000000..d37a5ac
--- /dev/null
@@ -0,0 +1,6957 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
+ * Josh MacDonald, Ryan Lortie
+ *
+ * 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include "config.h"
+
+#include <cairo-gobject.h>
+
+#include "gdksurface.h"
+
+#include "gdkrectangle.h"
+#include "gdkinternals.h"
+#include "gdkintl.h"
+#include "gdkdisplayprivate.h"
+#include "gdkdeviceprivate.h"
+#include "gdkmarshalers.h"
+#include "gdkframeclockidle.h"
+#include "gdksurfaceimpl.h"
+#include "gdkglcontextprivate.h"
+#include "gdkdrawingcontextprivate.h"
+#include "gdk-private.h"
+
+#include <math.h>
+
+#include <epoxy/gl.h>
+
+/* for the use of round() */
+#include "fallback-c89.c"
+
+#ifdef GDK_WINDOWING_WAYLAND
+#include "wayland/gdkwayland.h"
+#endif
+
+#undef DEBUG_WINDOW_PRINTING
+
+
+/**
+ * SECTION:windows
+ * @Short_description: Onscreen display areas in the target window system
+ * @Title: Windows
+ *
+ * A #GdkSurface is a (usually) rectangular region on the screen.
+ * It’s a low-level object, used to implement high-level objects such as
+ * #GtkWidget and #GtkWindow on the GTK+ level. A #GtkWindow is a toplevel
+ * window, the thing a user might think of as a â€świndow” with a titlebar
+ * and so on; a #GtkWindow may contain many sub-GdkSurfaces.
+ */
+
+/**
+ * GdkSurface:
+ *
+ * The GdkSurface struct contains only private fields and
+ * should not be accessed directly.
+ */
+
+/* Historically a GdkSurface always matches a platform native window,
+ * be it a toplevel window or a child window. In this setup the
+ * GdkSurface (and other GdkDrawables) were platform independent classes,
+ * and the actual platform specific implementation was in a delegate
+ * object available as â€śimpl” in the window object.
+ *
+ * With the addition of client side windows this changes a bit. The
+ * application-visible GdkSurface object behaves as it did before, but
+ * such windows now don't a corresponding native window. Instead subwindows
+ * windows are â€śclient side”, i.e. emulated by the gdk code such
+ * that clipping, drawing, moving, events etc work as expected.
+ *
+ * GdkSurfaces have a pointer to the â€śimpl window” they are in, i.e.
+ * the topmost GdkSurface which have the same â€śimpl” value. This is stored
+ * in impl_window, which is different from the window itself only for client
+ * side windows.
+ * All GdkSurfaces (native or not) track the position of the window in the parent
+ * (x, y), the size of the window (width, height), the position of the window
+ * with respect to the impl window (abs_x, abs_y). We also track the clip
+ * region of the window wrt parent windows, in window-relative coordinates (clip_region).
+ */
+
+enum {
+  MOVED_TO_RECT,
+  LAST_SIGNAL
+};
+
+enum {
+  PROP_0,
+  PROP_CURSOR,
+  PROP_DISPLAY,
+  PROP_STATE,
+  LAST_PROP
+};
+
+/* Global info */
+
+static void gdk_surface_finalize   (GObject              *object);
+
+static void gdk_surface_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec);
+static void gdk_surface_get_property (GObject      *object,
+                                     guint         prop_id,
+                                     GValue       *value,
+                                     GParamSpec   *pspec);
+
+static void gdk_surface_clear_backing_region (GdkSurface *window);
+
+static void recompute_visible_regions   (GdkSurface *private,
+                                        gboolean recalculate_children);
+static void gdk_surface_invalidate_in_parent (GdkSurface *private);
+static void update_cursor               (GdkDisplay *display,
+                                         GdkDevice  *device);
+static void impl_window_add_update_area (GdkSurface *impl_window,
+                                        cairo_region_t *region);
+static void gdk_surface_invalidate_region_full (GdkSurface       *window,
+                                              const cairo_region_t *region,
+                                              gboolean         invalidate_children);
+static void gdk_surface_invalidate_rect_full (GdkSurface          *window,
+                                            const GdkRectangle *rect,
+                                            gboolean            invalidate_children);
+static cairo_surface_t *gdk_surface_ref_impl_surface (GdkSurface *window);
+
+static void gdk_surface_set_frame_clock (GdkSurface      *window,
+                                        GdkFrameClock  *clock);
+
+
+static guint signals[LAST_SIGNAL] = { 0 };
+static GParamSpec *properties[LAST_PROP] = { NULL, };
+
+G_DEFINE_ABSTRACT_TYPE (GdkSurface, gdk_surface, G_TYPE_OBJECT)
+
+#ifdef DEBUG_WINDOW_PRINTING
+char *
+print_region (cairo_region_t *region)
+{
+  GString *s = g_string_new ("{");
+  if (cairo_region_is_empty (region))
+    {
+      g_string_append (s, "empty");
+    }
+  else
+    {
+      int num = cairo_region_num_rectangles (region);
+      cairo_rectangle_int_t r;
+
+      if (num == 1)
+       {
+         cairo_region_get_rectangle (region, 0, &r);
+         g_string_append_printf (s, "%dx%d @%d,%d", r.width, r.height, r.x, r.y);
+       }
+      else
+       {
+         int i;
+         cairo_region_get_extents (region, &r);
+         g_string_append_printf (s, "extent: %dx%d @%d,%d, details: ", r.width, r.height, r.x, r.y);
+         for (i = 0; i < num; i++)
+           {
+              cairo_region_get_rectangle (region, i, &r);
+             g_string_append_printf (s, "[%dx%d @%d,%d]", r.width, r.height, r.x, r.y);
+             if (i != num -1)
+               g_string_append (s, ", ");
+           }
+       }
+    }
+  g_string_append (s, "}");
+  return g_string_free (s, FALSE);
+}
+#endif
+
+static GList *
+list_insert_link_before (GList *list,
+                         GList *sibling,
+                         GList *link)
+{
+  if (list == NULL || sibling == list)
+    {
+      link->prev = NULL;
+      link->next = list;
+      if (list)
+        list->prev = link;
+      return link;
+    }
+  else if (sibling == NULL)
+    {
+      GList *last = g_list_last (list);
+
+      last->next = link;
+      link->prev = last;
+      link->next = NULL;
+
+      return list;
+    }
+  else
+    {
+      link->next = sibling;
+      link->prev = sibling->prev;
+      sibling->prev = link;
+
+      if (link->prev)
+        link->prev->next = link;
+
+      return list;
+    }
+}
+
+static void
+gdk_surface_init (GdkSurface *window)
+{
+  /* 0-initialization is good for all other fields. */
+
+  window->window_type = GDK_SURFACE_CHILD;
+
+  window->state = GDK_SURFACE_STATE_WITHDRAWN;
+  window->fullscreen_mode = GDK_FULLSCREEN_ON_CURRENT_MONITOR;
+  window->width = 1;
+  window->height = 1;
+  window->toplevel_window_type = -1;
+  window->children_list_node.data = window;
+
+  window->device_cursor = g_hash_table_new_full (NULL, NULL,
+                                                 NULL, g_object_unref);
+}
+
+static void
+gdk_surface_class_init (GdkSurfaceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gdk_surface_finalize;
+  object_class->set_property = gdk_surface_set_property;
+  object_class->get_property = gdk_surface_get_property;
+
+  /* Properties */
+
+  /**
+   * GdkSurface:cursor:
+   *
+   * The mouse pointer for a #GdkSurface. See gdk_surface_set_cursor() and
+   * gdk_surface_get_cursor() for details.
+   */
+  properties[PROP_CURSOR] =
+      g_param_spec_object ("cursor",
+                           P_("Cursor"),
+                           P_("Cursor"),
+                           GDK_TYPE_CURSOR,
+                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  /**
+   * GdkSurface:display:
+   *
+   * The #GdkDisplay connection of the window. See gdk_surface_get_display()
+   * for details.
+   */
+  properties[PROP_DISPLAY] =
+      g_param_spec_object ("display",
+                           P_("Display"),
+                           P_("Display"),
+                           GDK_TYPE_DISPLAY,
+                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_STATE] =
+      g_param_spec_flags ("state",
+                          P_("State"),
+                          P_("State"),
+                          GDK_TYPE_SURFACE_STATE, GDK_SURFACE_STATE_WITHDRAWN,
+                          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+  /**
+   * GdkSurface::moved-to-rect:
+   * @window: the #GdkSurface that moved
+   * @flipped_rect: (nullable): the position of @window after any possible
+   *                flipping or %NULL if the backend can't obtain it
+   * @final_rect: (nullable): the final position of @window or %NULL if the
+   *              backend can't obtain it
+   * @flipped_x: %TRUE if the anchors were flipped horizontally
+   * @flipped_y: %TRUE if the anchors were flipped vertically
+   *
+   * Emitted when the position of @window is finalized after being moved to a
+   * destination rectangle.
+   *
+   * @window might be flipped over the destination rectangle in order to keep
+   * it on-screen, in which case @flipped_x and @flipped_y will be set to %TRUE
+   * accordingly.
+   *
+   * @flipped_rect is the ideal position of @window after any possible
+   * flipping, but before any possible sliding. @final_rect is @flipped_rect,
+   * but possibly translated in the case that flipping is still ineffective in
+   * keeping @window on-screen.
+   * Stability: Private
+   */
+  signals[MOVED_TO_RECT] =
+    g_signal_new (g_intern_static_string ("moved-to-rect"),
+                  G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_FIRST,
+                  0,
+                  NULL,
+                  NULL,
+                  _gdk_marshal_VOID__POINTER_POINTER_BOOLEAN_BOOLEAN,
+                  G_TYPE_NONE,
+                  4,
+                  G_TYPE_POINTER,
+                  G_TYPE_POINTER,
+                  G_TYPE_BOOLEAN,
+                  G_TYPE_BOOLEAN);
+}
+
+static void
+seat_removed_cb (GdkDisplay *display,
+                 GdkSeat    *seat,
+                 GdkSurface  *window)
+{
+  GdkDevice *device = gdk_seat_get_pointer (seat);
+
+  window->devices_inside = g_list_remove (window->devices_inside, device);
+  g_hash_table_remove (window->device_cursor, device);
+
+  if (window->device_events)
+    g_hash_table_remove (window->device_events, device);
+}
+
+static void
+gdk_surface_finalize (GObject *object)
+{
+  GdkSurface *window = GDK_SURFACE (object);
+
+  g_signal_handlers_disconnect_by_func (gdk_surface_get_display (window),
+                                        seat_removed_cb, window);
+
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      if (GDK_SURFACE_TYPE (window) != GDK_SURFACE_FOREIGN)
+       {
+         g_warning ("losing last reference to undestroyed window");
+         _gdk_surface_destroy (window, FALSE);
+       }
+      else
+       /* We use TRUE here, to keep us from actually calling
+        * XDestroyWindow() on the window
+        */
+       _gdk_surface_destroy (window, TRUE);
+    }
+
+  if (window->impl)
+    {
+      g_object_unref (window->impl);
+      window->impl = NULL;
+    }
+
+  if (window->impl_window != window)
+    {
+      g_object_unref (window->impl_window);
+      window->impl_window = NULL;
+    }
+
+  if (window->shape)
+    cairo_region_destroy (window->shape);
+
+  if (window->input_shape)
+    cairo_region_destroy (window->input_shape);
+
+  if (window->cursor)
+    g_object_unref (window->cursor);
+
+  if (window->device_cursor)
+    g_hash_table_destroy (window->device_cursor);
+
+  if (window->device_events)
+    g_hash_table_destroy (window->device_events);
+
+  if (window->devices_inside)
+    g_list_free (window->devices_inside);
+
+  g_clear_object (&window->display);
+
+  if (window->opaque_region)
+    cairo_region_destroy (window->opaque_region);
+
+  G_OBJECT_CLASS (gdk_surface_parent_class)->finalize (object);
+}
+
+static void
+gdk_surface_set_property (GObject      *object,
+                         guint         prop_id,
+                         const GValue *value,
+                         GParamSpec   *pspec)
+{
+  GdkSurface *window = GDK_SURFACE (object);
+
+  switch (prop_id)
+    {
+    case PROP_CURSOR:
+      gdk_surface_set_cursor (window, g_value_get_object (value));
+      break;
+
+    case PROP_DISPLAY:
+      window->display = g_value_dup_object (value);
+      g_assert (window->display != NULL);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdk_surface_get_property (GObject    *object,
+                         guint       prop_id,
+                         GValue     *value,
+                         GParamSpec *pspec)
+{
+  GdkSurface *window = GDK_SURFACE (object);
+
+  switch (prop_id)
+    {
+    case PROP_CURSOR:
+      g_value_set_object (value, gdk_surface_get_cursor (window));
+      break;
+
+    case PROP_DISPLAY:
+      g_value_set_object (value, window->display);
+      break;
+
+    case PROP_STATE:
+      g_value_set_flags (value, window->state);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static gboolean
+gdk_surface_is_subsurface (GdkSurface *window)
+{
+   return window->window_type == GDK_SURFACE_SUBSURFACE;
+}
+
+static GdkSurface *
+gdk_surface_get_impl_window (GdkSurface *window)
+{
+  return window->impl_window;
+}
+
+GdkSurface *
+_gdk_surface_get_impl_window (GdkSurface *window)
+{
+  return gdk_surface_get_impl_window (window);
+}
+
+static gboolean
+gdk_surface_has_impl (GdkSurface *window)
+{
+  return window->impl_window == window;
+}
+
+static gboolean
+gdk_surface_is_toplevel (GdkSurface *window)
+{
+  return
+    window->parent == NULL ||
+    window->parent->window_type == GDK_SURFACE_ROOT;
+}
+
+gboolean
+_gdk_surface_has_impl (GdkSurface *window)
+{
+  return gdk_surface_has_impl (window);
+}
+
+static gboolean
+gdk_surface_has_no_impl (GdkSurface *window)
+{
+  return window->impl_window != window;
+}
+
+static void
+remove_sibling_overlapped_area (GdkSurface *window,
+                               cairo_region_t *region)
+{
+  GdkSurface *parent;
+  GdkSurface *sibling;
+  cairo_region_t *child_region;
+  GdkRectangle r;
+  GList *l;
+
+  parent = window->parent;
+
+  if (gdk_surface_is_toplevel (window))
+    return;
+
+  /* Convert from from window coords to parent coords */
+  cairo_region_translate (region, window->x, window->y);
+
+  for (l = parent->children; l; l = l->next)
+    {
+      sibling = l->data;
+
+      if (sibling == window)
+       break;
+
+      if (!GDK_SURFACE_IS_MAPPED (sibling) || sibling->input_only)
+       continue;
+
+      r.x = sibling->x;
+      r.y = sibling->y;
+      r.width = sibling->width;
+      r.height = sibling->height;
+
+      child_region = cairo_region_create_rectangle (&r);
+
+      if (sibling->shape)
+       {
+         /* Adjust shape region to parent window coords */
+         cairo_region_translate (sibling->shape, sibling->x, sibling->y);
+         cairo_region_intersect (child_region, sibling->shape);
+         cairo_region_translate (sibling->shape, -sibling->x, -sibling->y);
+       }
+
+      cairo_region_subtract (region, child_region);
+      cairo_region_destroy (child_region);
+    }
+
+  remove_sibling_overlapped_area (parent, region);
+
+  /* Convert back to window coords */
+  cairo_region_translate (region, -window->x, -window->y);
+}
+
+static void
+remove_child_area (GdkSurface *window,
+                  gboolean for_input,
+                  cairo_region_t *region)
+{
+  GdkSurface *child;
+  cairo_region_t *child_region;
+  GdkRectangle r;
+  GList *l;
+
+  for (l = window->children; l; l = l->next)
+    {
+      child = l->data;
+
+      /* If region is empty already, no need to do
+        anything potentially costly */
+      if (cairo_region_is_empty (region))
+       break;
+
+      if (!GDK_SURFACE_IS_MAPPED (child) || child->input_only)
+       continue;
+
+      r.x = child->x;
+      r.y = child->y;
+      r.width = child->width;
+      r.height = child->height;
+
+      /* Bail early if child totally outside region */
+      if (cairo_region_contains_rectangle (region, &r) == CAIRO_REGION_OVERLAP_OUT)
+       continue;
+
+      child_region = cairo_region_create_rectangle (&r);
+
+      if (child->shape)
+       {
+         /* Adjust shape region to parent window coords */
+         cairo_region_translate (child->shape, child->x, child->y);
+         cairo_region_intersect (child_region, child->shape);
+         cairo_region_translate (child->shape, -child->x, -child->y);
+       }
+
+      if (for_input)
+       {
+         if (child->input_shape)
+           cairo_region_intersect (child_region, child->input_shape);
+       }
+
+      cairo_region_subtract (region, child_region);
+      cairo_region_destroy (child_region);
+    }
+}
+
+static gboolean
+should_apply_clip_as_shape (GdkSurface *window)
+{
+  return
+    gdk_surface_has_impl (window) &&
+    /* Not for non-shaped toplevels */
+    (window->shape != NULL || window->applied_shape) &&
+    /* or for foreign windows */
+    window->window_type != GDK_SURFACE_FOREIGN &&
+    /* or for the root window */
+    window->window_type != GDK_SURFACE_ROOT;
+}
+
+static void
+apply_shape (GdkSurface *window,
+            cairo_region_t *region)
+{
+  GdkSurfaceImplClass *impl_class;
+
+  /* We trash whether we applied a shape so that
+     we can avoid unsetting it many times, which
+     could happen in e.g. apply_clip_as_shape as
+     windows get resized */
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+  if (region)
+    impl_class->shape_combine_region (window,
+                                     region, 0, 0);
+  else if (window->applied_shape)
+    impl_class->shape_combine_region (window,
+                                     NULL, 0, 0);
+
+  window->applied_shape = region != NULL;
+}
+
+static gboolean
+region_rect_equal (const cairo_region_t *region,
+                   const GdkRectangle *rect)
+{
+    GdkRectangle extents;
+
+    if (cairo_region_num_rectangles (region) != 1)
+        return FALSE;
+
+    cairo_region_get_extents (region, &extents);
+
+    return extents.x == rect->x &&
+        extents.y == rect->y &&
+        extents.width == rect->width &&
+        extents.height == rect->height;
+}
+
+static void
+apply_clip_as_shape (GdkSurface *window)
+{
+  GdkRectangle r;
+  cairo_region_t *region;
+
+  r.x = r.y = 0;
+  r.width = window->width;
+  r.height = window->height;
+
+  region = cairo_region_copy (window->clip_region);
+  remove_sibling_overlapped_area (window, region);
+
+  /* We only apply the clip region if would differ
+     from the actual clip region implied by the size
+     of the window. This is to avoid unneccessarily
+     adding meaningless shapes to all native subwindows */
+  if (!region_rect_equal (region, &r))
+    apply_shape (window, region);
+  else
+    apply_shape (window, NULL);
+
+  cairo_region_destroy (region);
+}
+
+static void
+recompute_visible_regions_internal (GdkSurface *private,
+                                   gboolean   recalculate_clip,
+                                   gboolean   recalculate_children)
+{
+  GdkRectangle r;
+  GList *l;
+  GdkSurface *child;
+  cairo_region_t *new_clip;
+  gboolean clip_region_changed;
+  gboolean abs_pos_changed;
+  int old_abs_x, old_abs_y;
+
+  old_abs_x = private->abs_x;
+  old_abs_y = private->abs_y;
+
+  /* Update absolute position */
+  if ((gdk_surface_has_impl (private) &&
+       private->window_type != GDK_SURFACE_SUBSURFACE) ||
+      (gdk_surface_is_toplevel (private) &&
+       private->window_type == GDK_SURFACE_SUBSURFACE))
+    {
+      /* Native windows and toplevel subsurfaces start here */
+      private->abs_x = 0;
+      private->abs_y = 0;
+    }
+  else
+    {
+      private->abs_x = private->parent->abs_x + private->x;
+      private->abs_y = private->parent->abs_y + private->y;
+    }
+
+  abs_pos_changed =
+    private->abs_x != old_abs_x ||
+    private->abs_y != old_abs_y;
+
+  /* Update clip region based on:
+   * parent clip
+   * window size/position
+   */
+  clip_region_changed = FALSE;
+  if (recalculate_clip)
+    {
+      if (private->viewable)
+       {
+         /* Calculate visible region (sans children) in parent window coords */
+         r.x = private->x;
+         r.y = private->y;
+         r.width = private->width;
+         r.height = private->height;
+         new_clip = cairo_region_create_rectangle (&r);
+
+         if (!gdk_surface_is_toplevel (private))
+           cairo_region_intersect (new_clip, private->parent->clip_region);
+
+         /* Convert from parent coords to window coords */
+         cairo_region_translate (new_clip, -private->x, -private->y);
+
+         if (should_apply_clip_as_shape (private) && private->shape)
+           cairo_region_intersect (new_clip, private->shape);
+       }
+      else
+         new_clip = cairo_region_create ();
+
+      if (private->clip_region == NULL ||
+         !cairo_region_equal (private->clip_region, new_clip))
+       clip_region_changed = TRUE;
+
+      if (private->clip_region)
+       cairo_region_destroy (private->clip_region);
+      private->clip_region = new_clip;
+    }
+
+  /* Update all children, recursively (except for root, where children are not exact). */
+  if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
+      private->window_type != GDK_SURFACE_ROOT)
+    {
+      for (l = private->children; l; l = l->next)
+       {
+         child = l->data;
+         /* Only recalculate clip if the the clip region changed, otherwise
+          * there is no way the child clip region could change (its has not e.g. moved)
+          * Except if recalculate_children is set to force child updates
+          */
+         recompute_visible_regions_internal (child,
+                                             recalculate_clip && (clip_region_changed || recalculate_children),
+                                             FALSE);
+       }
+    }
+}
+
+/* Call this when private has changed in one or more of these ways:
+ *  size changed
+ *  window moved
+ *  new window added
+ *  stacking order of window changed
+ *  child deleted
+ *
+ * It will recalculate abs_x/y and the clip regions
+ *
+ * Unless the window didn’t change stacking order or size/pos, pass in TRUE
+ * for recalculate_siblings. (Mostly used internally for the recursion)
+ *
+ * If a child window was removed (and you can’t use that child for
+ * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
+ */
+static void
+recompute_visible_regions (GdkSurface *private,
+                          gboolean recalculate_children)
+{
+  GdkSurface *toplevel;
+
+  toplevel = gdk_surface_get_toplevel (private);
+  toplevel->geometry_dirty = TRUE;
+
+  recompute_visible_regions_internal (private,
+                                     TRUE,
+                                     recalculate_children);
+}
+
+static void
+gdk_surface_clear_old_updated_area (GdkSurface *window)
+{
+  int i;
+
+  for (i = 0; i < 2; i++)
+    {
+      if (window->old_updated_area[i])
+        {
+          cairo_region_destroy (window->old_updated_area[i]);
+          window->old_updated_area[i] = NULL;
+        }
+    }
+}
+
+static void
+gdk_surface_append_old_updated_area (GdkSurface *window,
+                                    cairo_region_t *region)
+{
+  if (window->old_updated_area[1])
+    cairo_region_destroy (window->old_updated_area[1]);
+  window->old_updated_area[1] = window->old_updated_area[0];
+  window->old_updated_area[0] = cairo_region_reference (region);
+}
+
+void
+_gdk_surface_update_size (GdkSurface *window)
+{
+  gdk_surface_clear_old_updated_area (window);
+  recompute_visible_regions (window, FALSE);
+}
+
+static GdkEventMask
+get_native_device_event_mask (GdkSurface *private,
+                              GdkDevice *device)
+{
+  GdkEventMask event_mask;
+
+  if (device)
+    event_mask = GPOINTER_TO_INT (g_hash_table_lookup (private->device_events, device));
+  else
+    event_mask = private->event_mask;
+
+  if (private->window_type == GDK_SURFACE_ROOT ||
+      private->window_type == GDK_SURFACE_FOREIGN)
+    return event_mask;
+  else
+    {
+      GdkEventMask mask;
+
+      mask = private->event_mask;
+
+      /* We need thse for all native windows so we can
+        emulate events on children: */
+      mask |=
+       GDK_EXPOSURE_MASK |
+       GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
+        GDK_TOUCH_MASK |
+        GDK_POINTER_MOTION_MASK |
+        GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+        GDK_SCROLL_MASK;
+
+      return mask;
+    }
+}
+
+static GdkEventMask
+get_native_event_mask (GdkSurface *private)
+{
+  return get_native_device_event_mask (private, NULL);
+}
+
+GdkSurface*
+gdk_surface_new (GdkDisplay    *display,
+                GdkSurface     *parent,
+               GdkSurfaceAttr *attributes)
+{
+  GdkSurface *window;
+  gboolean native;
+  GdkEventMask event_mask;
+
+  g_return_val_if_fail (attributes != NULL, NULL);
+
+  if (parent != NULL && GDK_SURFACE_DESTROYED (parent))
+    {
+      g_warning ("gdk_surface_new(): parent is destroyed");
+      return NULL;
+    }
+
+  window = _gdk_display_create_window (display);
+
+  window->parent = parent;
+
+  window->accept_focus = TRUE;
+  window->focus_on_map = TRUE;
+
+  window->x = attributes->x;
+  window->y = attributes->y;
+  window->width = (attributes->width > 1) ? (attributes->width) : (1);
+  window->height = (attributes->height > 1) ? (attributes->height) : (1);
+  window->alpha = 255;
+
+  if (attributes->wclass == GDK_INPUT_ONLY)
+    {
+      /* Backwards compatiblity - we've always ignored
+       * attributes->window_type for input-only windows
+       * before
+       */
+      if (parent == NULL)
+       window->window_type = GDK_SURFACE_TEMP;
+      else
+       window->window_type = GDK_SURFACE_CHILD;
+    }
+  else
+    window->window_type = attributes->window_type;
+
+  /* Sanity checks */
+  switch (window->window_type)
+    {
+    case GDK_SURFACE_TOPLEVEL:
+    case GDK_SURFACE_TEMP:
+      if (parent != NULL && GDK_SURFACE_TYPE (parent) != GDK_SURFACE_ROOT)
+       g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
+                  "a window of type GDK_SURFACE_ROOT");
+      break;
+    case GDK_SURFACE_SUBSURFACE:
+#ifdef GDK_WINDOWING_WAYLAND
+      if (!GDK_IS_WAYLAND_DISPLAY (display))
+        {
+          g_warning (G_STRLOC "Subsurface windows can only be used on Wayland");
+          return NULL;
+        }
+#endif
+      break;
+    case GDK_SURFACE_CHILD:
+      if (GDK_SURFACE_TYPE (parent) == GDK_SURFACE_ROOT ||
+          GDK_SURFACE_TYPE (parent) == GDK_SURFACE_FOREIGN)
+        {
+          g_warning (G_STRLOC "Child windows must not be created as children of\n"
+                     "a window of type GDK_SURFACE_ROOT or GDK_SURFACE_FOREIGN");
+          return NULL;
+        }
+      break;
+    default:
+      g_warning (G_STRLOC "cannot make windows of type %d", window->window_type);
+      return NULL;
+    }
+
+  window->event_mask = GDK_ALL_EVENTS_MASK;
+
+  if (attributes->wclass == GDK_INPUT_OUTPUT)
+    {
+      window->input_only = FALSE;
+    }
+  else
+    {
+      window->input_only = TRUE;
+    }
+
+  native = FALSE;
+
+  if (window->parent != NULL)
+    window->parent->children = g_list_concat (&window->children_list_node, window->parent->children);
+  else
+    {
+      GdkFrameClock *frame_clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
+      gdk_surface_set_frame_clock (window, frame_clock);
+      g_object_unref (frame_clock);
+
+      native = TRUE; /* Always use native windows for toplevels */
+    }
+
+#ifdef GDK_WINDOWING_WAYLAND
+  if (window->window_type == GDK_SURFACE_SUBSURFACE)
+    native = TRUE; /* Always use native windows for subsurfaces as well */
+#endif
+
+  if (native)
+    {
+      event_mask = get_native_event_mask (window);
+
+      /* Create the impl */
+      _gdk_display_create_window_impl (display, window, parent, event_mask, attributes);
+      window->impl_window = window;
+    }
+  else
+    {
+      window->impl_window = g_object_ref (window->parent->impl_window);
+      window->impl = g_object_ref (window->impl_window->impl);
+    }
+
+  recompute_visible_regions (window, FALSE);
+
+  g_signal_connect (display, "seat-removed", G_CALLBACK (seat_removed_cb), window);
+
+  return window;
+}
+
+/**
+ * gdk_surface_new_toplevel: (constructor)
+ * @display: the display to create the window on
+ * @width: width of new window
+ * @height: height of new window
+ *
+ * Creates a new toplevel window. The window will be managed by the window
+ * manager.
+ *
+ * Returns: (transfer full): the new #GdkSurface
+ **/
+GdkSurface *
+gdk_surface_new_toplevel (GdkDisplay *display,
+                         gint        width,
+                         gint        height)
+{
+  GdkSurfaceAttr attr;
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  attr.wclass = GDK_INPUT_OUTPUT;
+  attr.x = 0;
+  attr.y = 0;
+  attr.width = width;
+  attr.height = height;
+  attr.window_type = GDK_SURFACE_TOPLEVEL;
+
+  return gdk_surface_new (display, NULL, &attr);
+}
+
+/**
+ * gdk_surface_new_popup: (constructor)
+ * @display: the display to create the window on
+ * @position: position of the window on screen
+ *
+ * Creates a new toplevel popup window. The window will bypass window
+ * management.
+ *
+ * Returns: (transfer full): the new #GdkSurface
+ **/
+GdkSurface *
+gdk_surface_new_popup (GdkDisplay         *display,
+                      const GdkRectangle *position)
+{
+  GdkSurfaceAttr attr;
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+  g_return_val_if_fail (position != NULL, NULL);
+
+  attr.wclass = GDK_INPUT_OUTPUT;
+  attr.x = position->x;
+  attr.y = position->y;
+  attr.width = position->width;
+  attr.height = position->height;
+  attr.window_type = GDK_SURFACE_TEMP;
+
+  return gdk_surface_new (display, NULL, &attr);
+}
+
+/**
+ * gdk_surface_new_temp: (constructor)
+ * @display: the display to create the window on
+ *
+ * Creates a new toplevel temporary window. The window will be
+ * situated off-screen and not handle output.
+ *
+ * You most likely do not want to use this function.
+ *
+ * Returns: (transfer full): the new #GdkSurface
+ **/
+GdkSurface *
+gdk_surface_new_temp (GdkDisplay *display)
+{
+  GdkSurfaceAttr attr;
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  attr.wclass = GDK_INPUT_ONLY;
+  attr.x = -100;
+  attr.y = -100;
+  attr.width = 10;
+  attr.height = 10;
+  attr.window_type = GDK_SURFACE_TEMP;
+
+  return gdk_surface_new (display, NULL, &attr);
+}
+
+/**
+ * gdk_surface_new_child: (constructor)
+ * @parent: the parent window
+ * @position: placement of the window inside @parent
+ *
+ * Creates a new client-side child window.
+ *
+ * Returns: (transfer full): the new #GdkSurface
+ **/
+GdkSurface *
+gdk_surface_new_child (GdkSurface          *parent,
+                      const GdkRectangle *position)
+{
+  GdkSurfaceAttr attr;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (parent), NULL);
+
+  attr.wclass = GDK_INPUT_OUTPUT;
+  attr.x = position->x;
+  attr.y = position->y;
+  attr.width = position->width;
+  attr.height = position->height;
+  attr.window_type = GDK_SURFACE_CHILD;
+
+  return gdk_surface_new (gdk_surface_get_display (parent), parent, &attr);
+}
+
+static void
+update_pointer_info_foreach (GdkDisplay           *display,
+                             GdkDevice            *device,
+                             GdkPointerSurfaceInfo *pointer_info,
+                             gpointer              user_data)
+{
+  GdkSurface *window = user_data;
+
+  if (pointer_info->window_under_pointer == window)
+    {
+      g_object_unref (pointer_info->window_under_pointer);
+      pointer_info->window_under_pointer = NULL;
+    }
+}
+
+static void
+window_remove_from_pointer_info (GdkSurface  *window,
+                                 GdkDisplay *display)
+{
+  _gdk_display_pointer_info_foreach (display,
+                                     update_pointer_info_foreach,
+                                     window);
+}
+
+static void
+gdk_surface_free_current_paint (GdkSurface *window)
+{
+  cairo_surface_destroy (window->current_paint.surface);
+  window->current_paint.surface = NULL;
+
+  cairo_region_destroy (window->current_paint.region);
+  window->current_paint.region = NULL;
+
+  window->current_paint.surface_needs_composite = FALSE;
+}
+
+/**
+ * _gdk_surface_destroy_hierarchy:
+ * @window: a #GdkSurface
+ * @recursing: If %TRUE, then this is being called because a parent
+ *            was destroyed.
+ * @recursing_native: If %TRUE, then this is being called because a native parent
+ *            was destroyed. This generally means that the call to the
+ *            windowing system to destroy the window can be omitted, since
+ *            it will be destroyed as a result of the parent being destroyed.
+ *            Unless @foreign_destroy.
+ * @foreign_destroy: If %TRUE, the window or a parent was destroyed by some
+ *            external agency. The window has already been destroyed and no
+ *            windowing system calls should be made. (This may never happen
+ *            for some windowing systems.)
+ *
+ * Internal function to destroy a window. Like gdk_surface_destroy(),
+ * but does not drop the reference count created by gdk_surface_new().
+ **/
+static void
+_gdk_surface_destroy_hierarchy (GdkSurface *window,
+                              gboolean   recursing,
+                              gboolean   recursing_native,
+                              gboolean   foreign_destroy)
+{
+  GdkSurfaceImplClass *impl_class;
+  GdkSurface *temp_window;
+  GdkDisplay *display;
+  GList *tmp;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  display = gdk_surface_get_display (window);
+
+  switch (window->window_type)
+    {
+    default:
+      g_assert_not_reached ();
+      break;
+
+    case GDK_SURFACE_ROOT:
+      if (!gdk_display_is_closed (display))
+       {
+         g_error ("attempted to destroy root window");
+         break;
+       }
+      /* else fall thru */
+    case GDK_SURFACE_TOPLEVEL:
+    case GDK_SURFACE_CHILD:
+    case GDK_SURFACE_TEMP:
+    case GDK_SURFACE_FOREIGN:
+    case GDK_SURFACE_SUBSURFACE:
+      if (window->window_type == GDK_SURFACE_FOREIGN && !foreign_destroy)
+       {
+       }
+      else
+       {
+         if (window->parent)
+           {
+             if (window->parent->children)
+                window->parent->children = g_list_remove_link (window->parent->children, &window->children_list_node);
+
+             if (!recursing &&
+                 GDK_SURFACE_IS_MAPPED (window))
+               {
+                 recompute_visible_regions (window, FALSE);
+                 gdk_surface_invalidate_in_parent (window);
+               }
+           }
+
+          if (window->gl_paint_context)
+            {
+              /* Make sure to destroy if current */
+              g_object_run_dispose (G_OBJECT (window->gl_paint_context));
+              g_object_unref (window->gl_paint_context);
+              window->gl_paint_context = NULL;
+            }
+
+          if (window->frame_clock)
+            {
+              g_object_run_dispose (G_OBJECT (window->frame_clock));
+              gdk_surface_set_frame_clock (window, NULL);
+            }
+
+          gdk_surface_free_current_paint (window);
+
+         if (window->window_type == GDK_SURFACE_FOREIGN)
+           g_assert (window->children == NULL);
+         else
+           {
+             tmp = window->children;
+             window->children = NULL;
+             /* No need to free children list, its all made up of in-struct nodes */
+
+             while (tmp)
+               {
+                 temp_window = tmp->data;
+                 tmp = tmp->next;
+
+                 if (temp_window)
+                   _gdk_surface_destroy_hierarchy (temp_window,
+                                                  TRUE,
+                                                  recursing_native || gdk_surface_has_impl (window),
+                                                  foreign_destroy);
+               }
+           }
+
+         _gdk_surface_clear_update_area (window);
+
+         impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+         if (gdk_surface_has_impl (window))
+           impl_class->destroy (window, recursing_native, foreign_destroy);
+         else
+           {
+             /* hide to make sure we repaint and break grabs */
+             gdk_surface_hide (window);
+           }
+
+         window->state |= GDK_SURFACE_STATE_WITHDRAWN;
+         window->parent = NULL;
+         window->destroyed = TRUE;
+
+         window_remove_from_pointer_info (window, display);
+
+         if (window->clip_region)
+           {
+             cairo_region_destroy (window->clip_region);
+             window->clip_region = NULL;
+           }
+
+          g_object_notify_by_pspec (G_OBJECT (window), properties[PROP_STATE]);
+       }
+      break;
+    }
+}
+
+/**
+ * _gdk_surface_destroy:
+ * @window: a #GdkSurface
+ * @foreign_destroy: If %TRUE, the window or a parent was destroyed by some
+ *            external agency. The window has already been destroyed and no
+ *            windowing system calls should be made. (This may never happen
+ *            for some windowing systems.)
+ *
+ * Internal function to destroy a window. Like gdk_surface_destroy(),
+ * but does not drop the reference count created by gdk_surface_new().
+ **/
+void
+_gdk_surface_destroy (GdkSurface *window,
+                    gboolean   foreign_destroy)
+{
+  _gdk_surface_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
+}
+
+/**
+ * gdk_surface_destroy:
+ * @window: a #GdkSurface
+ *
+ * Destroys the window system resources associated with @window and decrements @window's
+ * reference count. The window system resources for all children of @window are also
+ * destroyed, but the children’s reference counts are not decremented.
+ *
+ * Note that a window will not be destroyed automatically when its reference count
+ * reaches zero. You must call this function yourself before that happens.
+ *
+ **/
+void
+gdk_surface_destroy (GdkSurface *window)
+{
+  _gdk_surface_destroy_hierarchy (window, FALSE, FALSE, FALSE);
+  g_object_unref (window);
+}
+
+/**
+ * gdk_surface_set_user_data:
+ * @window: a #GdkSurface
+ * @user_data: (allow-none) (type GObject.Object): user data
+ *
+ * For most purposes this function is deprecated in favor of
+ * g_object_set_data(). However, for historical reasons GTK+ stores
+ * the #GtkWidget that owns a #GdkSurface as user data on the
+ * #GdkSurface. So, custom widget implementations should use
+ * this function for that. If GTK+ receives an event for a #GdkSurface,
+ * and the user data for the window is non-%NULL, GTK+ will assume the
+ * user data is a #GtkWidget, and forward the event to that widget.
+ *
+ **/
+void
+gdk_surface_set_user_data (GdkSurface *window,
+                         gpointer   user_data)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  window->user_data = user_data;
+}
+
+/**
+ * gdk_surface_get_user_data:
+ * @window: a #GdkSurface
+ * @data: (out): return location for user data
+ *
+ * Retrieves the user data for @window, which is normally the widget
+ * that @window belongs to. See gdk_surface_set_user_data().
+ *
+ **/
+void
+gdk_surface_get_user_data (GdkSurface *window,
+                         gpointer  *data)
+{
+  *data = window->user_data;
+}
+
+/**
+ * gdk_surface_get_window_type:
+ * @window: a #GdkSurface
+ *
+ * Gets the type of the window. See #GdkSurfaceType.
+ *
+ * Returns: type of window
+ **/
+GdkSurfaceType
+gdk_surface_get_window_type (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), (GdkSurfaceType) -1);
+
+  return GDK_SURFACE_TYPE (window);
+}
+
+/**
+ * gdk_surface_get_display:
+ * @window: a #GdkSurface
+ * 
+ * Gets the #GdkDisplay associated with a #GdkSurface.
+ * 
+ * Returns: (transfer none): the #GdkDisplay associated with @window
+ **/
+GdkDisplay *
+gdk_surface_get_display (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  return window->display;
+}
+/**
+ * gdk_surface_is_destroyed:
+ * @window: a #GdkSurface
+ *
+ * Check to see if a window is destroyed..
+ *
+ * Returns: %TRUE if the window is destroyed
+ **/
+gboolean
+gdk_surface_is_destroyed (GdkSurface *window)
+{
+  return GDK_SURFACE_DESTROYED (window);
+}
+
+/**
+ * gdk_surface_has_native:
+ * @window: a #GdkSurface
+ *
+ * Checks whether the window has a native window or not.
+ *
+ * Returns: %TRUE if the @window has a native window, %FALSE otherwise.
+ */
+gboolean
+gdk_surface_has_native (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  return window->parent == NULL || window->parent->impl != window->impl;
+}
+
+/**
+ * gdk_surface_get_position:
+ * @window: a #GdkSurface
+ * @x: (out) (allow-none): X coordinate of window
+ * @y: (out) (allow-none): Y coordinate of window
+ *
+ * Obtains the position of the window as reported in the
+ * most-recently-processed #GdkEventConfigure. Contrast with
+ * gdk_surface_get_geometry() which queries the X server for the
+ * current window position, regardless of which events have been
+ * received or processed.
+ *
+ * The position coordinates are relative to the window’s parent window.
+ *
+ **/
+void
+gdk_surface_get_position (GdkSurface *window,
+                        gint      *x,
+                        gint      *y)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (x)
+    *x = window->x;
+  if (y)
+    *y = window->y;
+}
+
+/**
+ * gdk_surface_get_parent:
+ * @window: a #GdkSurface
+ *
+ * Obtains the parent of @window, as known to GDK. Does not query the
+ * X server; thus this returns the parent as passed to gdk_surface_new(),
+ * not the actual parent. This should never matter unless you’re using
+ * Xlib calls mixed with GDK calls on the X11 platform. It may also
+ * matter for toplevel windows, because the window manager may choose
+ * to reparent them.
+ *
+ * Returns: (transfer none): parent of @window
+ **/
+GdkSurface*
+gdk_surface_get_parent (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  if (gdk_surface_is_subsurface (window))
+    return window->transient_for;
+  else
+    return window->parent;
+}
+
+/**
+ * gdk_surface_get_toplevel:
+ * @window: a #GdkSurface
+ *
+ * Gets the toplevel window that’s an ancestor of @window.
+ *
+ * Any window type but %GDK_SURFACE_CHILD is considered a
+ * toplevel window, as is a %GDK_SURFACE_CHILD window that
+ * has a root window as parent.
+ *
+ * Returns: (transfer none): the toplevel window containing @window
+ **/
+GdkSurface *
+gdk_surface_get_toplevel (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  while (window->window_type == GDK_SURFACE_CHILD ||
+         window->window_type == GDK_SURFACE_SUBSURFACE)
+    {
+      if (gdk_surface_is_toplevel (window))
+       break;
+      window = window->parent;
+    }
+
+  return window;
+}
+
+/**
+ * gdk_surface_get_children:
+ * @window: a #GdkSurface
+ *
+ * Gets the list of children of @window known to GDK.
+ * This function only returns children created via GDK,
+ * so for example it’s useless when used with the root window;
+ * it only returns windows an application created itself.
+ *
+ * The returned list must be freed, but the elements in the
+ * list need not be.
+ *
+ * Returns: (transfer container) (element-type GdkSurface):
+ *     list of child windows inside @window
+ **/
+GList*
+gdk_surface_get_children (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return NULL;
+
+  return g_list_copy (window->children);
+}
+
+/**
+ * gdk_surface_peek_children:
+ * @window: a #GdkSurface
+ *
+ * Like gdk_surface_get_children(), but does not copy the list of
+ * children, so the list does not need to be freed.
+ *
+ * Returns: (transfer none) (element-type GdkSurface):
+ *     a reference to the list of child windows in @window
+ **/
+GList *
+gdk_surface_peek_children (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return NULL;
+
+  return window->children;
+}
+
+
+/**
+ * gdk_surface_get_children_with_user_data:
+ * @window: a #GdkSurface
+ * @user_data: user data to look for
+ *
+ * Gets the list of children of @window known to GDK with a
+ * particular @user_data set on it.
+ *
+ * The returned list must be freed, but the elements in the
+ * list need not be.
+ *
+ * The list is returned in (relative) stacking order, i.e. the
+ * lowest window is first.
+ *
+ * Returns: (transfer container) (element-type GdkSurface):
+ *     list of child windows inside @window
+ **/
+GList *
+gdk_surface_get_children_with_user_data (GdkSurface *window,
+                                        gpointer   user_data)
+{
+  GdkSurface *child;
+  GList *res, *l;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return NULL;
+
+  res = NULL;
+  for (l = window->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      if (child->user_data == user_data)
+       res = g_list_prepend (res, child);
+    }
+
+  return res;
+}
+
+
+/**
+ * gdk_surface_is_visible:
+ * @window: a #GdkSurface
+ *
+ * Checks whether the window has been mapped (with gdk_surface_show() or
+ * gdk_surface_show_unraised()).
+ *
+ * Returns: %TRUE if the window is mapped
+ **/
+gboolean
+gdk_surface_is_visible (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  return GDK_SURFACE_IS_MAPPED (window);
+}
+
+/**
+ * gdk_surface_is_viewable:
+ * @window: a #GdkSurface
+ *
+ * Check if the window and all ancestors of the window are
+ * mapped. (This is not necessarily "viewable" in the X sense, since
+ * we only check as far as we have GDK window parents, not to the root
+ * window.)
+ *
+ * Returns: %TRUE if the window is viewable
+ **/
+gboolean
+gdk_surface_is_viewable (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  if (window->destroyed)
+    return FALSE;
+
+  return window->viewable;
+}
+
+/**
+ * gdk_surface_get_state:
+ * @window: a #GdkSurface
+ *
+ * Gets the bitwise OR of the currently active window state flags,
+ * from the #GdkSurfaceState enumeration.
+ *
+ * Returns: window state bitfield
+ **/
+GdkSurfaceState
+gdk_surface_get_state (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  return window->state;
+}
+
+static cairo_content_t
+gdk_surface_get_content (GdkSurface *window)
+{
+  cairo_surface_t *surface;
+  cairo_content_t content;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
+
+  surface = gdk_surface_ref_impl_surface (window);
+  content = cairo_surface_get_content (surface);
+  cairo_surface_destroy (surface);
+
+  return content;
+}
+
+static cairo_surface_t *
+gdk_surface_ref_impl_surface (GdkSurface *window)
+{
+  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->ref_cairo_surface (gdk_surface_get_impl_window (window));
+}
+
+GdkGLContext *
+gdk_surface_get_paint_gl_context (GdkSurface  *window,
+                                 GError    **error)
+{
+  GError *internal_error = NULL;
+
+  if (GDK_DISPLAY_DEBUG_CHECK (window->display, GL_DISABLE))
+    {
+      g_set_error_literal (error, GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("GL support disabled via GDK_DEBUG"));
+      return NULL;
+    }
+
+  if (window->impl_window->gl_paint_context == NULL)
+    {
+      GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+      if (impl_class->create_gl_context == NULL)
+        {
+          g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
+                               _("The current backend does not support OpenGL"));
+          return NULL;
+        }
+
+      window->impl_window->gl_paint_context =
+        impl_class->create_gl_context (window->impl_window,
+                                       TRUE,
+                                       NULL,
+                                       &internal_error);
+    }
+
+  if (internal_error != NULL)
+    {
+      g_propagate_error (error, internal_error);
+      g_clear_object (&(window->impl_window->gl_paint_context));
+      return NULL;
+    }
+
+  gdk_gl_context_realize (window->impl_window->gl_paint_context, &internal_error);
+  if (internal_error != NULL)
+    {
+      g_propagate_error (error, internal_error);
+      g_clear_object (&(window->impl_window->gl_paint_context));
+      return NULL;
+    }
+
+  return window->impl_window->gl_paint_context;
+}
+
+/**
+ * gdk_surface_create_gl_context:
+ * @window: a #GdkSurface
+ * @error: return location for an error
+ *
+ * Creates a new #GdkGLContext matching the
+ * framebuffer format to the visual of the #GdkSurface. The context
+ * is disconnected from any particular window or surface.
+ *
+ * If the creation of the #GdkGLContext failed, @error will be set.
+ *
+ * Before using the returned #GdkGLContext, you will need to
+ * call gdk_gl_context_make_current() or gdk_gl_context_realize().
+ *
+ * Returns: (transfer full): the newly created #GdkGLContext, or
+ * %NULL on error
+ **/
+GdkGLContext *
+gdk_surface_create_gl_context (GdkSurface    *window,
+                              GError      **error)
+{
+  GdkGLContext *paint_context;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  paint_context = gdk_surface_get_paint_gl_context (window, error);
+  if (paint_context == NULL)
+    return NULL;
+
+  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->create_gl_context (window->impl_window,
+                                                                     FALSE,
+                                                                      paint_context,
+                                                                      error);
+}
+
+/**
+ * gdk_surface_create_vulkan_context:
+ * @window: a #GdkSurface
+ * @error: return location for an error
+ *
+ * Creates a new #GdkVulkanContext for rendering on @window.
+ *
+ * If the creation of the #GdkVulkanContext failed, @error will be set.
+ *
+ * Returns: (transfer full): the newly created #GdkVulkanContext, or
+ * %NULL on error
+ **/
+GdkVulkanContext *
+gdk_surface_create_vulkan_context (GdkSurface  *window,
+                                  GError    **error)
+{
+  GdkDisplay *display;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  if (GDK_DISPLAY_DEBUG_CHECK (window->display, VULKAN_DISABLE))
+    {
+      g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
+                           _("Vulkan support disabled via GDK_DEBUG"));
+      return NULL;
+    }
+
+  display = gdk_surface_get_display (window);
+
+  if (GDK_DISPLAY_GET_CLASS (display)->vk_extension_name == NULL)
+    {
+      g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
+                   "The %s backend has no Vulkan support.", G_OBJECT_TYPE_NAME (display));
+      return FALSE;
+    }
+
+  return g_initable_new (GDK_DISPLAY_GET_CLASS (display)->vk_context_type,
+                         NULL,
+                         error,
+                         "window", window,
+                         NULL);
+}
+
+static void
+gdk_surface_begin_paint_internal (GdkSurface            *window,
+                                const cairo_region_t *region)
+{
+  GdkRectangle clip_box;
+  GdkSurfaceImplClass *impl_class;
+  double sx, sy;
+  gboolean needs_surface;
+  cairo_content_t surface_content;
+
+  if (window->current_paint.surface != NULL)
+    {
+      g_warning ("A paint operation on the window is alredy in progress. "
+                 "This is not allowed.");
+      return;
+    }
+
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+  needs_surface = TRUE;
+  if (impl_class->begin_paint)
+    needs_surface = impl_class->begin_paint (window);
+
+  window->current_paint.region = cairo_region_copy (region);
+  cairo_region_intersect (window->current_paint.region, window->clip_region);
+  cairo_region_get_extents (window->current_paint.region, &clip_box);
+
+  surface_content = gdk_surface_get_content (window);
+
+  if (needs_surface)
+    {
+      window->current_paint.surface = gdk_surface_create_similar_surface (window,
+                                                                         surface_content,
+                                                                         MAX (clip_box.width, 1),
+                                                                         MAX (clip_box.height, 1));
+      sx = sy = 1;
+      cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy);
+      cairo_surface_set_device_offset (window->current_paint.surface, -clip_box.x*sx, -clip_box.y*sy);
+      gdk_cairo_surface_mark_as_direct (window->current_paint.surface, window);
+
+      window->current_paint.surface_needs_composite = TRUE;
+    }
+  else
+    {
+      window->current_paint.surface = gdk_surface_ref_impl_surface (window);
+      window->current_paint.surface_needs_composite = FALSE;
+    }
+
+  if (!cairo_region_is_empty (window->current_paint.region))
+    gdk_surface_clear_backing_region (window);
+}
+
+static void
+gdk_surface_end_paint_internal (GdkSurface *window)
+{
+  GdkSurfaceImplClass *impl_class;
+  cairo_t *cr;
+
+  if (window->current_paint.surface == NULL)
+    {
+      g_warning (G_STRLOC": no preceding call to gdk_surface_begin_draw_frame(), see documentation");
+      return;
+    }
+
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+  if (impl_class->end_paint)
+    impl_class->end_paint (window);
+
+  if (window->current_paint.surface_needs_composite)
+    {
+      cairo_surface_t *surface;
+
+      surface = gdk_surface_ref_impl_surface (window);
+      cr = cairo_create (surface);
+
+      cairo_set_source_surface (cr, window->current_paint.surface, 0, 0);
+      gdk_cairo_region (cr, window->current_paint.region);
+      cairo_clip (cr);
+
+      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+      cairo_paint (cr);
+
+      cairo_destroy (cr);
+
+      cairo_surface_flush (surface);
+      cairo_surface_destroy (surface);
+    }
+
+  gdk_surface_free_current_paint (window);
+}
+
+/**
+ * gdk_surface_begin_draw_frame:
+ * @window: a #GdkSurface
+ * @context: (allow-none): the context used to draw the frame
+ * @region: a Cairo region
+ *
+ * Indicates that you are beginning the process of redrawing @region
+ * on @window, and provides you with a #GdkDrawingContext.
+ *
+ * If @window is a top level #GdkSurface, backed by a native window
+ * implementation, a backing store (offscreen buffer) large enough to
+ * contain @region will be created. The backing store will be initialized
+ * with the background color or background surface for @window. Then, all
+ * drawing operations performed on @window will be diverted to the
+ * backing store. When you call gdk_surface_end_frame(), the contents of
+ * the backing store will be copied to @window, making it visible
+ * on screen. Only the part of @window contained in @region will be
+ * modified; that is, drawing operations are clipped to @region.
+ *
+ * The net result of all this is to remove flicker, because the user
+ * sees the finished product appear all at once when you call
+ * gdk_surface_end_draw_frame(). If you draw to @window directly without
+ * calling gdk_surface_begin_draw_frame(), the user may see flicker
+ * as individual drawing operations are performed in sequence.
+ *
+ * When using GTK+, the widget system automatically places calls to
+ * gdk_surface_begin_draw_frame() and gdk_surface_end_draw_frame() around
+ * emissions of the `GtkWidget::draw` signal. That is, if you’re
+ * drawing the contents of the widget yourself, you can assume that the
+ * widget has a cleared background, is already set as the clip region,
+ * and already has a backing store. Therefore in most cases, application
+ * code in GTK does not need to call gdk_surface_begin_draw_frame()
+ * explicitly.
+ *
+ * Returns: (transfer none): a #GdkDrawingContext context that should be
+ *   used to draw the contents of the window; the returned context is owned
+ *   by GDK.
+ */
+GdkDrawingContext *
+gdk_surface_begin_draw_frame (GdkSurface            *window,
+                             GdkDrawContext       *draw_context,
+                             const cairo_region_t *region)
+{
+  GdkDrawingContext *context;
+  cairo_region_t *real_region;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+  g_return_val_if_fail (gdk_surface_has_native (window), NULL);
+  g_return_val_if_fail (gdk_surface_is_toplevel (window), NULL);
+  g_return_val_if_fail (region != NULL, NULL);
+  if (draw_context != NULL)
+    {
+      g_return_val_if_fail (GDK_IS_DRAW_CONTEXT (draw_context), NULL);
+      g_return_val_if_fail (gdk_draw_context_get_window (draw_context) == window, NULL);
+    }
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return NULL;
+
+  if (window->drawing_context != NULL)
+    {
+      g_critical ("The window %p already has a drawing context. You cannot "
+                  "call gdk_surface_begin_draw_frame() without calling "
+                  "gdk_surface_end_draw_frame() first.", window);
+      return NULL;
+    }
+
+  real_region = cairo_region_copy (region);
+
+  if (draw_context)
+    gdk_draw_context_begin_frame (draw_context, real_region);
+  else
+    gdk_surface_begin_paint_internal (window, real_region);
+
+  context = g_object_new (GDK_TYPE_DRAWING_CONTEXT,
+                          "window", window,
+                          "paint-context", draw_context,
+                          "clip", real_region,
+                          NULL);
+
+  /* Do not take a reference, to avoid creating cycles */
+  window->drawing_context = context;
+
+  cairo_region_destroy (real_region);
+
+  return context;
+}
+
+/**
+ * gdk_surface_end_draw_frame:
+ * @window: a #GdkSurface
+ * @context: the #GdkDrawingContext created by gdk_surface_begin_draw_frame()
+ *
+ * Indicates that the drawing of the contents of @window started with
+ * gdk_surface_begin_frame() has been completed.
+ *
+ * This function will take care of destroying the #GdkDrawingContext.
+ *
+ * It is an error to call this function without a matching
+ * gdk_surface_begin_frame() first.
+ */
+void
+gdk_surface_end_draw_frame (GdkSurface         *window,
+                           GdkDrawingContext *context)
+{
+  GdkDrawContext *paint_context;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (window->drawing_context == NULL)
+    {
+      g_critical ("The window %p has no drawing context. You must call "
+                  "gdk_surface_begin_draw_frame() before calling "
+                  "gdk_surface_end_draw_frame().", window);
+      return;
+    }
+  g_return_if_fail (window->drawing_context == context);
+
+  paint_context = gdk_drawing_context_get_paint_context (context);
+  if (paint_context)
+    {
+      cairo_region_t *clip = gdk_drawing_context_get_clip (context);
+
+      gdk_draw_context_end_frame (paint_context,
+                                  clip,
+                                  window->active_update_area);
+
+      cairo_region_destroy (clip);
+    }
+  else
+    {
+      gdk_surface_end_paint_internal (window);
+    }
+
+  window->drawing_context = NULL;
+
+  g_object_unref (context);
+}
+
+/*< private >
+ * gdk_surface_get_current_paint_region:
+ * @window: a #GdkSurface
+ *
+ * Retrieves a copy of the current paint region.
+ *
+ * Returns: (transfer full): a Cairo region
+ */
+cairo_region_t *
+gdk_surface_get_current_paint_region (GdkSurface *window)
+{
+  cairo_region_t *region;
+
+  if (window->impl_window->current_paint.region != NULL)
+    {
+      region = cairo_region_copy (window->impl_window->current_paint.region);
+      cairo_region_translate (region, -window->abs_x, -window->abs_y);
+    }
+  else
+    {
+      region = cairo_region_copy (window->clip_region);
+    }
+
+  return region;
+}
+
+/*< private >
+ * gdk_surface_get_drawing_context:
+ * @window: a #GdkSurface
+ *
+ * Retrieves the #GdkDrawingContext associated to @window by
+ * gdk_surface_begin_draw_frame().
+ *
+ * Returns: (transfer none) (nullable): a #GdkDrawingContext, if any is set
+ */
+GdkDrawingContext *
+gdk_surface_get_drawing_context (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return NULL;
+
+  return window->drawing_context;
+}
+
+/**
+ * gdk_surface_get_clip_region:
+ * @window: a #GdkSurface
+ * 
+ * Computes the region of a window that potentially can be written
+ * to by drawing primitives. This region may not take into account
+ * other factors such as if the window is obscured by other windows,
+ * but no area outside of this region will be affected by drawing
+ * primitives.
+ * 
+ * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
+ *          when you are done.
+ **/
+cairo_region_t*
+gdk_surface_get_clip_region (GdkSurface *window)
+{
+  cairo_region_t *result;
+
+  g_return_val_if_fail (GDK_SURFACE (window), NULL);
+
+  result = cairo_region_copy (window->clip_region);
+
+  if (window->current_paint.region != NULL)
+    cairo_region_intersect (result, window->current_paint.region);
+
+  return result;
+}
+
+/**
+ * gdk_surface_get_visible_region:
+ * @window: a #GdkSurface
+ * 
+ * Computes the region of the @window that is potentially visible.
+ * This does not necessarily take into account if the window is
+ * obscured by other windows, but no area outside of this region
+ * is visible.
+ * 
+ * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
+ *          when you are done.
+ **/
+cairo_region_t *
+gdk_surface_get_visible_region (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  return cairo_region_copy (window->clip_region);
+}
+
+static void
+gdk_surface_clear_backing_region (GdkSurface *window)
+{
+  cairo_t *cr;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  cr = cairo_create (window->current_paint.surface);
+
+  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+  gdk_cairo_region (cr, window->current_paint.region);
+  cairo_fill (cr);
+
+  cairo_destroy (cr);
+}
+
+/* This returns either the current working surface on the paint stack
+ * or the actual impl surface of the window. This should not be used
+ * from very many places: be careful! */
+static cairo_surface_t *
+ref_window_surface (GdkSurface *window)
+{
+  if (window->impl_window->current_paint.surface)
+    return cairo_surface_reference (window->impl_window->current_paint.surface);
+  else
+    return gdk_surface_ref_impl_surface (window);
+}
+
+/* This is used in places like gdk_cairo_set_source_window and
+ * other places to take "screenshots" of windows. Thus, we allow
+ * it to be used outside of a begin_paint / end_paint. */
+cairo_surface_t *
+_gdk_surface_ref_cairo_surface (GdkSurface *window)
+{
+  cairo_surface_t *surface;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  surface = ref_window_surface (window);
+
+  if (gdk_surface_has_impl (window))
+    {
+      return surface;
+    }
+  else
+    {
+      cairo_surface_t *subsurface;
+      subsurface = cairo_surface_create_for_rectangle (surface,
+                                                       window->abs_x,
+                                                       window->abs_y,
+                                                       window->width,
+                                                       window->height);
+      cairo_surface_destroy (surface);
+      return subsurface;
+    }
+}
+
+/* Code for dirty-region queueing
+ */
+static GSList *update_windows = NULL;
+
+static inline gboolean
+gdk_surface_is_ancestor (GdkSurface *window,
+                       GdkSurface *ancestor)
+{
+  while (window)
+    {
+      GdkSurface *parent = window->parent;
+
+      if (parent == ancestor)
+       return TRUE;
+
+      window = parent;
+    }
+
+  return FALSE;
+}
+
+static void
+gdk_surface_add_update_window (GdkSurface *window)
+{
+  GSList *tmp;
+  GSList *prev = NULL;
+  gboolean has_ancestor_in_list = FALSE;
+
+  /*  Check whether "window" is already in "update_windows" list.
+   *  It could be added during execution of gtk_widget_destroy() when
+   *  setting focus widget to NULL and redrawing old focus widget.
+   *  See bug 711552.
+   */
+  tmp = g_slist_find (update_windows, window);
+  if (tmp != NULL)
+    return;
+
+  for (tmp = update_windows; tmp; tmp = tmp->next)
+    {
+      GdkSurface *parent = window->parent;
+
+      /*  check if tmp is an ancestor of "window"; if it is, set a
+       *  flag indicating that all following windows are either
+       *  children of "window" or from a differen hierarchy
+       */
+      if (!has_ancestor_in_list && gdk_surface_is_ancestor (window, tmp->data))
+       has_ancestor_in_list = TRUE;
+
+      /* insert in reverse stacking order when adding around siblings,
+       * so processing updates properly paints over lower stacked windows
+       */
+      if (parent == GDK_SURFACE (tmp->data)->parent)
+       {
+          if (parent != NULL)
+            {
+              gint index = g_list_index (parent->children, window);
+              for (; tmp && parent == GDK_SURFACE (tmp->data)->parent; tmp = tmp->next)
+                {
+                  gint sibling_index = g_list_index (parent->children, tmp->data);
+                  if (index > sibling_index)
+                    break;
+                  prev = tmp;
+                }
+            }
+         /* here, tmp got advanced past all lower stacked siblings */
+         tmp = g_slist_prepend (tmp, g_object_ref (window));
+         if (prev)
+           prev->next = tmp;
+         else
+           update_windows = tmp;
+         return;
+       }
+
+      /*  if "window" has an ancestor in the list and tmp is one of
+       *  "window's" children, insert "window" before tmp
+       */
+      if (has_ancestor_in_list && gdk_surface_is_ancestor (tmp->data, window))
+       {
+         tmp = g_slist_prepend (tmp, g_object_ref (window));
+
+         if (prev)
+           prev->next = tmp;
+         else
+           update_windows = tmp;
+         return;
+       }
+
+      /*  if we're at the end of the list and had an ancestor it it,
+       *  append to the list
+       */
+      if (! tmp->next && has_ancestor_in_list)
+       {
+         tmp = g_slist_append (tmp, g_object_ref (window));
+         return;
+       }
+
+      prev = tmp;
+    }
+
+  /*  if all above checks failed ("window" is from a different
+   *  hierarchy than what is already in the list) or the list is
+   *  empty, prepend
+   */
+  update_windows = g_slist_prepend (update_windows, g_object_ref (window));
+}
+
+static void
+gdk_surface_remove_update_window (GdkSurface *window)
+{
+  GSList *link;
+
+  link = g_slist_find (update_windows, window);
+  if (link != NULL)
+    {
+      update_windows = g_slist_delete_link (update_windows, link);
+      g_object_unref (window);
+    }
+}
+
+static gboolean
+gdk_surface_is_toplevel_frozen (GdkSurface *window)
+{
+  GdkSurface *toplevel;
+
+  toplevel = gdk_surface_get_toplevel (window);
+
+  return toplevel->update_and_descendants_freeze_count > 0;
+}
+
+static void
+gdk_surface_schedule_update (GdkSurface *window)
+{
+  GdkFrameClock *frame_clock;
+
+  if (window &&
+      (window->update_freeze_count ||
+       gdk_surface_is_toplevel_frozen (window)))
+    return;
+
+  /* If there's no frame clock (a foreign window), then the invalid
+   * region will just stick around unless gdk_surface_process_updates()
+   * is called. */
+  frame_clock = gdk_surface_get_frame_clock (window);
+  if (frame_clock)
+    gdk_frame_clock_request_phase (gdk_surface_get_frame_clock (window),
+                                   GDK_FRAME_CLOCK_PHASE_PAINT);
+}
+
+void
+_gdk_surface_process_updates_recurse (GdkSurface *window,
+                                     cairo_region_t *expose_region)
+{
+  cairo_region_t *clipped_expose_region;
+  GdkEvent *event;
+
+  if (window->destroyed)
+    return;
+
+  clipped_expose_region = cairo_region_copy (expose_region);
+
+  cairo_region_intersect (clipped_expose_region, window->clip_region);
+
+  if (cairo_region_is_empty (clipped_expose_region))
+    goto out;
+
+  /* Paint the window before the children, clipped to the window region */
+
+  event = gdk_event_new (GDK_EXPOSE);
+  event->any.window = g_object_ref (window);
+  event->any.send_event = FALSE;
+  event->expose.count = 0;
+  event->expose.region = cairo_region_reference (clipped_expose_region);
+  cairo_region_get_extents (clipped_expose_region, &event->expose.area);
+
+  _gdk_event_emit (event);
+  gdk_event_free (event);
+
+ out:
+  cairo_region_destroy (clipped_expose_region);
+}
+
+
+static void
+gdk_surface_update_native_shapes (GdkSurface *window)
+{
+  if (should_apply_clip_as_shape (window))
+    apply_clip_as_shape (window);
+}
+
+/* Process and remove any invalid area on the native window by creating
+ * expose events for the window and all non-native descendants.
+ */
+static void
+gdk_surface_process_updates_internal (GdkSurface *window)
+{
+  GdkSurfaceImplClass *impl_class;
+  GdkSurface *toplevel;
+
+  toplevel = gdk_surface_get_toplevel (window);
+  if (toplevel->geometry_dirty)
+    {
+      gdk_surface_update_native_shapes (toplevel);
+      toplevel->geometry_dirty = FALSE;
+    }
+
+  /* Ensure the window lives while updating it */
+  g_object_ref (window);
+
+  window->in_update = TRUE;
+
+  /* If an update got queued during update processing, we can get a
+   * window in the update queue that has an empty update_area.
+   * just ignore it.
+   */
+  if (window->update_area)
+    {
+      g_assert (window->active_update_area == NULL); /* No reentrancy */
+
+      window->active_update_area = window->update_area;
+      window->update_area = NULL;
+
+      if (gdk_surface_is_viewable (window))
+       {
+         cairo_region_t *expose_region;
+
+         expose_region = cairo_region_copy (window->active_update_area);
+
+         impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+         /* Clip to part visible in impl window */
+         cairo_region_intersect (expose_region, window->clip_region);
+
+          if (impl_class->queue_antiexpose)
+            impl_class->queue_antiexpose (window, expose_region);
+
+          impl_class->process_updates_recurse (window, expose_region);
+
+          gdk_surface_append_old_updated_area (window, window->active_update_area);
+
+          cairo_region_destroy (expose_region);
+        }
+
+      cairo_region_destroy (window->active_update_area);
+      window->active_update_area = NULL;
+    }
+
+  window->in_update = FALSE;
+
+  g_object_unref (window);
+}
+
+static void
+gdk_surface_paint_on_clock (GdkFrameClock *clock,
+                          void          *data)
+{
+  GdkSurface *window;
+
+  window = GDK_SURFACE (data);
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (window->impl_window == window);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  g_object_ref (window);
+
+  if (window->update_area &&
+      !window->update_freeze_count &&
+      !gdk_surface_is_toplevel_frozen (window) &&
+
+      /* Don't recurse into process_updates_internal, we'll
+       * do the update later when idle instead. */
+      !window->in_update)
+    {
+      gdk_surface_process_updates_internal (window);
+      gdk_surface_remove_update_window (window);
+    }
+
+  g_object_unref (window);
+}
+
+static void
+gdk_surface_invalidate_rect_full (GdkSurface          *window,
+                                 const GdkRectangle *rect,
+                                 gboolean            invalidate_children)
+{
+  GdkRectangle window_rect;
+  cairo_region_t *region;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (window->input_only || !window->viewable)
+    return;
+
+  if (!rect)
+    {
+      window_rect.x = 0;
+      window_rect.y = 0;
+      window_rect.width = window->width;
+      window_rect.height = window->height;
+      rect = &window_rect;
+    }
+
+  region = cairo_region_create_rectangle (rect);
+  gdk_surface_invalidate_region_full (window, region, invalidate_children);
+  cairo_region_destroy (region);
+}
+
+/**
+ * gdk_surface_invalidate_rect:
+ * @window: a #GdkSurface
+ * @rect: (allow-none): rectangle to invalidate or %NULL to invalidate the whole
+ *      window
+ * @invalidate_children: whether to also invalidate child windows
+ *
+ * A convenience wrapper around gdk_surface_invalidate_region() which
+ * invalidates a rectangular region. See
+ * gdk_surface_invalidate_region() for details.
+ **/
+void
+gdk_surface_invalidate_rect (GdkSurface          *window,
+                           const GdkRectangle *rect,
+                           gboolean            invalidate_children)
+{
+  gdk_surface_invalidate_rect_full (window, rect, invalidate_children);
+}
+
+static void
+impl_window_add_update_area (GdkSurface *impl_window,
+                            cairo_region_t *region)
+{
+  if (impl_window->update_area)
+    cairo_region_union (impl_window->update_area, region);
+  else
+    {
+      gdk_surface_add_update_window (impl_window);
+      impl_window->update_area = cairo_region_copy (region);
+      gdk_surface_schedule_update (impl_window);
+    }
+}
+
+static void
+gdk_surface_invalidate_maybe_recurse_full (GdkSurface            *window,
+                                         const cairo_region_t *region,
+                                          GdkSurfaceChildFunc    child_func,
+                                         gpointer              user_data)
+{
+  cairo_region_t *visible_region;
+  cairo_rectangle_int_t r;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (window->input_only ||
+      !window->viewable ||
+      cairo_region_is_empty (region) ||
+      window->window_type == GDK_SURFACE_ROOT)
+    return;
+
+  r.x = 0;
+  r.y = 0;
+
+  visible_region = cairo_region_copy (region);
+
+  while (window != NULL && 
+        !cairo_region_is_empty (visible_region))
+    {
+      r.width = window->width;
+      r.height = window->height;
+      cairo_region_intersect_rectangle (visible_region, &r);
+
+      if (gdk_surface_has_impl (window))
+       {
+         impl_window_add_update_area (window, visible_region);
+         break;
+       }
+      else
+       {
+         cairo_region_translate (visible_region,
+                                 window->x, window->y);
+         window = window->parent;
+       }
+    }
+
+  cairo_region_destroy (visible_region);
+}
+
+/**
+ * gdk_surface_invalidate_maybe_recurse:
+ * @window: a #GdkSurface
+ * @region: a #cairo_region_t
+ * @child_func: (scope call) (allow-none): function to use to decide if to
+ *     recurse to a child, %NULL means never recurse.
+ * @user_data: data passed to @child_func
+ *
+ * Adds @region to the update area for @window. The update area is the
+ * region that needs to be redrawn, or â€śdirty region.”
+ *
+ * GDK will process all updates whenever the frame clock schedules a redraw,
+ * so there’s no need to do forces redraws manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * The @child_func parameter controls whether the region of
+ * each child window that intersects @region will also be invalidated.
+ * Only children for which @child_func returns #TRUE will have the area
+ * invalidated.
+ **/
+void
+gdk_surface_invalidate_maybe_recurse (GdkSurface            *window,
+                                    const cairo_region_t *region,
+                                     GdkSurfaceChildFunc    child_func,
+                                    gpointer              user_data)
+{
+  gdk_surface_invalidate_maybe_recurse_full (window, region,
+                                           child_func, user_data);
+}
+
+static gboolean
+true_predicate (GdkSurface *window,
+               gpointer   user_data)
+{
+  return TRUE;
+}
+
+static void
+gdk_surface_invalidate_region_full (GdkSurface       *window,
+                                   const cairo_region_t *region,
+                                   gboolean         invalidate_children)
+{
+  gdk_surface_invalidate_maybe_recurse_full (window, region,
+                                           invalidate_children ?
+                                           true_predicate : (gboolean (*) (GdkSurface *, gpointer))NULL,
+                                      NULL);
+}
+
+/**
+ * gdk_surface_invalidate_region:
+ * @window: a #GdkSurface
+ * @region: a #cairo_region_t
+ * @invalidate_children: %TRUE to also invalidate child windows
+ *
+ * Adds @region to the update area for @window. The update area is the
+ * region that needs to be redrawn, or â€śdirty region.”
+ *
+ * GDK will process all updates whenever the frame clock schedules a redraw,
+ * so there’s no need to do forces redraws manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * The @invalidate_children parameter controls whether the region of
+ * each child window that intersects @region will also be invalidated.
+ * If %FALSE, then the update area for child windows will remain
+ * unaffected. See gdk_surface_invalidate_maybe_recurse if you need
+ * fine grained control over which children are invalidated.
+ **/
+void
+gdk_surface_invalidate_region (GdkSurface       *window,
+                             const cairo_region_t *region,
+                             gboolean         invalidate_children)
+{
+  gdk_surface_invalidate_maybe_recurse (window, region,
+                                      invalidate_children ?
+                                        true_predicate : (gboolean (*) (GdkSurface *, gpointer))NULL,
+                                      NULL);
+}
+
+/**
+ * _gdk_surface_invalidate_for_expose:
+ * @window: a #GdkSurface
+ * @region: a #cairo_region_t
+ *
+ * Adds @region to the update area for @window.
+ *
+ * GDK will process all updates whenever the frame clock schedules a redraw,
+ * so there’s no need to do forces redraws manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * This version of invalidation is used when you recieve expose events
+ * from the native window system. It exposes the native window, plus
+ * any non-native child windows.
+ **/
+void
+_gdk_surface_invalidate_for_expose (GdkSurface       *window,
+                                  cairo_region_t       *region)
+{
+  gdk_surface_invalidate_maybe_recurse_full (window, region,
+                                           (gboolean (*) (GdkSurface *, gpointer))gdk_surface_has_no_impl,
+                                           NULL);
+}
+
+
+/**
+ * gdk_surface_get_update_area:
+ * @window: a #GdkSurface
+ *
+ * Transfers ownership of the update area from @window to the caller
+ * of the function. That is, after calling this function, @window will
+ * no longer have an invalid/dirty region; the update area is removed
+ * from @window and handed to you. If a window has no update area,
+ * gdk_surface_get_update_area() returns %NULL. You are responsible for
+ * calling cairo_region_destroy() on the returned region if it’s non-%NULL.
+ *
+ * Returns: the update area for @window
+ **/
+cairo_region_t *
+gdk_surface_get_update_area (GdkSurface *window)
+{
+  GdkSurface *impl_window;
+  cairo_region_t *tmp_region, *to_remove;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  impl_window = gdk_surface_get_impl_window (window);
+
+  if (impl_window->update_area)
+    {
+      tmp_region = cairo_region_copy (window->clip_region);
+      /* Convert to impl coords */
+      cairo_region_translate (tmp_region, window->abs_x, window->abs_y);
+      cairo_region_intersect (tmp_region, impl_window->update_area);
+
+      if (cairo_region_is_empty (tmp_region))
+       {
+         cairo_region_destroy (tmp_region);
+         return NULL;
+       }
+      else
+       {
+         /* Convert from impl coords */
+         cairo_region_translate (tmp_region, -window->abs_x, -window->abs_y);
+
+         /* Don't remove any update area that is overlapped by sibling windows
+            or child windows as these really need to be repainted independently of this window. */
+         to_remove = cairo_region_copy (tmp_region);
+
+         remove_child_area (window, FALSE, to_remove);
+         remove_sibling_overlapped_area (window, to_remove);
+
+         /* Remove from update_area */
+         cairo_region_translate (to_remove, window->abs_x, window->abs_y);
+         cairo_region_subtract (impl_window->update_area, to_remove);
+
+         cairo_region_destroy (to_remove);
+
+         if (cairo_region_is_empty (impl_window->update_area))
+           {
+             cairo_region_destroy (impl_window->update_area);
+             impl_window->update_area = NULL;
+
+             gdk_surface_remove_update_window ((GdkSurface *)impl_window);
+           }
+
+         return tmp_region;
+       }
+    }
+  else
+    return NULL;
+}
+
+/**
+ * _gdk_surface_clear_update_area:
+ * @window: a #GdkSurface.
+ *
+ * Internal function to clear the update area for a window. This
+ * is called when the window is hidden or destroyed.
+ **/
+void
+_gdk_surface_clear_update_area (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->update_area)
+    {
+      gdk_surface_remove_update_window (window);
+
+      cairo_region_destroy (window->update_area);
+      window->update_area = NULL;
+    }
+}
+
+/**
+ * gdk_surface_freeze_updates:
+ * @window: a #GdkSurface
+ *
+ * Temporarily freezes a window such that it won’t receive expose
+ * events.  The window will begin receiving expose events again when
+ * gdk_surface_thaw_updates() is called. If gdk_surface_freeze_updates()
+ * has been called more than once, gdk_surface_thaw_updates() must be called
+ * an equal number of times to begin processing exposes.
+ **/
+void
+gdk_surface_freeze_updates (GdkSurface *window)
+{
+  GdkSurface *impl_window;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  impl_window = gdk_surface_get_impl_window (window);
+  impl_window->update_freeze_count++;
+}
+
+/**
+ * gdk_surface_thaw_updates:
+ * @window: a #GdkSurface
+ *
+ * Thaws a window frozen with gdk_surface_freeze_updates().
+ **/
+void
+gdk_surface_thaw_updates (GdkSurface *window)
+{
+  GdkSurface *impl_window;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  impl_window = gdk_surface_get_impl_window (window);
+
+  g_return_if_fail (impl_window->update_freeze_count > 0);
+
+  if (--impl_window->update_freeze_count == 0)
+    gdk_surface_schedule_update (GDK_SURFACE (impl_window));
+}
+
+void
+gdk_surface_freeze_toplevel_updates (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (window->window_type != GDK_SURFACE_CHILD);
+
+  window->update_and_descendants_freeze_count++;
+  _gdk_frame_clock_freeze (gdk_surface_get_frame_clock (window));
+}
+
+void
+gdk_surface_thaw_toplevel_updates (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (window->window_type != GDK_SURFACE_CHILD);
+  g_return_if_fail (window->update_and_descendants_freeze_count > 0);
+
+  window->update_and_descendants_freeze_count--;
+  _gdk_frame_clock_thaw (gdk_surface_get_frame_clock (window));
+
+  gdk_surface_schedule_update (window);
+}
+
+/**
+ * gdk_surface_constrain_size:
+ * @geometry: a #GdkGeometry structure
+ * @flags: a mask indicating what portions of @geometry are set
+ * @width: desired width of window
+ * @height: desired height of the window
+ * @new_width: (out): location to store resulting width
+ * @new_height: (out): location to store resulting height
+ *
+ * Constrains a desired width and height according to a
+ * set of geometry hints (such as minimum and maximum size).
+ */
+void
+gdk_surface_constrain_size (GdkGeometry    *geometry,
+                          GdkSurfaceHints  flags,
+                          gint            width,
+                          gint            height,
+                          gint           *new_width,
+                          gint           *new_height)
+{
+  /* This routine is partially borrowed from fvwm.
+   *
+   * Copyright 1993, Robert Nation
+   *     You may use this code for any purpose, as long as the original
+   *     copyright remains in the source code and all documentation
+   *
+   * which in turn borrows parts of the algorithm from uwm
+   */
+  gint min_width = 0;
+  gint min_height = 0;
+  gint base_width = 0;
+  gint base_height = 0;
+  gint xinc = 1;
+  gint yinc = 1;
+  gint max_width = G_MAXINT;
+  gint max_height = G_MAXINT;
+
+#define FLOOR(value, base)     ( ((gint) ((value) / (base))) * (base) )
+
+  if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
+    {
+      base_width = geometry->base_width;
+      base_height = geometry->base_height;
+      min_width = geometry->min_width;
+      min_height = geometry->min_height;
+    }
+  else if (flags & GDK_HINT_BASE_SIZE)
+    {
+      base_width = geometry->base_width;
+      base_height = geometry->base_height;
+      min_width = geometry->base_width;
+      min_height = geometry->base_height;
+    }
+  else if (flags & GDK_HINT_MIN_SIZE)
+    {
+      base_width = geometry->min_width;
+      base_height = geometry->min_height;
+      min_width = geometry->min_width;
+      min_height = geometry->min_height;
+    }
+
+  if (flags & GDK_HINT_MAX_SIZE)
+    {
+      max_width = geometry->max_width ;
+      max_height = geometry->max_height;
+    }
+
+  if (flags & GDK_HINT_RESIZE_INC)
+    {
+      xinc = MAX (xinc, geometry->width_inc);
+      yinc = MAX (yinc, geometry->height_inc);
+    }
+
+  /* clamp width and height to min and max values
+   */
+  width = CLAMP (width, min_width, max_width);
+  height = CLAMP (height, min_height, max_height);
+
+  /* shrink to base + N * inc
+   */
+  width = base_width + FLOOR (width - base_width, xinc);
+  height = base_height + FLOOR (height - base_height, yinc);
+
+  /* constrain aspect ratio, according to:
+   *
+   *                width
+   * min_aspect <= -------- <= max_aspect
+   *                height
+   */
+
+  if (flags & GDK_HINT_ASPECT &&
+      geometry->min_aspect > 0 &&
+      geometry->max_aspect > 0)
+    {
+      gint delta;
+
+      if (geometry->min_aspect * height > width)
+       {
+         delta = FLOOR (height - width / geometry->min_aspect, yinc);
+         if (height - delta >= min_height)
+           height -= delta;
+         else
+           {
+             delta = FLOOR (height * geometry->min_aspect - width, xinc);
+             if (width + delta <= max_width)
+               width += delta;
+           }
+       }
+
+      if (geometry->max_aspect * height < width)
+       {
+         delta = FLOOR (width - height * geometry->max_aspect, xinc);
+         if (width - delta >= min_width)
+           width -= delta;
+         else
+           {
+             delta = FLOOR (width / geometry->max_aspect - height, yinc);
+             if (height + delta <= max_height)
+               height += delta;
+           }
+       }
+    }
+
+#undef FLOOR
+
+  *new_width = width;
+  *new_height = height;
+}
+
+/**
+ * gdk_surface_get_device_position_double:
+ * @window: a #GdkSurface.
+ * @device: pointer #GdkDevice to query to.
+ * @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
+ * @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
+ * @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
+ *
+ * Obtains the current device position in doubles and modifier state.
+ * The position is given in coordinates relative to the upper left
+ * corner of @window.
+ *
+ * Returns: (nullable) (transfer none): The window underneath @device
+ * (as with gdk_device_get_window_at_position()), or %NULL if the
+ * window is not known to GDK.
+ **/
+GdkSurface *
+gdk_surface_get_device_position_double (GdkSurface       *window,
+                                       GdkDevice       *device,
+                                       double          *x,
+                                       double          *y,
+                                       GdkModifierType *mask)
+{
+  gdouble tmp_x, tmp_y;
+  GdkModifierType tmp_mask;
+  gboolean normal_child;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
+  g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
+
+  tmp_x = tmp_y = 0;
+  tmp_mask = 0;
+  normal_child = GDK_SURFACE_IMPL_GET_CLASS (window->impl)->get_device_state (window,
+                                                                             device,
+                                                                             &tmp_x, &tmp_y,
+                                                                             &tmp_mask);
+  /* We got the coords on the impl, convert to the window */
+  tmp_x -= window->abs_x;
+  tmp_y -= window->abs_y;
+
+  if (x)
+    *x = tmp_x;
+  if (y)
+    *y = tmp_y;
+  if (mask)
+    *mask = tmp_mask;
+
+  if (normal_child)
+    return _gdk_surface_find_child_at (window, tmp_x, tmp_y);
+  return NULL;
+}
+
+/**
+ * gdk_surface_get_device_position:
+ * @window: a #GdkSurface.
+ * @device: pointer #GdkDevice to query to.
+ * @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
+ * @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
+ * @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
+ *
+ * Obtains the current device position and modifier state.
+ * The position is given in coordinates relative to the upper left
+ * corner of @window.
+ *
+ * Use gdk_surface_get_device_position_double() if you need subpixel precision.
+ *
+ * Returns: (nullable) (transfer none): The window underneath @device
+ * (as with gdk_device_get_window_at_position()), or %NULL if the
+ * window is not known to GDK.
+ **/
+GdkSurface *
+gdk_surface_get_device_position (GdkSurface       *window,
+                                GdkDevice       *device,
+                                gint            *x,
+                                gint            *y,
+                                GdkModifierType *mask)
+{
+  gdouble tmp_x, tmp_y;
+
+  window = gdk_surface_get_device_position_double (window, device,
+                                                  &tmp_x, &tmp_y, mask);
+  if (x)
+    *x = round (tmp_x);
+  if (y)
+    *y = round (tmp_y);
+
+  return window;
+}
+
+static gboolean
+gdk_surface_raise_internal (GdkSurface *window)
+{
+  GdkSurface *parent = window->parent;
+  GdkSurfaceImplClass *impl_class;
+  gboolean did_raise = FALSE;
+
+  if (parent && parent->children->data != window)
+    {
+      parent->children = g_list_remove_link (parent->children, &window->children_list_node);
+      parent->children = g_list_concat (&window->children_list_node, parent->children);
+      did_raise = TRUE;
+    }
+
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+  /* Just do native raise for toplevels */
+  if (gdk_surface_has_impl (window))
+      impl_class->raise (window);
+
+  return did_raise;
+}
+
+/* Returns TRUE If the native window was mapped or unmapped */
+static gboolean
+set_viewable (GdkSurface *w,
+             gboolean val)
+{
+  GdkSurface *child;
+  GList *l;
+
+  if (w->viewable == val)
+    return FALSE;
+
+  w->viewable = val;
+
+  if (val)
+    recompute_visible_regions (w, FALSE);
+
+  for (l = w->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      if (GDK_SURFACE_IS_MAPPED (child))
+       set_viewable (child, val);
+    }
+
+  return FALSE;
+}
+
+/* Returns TRUE If the native window was mapped or unmapped */
+gboolean
+_gdk_surface_update_viewable (GdkSurface *window)
+{
+  gboolean viewable;
+
+  if (window->window_type == GDK_SURFACE_FOREIGN ||
+      window->window_type == GDK_SURFACE_ROOT)
+    viewable = TRUE;
+  else if (gdk_surface_is_toplevel (window) ||
+          window->parent->viewable)
+    viewable = GDK_SURFACE_IS_MAPPED (window);
+  else
+    viewable = FALSE;
+
+  return set_viewable (window, viewable);
+}
+
+static void
+gdk_surface_show_internal (GdkSurface *window, gboolean raise)
+{
+  GdkSurfaceImplClass *impl_class;
+  gboolean was_mapped, was_viewable;
+  gboolean did_show, did_raise = FALSE;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->destroyed)
+    return;
+
+  was_mapped = GDK_SURFACE_IS_MAPPED (window);
+  was_viewable = window->viewable;
+
+  if (raise)
+    {
+      /* Keep children in (reverse) stacking order */
+      did_raise = gdk_surface_raise_internal (window);
+    }
+
+  if (gdk_surface_has_impl (window))
+    {
+      if (!was_mapped)
+        gdk_synthesize_window_state (window,
+                                     GDK_SURFACE_STATE_WITHDRAWN,
+                                     0);
+    }
+  else
+    {
+      window->state = 0;
+      g_object_notify_by_pspec (G_OBJECT (window), properties[PROP_STATE]);
+    }
+
+  did_show = _gdk_surface_update_viewable (window);
+
+  /* If it was already viewable the backend show op won't be called, call it
+     again to ensure things happen right if the mapped tracking was not right
+     for e.g. a foreign window.
+     Dunno if this is strictly needed but its what happened pre-csw.
+     Also show if not done by gdk_surface_update_viewable. */
+  if (gdk_surface_has_impl (window) && (was_viewable || !did_show))
+    {
+      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+      impl_class->show (window, !did_show ? was_mapped : TRUE);
+    }
+
+  if (!was_mapped && !gdk_surface_has_impl (window))
+    {
+      if (window->event_mask & GDK_STRUCTURE_MASK)
+       _gdk_make_event (window, GDK_MAP, NULL, FALSE);
+
+      if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+       _gdk_make_event (window, GDK_MAP, NULL, FALSE);
+    }
+
+  if (!was_mapped || did_raise)
+    {
+      recompute_visible_regions (window, FALSE);
+
+      if (gdk_surface_is_viewable (window))
+        gdk_surface_invalidate_rect_full (window, NULL, TRUE);
+    }
+}
+
+/**
+ * gdk_surface_show_unraised:
+ * @window: a #GdkSurface
+ *
+ * Shows a #GdkSurface onscreen, but does not modify its stacking
+ * order. In contrast, gdk_surface_show() will raise the window
+ * to the top of the window stack.
+ *
+ * On the X11 platform, in Xlib terms, this function calls
+ * XMapWindow() (it also updates some internal GDK state, which means
+ * that you can’t really use XMapWindow() directly on a GDK window).
+ */
+void
+gdk_surface_show_unraised (GdkSurface *window)
+{
+  gdk_surface_show_internal (window, FALSE);
+}
+
+/**
+ * gdk_surface_raise:
+ * @window: a #GdkSurface
+ *
+ * Raises @window to the top of the Z-order (stacking order), so that
+ * other windows with the same parent window appear below @window.
+ * This is true whether or not the windows are visible.
+ *
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_surface_raise() only
+ * requests the restack, does not guarantee it.
+ */
+void
+gdk_surface_raise (GdkSurface *window)
+{
+  gboolean did_raise;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->destroyed)
+    return;
+
+  /* Keep children in (reverse) stacking order */
+  did_raise = gdk_surface_raise_internal (window);
+
+  if (did_raise &&
+      !gdk_surface_is_toplevel (window) &&
+      gdk_surface_is_viewable (window) &&
+      !window->input_only)
+    gdk_surface_invalidate_region_full (window, window->clip_region, TRUE);
+}
+
+static void
+gdk_surface_lower_internal (GdkSurface *window)
+{
+  GdkSurface *parent = window->parent;
+  GdkSurfaceImplClass *impl_class;
+
+  if (parent)
+    {
+      parent->children = g_list_remove_link (parent->children, &window->children_list_node);
+      parent->children = g_list_concat (parent->children, &window->children_list_node);
+    }
+
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+  /* Just do native lower for toplevels */
+  if (gdk_surface_has_impl (window))
+    impl_class->lower (window);
+}
+
+static void
+gdk_surface_invalidate_in_parent (GdkSurface *private)
+{
+  GdkRectangle r, child;
+
+  if (gdk_surface_is_toplevel (private))
+    return;
+
+  /* get the visible rectangle of the parent */
+  r.x = r.y = 0;
+  r.width = private->parent->width;
+  r.height = private->parent->height;
+
+  child.x = private->x;
+  child.y = private->y;
+  child.width = private->width;
+  child.height = private->height;
+  gdk_rectangle_intersect (&r, &child, &r);
+
+  gdk_surface_invalidate_rect_full (private->parent, &r, TRUE);
+}
+
+
+/**
+ * gdk_surface_lower:
+ * @window: a #GdkSurface
+ *
+ * Lowers @window to the bottom of the Z-order (stacking order), so that
+ * other windows with the same parent window appear above @window.
+ * This is true whether or not the other windows are visible.
+ *
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_surface_lower() only
+ * requests the restack, does not guarantee it.
+ *
+ * Note that gdk_surface_show() raises the window again, so don’t call this
+ * function before gdk_surface_show(). (Try gdk_surface_show_unraised().)
+ */
+void
+gdk_surface_lower (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->destroyed)
+    return;
+
+  /* Keep children in (reverse) stacking order */
+  gdk_surface_lower_internal (window);
+
+  gdk_surface_invalidate_in_parent (window);
+}
+
+/**
+ * gdk_surface_restack:
+ * @window: a #GdkSurface
+ * @sibling: (allow-none): a #GdkSurface that is a sibling of @window, or %NULL
+ * @above: a boolean
+ *
+ * Changes the position of  @window in the Z-order (stacking order), so that
+ * it is above @sibling (if @above is %TRUE) or below @sibling (if @above is
+ * %FALSE).
+ *
+ * If @sibling is %NULL, then this either raises (if @above is %TRUE) or
+ * lowers the window.
+ *
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_surface_restack() only
+ * requests the restack, does not guarantee it.
+ */
+void
+gdk_surface_restack (GdkSurface     *window,
+                   GdkSurface     *sibling,
+                   gboolean       above)
+{
+  GdkSurfaceImplClass *impl_class;
+  GdkSurface *parent;
+  GList *sibling_link;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (sibling == NULL || GDK_IS_SURFACE (sibling));
+
+  if (window->destroyed)
+    return;
+
+  if (sibling == NULL)
+    {
+      if (above)
+       gdk_surface_raise (window);
+      else
+       gdk_surface_lower (window);
+      return;
+    }
+
+  if (gdk_surface_is_toplevel (window))
+    {
+      g_return_if_fail (gdk_surface_is_toplevel (sibling));
+      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+      impl_class->restack_toplevel (window, sibling, above);
+      return;
+    }
+
+  parent = window->parent;
+  if (parent)
+    {
+      sibling_link = g_list_find (parent->children, sibling);
+      g_return_if_fail (sibling_link != NULL);
+      if (sibling_link == NULL)
+       return;
+
+      parent->children = g_list_remove_link (parent->children, &window->children_list_node);
+      if (above)
+       parent->children = list_insert_link_before (parent->children,
+                                                    sibling_link,
+                                                    &window->children_list_node);
+      else
+       parent->children = list_insert_link_before (parent->children,
+                                                    sibling_link->next,
+                                                    &window->children_list_node);
+    }
+
+  gdk_surface_invalidate_in_parent (window);
+}
+
+
+/**
+ * gdk_surface_show:
+ * @window: a #GdkSurface
+ *
+ * Like gdk_surface_show_unraised(), but also raises the window to the
+ * top of the window stack (moves the window to the front of the
+ * Z-order).
+ *
+ * This function maps a window so it’s visible onscreen. Its opposite
+ * is gdk_surface_hide().
+ *
+ * When implementing a #GtkWidget, you should call this function on the widget's
+ * #GdkSurface as part of the â€śmap” method.
+ */
+void
+gdk_surface_show (GdkSurface *window)
+{
+  gdk_surface_show_internal (window, TRUE);
+}
+
+/**
+ * gdk_surface_hide:
+ * @window: a #GdkSurface
+ *
+ * For toplevel windows, withdraws them, so they will no longer be
+ * known to the window manager; for all windows, unmaps them, so
+ * they won’t be displayed. Normally done automatically as
+ * part of gtk_widget_hide().
+ */
+void
+gdk_surface_hide (GdkSurface *window)
+{
+  GdkSurfaceImplClass *impl_class;
+  gboolean was_mapped, did_hide;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->destroyed)
+    return;
+
+  was_mapped = GDK_SURFACE_IS_MAPPED (window);
+
+  if (gdk_surface_has_impl (window))
+    {
+
+      if (GDK_SURFACE_IS_MAPPED (window))
+       gdk_synthesize_window_state (window,
+                                    0,
+                                    GDK_SURFACE_STATE_WITHDRAWN);
+    }
+  else if (was_mapped)
+    {
+      window->state = GDK_SURFACE_STATE_WITHDRAWN;
+      g_object_notify_by_pspec (G_OBJECT (window), properties[PROP_STATE]);
+    }
+
+  if (was_mapped)
+    {
+      GdkDisplay *display;
+      GdkSeat *seat;
+      GList *devices, *d;
+
+      /* May need to break grabs on children */
+      display = gdk_surface_get_display (window);
+      seat = gdk_display_get_default_seat (display);
+
+      devices = gdk_seat_get_slaves (seat, GDK_SEAT_CAPABILITY_ALL);
+      devices = g_list_prepend (devices, gdk_seat_get_keyboard (seat));
+      devices = g_list_prepend (devices, gdk_seat_get_pointer (seat));
+
+      for (d = devices; d; d = d->next)
+        {
+          GdkDevice *device = d->data;
+
+          if (_gdk_display_end_device_grab (display,
+                                            device,
+                                            _gdk_display_get_next_serial (display),
+                                            window,
+                                            TRUE))
+            {
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+              gdk_device_ungrab (device, GDK_CURRENT_TIME);
+G_GNUC_END_IGNORE_DEPRECATIONS
+            }
+        }
+
+      g_list_free (devices);
+    }
+
+  did_hide = _gdk_surface_update_viewable (window);
+
+  /* Hide foreign window as those are not handled by update_viewable. */
+  if (gdk_surface_has_impl (window) && (!did_hide))
+    {
+      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+      impl_class->hide (window);
+    }
+
+  gdk_surface_clear_old_updated_area (window);
+  recompute_visible_regions (window, FALSE);
+
+  if (was_mapped && !gdk_surface_has_impl (window))
+    {
+      if (window->event_mask & GDK_STRUCTURE_MASK)
+       _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
+
+      if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+       _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
+    }
+
+  /* Invalidate the rect */
+  if (was_mapped)
+    gdk_surface_invalidate_in_parent (window);
+}
+
+/**
+ * gdk_surface_withdraw:
+ * @window: a toplevel #GdkSurface
+ *
+ * Withdraws a window (unmaps it and asks the window manager to forget about it).
+ * This function is not really useful as gdk_surface_hide() automatically
+ * withdraws toplevel windows before hiding them.
+ **/
+void
+gdk_surface_withdraw (GdkSurface *window)
+{
+  GdkSurfaceImplClass *impl_class;
+  gboolean was_mapped;
+  GdkGLContext *current_context;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->destroyed)
+    return;
+
+  was_mapped = GDK_SURFACE_IS_MAPPED (window);
+
+  if (gdk_surface_has_impl (window))
+    {
+      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+      impl_class->withdraw (window);
+
+      if (was_mapped)
+       {
+         if (window->event_mask & GDK_STRUCTURE_MASK)
+           _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
+
+         if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+           _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
+       }
+
+      current_context = gdk_gl_context_get_current ();
+      if (current_context != NULL && gdk_gl_context_get_window (current_context) == window)
+        gdk_gl_context_clear_current ();
+
+      recompute_visible_regions (window, FALSE);
+      gdk_surface_clear_old_updated_area (window);
+    }
+}
+
+/**
+ * gdk_surface_set_events:
+ * @window: a #GdkSurface
+ * @event_mask: event mask for @window
+ *
+ * The event mask for a window determines which events will be reported
+ * for that window from all master input devices. For example, an event mask
+ * including #GDK_BUTTON_PRESS_MASK means the window should report button
+ * press events. The event mask is the bitwise OR of values from the
+ * #GdkEventMask enumeration.
+ *
+ * See the [input handling overview][event-masks] for details.
+ **/
+void
+gdk_surface_set_events (GdkSurface       *window,
+                      GdkEventMask     event_mask)
+{
+  GdkSurfaceImplClass *impl_class;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->destroyed)
+    return;
+
+  window->event_mask = event_mask;
+
+  if (gdk_surface_has_impl (window))
+    {
+      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+      impl_class->set_events (window,
+                             get_native_event_mask (window));
+    }
+
+}
+
+/**
+ * gdk_surface_get_events:
+ * @window: a #GdkSurface
+ *
+ * Gets the event mask for @window for all master input devices. See
+ * gdk_surface_set_events().
+ *
+ * Returns: event mask for @window
+ **/
+GdkEventMask
+gdk_surface_get_events (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
+
+  if (window->destroyed)
+    return 0;
+
+  return window->event_mask;
+}
+
+/**
+ * gdk_surface_set_device_events:
+ * @window: a #GdkSurface
+ * @device: #GdkDevice to enable events for.
+ * @event_mask: event mask for @window
+ *
+ * Sets the event mask for a given device (Normally a floating device, not
+ * attached to any visible pointer) to @window. For example, an event mask
+ * including #GDK_BUTTON_PRESS_MASK means the window should report button
+ * press events. The event mask is the bitwise OR of values from the
+ * #GdkEventMask enumeration.
+ *
+ * See the [input handling overview][event-masks] for details.
+ **/
+void
+gdk_surface_set_device_events (GdkSurface    *window,
+                              GdkDevice    *device,
+                              GdkEventMask  event_mask)
+{
+  GdkEventMask device_mask;
+  GdkSurface *native;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (GDK_IS_DEVICE (device));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (G_UNLIKELY (!window->device_events))
+    window->device_events = g_hash_table_new (NULL, NULL);
+
+  if (event_mask == 0)
+    {
+      /* FIXME: unsetting events on a master device
+       * would restore window->event_mask
+       */
+      g_hash_table_remove (window->device_events, device);
+    }
+  else
+    g_hash_table_insert (window->device_events, device,
+                         GINT_TO_POINTER (event_mask));
+
+  native = gdk_surface_get_toplevel (window);
+
+  device_mask = get_native_device_event_mask (window, device);
+  GDK_DEVICE_GET_CLASS (device)->select_window_events (device, native, device_mask);
+}
+
+/**
+ * gdk_surface_get_device_events:
+ * @window: a #GdkSurface.
+ * @device: a #GdkDevice.
+ *
+ * Returns the event mask for @window corresponding to an specific device.
+ *
+ * Returns: device event mask for @window
+ **/
+GdkEventMask
+gdk_surface_get_device_events (GdkSurface *window,
+                              GdkDevice *device)
+{
+  GdkEventMask mask;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
+  g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return 0;
+
+  if (!window->device_events)
+    return 0;
+
+  mask = GPOINTER_TO_INT (g_hash_table_lookup (window->device_events, device));
+
+  /* FIXME: device could be controlled by window->event_mask */
+
+  return mask;
+}
+
+static void
+gdk_surface_move_resize_toplevel (GdkSurface *window,
+                                 gboolean   with_move,
+                                 gint       x,
+                                 gint       y,
+                                 gint       width,
+                                 gint       height)
+{
+  cairo_region_t *old_region, *new_region;
+  GdkSurfaceImplClass *impl_class;
+  gboolean expose;
+  gboolean is_resize;
+
+  expose = FALSE;
+  old_region = NULL;
+
+  is_resize = (width != -1) || (height != -1);
+
+  if (gdk_surface_is_viewable (window) &&
+      !window->input_only)
+    {
+      expose = TRUE;
+      old_region = cairo_region_copy (window->clip_region);
+    }
+
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+  impl_class->move_resize (window, with_move, x, y, width, height);
+
+  /* Avoid recomputing for pure toplevel moves, for performance reasons */
+  if (is_resize)
+    recompute_visible_regions (window, FALSE);
+
+  if (expose)
+    {
+      new_region = cairo_region_copy (window->clip_region);
+
+      /* This is the newly exposed area (due to any resize),
+       * X will expose it, but lets do that without the roundtrip
+       */
+      cairo_region_subtract (new_region, old_region);
+      gdk_surface_invalidate_region_full (window, new_region, TRUE);
+
+      cairo_region_destroy (old_region);
+      cairo_region_destroy (new_region);
+    }
+}
+
+
+static void
+gdk_surface_move_resize_internal (GdkSurface *window,
+                                gboolean   with_move,
+                                gint       x,
+                                gint       y,
+                                gint       width,
+                                gint       height)
+{
+  cairo_region_t *old_region, *new_region;
+  gboolean expose;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->destroyed)
+    return;
+
+  if (gdk_surface_is_toplevel (window))
+    {
+      gdk_surface_move_resize_toplevel (window, with_move, x, y, width, height);
+      return;
+    }
+
+  if (width == 0)
+    width = 1;
+  if (height == 0)
+    height = 1;
+
+  /* Bail early if no change */
+  if (window->width == width &&
+      window->height == height &&
+      (!with_move ||
+       (window->x == x &&
+       window->y == y)))
+    return;
+
+  /* Handle child windows */
+
+  expose = FALSE;
+  old_region = NULL;
+
+  if (gdk_surface_is_viewable (window) &&
+      !window->input_only)
+    {
+      GdkRectangle r;
+
+      expose = TRUE;
+
+      r.x = window->x;
+      r.y = window->y;
+      r.width = window->width;
+      r.height = window->height;
+
+      old_region = cairo_region_create_rectangle (&r);
+    }
+
+  /* Set the new position and size */
+  if (with_move)
+    {
+      window->x = x;
+      window->y = y;
+    }
+  if (!(width < 0 && height < 0))
+    {
+      window->width = width;
+      window->height = height;
+    }
+
+  recompute_visible_regions (window, FALSE);
+
+  if (expose)
+    {
+      GdkRectangle r;
+
+      r.x = window->x;
+      r.y = window->y;
+      r.width = window->width;
+      r.height = window->height;
+
+      new_region = cairo_region_create_rectangle (&r);
+
+      cairo_region_union (new_region, old_region);
+
+      gdk_surface_invalidate_region_full (window->parent, new_region, TRUE);
+
+      cairo_region_destroy (old_region);
+      cairo_region_destroy (new_region);
+    }
+}
+
+
+
+/**
+ * gdk_surface_move:
+ * @window: a #GdkSurface
+ * @x: X coordinate relative to window’s parent
+ * @y: Y coordinate relative to window’s parent
+ *
+ * Repositions a window relative to its parent window.
+ * For toplevel windows, window managers may ignore or modify the move;
+ * you should probably use gtk_window_move() on a #GtkWindow widget
+ * anyway, instead of using GDK functions. For child windows,
+ * the move will reliably succeed.
+ *
+ * If you’re also planning to resize the window, use gdk_surface_move_resize()
+ * to both move and resize simultaneously, for a nicer visual effect.
+ **/
+void
+gdk_surface_move (GdkSurface *window,
+                gint       x,
+                gint       y)
+{
+  gdk_surface_move_resize_internal (window, TRUE, x, y, -1, -1);
+}
+
+/**
+ * gdk_surface_resize:
+ * @window: a #GdkSurface
+ * @width: new width of the window
+ * @height: new height of the window
+ *
+ * Resizes @window; for toplevel windows, asks the window manager to resize
+ * the window. The window manager may not allow the resize. When using GTK+,
+ * use gtk_window_resize() instead of this low-level GDK function.
+ *
+ * Windows may not be resized below 1x1.
+ *
+ * If you’re also planning to move the window, use gdk_surface_move_resize()
+ * to both move and resize simultaneously, for a nicer visual effect.
+ **/
+void
+gdk_surface_resize (GdkSurface *window,
+                  gint       width,
+                  gint       height)
+{
+  gdk_surface_move_resize_internal (window, FALSE, 0, 0, width, height);
+}
+
+
+/**
+ * gdk_surface_move_resize:
+ * @window: a #GdkSurface
+ * @x: new X position relative to window’s parent
+ * @y: new Y position relative to window’s parent
+ * @width: new width
+ * @height: new height
+ *
+ * Equivalent to calling gdk_surface_move() and gdk_surface_resize(),
+ * except that both operations are performed at once, avoiding strange
+ * visual effects. (i.e. the user may be able to see the window first
+ * move, then resize, if you don’t use gdk_surface_move_resize().)
+ **/
+void
+gdk_surface_move_resize (GdkSurface *window,
+                       gint       x,
+                       gint       y,
+                       gint       width,
+                       gint       height)
+{
+  gdk_surface_move_resize_internal (window, TRUE, x, y, width, height);
+}
+
+/**
+ * gdk_surface_move_to_rect:
+ * @window: the #GdkSurface to move
+ * @rect: (not nullable): the destination #GdkRectangle to align @window with
+ * @rect_anchor: the point on @rect to align with @window's anchor point
+ * @window_anchor: the point on @window to align with @rect's anchor point
+ * @anchor_hints: positioning hints to use when limited on space
+ * @rect_anchor_dx: horizontal offset to shift @window, i.e. @rect's anchor
+ *                  point
+ * @rect_anchor_dy: vertical offset to shift @window, i.e. @rect's anchor point
+ *
+ * Moves @window to @rect, aligning their anchor points.
+ *
+ * @rect is relative to the top-left corner of the window that @window is
+ * transient for. @rect_anchor and @window_anchor determine anchor points on
+ * @rect and @window to pin together. @rect's anchor point can optionally be
+ * offset by @rect_anchor_dx and @rect_anchor_dy, which is equivalent to
+ * offsetting the position of @window.
+ *
+ * @anchor_hints determines how @window will be moved if the anchor points cause
+ * it to move off-screen. For example, %GDK_ANCHOR_FLIP_X will replace
+ * %GDK_GRAVITY_NORTH_WEST with %GDK_GRAVITY_NORTH_EAST and vice versa if
+ * @window extends beyond the left or right edges of the monitor.
+ *
+ * Connect to the #GdkSurface::moved-to-rect signal to find out how it was
+ * actually positioned.
+ *
+ * Stability: Private
+ */
+void
+gdk_surface_move_to_rect (GdkSurface          *window,
+                         const GdkRectangle *rect,
+                         GdkGravity          rect_anchor,
+                         GdkGravity          window_anchor,
+                         GdkAnchorHints      anchor_hints,
+                         gint                rect_anchor_dx,
+                         gint                rect_anchor_dy)
+{
+  GdkSurfaceImplClass *impl_class;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (window->transient_for);
+  g_return_if_fail (rect);
+
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+  impl_class->move_to_rect (window,
+                            rect,
+                            rect_anchor,
+                            window_anchor,
+                            anchor_hints,
+                            rect_anchor_dx,
+                            rect_anchor_dy);
+}
+
+/**
+ * gdk_surface_scroll:
+ * @window: a #GdkSurface
+ * @dx: Amount to scroll in the X direction
+ * @dy: Amount to scroll in the Y direction
+ *
+ * Scroll the contents of @window, both pixels and children, by the
+ * given amount. @window itself does not move. Portions of the window
+ * that the scroll operation brings in from offscreen areas are
+ * invalidated. The invalidated region may be bigger than what would
+ * strictly be necessary.
+ *
+ * For X11, a minimum area will be invalidated if the window has no
+ * subwindows, or if the edges of the window’s parent do not extend
+ * beyond the edges of the window. In other cases, a multi-step process
+ * is used to scroll the window which may produce temporary visual
+ * artifacts and unnecessary invalidations.
+ **/
+void
+gdk_surface_scroll (GdkSurface *window,
+                  gint       dx,
+                  gint       dy)
+{
+  GList *tmp_list;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (dx == 0 && dy == 0)
+    return;
+
+  if (window->destroyed)
+    return;
+
+  /* First move all child windows, without causing invalidation */
+
+  tmp_list = window->children;
+  while (tmp_list)
+    {
+      GdkSurface *child = GDK_SURFACE (tmp_list->data);
+
+      /* Just update the positions, the bits will move with the copy */
+      child->x += dx;
+      child->y += dy;
+
+      tmp_list = tmp_list->next;
+    }
+
+  recompute_visible_regions (window, TRUE);
+
+  gdk_surface_invalidate_rect_full (window, NULL, TRUE);
+}
+
+/**
+ * gdk_surface_move_region:
+ * @window: a #GdkSurface
+ * @region: The #cairo_region_t to move
+ * @dx: Amount to move in the X direction
+ * @dy: Amount to move in the Y direction
+ *
+ * Move the part of @window indicated by @region by @dy pixels in the Y
+ * direction and @dx pixels in the X direction. The portions of @region
+ * that not covered by the new position of @region are invalidated.
+ *
+ * Child windows are not moved.
+ */
+void
+gdk_surface_move_region (GdkSurface            *window,
+                        const cairo_region_t *region,
+                        gint                  dx,
+                        gint                  dy)
+{
+  cairo_region_t *expose_area;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (region != NULL);
+
+  if (dx == 0 && dy == 0)
+    return;
+
+  if (window->destroyed)
+    return;
+
+  expose_area = cairo_region_copy (region);
+  cairo_region_translate (expose_area, dx, dy);
+  cairo_region_union (expose_area, region);
+
+  gdk_surface_invalidate_region_full (window, expose_area, FALSE);
+  cairo_region_destroy (expose_area);
+}
+
+static void
+gdk_surface_set_cursor_internal (GdkSurface *window,
+                                GdkDevice *device,
+                                GdkCursor *cursor)
+{
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  g_assert (gdk_surface_get_display (window) == gdk_device_get_display (device));
+
+  if (window->window_type == GDK_SURFACE_ROOT ||
+      window->window_type == GDK_SURFACE_FOREIGN)
+    GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
+  else
+    {
+      GdkPointerSurfaceInfo *pointer_info;
+      GdkDisplay *display;
+
+      display = gdk_surface_get_display (window);
+      pointer_info = _gdk_display_get_pointer_info (display, device);
+
+      if (_gdk_surface_event_parent_of (window, pointer_info->window_under_pointer))
+        update_cursor (display, device);
+    }
+}
+
+/**
+ * gdk_surface_get_cursor:
+ * @window: a #GdkSurface
+ *
+ * Retrieves a #GdkCursor pointer for the cursor currently set on the
+ * specified #GdkSurface, or %NULL.  If the return value is %NULL then
+ * there is no custom cursor set on the specified window, and it is
+ * using the cursor for its parent window.
+ *
+ * Returns: (nullable) (transfer none): a #GdkCursor, or %NULL. The
+ *   returned object is owned by the #GdkSurface and should not be
+ *   unreferenced directly. Use gdk_surface_set_cursor() to unset the
+ *   cursor of the window
+ */
+GdkCursor *
+gdk_surface_get_cursor (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  return window->cursor;
+}
+
+/**
+ * gdk_surface_set_cursor:
+ * @window: a #GdkSurface
+ * @cursor: (allow-none): a cursor
+ *
+ * Sets the default mouse pointer for a #GdkSurface.
+ *
+ * Note that @cursor must be for the same display as @window.
+ *
+ * Use gdk_cursor_new_for_display() or gdk_cursor_new_from_texture() to
+ * create the cursor. To make the cursor invisible, use %GDK_BLANK_CURSOR.
+ * Passing %NULL for the @cursor argument to gdk_surface_set_cursor() means
+ * that @window will use the cursor of its parent window. Most windows
+ * should use this default.
+ */
+void
+gdk_surface_set_cursor (GdkSurface *window,
+                      GdkCursor *cursor)
+{
+  GdkDisplay *display;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  display = gdk_surface_get_display (window);
+
+  if (window->cursor)
+    {
+      g_object_unref (window->cursor);
+      window->cursor = NULL;
+    }
+
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      GdkDevice *device;
+      GList *seats, *s;
+
+      if (cursor)
+       window->cursor = g_object_ref (cursor);
+
+      seats = gdk_display_list_seats (display);
+
+      for (s = seats; s; s = s->next)
+        {
+          GList *devices, *d;
+
+          device = gdk_seat_get_pointer (s->data);
+          gdk_surface_set_cursor_internal (window, device, window->cursor);
+
+          devices = gdk_seat_get_slaves (s->data, GDK_SEAT_CAPABILITY_TABLET_STYLUS);
+          for (d = devices; d; d = d->next)
+            {
+              device = gdk_device_get_associated_device (d->data);
+              gdk_surface_set_cursor_internal (window, device, window->cursor);
+            }
+          g_list_free (devices);
+        }
+
+      g_list_free (seats);
+      g_object_notify_by_pspec (G_OBJECT (window), properties[PROP_CURSOR]);
+    }
+}
+
+/**
+ * gdk_surface_get_device_cursor:
+ * @window: a #GdkSurface.
+ * @device: a master, pointer #GdkDevice.
+ *
+ * Retrieves a #GdkCursor pointer for the @device currently set on the
+ * specified #GdkSurface, or %NULL.  If the return value is %NULL then
+ * there is no custom cursor set on the specified window, and it is
+ * using the cursor for its parent window.
+ *
+ * Returns: (nullable) (transfer none): a #GdkCursor, or %NULL. The
+ *   returned object is owned by the #GdkSurface and should not be
+ *   unreferenced directly. Use gdk_surface_set_cursor() to unset the
+ *   cursor of the window
+ **/
+GdkCursor *
+gdk_surface_get_device_cursor (GdkSurface *window,
+                              GdkDevice *device)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
+  g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
+  g_return_val_if_fail (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER, NULL);
+
+  return g_hash_table_lookup (window->device_cursor, device);
+}
+
+/**
+ * gdk_surface_set_device_cursor:
+ * @window: a #GdkSurface
+ * @device: a master, pointer #GdkDevice
+ * @cursor: a #GdkCursor
+ *
+ * Sets a specific #GdkCursor for a given device when it gets inside @window.
+ * Use gdk_cursor_new_for_display() or gdk_cursor_new_from_texture() to create
+ * the cursor. To make the cursor invisible, use %GDK_BLANK_CURSOR. Passing
+ * %NULL for the @cursor argument to gdk_surface_set_cursor() means that
+ * @window will use the cursor of its parent window. Most windows should
+ * use this default.
+ **/
+void
+gdk_surface_set_device_cursor (GdkSurface *window,
+                              GdkDevice *device,
+                              GdkCursor *cursor)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (GDK_IS_DEVICE (device));
+  g_return_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD);
+  g_return_if_fail (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER);
+
+  if (!cursor)
+    g_hash_table_remove (window->device_cursor, device);
+  else
+    g_hash_table_replace (window->device_cursor, device, g_object_ref (cursor));
+
+  gdk_surface_set_cursor_internal (window, device, cursor);
+}
+
+/**
+ * gdk_surface_get_geometry:
+ * @window: a #GdkSurface
+ * @x: (out) (allow-none): return location for X coordinate of window (relative to its parent)
+ * @y: (out) (allow-none): return location for Y coordinate of window (relative to its parent)
+ * @width: (out) (allow-none): return location for width of window
+ * @height: (out) (allow-none): return location for height of window
+ *
+ * Any of the return location arguments to this function may be %NULL,
+ * if you aren’t interested in getting the value of that field.
+ *
+ * The X and Y coordinates returned are relative to the parent window
+ * of @window, which for toplevels usually means relative to the
+ * window decorations (titlebar, etc.) rather than relative to the
+ * root window (screen-size background window).
+ *
+ * On the X11 platform, the geometry is obtained from the X server,
+ * so reflects the latest position of @window; this may be out-of-sync
+ * with the position of @window delivered in the most-recently-processed
+ * #GdkEventConfigure. gdk_surface_get_position() in contrast gets the
+ * position from the most recent configure event.
+ *
+ * Note: If @window is not a toplevel, it is much better
+ * to call gdk_surface_get_position(), gdk_surface_get_width() and
+ * gdk_surface_get_height() instead, because it avoids the roundtrip to
+ * the X server and because these functions support the full 32-bit
+ * coordinate space, whereas gdk_surface_get_geometry() is restricted to
+ * the 16-bit coordinates of X11.
+ */
+void
+gdk_surface_get_geometry (GdkSurface *window,
+                        gint      *x,
+                        gint      *y,
+                        gint      *width,
+                        gint      *height)
+{
+  GdkSurface *parent;
+  GdkSurfaceImplClass *impl_class;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      if (gdk_surface_has_impl (window))
+       {
+         impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+         impl_class->get_geometry (window, x, y,
+                                   width, height);
+         /* This reports the position wrt to the native parent, we need to convert
+            it to be relative to the client side parent */
+         parent = window->parent;
+         if (parent && !gdk_surface_has_impl (parent))
+           {
+             if (x)
+               *x -= parent->abs_x;
+             if (y)
+               *y -= parent->abs_y;
+           }
+       }
+      else
+       {
+          if (x)
+            *x = window->x;
+          if (y)
+            *y = window->y;
+         if (width)
+           *width = window->width;
+         if (height)
+           *height = window->height;
+       }
+    }
+}
+
+/**
+ * gdk_surface_get_width:
+ * @window: a #GdkSurface
+ *
+ * Returns the width of the given @window.
+ *
+ * On the X11 platform the returned size is the size reported in the
+ * most-recently-processed configure event, rather than the current
+ * size on the X server.
+ *
+ * Returns: The width of @window
+ */
+int
+gdk_surface_get_width (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
+
+  return window->width;
+}
+
+/**
+ * gdk_surface_get_height:
+ * @window: a #GdkSurface
+ *
+ * Returns the height of the given @window.
+ *
+ * On the X11 platform the returned size is the size reported in the
+ * most-recently-processed configure event, rather than the current
+ * size on the X server.
+ *
+ * Returns: The height of @window
+ */
+int
+gdk_surface_get_height (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
+
+  return window->height;
+}
+
+/**
+ * gdk_surface_get_origin:
+ * @window: a #GdkSurface
+ * @x: (out) (allow-none): return location for X coordinate
+ * @y: (out) (allow-none): return location for Y coordinate
+ *
+ * Obtains the position of a window in root window coordinates.
+ * (Compare with gdk_surface_get_position() and
+ * gdk_surface_get_geometry() which return the position of a window
+ * relative to its parent window.)
+ *
+ * Returns: not meaningful, ignore
+ */
+gint
+gdk_surface_get_origin (GdkSurface *window,
+                      gint      *x,
+                      gint      *y)
+{
+  gint dummy_x, dummy_y;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
+
+  gdk_surface_get_root_coords (window,
+                              0, 0,
+                              x ? x : &dummy_x,
+                              y ? y : &dummy_y);
+
+  return TRUE;
+}
+
+/**
+ * gdk_surface_get_root_coords:
+ * @window: a #GdkSurface
+ * @x: X coordinate in window
+ * @y: Y coordinate in window
+ * @root_x: (out): return location for X coordinate
+ * @root_y: (out): return location for Y coordinate
+ *
+ * Obtains the position of a window position in root
+ * window coordinates. This is similar to
+ * gdk_surface_get_origin() but allows you to pass
+ * in any position in the window, not just the origin.
+ */
+void
+gdk_surface_get_root_coords (GdkSurface *window,
+                           gint       x,
+                           gint       y,
+                           gint      *root_x,
+                           gint      *root_y)
+{
+  GdkSurfaceImplClass *impl_class;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    {
+      *root_x = 0;
+      *root_y = 0;
+      return;
+    }
+  
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+  impl_class->get_root_coords (window->impl_window,
+                              x + window->abs_x,
+                              y + window->abs_y,
+                              root_x, root_y);
+}
+
+/**
+ * gdk_surface_coords_to_parent:
+ * @window: a child window
+ * @x: X coordinate in child’s coordinate system
+ * @y: Y coordinate in child’s coordinate system
+ * @parent_x: (out) (allow-none): return location for X coordinate
+ * in parent’s coordinate system, or %NULL
+ * @parent_y: (out) (allow-none): return location for Y coordinate
+ * in parent’s coordinate system, or %NULL
+ *
+ * Transforms window coordinates from a child window to its parent
+ * window. Calling this function is equivalent to adding the return
+ * values of gdk_surface_get_position() to the child coordinates.
+ *
+ * See also: gdk_surface_coords_from_parent()
+ **/
+void
+gdk_surface_coords_to_parent (GdkSurface *window,
+                             gdouble    x,
+                             gdouble    y,
+                             gdouble   *parent_x,
+                             gdouble   *parent_y)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (parent_x)
+    *parent_x = x + window->x;
+
+  if (parent_y)
+    *parent_y = y + window->y;
+}
+
+/**
+ * gdk_surface_coords_from_parent:
+ * @window: a child window
+ * @parent_x: X coordinate in parent’s coordinate system
+ * @parent_y: Y coordinate in parent’s coordinate system
+ * @x: (out) (allow-none): return location for X coordinate in child’s coordinate system
+ * @y: (out) (allow-none): return location for Y coordinate in child’s coordinate system
+ *
+ * Transforms window coordinates from a parent window to a child
+ * window.
+ *
+ * Calling this function is equivalent to subtracting the return
+ * values of gdk_surface_get_position() from the parent coordinates.
+ *
+ * See also: gdk_surface_coords_to_parent()
+ **/
+void
+gdk_surface_coords_from_parent (GdkSurface *window,
+                               gdouble    parent_x,
+                               gdouble    parent_y,
+                               gdouble   *x,
+                               gdouble   *y)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (x)
+    *x = parent_x - window->x;
+
+  if (y)
+    *y = parent_y - window->y;
+}
+
+/**
+ * gdk_surface_shape_combine_region:
+ * @window: a #GdkSurface
+ * @shape_region: (allow-none): region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ *
+ * Makes pixels in @window outside @shape_region be transparent,
+ * so that the window may be nonrectangular.
+ *
+ * If @shape_region is %NULL, the shape will be unset, so the whole
+ * window will be opaque again. @offset_x and @offset_y are ignored
+ * if @shape_region is %NULL.
+ *
+ * On the X11 platform, this uses an X server extension which is
+ * widely available on most common platforms, but not available on
+ * very old X servers, and occasionally the implementation will be
+ * buggy. On servers without the shape extension, this function
+ * will do nothing.
+ *
+ * This function works on both toplevel and child windows.
+ */
+void
+gdk_surface_shape_combine_region (GdkSurface       *window,
+                                const cairo_region_t *shape_region,
+                                gint             offset_x,
+                                gint             offset_y)
+{
+  cairo_region_t *old_region, *new_region, *diff;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (!window->shape && shape_region == NULL)
+    return;
+
+  window->shaped = (shape_region != NULL);
+
+  if (window->shape)
+    cairo_region_destroy (window->shape);
+
+  old_region = NULL;
+  if (GDK_SURFACE_IS_MAPPED (window))
+    old_region = cairo_region_copy (window->clip_region);
+
+  if (shape_region)
+    {
+      window->shape = cairo_region_copy (shape_region);
+      cairo_region_translate (window->shape, offset_x, offset_y);
+    }
+  else
+    window->shape = NULL;
+
+  recompute_visible_regions (window, FALSE);
+
+  if (old_region)
+    {
+      new_region = cairo_region_copy (window->clip_region);
+
+      /* New area in the window, needs invalidation */
+      diff = cairo_region_copy (new_region);
+      cairo_region_subtract (diff, old_region);
+
+      gdk_surface_invalidate_region_full (window, diff, TRUE);
+
+      cairo_region_destroy (diff);
+
+      if (!gdk_surface_is_toplevel (window))
+       {
+         /* New area in the non-root parent window, needs invalidation */
+         diff = cairo_region_copy (old_region);
+         cairo_region_subtract (diff, new_region);
+
+         /* Adjust region to parent window coords */
+         cairo_region_translate (diff, window->x, window->y);
+
+         gdk_surface_invalidate_region_full (window->parent, diff, TRUE);
+
+         cairo_region_destroy (diff);
+       }
+
+      cairo_region_destroy (new_region);
+      cairo_region_destroy (old_region);
+    }
+}
+
+static void
+do_child_shapes (GdkSurface *window,
+                gboolean merge)
+{
+  GdkRectangle r;
+  cairo_region_t *region;
+
+  r.x = 0;
+  r.y = 0;
+  r.width = window->width;
+  r.height = window->height;
+
+  region = cairo_region_create_rectangle (&r);
+  remove_child_area (window, FALSE, region);
+
+  if (merge && window->shape)
+    cairo_region_subtract (region, window->shape);
+
+  cairo_region_xor_rectangle (region, &r);
+
+  gdk_surface_shape_combine_region (window, region, 0, 0);
+
+  cairo_region_destroy (region);
+}
+
+/**
+ * gdk_surface_set_child_shapes:
+ * @window: a #GdkSurface
+ *
+ * Sets the shape mask of @window to the union of shape masks
+ * for all children of @window, ignoring the shape mask of @window
+ * itself. Contrast with gdk_surface_merge_child_shapes() which includes
+ * the shape mask of @window in the masks to be merged.
+ **/
+void
+gdk_surface_set_child_shapes (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  do_child_shapes (window, FALSE);
+}
+
+/**
+ * gdk_surface_merge_child_shapes:
+ * @window: a #GdkSurface
+ *
+ * Merges the shape masks for any child windows into the
+ * shape mask for @window. i.e. the union of all masks
+ * for @window and its children will become the new mask
+ * for @window. See gdk_surface_shape_combine_region().
+ *
+ * This function is distinct from gdk_surface_set_child_shapes()
+ * because it includes @window’s shape mask in the set of shapes to
+ * be merged.
+ */
+void
+gdk_surface_merge_child_shapes (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  do_child_shapes (window, TRUE);
+}
+
+/**
+ * gdk_surface_input_shape_combine_region:
+ * @window: a #GdkSurface
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ *
+ * Like gdk_surface_shape_combine_region(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the
+ * mask will be passed on the window below @window.
+ *
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * â€śclickable”.
+ *
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * On the Win32 platform, this functionality is not present and the
+ * function does nothing.
+ */
+void
+gdk_surface_input_shape_combine_region (GdkSurface       *window,
+                                      const cairo_region_t *shape_region,
+                                      gint             offset_x,
+                                      gint             offset_y)
+{
+  GdkSurfaceImplClass *impl_class;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (window->input_shape)
+    cairo_region_destroy (window->input_shape);
+
+  if (shape_region)
+    {
+      window->input_shape = cairo_region_copy (shape_region);
+      cairo_region_translate (window->input_shape, offset_x, offset_y);
+    }
+  else
+    window->input_shape = NULL;
+
+  if (gdk_surface_has_impl (window))
+    {
+      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+      impl_class->input_shape_combine_region (window, window->input_shape, 0, 0);
+    }
+}
+
+static void
+do_child_input_shapes (GdkSurface *window,
+                      gboolean merge)
+{
+  GdkRectangle r;
+  cairo_region_t *region;
+
+  r.x = 0;
+  r.y = 0;
+  r.width = window->width;
+  r.height = window->height;
+
+  region = cairo_region_create_rectangle (&r);
+  remove_child_area (window, TRUE, region);
+
+  if (merge && window->shape)
+    cairo_region_subtract (region, window->shape);
+  if (merge && window->input_shape)
+    cairo_region_subtract (region, window->input_shape);
+
+  cairo_region_xor_rectangle (region, &r);
+
+  gdk_surface_input_shape_combine_region (window, region, 0, 0);
+}
+
+
+/**
+ * gdk_surface_set_child_input_shapes:
+ * @window: a #GdkSurface
+ *
+ * Sets the input shape mask of @window to the union of input shape masks
+ * for all children of @window, ignoring the input shape mask of @window
+ * itself. Contrast with gdk_surface_merge_child_input_shapes() which includes
+ * the input shape mask of @window in the masks to be merged.
+ **/
+void
+gdk_surface_set_child_input_shapes (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  do_child_input_shapes (window, FALSE);
+}
+
+/**
+ * gdk_surface_set_pass_through:
+ * @window: a #GdkSurface
+ * @pass_through: a boolean
+ *
+ * Sets whether input to the window is passed through to the window
+ * below.
+ *
+ * The default value of this is %FALSE, which means that pointer
+ * events that happen inside the window are send first to the window,
+ * but if the event is not selected by the event mask then the event
+ * is sent to the parent window, and so on up the hierarchy.
+ *
+ * If @pass_through is %TRUE then such pointer events happen as if the
+ * window wasn't there at all, and thus will be sent first to any
+ * windows below @window. This is useful if the window is used in a
+ * transparent fashion. In the terminology of the web this would be called
+ * "pointer-events: none".
+ *
+ * Note that a window with @pass_through %TRUE can still have a subwindow
+ * without pass through, so you can get events on a subset of a window. And in
+ * that cases you would get the in-between related events such as the pointer
+ * enter/leave events on its way to the destination window.
+ **/
+void
+gdk_surface_set_pass_through (GdkSurface *window,
+                             gboolean   pass_through)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  window->pass_through = !!pass_through;
+}
+
+/**
+ * gdk_surface_get_pass_through:
+ * @window: a #GdkSurface
+ *
+ * Returns whether input to the window is passed through to the window
+ * below.
+ *
+ * See gdk_surface_set_pass_through() for details
+ **/
+gboolean
+gdk_surface_get_pass_through (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  return window->pass_through;
+}
+
+/**
+ * gdk_surface_merge_child_input_shapes:
+ * @window: a #GdkSurface
+ *
+ * Merges the input shape masks for any child windows into the
+ * input shape mask for @window. i.e. the union of all input masks
+ * for @window and its children will become the new input mask
+ * for @window. See gdk_surface_input_shape_combine_region().
+ *
+ * This function is distinct from gdk_surface_set_child_input_shapes()
+ * because it includes @window’s input shape mask in the set of
+ * shapes to be merged.
+ **/
+void
+gdk_surface_merge_child_input_shapes (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  do_child_input_shapes (window, TRUE);
+}
+
+
+/**
+ * gdk_surface_get_modal_hint:
+ * @window: A toplevel #GdkSurface.
+ *
+ * Determines whether or not the window manager is hinted that @window
+ * has modal behaviour.
+ *
+ * Returns: whether or not the window has the modal hint set.
+ */
+gboolean
+gdk_surface_get_modal_hint (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  return window->modal_hint;
+}
+
+/**
+ * gdk_surface_get_accept_focus:
+ * @window: a toplevel #GdkSurface.
+ *
+ * Determines whether or not the desktop environment shuld be hinted that
+ * the window does not want to receive input focus.
+ *
+ * Returns: whether or not the window should receive input focus.
+ */
+gboolean
+gdk_surface_get_accept_focus (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  return window->accept_focus;
+}
+
+/**
+ * gdk_surface_get_focus_on_map:
+ * @window: a toplevel #GdkSurface.
+ *
+ * Determines whether or not the desktop environment should be hinted that the
+ * window does not want to receive input focus when it is mapped.
+ *
+ * Returns: whether or not the window wants to receive input focus when
+ * it is mapped.
+ */
+gboolean
+gdk_surface_get_focus_on_map (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  return window->focus_on_map;
+}
+
+/**
+ * gdk_surface_is_input_only:
+ * @window: a toplevel #GdkSurface
+ *
+ * Determines whether or not the window is an input only window.
+ *
+ * Returns: %TRUE if @window is input only
+ */
+gboolean
+gdk_surface_is_input_only (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  return window->input_only;
+}
+
+/**
+ * gdk_surface_is_shaped:
+ * @window: a toplevel #GdkSurface
+ *
+ * Determines whether or not the window is shaped.
+ *
+ * Returns: %TRUE if @window is shaped
+ */
+gboolean
+gdk_surface_is_shaped (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  return window->shaped;
+}
+
+/* Gets the toplevel for a window as used for events,
+   i.e. including offscreen parents going up to the native
+   toplevel */
+static GdkSurface *
+get_event_toplevel (GdkSurface *window)
+{
+  GdkSurface *parent;
+
+  while ((parent = window->parent) != NULL &&
+        (parent->window_type != GDK_SURFACE_ROOT))
+    window = parent;
+
+  return window;
+}
+
+gboolean
+_gdk_surface_event_parent_of (GdkSurface *parent,
+                            GdkSurface *child)
+{
+  GdkSurface *w;
+
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+       return TRUE;
+
+      w = w->parent;
+    }
+
+  return FALSE;
+}
+
+static void
+update_cursor (GdkDisplay *display,
+               GdkDevice  *device)
+{
+  GdkSurface *cursor_window, *parent, *toplevel;
+  GdkSurface *pointer_window;
+  GdkPointerSurfaceInfo *pointer_info;
+  GdkDeviceGrabInfo *grab;
+  GdkCursor *cursor;
+
+  pointer_info = _gdk_display_get_pointer_info (display, device);
+  pointer_window = pointer_info->window_under_pointer;
+
+  /* We ignore the serials here and just pick the last grab
+     we've sent, as that would shortly be used anyway. */
+  grab = _gdk_display_get_last_device_grab (display, device);
+  if (/* have grab */
+      grab != NULL &&
+      /* the pointer is not in a descendant of the grab window */
+      !_gdk_surface_event_parent_of (grab->window, pointer_window))
+    {
+      /* use the cursor from the grab window */
+      cursor_window = grab->window;
+    }
+  else
+    {
+      /* otherwise use the cursor from the pointer window */
+      cursor_window = pointer_window;
+    }
+
+  /* Find the first window with the cursor actually set, as
+     the cursor is inherited from the parent */
+  while (cursor_window->cursor == NULL &&
+         !g_hash_table_contains (cursor_window->device_cursor, device) &&
+        (parent = cursor_window->parent) != NULL &&
+        parent->window_type != GDK_SURFACE_ROOT)
+    cursor_window = parent;
+
+  cursor = g_hash_table_lookup (cursor_window->device_cursor, device);
+
+  if (!cursor)
+    cursor = cursor_window->cursor;
+
+  /* Set all cursors on toplevel, otherwise its tricky to keep track of
+   * which native window has what cursor set. */
+  toplevel = get_event_toplevel (pointer_window);
+  GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, toplevel, cursor);
+}
+
+static gboolean
+point_in_window (GdkSurface *window,
+                gdouble    x,
+                 gdouble    y)
+{
+  return
+    x >= 0 && x < window->width &&
+    y >= 0 && y < window->height &&
+    (window->shape == NULL ||
+     cairo_region_contains_point (window->shape,
+                         x, y)) &&
+    (window->input_shape == NULL ||
+     cairo_region_contains_point (window->input_shape,
+                         x, y));
+}
+
+/* Same as point_in_window, except it also takes pass_through and its
+   interaction with child windows into account */
+static gboolean
+point_in_input_window (GdkSurface *window,
+                      gdouble    x,
+                      gdouble    y,
+                      GdkSurface **input_window,
+                      gdouble   *input_window_x,
+                      gdouble   *input_window_y)
+{
+  GdkSurface *sub;
+  double child_x, child_y;
+  GList *l;
+
+  if (!point_in_window (window, x, y))
+    return FALSE;
+
+  if (!window->pass_through)
+    {
+      if (input_window)
+       {
+         *input_window = window;
+         *input_window_x = x;
+         *input_window_y = y;
+       }
+      return TRUE;
+    }
+
+  /* For pass-through, must be over a child input window */
+
+  /* Children is ordered in reverse stack order, i.e. first is topmost */
+  for (l = window->children; l != NULL; l = l->next)
+    {
+      sub = l->data;
+
+      if (!GDK_SURFACE_IS_MAPPED (sub))
+       continue;
+
+      gdk_surface_coords_from_parent ((GdkSurface *)sub,
+                                    x, y,
+                                    &child_x, &child_y);
+      if (point_in_input_window (sub, child_x, child_y,
+                                input_window, input_window_x, input_window_y))
+       {
+         if (input_window)
+           gdk_surface_coords_to_parent (sub,
+                                        *input_window_x,
+                                        *input_window_y,
+                                        input_window_x,
+                                        input_window_y);
+         return TRUE;
+       }
+    }
+
+  return FALSE;
+}
+
+GdkSurface *
+_gdk_surface_find_child_at (GdkSurface *window,
+                          double     x,
+                           double     y)
+{
+  GdkSurface *sub;
+  double child_x, child_y;
+  GList *l;
+
+  if (point_in_window (window, x, y))
+    {
+      /* Children is ordered in reverse stack order, i.e. first is topmost */
+      for (l = window->children; l != NULL; l = l->next)
+       {
+         sub = l->data;
+
+         if (!GDK_SURFACE_IS_MAPPED (sub))
+           continue;
+
+         gdk_surface_coords_from_parent ((GdkSurface *)sub,
+                                         x, y,
+                                         &child_x, &child_y);
+         if (point_in_input_window (sub, child_x, child_y,
+                                    NULL, NULL, NULL))
+           return (GdkSurface *)sub;
+       }
+    }
+
+  return NULL;
+}
+
+GdkSurface *
+_gdk_surface_find_descendant_at (GdkSurface *window,
+                               gdouble    x,
+                                gdouble    y,
+                               gdouble   *found_x,
+                               gdouble   *found_y)
+{
+  GdkSurface *sub, *input_window;
+  gdouble child_x, child_y;
+  GList *l;
+  gboolean found;
+
+  if (point_in_window (window, x, y))
+    {
+      do
+       {
+         found = FALSE;
+         /* Children is ordered in reverse stack order, i.e. first is topmost */
+         for (l = window->children; l != NULL; l = l->next)
+           {
+             sub = l->data;
+
+             if (!GDK_SURFACE_IS_MAPPED (sub))
+               continue;
+
+             gdk_surface_coords_from_parent ((GdkSurface *)sub,
+                                             x, y,
+                                             &child_x, &child_y);
+             if (point_in_input_window (sub, child_x, child_y,
+                                        &input_window, &child_x, &child_y))
+               {
+                 x = child_x;
+                 y = child_y;
+                 window = input_window;
+                 found = TRUE;
+                 break;
+               }
+           }
+       }
+      while (found);
+    }
+  else
+    {
+      /* Not in window at all */
+      window = NULL;
+    }
+
+  if (found_x)
+    *found_x = x;
+  if (found_y)
+    *found_y = y;
+
+  return window;
+}
+
+/**
+ * gdk_surface_beep:
+ * @window: a toplevel #GdkSurface
+ *
+ * Emits a short beep associated to @window in the appropriate
+ * display, if supported. Otherwise, emits a short beep on
+ * the display just as gdk_display_beep().
+ **/
+void
+gdk_surface_beep (GdkSurface *window)
+{
+  GdkDisplay *display;
+  GdkSurface *toplevel;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  toplevel = get_event_toplevel (window);
+  display = gdk_surface_get_display (window);
+
+  if (toplevel)
+    {
+      if (GDK_SURFACE_IMPL_GET_CLASS (toplevel->impl)->beep (toplevel))
+        return;
+    }
+  
+  /* If windows fail to beep, we beep the display. */
+  gdk_display_beep (display);
+}
+
+/**
+ * gdk_surface_set_support_multidevice:
+ * @window: a #GdkSurface.
+ * @support_multidevice: %TRUE to enable multidevice support in @window.
+ *
+ * This function will enable multidevice features in @window.
+ *
+ * Multidevice aware windows will need to handle properly multiple,
+ * per device enter/leave events, device grabs and grab ownerships.
+ **/
+void
+gdk_surface_set_support_multidevice (GdkSurface *window,
+                                    gboolean   support_multidevice)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (window->support_multidevice == support_multidevice)
+    return;
+
+  window->support_multidevice = support_multidevice;
+
+  /* FIXME: What to do if called when some pointers are inside the window ? */
+}
+
+/**
+ * gdk_surface_get_support_multidevice:
+ * @window: a #GdkSurface.
+ *
+ * Returns %TRUE if the window is aware of the existence of multiple
+ * devices.
+ *
+ * Returns: %TRUE if the window handles multidevice features.
+ **/
+gboolean
+gdk_surface_get_support_multidevice (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return FALSE;
+
+  return window->support_multidevice;
+}
+
+/* send motion events if the right buttons are down */
+
+GdkEvent *
+_gdk_make_event (GdkSurface    *window,
+                GdkEventType  type,
+                GdkEvent     *event_in_queue,
+                gboolean      before_event)
+{
+  GdkEvent *event = gdk_event_new (type);
+  guint32 the_time;
+  GdkModifierType the_state;
+
+  the_time = gdk_event_get_time (event_in_queue);
+  gdk_event_get_state (event_in_queue, &the_state);
+
+  event->any.window = g_object_ref (window);
+  event->any.send_event = FALSE;
+  if (event_in_queue && event_in_queue->any.send_event)
+    event->any.send_event = TRUE;
+
+  switch ((guint) type)
+    {
+    case GDK_MOTION_NOTIFY:
+      event->motion.time = the_time;
+      event->motion.axes = NULL;
+      event->motion.state = the_state;
+      break;
+
+    case GDK_BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+      event->button.time = the_time;
+      event->button.axes = NULL;
+      event->button.state = the_state;
+      break;
+
+    case GDK_TOUCH_BEGIN:
+    case GDK_TOUCH_UPDATE:
+    case GDK_TOUCH_END:
+    case GDK_TOUCH_CANCEL:
+      event->touch.time = the_time;
+      event->touch.axes = NULL;
+      event->touch.state = the_state;
+      break;
+
+    case GDK_SCROLL:
+      event->scroll.time = the_time;
+      event->scroll.state = the_state;
+      break;
+
+    case GDK_KEY_PRESS:
+    case GDK_KEY_RELEASE:
+      event->key.time = the_time;
+      event->key.state = the_state;
+      break;
+
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      event->crossing.time = the_time;
+      event->crossing.state = the_state;
+      break;
+
+    case GDK_PROXIMITY_IN:
+    case GDK_PROXIMITY_OUT:
+      event->proximity.time = the_time;
+      break;
+
+    case GDK_DRAG_ENTER:
+    case GDK_DRAG_LEAVE:
+    case GDK_DRAG_MOTION:
+    case GDK_DROP_START:
+      event->dnd.time = the_time;
+      break;
+
+    case GDK_TOUCHPAD_SWIPE:
+      event->touchpad_swipe.time = the_time;
+      event->touchpad_swipe.state = the_state;
+      break;
+
+    case GDK_TOUCHPAD_PINCH:
+      event->touchpad_pinch.time = the_time;
+      event->touchpad_pinch.state = the_state;
+      break;
+
+    case GDK_FOCUS_CHANGE:
+    case GDK_CONFIGURE:
+    case GDK_MAP:
+    case GDK_UNMAP:
+    case GDK_DELETE:
+    case GDK_DESTROY:
+    case GDK_EXPOSE:
+    default:
+      break;
+    }
+
+  if (event_in_queue)
+    {
+    if (before_event)
+      _gdk_event_queue_insert_before (gdk_surface_get_display (window), event_in_queue, event);
+    else
+      _gdk_event_queue_insert_after (gdk_surface_get_display (window), event_in_queue, event);
+    }
+  else
+    _gdk_event_queue_append (gdk_surface_get_display (window), event);
+
+  return event;
+}
+
+void
+_gdk_display_set_window_under_pointer (GdkDisplay *display,
+                                       GdkDevice  *device,
+                                      GdkSurface  *window)
+{
+  GdkPointerSurfaceInfo *device_info;
+
+  device_info = _gdk_display_get_pointer_info (display, device);
+
+  if (device_info->window_under_pointer)
+    g_object_unref (device_info->window_under_pointer);
+  device_info->window_under_pointer = window;
+
+  if (window)
+    {
+      g_object_ref (window);
+      update_cursor (display, device);
+    }
+}
+
+#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
+                            GDK_BUTTON2_MASK | \
+                            GDK_BUTTON3_MASK | \
+                            GDK_BUTTON4_MASK | \
+                            GDK_BUTTON5_MASK)
+
+#ifdef DEBUG_WINDOW_PRINTING
+
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h"
+#endif
+
+static void
+gdk_surface_print (GdkSurface *window,
+                 int indent)
+{
+  char *s;
+  const char *window_types[] = {
+    "root",
+    "toplevel",
+    "child",
+    "dialog",
+    "temp",
+    "foreign",
+    "subsurface"
+  };
+
+  g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
+          window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
+          window->x, window->y,
+          window->width, window->height
+          );
+
+  if (gdk_surface_has_impl (window))
+    {
+#ifdef GDK_WINDOWING_X11
+      g_print (" impl(0x%lx)", gdk_x11_surface_get_xid (window));
+#endif
+    }
+
+  if (window->window_type != GDK_SURFACE_CHILD)
+    g_print (" %s", window_types[window->window_type]);
+
+  if (window->input_only)
+    g_print (" input-only");
+
+  if (window->shaped)
+    g_print (" shaped");
+
+  if (!gdk_surface_is_visible ((GdkSurface *)window))
+    g_print (" hidden");
+
+  g_print (" abs[%d,%d]",
+          window->abs_x, window->abs_y);
+
+  if (window->alpha != 255)
+    g_print (" alpha[%d]",
+          window->alpha);
+
+  s = print_region (window->clip_region);
+  g_print (" clipbox[%s]", s);
+
+  g_print ("\n");
+}
+
+
+static void
+gdk_surface_print_tree (GdkSurface *window,
+                      int indent,
+                      gboolean include_input_only)
+{
+  GList *l;
+
+  if (window->input_only && !include_input_only)
+    return;
+
+  gdk_surface_print (window, indent);
+
+  for (l = window->children; l != NULL; l = l->next)
+    gdk_surface_print_tree (l->data, indent + 4, include_input_only);
+}
+
+#endif /* DEBUG_WINDOW_PRINTING */
+
+void
+_gdk_windowing_got_event (GdkDisplay *display,
+                          GList      *event_link,
+                          GdkEvent   *event,
+                          gulong      serial)
+{
+  GdkSurface *event_window;
+  gboolean unlink_event = FALSE;
+  GdkDeviceGrabInfo *button_release_grab;
+  GdkPointerSurfaceInfo *pointer_info = NULL;
+  GdkDevice *device, *source_device;
+
+  _gdk_display_update_last_event (display, event);
+
+  device = gdk_event_get_device (event);
+  source_device = gdk_event_get_source_device (event);
+
+  if (device)
+    {
+      if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD &&
+          gdk_device_get_source (device) != GDK_SOURCE_TABLET_PAD)
+        {
+          pointer_info = _gdk_display_get_pointer_info (display, device);
+
+          if (source_device != pointer_info->last_slave &&
+              gdk_device_get_device_type (source_device) == GDK_DEVICE_TYPE_SLAVE)
+            pointer_info->last_slave = source_device;
+          else if (pointer_info->last_slave)
+            source_device = pointer_info->last_slave;
+        }
+
+      _gdk_display_device_grab_update (display, device, source_device, serial);
+
+      if (gdk_device_get_input_mode (device) == GDK_MODE_DISABLED ||
+          !_gdk_display_check_grab_ownership (display, device, serial))
+        {
+          /* Device events are blocked by another
+           * device grab, or the device is disabled
+           */
+          unlink_event = TRUE;
+          goto out;
+        }
+    }
+
+  event_window = event->any.window;
+  if (!event_window)
+    goto out;
+
+#ifdef DEBUG_WINDOW_PRINTING
+  if (event->any.type == GDK_KEY_PRESS &&
+      (event->key.keyval == 0xa7 ||
+       event->key.keyval == 0xbd))
+    {
+      gdk_surface_print_tree (event_window, 0, event->key.keyval == 0xbd);
+    }
+#endif
+
+  if (event_window->window_type == GDK_SURFACE_ROOT)
+    goto out;
+
+  if (event->any.type == GDK_ENTER_NOTIFY)
+    _gdk_display_set_window_under_pointer (display, device, event_window);
+  else if (event->any.type == GDK_LEAVE_NOTIFY)
+    _gdk_display_set_window_under_pointer (display, device, NULL);
+
+  if ((event->any.type == GDK_BUTTON_RELEASE ||
+       event->any.type == GDK_TOUCH_CANCEL ||
+       event->any.type == GDK_TOUCH_END) &&
+      !event->any.send_event)
+    {
+      if (event->any.type == GDK_BUTTON_RELEASE ||
+          gdk_event_get_pointer_emulated (event))
+        {
+          button_release_grab =
+            _gdk_display_has_device_grab (display, device, serial);
+
+          if (button_release_grab &&
+              button_release_grab->implicit &&
+              (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
+            {
+              button_release_grab->serial_end = serial;
+              button_release_grab->implicit_ungrab = FALSE;
+              _gdk_display_device_grab_update (display, device, source_device, serial);
+            }
+        }
+    }
+
+ out:
+  if (unlink_event)
+    {
+      _gdk_event_queue_remove_link (display, event_link);
+      g_list_free_1 (event_link);
+      gdk_event_free (event);
+    }
+
+  /* This does two things - first it sees if there are motions at the
+   * end of the queue that can be compressed. Second, if there is just
+   * a single motion that won't be dispatched because it is a compression
+   * candidate it queues up flushing the event queue.
+   */
+  _gdk_event_queue_handle_motion_compression (display);
+}
+
+/**
+ * gdk_surface_create_similar_surface:
+ * @window: window to make new surface similar to
+ * @content: the content for the new surface
+ * @width: width of the new surface
+ * @height: height of the new surface
+ *
+ * Create a new surface that is as compatible as possible with the
+ * given @window. For example the new surface will have the same
+ * fallback resolution and font options as @window. Generally, the new
+ * surface will also use the same backend as @window, unless that is
+ * not possible for some reason. The type of the returned surface may
+ * be examined with cairo_surface_get_type().
+ *
+ * Initially the surface contents are all 0 (transparent if contents
+ * have transparency, black otherwise.)
+ *
+ * Returns: a pointer to the newly allocated surface. The caller
+ * owns the surface and should call cairo_surface_destroy() when done
+ * with it.
+ *
+ * This function always returns a valid pointer, but it will return a
+ * pointer to a â€śnil” surface if @other is already in an error state
+ * or any other error occurs.
+ **/
+cairo_surface_t *
+gdk_surface_create_similar_surface (GdkSurface *     window,
+                                   cairo_content_t content,
+                                   int             width,
+                                   int             height)
+{
+  cairo_surface_t *window_surface, *surface;
+  double sx, sy;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  window_surface = gdk_surface_ref_impl_surface (window);
+  sx = sy = 1;
+  cairo_surface_get_device_scale (window_surface, &sx, &sy);
+
+  if (GDK_DISPLAY_DEBUG_CHECK (window->display, CAIRO_IMAGE))
+    {
+      surface = cairo_image_surface_create (content == CAIRO_CONTENT_COLOR ? CAIRO_FORMAT_RGB24 :
+                                            content == CAIRO_CONTENT_ALPHA ? CAIRO_FORMAT_A8 : CAIRO_FORMAT_ARGB32,
+                                            width * sx, height * sy);
+      cairo_surface_set_device_scale (surface, sx, sy);
+    }
+  else
+    {
+      surface = cairo_surface_create_similar (window_surface,
+                                              content,
+                                              width, height);
+    }
+
+  cairo_surface_destroy (window_surface);
+
+  return surface;
+}
+
+
+/**
+ * gdk_surface_create_similar_image_surface:
+ * @window: (nullable): window to make new surface similar to, or
+ *   %NULL if none
+ * @format: (type int): the format for the new surface
+ * @width: width of the new surface
+ * @height: height of the new surface
+ * @scale: the scale of the new surface, or 0 to use same as @window
+ *
+ * Create a new image surface that is efficient to draw on the
+ * given @window.
+ *
+ * Initially the surface contents are all 0 (transparent if contents
+ * have transparency, black otherwise.)
+ *
+ * The @width and @height of the new surface are not affected by
+ * the scaling factor of the @window, or by the @scale argument; they
+ * are the size of the surface in device pixels. If you wish to create
+ * an image surface capable of holding the contents of @window you can
+ * use:
+ *
+ * |[<!-- language="C" -->
+ *   int scale = gdk_surface_get_scale_factor (window);
+ *   int width = gdk_surface_get_width (window) * scale;
+ *   int height = gdk_surface_get_height (window) * scale;
+ *
+ *   // format is set elsewhere
+ *   cairo_surface_t *surface =
+ *     gdk_surface_create_similar_image_surface (window,
+ *                                              format,
+ *                                              width, height,
+ *                                              scale);
+ * ]|
+ *
+ * Note that unlike cairo_surface_create_similar_image(), the new
+ * surface's device scale is set to @scale, or to the scale factor of
+ * @window if @scale is 0.
+ *
+ * Returns: a pointer to the newly allocated surface. The caller
+ * owns the surface and should call cairo_surface_destroy() when done
+ * with it.
+ *
+ * This function always returns a valid pointer, but it will return a
+ * pointer to a â€śnil” surface if @other is already in an error state
+ * or any other error occurs.
+ **/
+cairo_surface_t *
+gdk_surface_create_similar_image_surface (GdkSurface *     window,
+                                        cairo_format_t  format,
+                                        int             width,
+                                        int             height,
+                                        int             scale)
+{
+  cairo_surface_t *surface;
+
+  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), NULL);
+
+  if (window == NULL)
+    {
+      surface = cairo_image_surface_create (format, width, height);
+    }
+  else if (GDK_SURFACE_IMPL_GET_CLASS (window->impl)->create_similar_image_surface)
+    {
+      surface =
+        GDK_SURFACE_IMPL_GET_CLASS (window->impl)->create_similar_image_surface (window, format, width, height);
+    }
+  else
+    {
+      cairo_surface_t *window_surface;
+
+      window_surface = gdk_surface_ref_impl_surface (window);
+      surface =
+        cairo_surface_create_similar_image (window_surface,
+                                            format,
+                                            width,
+                                            height);
+      cairo_surface_destroy (window_surface);
+    }
+
+  if (scale == 0)
+    scale = gdk_surface_get_scale_factor (window);
+
+  cairo_surface_set_device_scale (surface, scale, scale);
+
+  return surface;
+}
+
+
+/**
+ * gdk_surface_focus:
+ * @window: a #GdkSurface
+ * @timestamp: timestamp of the event triggering the window focus
+ *
+ * Sets keyboard focus to @window. In most cases, gtk_window_present()
+ * should be used on a #GtkWindow, rather than calling this function.
+ *
+ **/
+void
+gdk_surface_focus (GdkSurface *window,
+                  guint32    timestamp)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->focus (window, timestamp);
+}
+
+/**
+ * gdk_surface_set_type_hint:
+ * @window: A toplevel #GdkSurface
+ * @hint: A hint of the function this window will have
+ *
+ * The application can use this call to provide a hint to the window
+ * manager about the functionality of a window. The window manager
+ * can use this information when determining the decoration and behaviour
+ * of the window.
+ *
+ * The hint must be set before the window is mapped.
+ **/
+void
+gdk_surface_set_type_hint (GdkSurface        *window,
+                         GdkSurfaceTypeHint hint)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_type_hint (window, hint);
+}
+
+/**
+ * gdk_surface_get_type_hint:
+ * @window: A toplevel #GdkSurface
+ *
+ * This function returns the type hint set for a window.
+ *
+ * Returns: The type hint set for @window
+ **/
+GdkSurfaceTypeHint
+gdk_surface_get_type_hint (GdkSurface *window)
+{
+  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->get_type_hint (window);
+}
+
+/**
+ * gdk_surface_set_modal_hint:
+ * @window: A toplevel #GdkSurface
+ * @modal: %TRUE if the window is modal, %FALSE otherwise.
+ *
+ * The application can use this hint to tell the window manager
+ * that a certain window has modal behaviour. The window manager
+ * can use this information to handle modal windows in a special
+ * way.
+ *
+ * You should only use this on windows for which you have
+ * previously called gdk_surface_set_transient_for()
+ **/
+void
+gdk_surface_set_modal_hint (GdkSurface *window,
+                          gboolean   modal)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_modal_hint (window, modal);
+}
+
+/**
+ * gdk_surface_set_skip_taskbar_hint:
+ * @window: a toplevel #GdkSurface
+ * @skips_taskbar: %TRUE to skip the taskbar
+ *
+ * Toggles whether a window should appear in a task list or window
+ * list. If a window’s semantic type as specified with
+ * gdk_surface_set_type_hint() already fully describes the window, this
+ * function should not be called in addition,
+ * instead you should allow the window to be treated according to
+ * standard policy for its semantic type.
+ **/
+void
+gdk_surface_set_skip_taskbar_hint (GdkSurface *window,
+                                  gboolean   skips_taskbar)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_skip_taskbar_hint (window, skips_taskbar);
+}
+
+/**
+ * gdk_surface_set_skip_pager_hint:
+ * @window: a toplevel #GdkSurface
+ * @skips_pager: %TRUE to skip the pager
+ *
+ * Toggles whether a window should appear in a pager (workspace
+ * switcher, or other desktop utility program that displays a small
+ * thumbnail representation of the windows on the desktop). If a
+ * window’s semantic type as specified with gdk_surface_set_type_hint()
+ * already fully describes the window, this function should
+ * not be called in addition, instead you should
+ * allow the window to be treated according to standard policy for
+ * its semantic type.
+ **/
+void
+gdk_surface_set_skip_pager_hint (GdkSurface *window,
+                                gboolean   skips_pager)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_skip_pager_hint (window, skips_pager);
+}
+
+/**
+ * gdk_surface_set_urgency_hint:
+ * @window: a toplevel #GdkSurface
+ * @urgent: %TRUE if the window is urgent
+ *
+ * Toggles whether a window needs the user's
+ * urgent attention.
+ **/
+void
+gdk_surface_set_urgency_hint (GdkSurface *window,
+                            gboolean   urgent)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_urgency_hint (window, urgent);
+}
+
+/**
+ * gdk_surface_set_geometry_hints:
+ * @window: a toplevel #GdkSurface
+ * @geometry: geometry hints
+ * @geom_mask: bitmask indicating fields of @geometry to pay attention to
+ *
+ * Sets the geometry hints for @window. Hints flagged in @geom_mask
+ * are set, hints not flagged in @geom_mask are unset.
+ * To unset all hints, use a @geom_mask of 0 and a @geometry of %NULL.
+ *
+ * This function provides hints to the windowing system about
+ * acceptable sizes for a toplevel window. The purpose of
+ * this is to constrain user resizing, but the windowing system
+ * will typically  (but is not required to) also constrain the
+ * current size of the window to the provided values and
+ * constrain programatic resizing via gdk_surface_resize() or
+ * gdk_surface_move_resize().
+ *
+ * Note that on X11, this effect has no effect on windows
+ * of type %GDK_SURFACE_TEMP since these windows are not resizable
+ * by the user.
+ *
+ * Since you can’t count on the windowing system doing the
+ * constraints for programmatic resizes, you should generally
+ * call gdk_surface_constrain_size() yourself to determine
+ * appropriate sizes.
+ *
+ **/
+void
+gdk_surface_set_geometry_hints (GdkSurface         *window,
+                              const GdkGeometry *geometry,
+                              GdkSurfaceHints     geom_mask)
+{
+  g_return_if_fail (geometry != NULL || geom_mask == 0);
+
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_geometry_hints (window, geometry, geom_mask);
+}
+
+/**
+ * gdk_surface_set_title:
+ * @window: a toplevel #GdkSurface
+ * @title: title of @window
+ *
+ * Sets the title of a toplevel window, to be displayed in the titlebar.
+ * If you haven’t explicitly set the icon name for the window
+ * (using gdk_surface_set_icon_name()), the icon name will be set to
+ * @title as well. @title must be in UTF-8 encoding (as with all
+ * user-readable strings in GDK/GTK+). @title may not be %NULL.
+ **/
+void
+gdk_surface_set_title (GdkSurface   *window,
+                     const gchar *title)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_title (window, title);
+}
+
+/**
+ * gdk_surface_set_role:
+ * @window: a toplevel #GdkSurface
+ * @role: a string indicating its role
+ *
+ * When using GTK+, typically you should use gtk_window_set_role() instead
+ * of this low-level function.
+ *
+ * The window manager and session manager use a window’s role to
+ * distinguish it from other kinds of window in the same application.
+ * When an application is restarted after being saved in a previous
+ * session, all windows with the same title and role are treated as
+ * interchangeable.  So if you have two windows with the same title
+ * that should be distinguished for session management purposes, you
+ * should set the role on those windows. It doesn’t matter what string
+ * you use for the role, as long as you have a different role for each
+ * non-interchangeable kind of window.
+ *
+ **/
+void
+gdk_surface_set_role (GdkSurface   *window,
+                    const gchar *role)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_role (window, role);
+}
+
+/**
+ * gdk_surface_set_startup_id:
+ * @window: a toplevel #GdkSurface
+ * @startup_id: a string with startup-notification identifier
+ *
+ * When using GTK+, typically you should use gtk_window_set_startup_id()
+ * instead of this low-level function.
+ **/
+void
+gdk_surface_set_startup_id (GdkSurface   *window,
+                          const gchar *startup_id)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_startup_id (window, startup_id);
+}
+
+/**
+ * gdk_surface_set_transient_for:
+ * @window: a toplevel #GdkSurface
+ * @parent: another toplevel #GdkSurface
+ *
+ * Indicates to the window manager that @window is a transient dialog
+ * associated with the application window @parent. This allows the
+ * window manager to do things like center @window on @parent and
+ * keep @window above @parent.
+ *
+ * See gtk_window_set_transient_for() if you’re using #GtkWindow or
+ * #GtkDialog.
+ **/
+void
+gdk_surface_set_transient_for (GdkSurface *window,
+                             GdkSurface *parent)
+{
+  window->transient_for = parent;
+
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_transient_for (window, parent);
+}
+
+/**
+ * gdk_surface_get_root_origin:
+ * @window: a toplevel #GdkSurface
+ * @x: (out): return location for X position of window frame
+ * @y: (out): return location for Y position of window frame
+ *
+ * Obtains the top-left corner of the window manager frame in root
+ * window coordinates.
+ *
+ **/
+void
+gdk_surface_get_root_origin (GdkSurface *window,
+                           gint      *x,
+                           gint      *y)
+{
+  GdkRectangle rect;
+
+  gdk_surface_get_frame_extents (window, &rect);
+
+  if (x)
+    *x = rect.x;
+
+  if (y)
+    *y = rect.y;
+}
+
+/**
+ * gdk_surface_get_frame_extents:
+ * @window: a toplevel #GdkSurface
+ * @rect: (out): rectangle to fill with bounding box of the window frame
+ *
+ * Obtains the bounding box of the window, including window manager
+ * titlebar/borders if any. The frame position is given in root window
+ * coordinates. To get the position of the window itself (rather than
+ * the frame) in root window coordinates, use gdk_surface_get_origin().
+ *
+ **/
+void
+gdk_surface_get_frame_extents (GdkSurface    *window,
+                              GdkRectangle *rect)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->get_frame_extents (window, rect);
+}
+
+/**
+ * gdk_surface_set_accept_focus:
+ * @window: a toplevel #GdkSurface
+ * @accept_focus: %TRUE if the window should receive input focus
+ *
+ * Setting @accept_focus to %FALSE hints the desktop environment that the
+ * window doesn’t want to receive input focus.
+ *
+ * On X, it is the responsibility of the window manager to interpret this
+ * hint. ICCCM-compliant window manager usually respect it.
+ **/
+void
+gdk_surface_set_accept_focus (GdkSurface *window,
+                            gboolean accept_focus)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_accept_focus (window, accept_focus);
+}
+
+/**
+ * gdk_surface_set_focus_on_map:
+ * @window: a toplevel #GdkSurface
+ * @focus_on_map: %TRUE if the window should receive input focus when mapped
+ *
+ * Setting @focus_on_map to %FALSE hints the desktop environment that the
+ * window doesn’t want to receive input focus when it is mapped.
+ * focus_on_map should be turned off for windows that aren’t triggered
+ * interactively (such as popups from network activity).
+ *
+ * On X, it is the responsibility of the window manager to interpret
+ * this hint. Window managers following the freedesktop.org window
+ * manager extension specification should respect it.
+ **/
+void
+gdk_surface_set_focus_on_map (GdkSurface *window,
+                            gboolean focus_on_map)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_focus_on_map (window, focus_on_map);
+}
+
+/**
+ * gdk_surface_set_icon_list:
+ * @window: The #GdkSurface toplevel window to set the icon of.
+ * @surfaces: (transfer none) (element-type GdkTexture):
+ *     A list of image surfaces, of different sizes.
+ *
+ * Sets a list of icons for the window. One of these will be used
+ * to represent the window when it has been iconified. The icon is
+ * usually shown in an icon box or some sort of task bar. Which icon
+ * size is shown depends on the window manager. The window manager
+ * can scale the icon  but setting several size icons can give better
+ * image quality since the window manager may only need to scale the
+ * icon by a small amount or not at all.
+ *
+ * Note that some platforms don't support window icons.
+ */
+void
+gdk_surface_set_icon_list (GdkSurface *window,
+                          GList     *textures)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_icon_list (window, textures);
+}
+
+/**
+ * gdk_surface_set_icon_name:
+ * @window: a toplevel #GdkSurface
+ * @name: (allow-none): name of window while iconified (minimized)
+ *
+ * Windows may have a name used while minimized, distinct from the
+ * name they display in their titlebar. Most of the time this is a bad
+ * idea from a user interface standpoint. But you can set such a name
+ * with this function, if you like.
+ *
+ * After calling this with a non-%NULL @name, calls to gdk_surface_set_title()
+ * will not update the icon title.
+ *
+ * Using %NULL for @name unsets the icon title; further calls to
+ * gdk_surface_set_title() will again update the icon title as well.
+ *
+ * Note that some platforms don't support window icons.
+ **/
+void
+gdk_surface_set_icon_name (GdkSurface   *window,
+                         const gchar *name)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_icon_name (window, name);
+}
+
+/**
+ * gdk_surface_iconify:
+ * @window: a toplevel #GdkSurface
+ *
+ * Asks to iconify (minimize) @window. The window manager may choose
+ * to ignore the request, but normally will honor it. Using
+ * gtk_window_iconify() is preferred, if you have a #GtkWindow widget.
+ *
+ * This function only makes sense when @window is a toplevel window.
+ *
+ **/
+void
+gdk_surface_iconify (GdkSurface *window)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->iconify (window);
+}
+
+/**
+ * gdk_surface_deiconify:
+ * @window: a toplevel #GdkSurface
+ *
+ * Attempt to deiconify (unminimize) @window. On X11 the window manager may
+ * choose to ignore the request to deiconify. When using GTK+,
+ * use gtk_window_deiconify() instead of the #GdkSurface variant. Or better yet,
+ * you probably want to use gtk_window_present(), which raises the window, focuses it,
+ * unminimizes it, and puts it on the current desktop.
+ *
+ **/
+void
+gdk_surface_deiconify (GdkSurface *window)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->deiconify (window);
+}
+
+/**
+ * gdk_surface_stick:
+ * @window: a toplevel #GdkSurface
+ *
+ * â€śPins” a window such that it’s on all workspaces and does not scroll
+ * with viewports, for window managers that have scrollable viewports.
+ * (When using #GtkWindow, gtk_window_stick() may be more useful.)
+ *
+ * On the X11 platform, this function depends on window manager
+ * support, so may have no effect with many window managers. However,
+ * GDK will do the best it can to convince the window manager to stick
+ * the window. For window managers that don’t support this operation,
+ * there’s nothing you can do to force it to happen.
+ *
+ **/
+void
+gdk_surface_stick (GdkSurface *window)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->stick (window);
+}
+
+/**
+ * gdk_surface_unstick:
+ * @window: a toplevel #GdkSurface
+ *
+ * Reverse operation for gdk_surface_stick(); see gdk_surface_stick(),
+ * and gtk_window_unstick().
+ *
+ **/
+void
+gdk_surface_unstick (GdkSurface *window)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->unstick (window);
+}
+
+/**
+ * gdk_surface_maximize:
+ * @window: a toplevel #GdkSurface
+ *
+ * Maximizes the window. If the window was already maximized, then
+ * this function does nothing.
+ *
+ * On X11, asks the window manager to maximize @window, if the window
+ * manager supports this operation. Not all window managers support
+ * this, and some deliberately ignore it or don’t have a concept of
+ * â€śmaximized”; so you can’t rely on the maximization actually
+ * happening. But it will happen with most standard window managers,
+ * and GDK makes a best effort to get it to happen.
+ *
+ * On Windows, reliably maximizes the window.
+ *
+ **/
+void
+gdk_surface_maximize (GdkSurface *window)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->maximize (window);
+}
+
+/**
+ * gdk_surface_unmaximize:
+ * @window: a toplevel #GdkSurface
+ *
+ * Unmaximizes the window. If the window wasn’t maximized, then this
+ * function does nothing.
+ *
+ * On X11, asks the window manager to unmaximize @window, if the
+ * window manager supports this operation. Not all window managers
+ * support this, and some deliberately ignore it or don’t have a
+ * concept of â€śmaximized”; so you can’t rely on the unmaximization
+ * actually happening. But it will happen with most standard window
+ * managers, and GDK makes a best effort to get it to happen.
+ *
+ * On Windows, reliably unmaximizes the window.
+ *
+ **/
+void
+gdk_surface_unmaximize (GdkSurface *window)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->unmaximize (window);
+}
+
+/**
+ * gdk_surface_fullscreen:
+ * @window: a toplevel #GdkSurface
+ *
+ * Moves the window into fullscreen mode. This means the
+ * window covers the entire screen and is above any panels
+ * or task bars.
+ *
+ * If the window was already fullscreen, then this function does nothing.
+ *
+ * On X11, asks the window manager to put @window in a fullscreen
+ * state, if the window manager supports this operation. Not all
+ * window managers support this, and some deliberately ignore it or
+ * don’t have a concept of â€śfullscreen”; so you can’t rely on the
+ * fullscreenification actually happening. But it will happen with
+ * most standard window managers, and GDK makes a best effort to get
+ * it to happen.
+ **/
+void
+gdk_surface_fullscreen (GdkSurface *window)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->fullscreen (window);
+}
+
+/**
+ * gdk_surface_fullscreen_on_monitor:
+ * @window: a toplevel #GdkSurface
+ * @monitor: Which monitor to display fullscreen on.
+ *
+ * Moves the window into fullscreen mode on the given monitor. This means
+ * the window covers the entire screen and is above any panels or task bars.
+ *
+ * If the window was already fullscreen, then this function does nothing.
+ **/
+void
+gdk_surface_fullscreen_on_monitor (GdkSurface  *window,
+                                  GdkMonitor *monitor)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (GDK_IS_MONITOR (monitor));
+  g_return_if_fail (gdk_monitor_get_display (monitor) == gdk_surface_get_display (window));
+  g_return_if_fail (gdk_monitor_is_valid (monitor));
+
+  if (GDK_SURFACE_IMPL_GET_CLASS (window->impl)->fullscreen_on_monitor != NULL)
+    GDK_SURFACE_IMPL_GET_CLASS (window->impl)->fullscreen_on_monitor (window, monitor);
+  else
+    GDK_SURFACE_IMPL_GET_CLASS (window->impl)->fullscreen (window);
+}
+
+/**
+ * gdk_surface_set_fullscreen_mode:
+ * @window: a toplevel #GdkSurface
+ * @mode: fullscreen mode
+ *
+ * Specifies whether the @window should span over all monitors (in a multi-head
+ * setup) or only the current monitor when in fullscreen mode.
+ *
+ * The @mode argument is from the #GdkFullscreenMode enumeration.
+ * If #GDK_FULLSCREEN_ON_ALL_MONITORS is specified, the fullscreen @window will
+ * span over all monitors of the display.
+ *
+ * On X11, searches through the list of monitors display the ones
+ * which delimit the 4 edges of the entire display and will ask the window
+ * manager to span the @window over these monitors.
+ *
+ * If the XINERAMA extension is not available or not usable, this function
+ * has no effect.
+ *
+ * Not all window managers support this, so you can’t rely on the fullscreen
+ * window to span over the multiple monitors when #GDK_FULLSCREEN_ON_ALL_MONITORS
+ * is specified.
+ **/
+void
+gdk_surface_set_fullscreen_mode (GdkSurface        *window,
+                                GdkFullscreenMode mode)
+{
+  GdkSurfaceImplClass *impl_class;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->fullscreen_mode != mode)
+    {
+      window->fullscreen_mode = mode;
+
+      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+      if (impl_class->apply_fullscreen_mode != NULL)
+        impl_class->apply_fullscreen_mode (window);
+    }
+}
+
+/**
+ * gdk_surface_get_fullscreen_mode:
+ * @window: a toplevel #GdkSurface
+ *
+ * Obtains the #GdkFullscreenMode of the @window.
+ *
+ * Returns: The #GdkFullscreenMode applied to the window when fullscreen.
+ **/
+GdkFullscreenMode
+gdk_surface_get_fullscreen_mode (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), GDK_FULLSCREEN_ON_CURRENT_MONITOR);
+
+  return window->fullscreen_mode;
+}
+
+/**
+ * gdk_surface_unfullscreen:
+ * @window: a toplevel #GdkSurface
+ *
+ * Moves the window out of fullscreen mode. If the window was not
+ * fullscreen, does nothing.
+ *
+ * On X11, asks the window manager to move @window out of the fullscreen
+ * state, if the window manager supports this operation. Not all
+ * window managers support this, and some deliberately ignore it or
+ * don’t have a concept of â€śfullscreen”; so you can’t rely on the
+ * unfullscreenification actually happening. But it will happen with
+ * most standard window managers, and GDK makes a best effort to get
+ * it to happen.
+ **/
+void
+gdk_surface_unfullscreen (GdkSurface *window)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->unfullscreen (window);
+}
+
+/**
+ * gdk_surface_set_keep_above:
+ * @window: a toplevel #GdkSurface
+ * @setting: whether to keep @window above other windows
+ *
+ * Set if @window must be kept above other windows. If the
+ * window was already above, then this function does nothing.
+ *
+ * On X11, asks the window manager to keep @window above, if the window
+ * manager supports this operation. Not all window managers support
+ * this, and some deliberately ignore it or don’t have a concept of
+ * â€śkeep above”; so you can’t rely on the window being kept above.
+ * But it will happen with most standard window managers,
+ * and GDK makes a best effort to get it to happen.
+ **/
+void
+gdk_surface_set_keep_above (GdkSurface *window,
+                           gboolean   setting)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_keep_above (window, setting);
+}
+
+/**
+ * gdk_surface_set_keep_below:
+ * @window: a toplevel #GdkSurface
+ * @setting: whether to keep @window below other windows
+ *
+ * Set if @window must be kept below other windows. If the
+ * window was already below, then this function does nothing.
+ *
+ * On X11, asks the window manager to keep @window below, if the window
+ * manager supports this operation. Not all window managers support
+ * this, and some deliberately ignore it or don’t have a concept of
+ * â€śkeep below”; so you can’t rely on the window being kept below.
+ * But it will happen with most standard window managers,
+ * and GDK makes a best effort to get it to happen.
+ **/
+void
+gdk_surface_set_keep_below (GdkSurface *window, gboolean setting)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_keep_below (window, setting);
+}
+
+/**
+ * gdk_surface_get_group:
+ * @window: a toplevel #GdkSurface
+ *
+ * Returns the group leader window for @window. See gdk_surface_set_group().
+ *
+ * Returns: (transfer none): the group leader window for @window
+ **/
+GdkSurface *
+gdk_surface_get_group (GdkSurface *window)
+{
+  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->get_group (window);
+}
+
+/**
+ * gdk_surface_set_group:
+ * @window: a toplevel #GdkSurface
+ * @leader: (allow-none): group leader window, or %NULL to restore the default group leader window
+ *
+ * Sets the group leader window for @window. By default,
+ * GDK sets the group leader for all toplevel windows
+ * to a global window implicitly created by GDK. With this function
+ * you can override this default.
+ *
+ * The group leader window allows the window manager to distinguish
+ * all windows that belong to a single application. It may for example
+ * allow users to minimize/unminimize all windows belonging to an
+ * application at once. You should only set a non-default group window
+ * if your application pretends to be multiple applications.
+ **/
+void
+gdk_surface_set_group (GdkSurface *window,
+                     GdkSurface *leader)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_group (window, leader);
+}
+
+/**
+ * gdk_surface_set_decorations:
+ * @window: a toplevel #GdkSurface
+ * @decorations: decoration hint mask
+ *
+ * â€śDecorations” are the features the window manager adds to a toplevel #GdkSurface.
+ * This function sets the traditional Motif window manager hints that tell the
+ * window manager which decorations you would like your window to have.
+ * Usually you should use gtk_window_set_decorated() on a #GtkWindow instead of
+ * using the GDK function directly.
+ *
+ * The @decorations argument is the logical OR of the fields in
+ * the #GdkWMDecoration enumeration. If #GDK_DECOR_ALL is included in the
+ * mask, the other bits indicate which decorations should be turned off.
+ * If #GDK_DECOR_ALL is not included, then the other bits indicate
+ * which decorations should be turned on.
+ *
+ * Most window managers honor a decorations hint of 0 to disable all decorations,
+ * but very few honor all possible combinations of bits.
+ *
+ **/
+void
+gdk_surface_set_decorations (GdkSurface      *window,
+                           GdkWMDecoration decorations)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_decorations (window, decorations);
+}
+
+/**
+ * gdk_surface_get_decorations:
+ * @window: The toplevel #GdkSurface to get the decorations from
+ * @decorations: (out): The window decorations will be written here
+ *
+ * Returns the decorations set on the GdkSurface with
+ * gdk_surface_set_decorations().
+ *
+ * Returns: %TRUE if the window has decorations set, %FALSE otherwise.
+ **/
+gboolean
+gdk_surface_get_decorations(GdkSurface       *window,
+                          GdkWMDecoration *decorations)
+{
+  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->get_decorations (window, decorations);
+}
+
+/**
+ * gdk_surface_set_functions:
+ * @window: a toplevel #GdkSurface
+ * @functions: bitmask of operations to allow on @window
+ *
+ * Sets hints about the window management functions to make available
+ * via buttons on the window frame.
+ *
+ * On the X backend, this function sets the traditional Motif window
+ * manager hint for this purpose. However, few window managers do
+ * anything reliable or interesting with this hint. Many ignore it
+ * entirely.
+ *
+ * The @functions argument is the logical OR of values from the
+ * #GdkWMFunction enumeration. If the bitmask includes #GDK_FUNC_ALL,
+ * then the other bits indicate which functions to disable; if
+ * it doesn’t include #GDK_FUNC_ALL, it indicates which functions to
+ * enable.
+ *
+ **/
+void
+gdk_surface_set_functions (GdkSurface    *window,
+                         GdkWMFunction functions)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_functions (window, functions);
+}
+
+/**
+ * gdk_surface_begin_resize_drag_for_device:
+ * @window: a toplevel #GdkSurface
+ * @edge: the edge or corner from which the drag is started
+ * @device: the device used for the operation
+ * @button: the button being used to drag, or 0 for a keyboard-initiated drag
+ * @root_x: root window X coordinate of mouse click that began the drag
+ * @root_y: root window Y coordinate of mouse click that began the drag
+ * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
+ *
+ * Begins a window resize operation (for a toplevel window).
+ * You might use this function to implement a â€świndow resize grip,” for
+ * example; in fact #GtkStatusbar uses it. The function works best
+ * with window managers that support the
+ * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec)
+ * but has a fallback implementation for other window managers.
+ */
+void
+gdk_surface_begin_resize_drag_for_device (GdkSurface     *window,
+                                         GdkSurfaceEdge  edge,
+                                         GdkDevice     *device,
+                                         gint           button,
+                                         gint           root_x,
+                                         gint           root_y,
+                                         guint32        timestamp)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->begin_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
+}
+
+/**
+ * gdk_surface_begin_resize_drag:
+ * @window: a toplevel #GdkSurface
+ * @edge: the edge or corner from which the drag is started
+ * @button: the button being used to drag, or 0 for a keyboard-initiated drag
+ * @root_x: root window X coordinate of mouse click that began the drag
+ * @root_y: root window Y coordinate of mouse click that began the drag
+ * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
+ *
+ * Begins a window resize operation (for a toplevel window).
+ *
+ * This function assumes that the drag is controlled by the
+ * client pointer device, use gdk_surface_begin_resize_drag_for_device()
+ * to begin a drag with a different device.
+ */
+void
+gdk_surface_begin_resize_drag (GdkSurface     *window,
+                              GdkSurfaceEdge  edge,
+                              gint           button,
+                              gint           root_x,
+                              gint           root_y,
+                              guint32        timestamp)
+{
+  GdkDisplay *display;
+  GdkDevice *device;
+
+  display = gdk_surface_get_display (window);
+  device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
+  gdk_surface_begin_resize_drag_for_device (window, edge,
+                                           device, button, root_x, root_y, timestamp);
+}
+
+/**
+ * gdk_surface_begin_move_drag_for_device:
+ * @window: a toplevel #GdkSurface
+ * @device: the device used for the operation
+ * @button: the button being used to drag, or 0 for a keyboard-initiated drag
+ * @root_x: root window X coordinate of mouse click that began the drag
+ * @root_y: root window Y coordinate of mouse click that began the drag
+ * @timestamp: timestamp of mouse click that began the drag
+ *
+ * Begins a window move operation (for a toplevel window).
+ * You might use this function to implement a â€świndow move grip,” for
+ * example. The function works best with window managers that support the
+ * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec)
+ * but has a fallback implementation for other window managers.
+ */
+void
+gdk_surface_begin_move_drag_for_device (GdkSurface *window,
+                                       GdkDevice *device,
+                                       gint       button,
+                                       gint       root_x,
+                                       gint       root_y,
+                                       guint32    timestamp)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->begin_move_drag (window,
+                                                             device, button, root_x, root_y, timestamp);
+}
+
+/**
+ * gdk_surface_begin_move_drag:
+ * @window: a toplevel #GdkSurface
+ * @button: the button being used to drag, or 0 for a keyboard-initiated drag
+ * @root_x: root window X coordinate of mouse click that began the drag
+ * @root_y: root window Y coordinate of mouse click that began the drag
+ * @timestamp: timestamp of mouse click that began the drag
+ *
+ * Begins a window move operation (for a toplevel window).
+ *
+ * This function assumes that the drag is controlled by the
+ * client pointer device, use gdk_surface_begin_move_drag_for_device()
+ * to begin a drag with a different device.
+ */
+void
+gdk_surface_begin_move_drag (GdkSurface *window,
+                            gint       button,
+                            gint       root_x,
+                            gint       root_y,
+                            guint32    timestamp)
+{
+  GdkDisplay *display;
+  GdkDevice *device;
+
+  display = gdk_surface_get_display (window);
+  device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
+  gdk_surface_begin_move_drag_for_device (window, device, button, root_x, root_y, timestamp);
+}
+
+/**
+ * gdk_surface_set_opacity:
+ * @window: a top-level or non-native #GdkSurface
+ * @opacity: opacity
+ *
+ * Set @window to render as partially transparent,
+ * with opacity 0 being fully transparent and 1 fully opaque. (Values
+ * of the opacity parameter are clamped to the [0,1] range.) 
+ *
+ * For toplevel windows this depends on support from the windowing system
+ * that may not always be there. For instance, On X11, this works only on
+ * X screens with a compositing manager running. On Wayland, there is no
+ * per-window opacity value that the compositor would apply. Instead, use
+ * `gdk_surface_set_opaque_region (window, NULL)` to tell the compositor
+ * that the entire window is (potentially) non-opaque, and draw your content
+ * with alpha, or use gtk_widget_set_opacity() to set an overall opacity
+ * for your widgets.
+ *
+ * Support for non-toplevel windows was added in 3.8.
+ */
+void
+gdk_surface_set_opacity (GdkSurface *window,
+                       gdouble    opacity)
+{
+  if (opacity < 0)
+    opacity = 0;
+  else if (opacity > 1)
+    opacity = 1;
+
+  window->alpha = round (opacity * 255);
+
+  if (window->destroyed)
+    return;
+
+  if (gdk_surface_has_impl (window))
+    GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_opacity (window, opacity);
+  else
+    {
+      recompute_visible_regions (window, FALSE);
+      gdk_surface_invalidate_rect_full (window, NULL, TRUE);
+    }
+}
+
+/* This function is called when the XWindow is really gone.
+ */
+void
+gdk_surface_destroy_notify (GdkSurface *window)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->destroy_notify (window);
+}
+
+/**
+ * gdk_surface_register_dnd:
+ * @window: a #GdkSurface.
+ *
+ * Registers a window as a potential drop destination.
+ */
+void
+gdk_surface_register_dnd (GdkSurface *window)
+{
+  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->register_dnd (window);
+}
+
+/**
+ * gdk_drag_begin:
+ * @window: the source window for this drag
+ * @device: the device that controls this drag
+ * @content: (transfer none): the offered content
+ * @actions: the actions supported by this drag
+ * @dx: the x offset to @device's position where the drag nominally started
+ * @dy: the y offset to @device's position where the drag nominally started
+ *
+ * Starts a drag and creates a new drag context for it.
+ *
+ * This function is called by the drag source.
+ *
+ * Returns: (transfer full) (nullable): a newly created #GdkDragContext or
+ *     %NULL on error.
+ */
+GdkDragContext *
+gdk_drag_begin (GdkSurface          *window,
+                GdkDevice          *device,
+                GdkContentProvider *content,
+                GdkDragAction       actions,
+                gint                dx,
+                gint                dy)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
+  g_return_val_if_fail (gdk_surface_get_display (window) == gdk_device_get_display (device), NULL);
+  g_return_val_if_fail (GDK_IS_CONTENT_PROVIDER (content), NULL);
+
+  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->drag_begin (window, device, content, actions, dx, dy);
+}
+
+static void
+gdk_surface_flush_events (GdkFrameClock *clock,
+                         void          *data)
+{
+  GdkSurface *window;
+  GdkDisplay *display;
+
+  window = GDK_SURFACE (data);
+
+  display = gdk_surface_get_display (window);
+  _gdk_event_queue_flush (display);
+  _gdk_display_pause_events (display);
+
+  gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_RESUME_EVENTS);
+
+  window->frame_clock_events_paused = TRUE;
+}
+
+static void
+gdk_surface_resume_events (GdkFrameClock *clock,
+                          void          *data)
+{
+  GdkSurface *window;
+  GdkDisplay *display;
+
+  window = GDK_SURFACE (data);
+
+  display = gdk_surface_get_display (window);
+  _gdk_display_unpause_events (display);
+
+  window->frame_clock_events_paused = FALSE;
+}
+
+static void
+gdk_surface_set_frame_clock (GdkSurface     *window,
+                            GdkFrameClock *clock)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (clock == NULL || GDK_IS_FRAME_CLOCK (clock));
+  g_return_if_fail (clock == NULL || gdk_surface_is_toplevel (window));
+
+  if (clock == window->frame_clock)
+    return;
+
+  if (clock)
+    {
+      g_object_ref (clock);
+      g_signal_connect (G_OBJECT (clock),
+                        "flush-events",
+                        G_CALLBACK (gdk_surface_flush_events),
+                        window);
+      g_signal_connect (G_OBJECT (clock),
+                        "paint",
+                        G_CALLBACK (gdk_surface_paint_on_clock),
+                        window);
+      g_signal_connect (G_OBJECT (clock),
+                        "resume-events",
+                        G_CALLBACK (gdk_surface_resume_events),
+                        window);
+    }
+
+  if (window->frame_clock)
+    {
+      if (window->frame_clock_events_paused)
+        gdk_surface_resume_events (window->frame_clock, G_OBJECT (window));
+
+      g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),
+                                            G_CALLBACK (gdk_surface_flush_events),
+                                            window);
+      g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),
+                                            G_CALLBACK (gdk_surface_paint_on_clock),
+                                            window);
+      g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),
+                                            G_CALLBACK (gdk_surface_resume_events),
+                                            window);
+      g_object_unref (window->frame_clock);
+    }
+
+  window->frame_clock = clock;
+}
+
+/**
+ * gdk_surface_get_frame_clock:
+ * @window: window to get frame clock for
+ *
+ * Gets the frame clock for the window. The frame clock for a window
+ * never changes unless the window is reparented to a new toplevel
+ * window.
+ *
+ * Returns: (transfer none): the frame clock
+ */
+GdkFrameClock*
+gdk_surface_get_frame_clock (GdkSurface *window)
+{
+  GdkSurface *toplevel;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  toplevel = gdk_surface_get_toplevel (window);
+
+  return toplevel->frame_clock;
+}
+
+/**
+ * gdk_surface_get_scale_factor:
+ * @window: window to get scale factor for
+ *
+ * Returns the internal scale factor that maps from window coordiantes
+ * to the actual device pixels. On traditional systems this is 1, but
+ * on very high density outputs this can be a higher value (often 2).
+ *
+ * A higher value means that drawing is automatically scaled up to
+ * a higher resolution, so any code doing drawing will automatically look
+ * nicer. However, if you are supplying pixel-based data the scale
+ * value can be used to determine whether to use a pixel resource
+ * with higher resolution data.
+ *
+ * The scale of a window may change during runtime, if this happens
+ * a configure event will be sent to the toplevel window.
+ *
+ * Returns: the scale factor
+ */
+gint
+gdk_surface_get_scale_factor (GdkSurface *window)
+{
+  GdkSurfaceImplClass *impl_class;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), 1);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return 1;
+
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+  if (impl_class->get_scale_factor)
+    return impl_class->get_scale_factor (window);
+
+  return 1;
+}
+
+/* Returns the *real* unscaled size, which may be a fractional size
+   in window scale coordinates. We need this to properly handle GL
+   coordinates which are y-flipped in the real coordinates. */
+void
+gdk_surface_get_unscaled_size (GdkSurface *window,
+                              int *unscaled_width,
+                              int *unscaled_height)
+{
+  GdkSurfaceImplClass *impl_class;
+  gint scale;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->impl_window == window)
+    {
+      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+      if (impl_class->get_unscaled_size)
+        {
+          impl_class->get_unscaled_size (window, unscaled_width, unscaled_height);
+          return;
+        }
+    }
+
+  scale = gdk_surface_get_scale_factor (window);
+
+  if (unscaled_width)
+    *unscaled_width = window->width * scale;
+
+  if (unscaled_height)
+    *unscaled_height = window->height * scale;
+}
+
+
+/**
+ * gdk_surface_set_opaque_region:
+ * @window: a top-level or non-native #GdkSurface
+ * @region: (allow-none):  a region, or %NULL
+ *
+ * For optimisation purposes, compositing window managers may
+ * like to not draw obscured regions of windows, or turn off blending
+ * during for these regions. With RGB windows with no transparency,
+ * this is just the shape of the window, but with ARGB32 windows, the
+ * compositor does not know what regions of the window are transparent
+ * or not.
+ *
+ * This function only works for toplevel windows.
+ *
+ * GTK+ will update this property automatically if
+ * the @window background is opaque, as we know where the opaque regions
+ * are. If your window background is not opaque, please update this
+ * property in your #GtkWidget::style-updated handler.
+ */
+void
+gdk_surface_set_opaque_region (GdkSurface      *window,
+                              cairo_region_t *region)
+{
+  GdkSurfaceImplClass *impl_class;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (!GDK_SURFACE_DESTROYED (window));
+
+  if (cairo_region_equal (window->opaque_region, region))
+    return;
+
+  g_clear_pointer (&window->opaque_region, cairo_region_destroy);
+
+  if (region != NULL)
+    window->opaque_region = cairo_region_reference (region);
+
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+  if (impl_class->set_opaque_region)
+    impl_class->set_opaque_region (window, region);
+}
+
+/**
+ * gdk_surface_set_shadow_width:
+ * @window: a #GdkSurface
+ * @left: The left extent
+ * @right: The right extent
+ * @top: The top extent
+ * @bottom: The bottom extent
+ *
+ * Newer GTK+ windows using client-side decorations use extra geometry
+ * around their frames for effects like shadows and invisible borders.
+ * Window managers that want to maximize windows or snap to edges need
+ * to know where the extents of the actual frame lie, so that users
+ * don’t feel like windows are snapping against random invisible edges.
+ *
+ * Note that this property is automatically updated by GTK+, so this
+ * function should only be used by applications which do not use GTK+
+ * to create toplevel windows.
+ */
+void
+gdk_surface_set_shadow_width (GdkSurface *window,
+                             gint       left,
+                             gint       right,
+                             gint       top,
+                             gint       bottom)
+{
+  GdkSurfaceImplClass *impl_class;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (!GDK_SURFACE_DESTROYED (window));
+  g_return_if_fail (left >= 0 && right >= 0 && top >= 0 && bottom >= 0);
+
+  window->shadow_top = top;
+  window->shadow_left = left;
+  window->shadow_right = right;
+  window->shadow_bottom = bottom;
+
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+  if (impl_class->set_shadow_width)
+    impl_class->set_shadow_width (window, left, right, top, bottom);
+}
+
+/**
+ * gdk_surface_show_window_menu:
+ * @window: a #GdkSurface
+ * @event: a #GdkEvent to show the menu for
+ *
+ * Asks the windowing system to show the window menu. The window menu
+ * is the menu shown when right-clicking the titlebar on traditional
+ * windows managed by the window manager. This is useful for windows
+ * using client-side decorations, activating it with a right-click
+ * on the window decorations.
+ *
+ * Returns: %TRUE if the window menu was shown and %FALSE otherwise.
+ */
+gboolean
+gdk_surface_show_window_menu (GdkSurface *window,
+                             GdkEvent  *event)
+{
+  GdkSurfaceImplClass *impl_class;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+  g_return_val_if_fail (!GDK_SURFACE_DESTROYED (window), FALSE);
+
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+  if (impl_class->show_window_menu)
+    return impl_class->show_window_menu (window, event);
+  else
+    return FALSE;
+}
+
+gboolean
+gdk_surface_supports_edge_constraints (GdkSurface *window)
+{
+  GdkSurfaceImplClass *impl_class;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+  g_return_val_if_fail (!GDK_SURFACE_DESTROYED (window), FALSE);
+
+  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
+
+  if (impl_class->supports_edge_constraints)
+    return impl_class->supports_edge_constraints (window);
+  else
+    return FALSE;
+}
+
+void
+gdk_surface_set_state (GdkSurface      *window,
+                      GdkSurfaceState  new_state)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (new_state == window->state)
+    return; /* No actual work to do, nothing changed. */
+
+  /* Actually update the field in GdkSurface, this is sort of an odd
+   * place to do it, but seems like the safest since it ensures we expose no
+   * inconsistent state to the user.
+   */
+
+  window->state = new_state;
+
+  _gdk_surface_update_viewable (window);
+
+  /* We only really send the event to toplevels, since
+   * all the window states don't apply to non-toplevels.
+   * Non-toplevels do use the GDK_SURFACE_STATE_WITHDRAWN flag
+   * internally so we needed to update window->state.
+   */
+  switch (window->window_type)
+    {
+    case GDK_SURFACE_TOPLEVEL:
+    case GDK_SURFACE_TEMP: /* ? */
+      g_object_notify (G_OBJECT (window), "state");
+      break;
+    case GDK_SURFACE_FOREIGN:
+    case GDK_SURFACE_ROOT:
+    case GDK_SURFACE_CHILD:
+    default:
+      break;
+    }
+}
+
+void
+gdk_synthesize_window_state (GdkSurface     *window,
+                             GdkSurfaceState unset_flags,
+                             GdkSurfaceState set_flags)
+{
+  gdk_surface_set_state (window, (window->state | set_flags) & ~unset_flags);
+}
diff --git a/gdk/gdksurface.h b/gdk/gdksurface.h
new file mode 100644 (file)
index 0000000..9cc1b57
--- /dev/null
@@ -0,0 +1,933 @@
+/* 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __GDK_SURFACE_H__
+#define __GDK_SURFACE_H__
+
+#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdk.h> can be included directly."
+#endif
+
+#include <gdk/gdkversionmacros.h>
+#include <gdk/gdktypes.h>
+#include <gdk/gdkdrawingcontext.h>
+#include <gdk/gdkevents.h>
+#include <gdk/gdkframeclock.h>
+#include <gdk/gdkmonitor.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdkGeometry          GdkGeometry;
+
+/**
+ * GdkSurfaceType:
+ * @GDK_SURFACE_ROOT: root window; this window has no parent, covers the entire
+ *  screen, and is created by the window system
+ * @GDK_SURFACE_TOPLEVEL: toplevel window (used to implement #GtkWindow)
+ * @GDK_SURFACE_CHILD: child window (used to implement e.g. #GtkEntry)
+ * @GDK_SURFACE_TEMP: override redirect temporary window (used to implement
+ *  #GtkMenu)
+ * @GDK_SURFACE_FOREIGN: foreign window (see gdk_surface_foreign_new())
+ * @GDK_SURFACE_SUBSURFACE: subsurface-based window; This window is visually
+ *  tied to a toplevel, and is moved/stacked with it. Currently this window
+ *  type is only implemented in Wayland. Since 3.14
+ *
+ * Describes the kind of window.
+ */
+typedef enum
+{
+  GDK_SURFACE_ROOT,
+  GDK_SURFACE_TOPLEVEL,
+  GDK_SURFACE_CHILD,
+  GDK_SURFACE_TEMP,
+  GDK_SURFACE_FOREIGN,
+  GDK_SURFACE_SUBSURFACE
+} GdkSurfaceType;
+
+/* Size restriction enumeration.
+ */
+/**
+ * GdkSurfaceHints:
+ * @GDK_HINT_POS: indicates that the program has positioned the window
+ * @GDK_HINT_MIN_SIZE: min size fields are set
+ * @GDK_HINT_MAX_SIZE: max size fields are set
+ * @GDK_HINT_BASE_SIZE: base size fields are set
+ * @GDK_HINT_ASPECT: aspect ratio fields are set
+ * @GDK_HINT_RESIZE_INC: resize increment fields are set
+ * @GDK_HINT_WIN_GRAVITY: window gravity field is set
+ * @GDK_HINT_USER_POS: indicates that the window’s position was explicitly set
+ *  by the user
+ * @GDK_HINT_USER_SIZE: indicates that the window’s size was explicitly set by
+ *  the user
+ *
+ * Used to indicate which fields of a #GdkGeometry struct should be paid
+ * attention to. Also, the presence/absence of @GDK_HINT_POS,
+ * @GDK_HINT_USER_POS, and @GDK_HINT_USER_SIZE is significant, though they don't
+ * directly refer to #GdkGeometry fields. @GDK_HINT_USER_POS will be set
+ * automatically by #GtkWindow if you call gtk_window_move().
+ * @GDK_HINT_USER_POS and @GDK_HINT_USER_SIZE should be set if the user
+ * specified a size/position using a --geometry command-line argument;
+ * gtk_window_parse_geometry() automatically sets these flags.
+ */
+typedef enum
+{
+  GDK_HINT_POS        = 1 << 0,
+  GDK_HINT_MIN_SIZE    = 1 << 1,
+  GDK_HINT_MAX_SIZE    = 1 << 2,
+  GDK_HINT_BASE_SIZE   = 1 << 3,
+  GDK_HINT_ASPECT      = 1 << 4,
+  GDK_HINT_RESIZE_INC  = 1 << 5,
+  GDK_HINT_WIN_GRAVITY = 1 << 6,
+  GDK_HINT_USER_POS    = 1 << 7,
+  GDK_HINT_USER_SIZE   = 1 << 8
+} GdkSurfaceHints;
+
+/* The next two enumeration values current match the
+ * Motif constants. If this is changed, the implementation
+ * of gdk_surface_set_decorations/gdk_surface_set_functions
+ * will need to change as well.
+ */
+/**
+ * GdkWMDecoration:
+ * @GDK_DECOR_ALL: all decorations should be applied.
+ * @GDK_DECOR_BORDER: a frame should be drawn around the window.
+ * @GDK_DECOR_RESIZEH: the frame should have resize handles.
+ * @GDK_DECOR_TITLE: a titlebar should be placed above the window.
+ * @GDK_DECOR_MENU: a button for opening a menu should be included.
+ * @GDK_DECOR_MINIMIZE: a minimize button should be included.
+ * @GDK_DECOR_MAXIMIZE: a maximize button should be included.
+ *
+ * These are hints originally defined by the Motif toolkit.
+ * The window manager can use them when determining how to decorate
+ * the window. The hint must be set before mapping the window.
+ */
+typedef enum
+{
+  GDK_DECOR_ALL                = 1 << 0,
+  GDK_DECOR_BORDER     = 1 << 1,
+  GDK_DECOR_RESIZEH    = 1 << 2,
+  GDK_DECOR_TITLE      = 1 << 3,
+  GDK_DECOR_MENU       = 1 << 4,
+  GDK_DECOR_MINIMIZE   = 1 << 5,
+  GDK_DECOR_MAXIMIZE   = 1 << 6
+} GdkWMDecoration;
+
+/**
+ * GdkWMFunction:
+ * @GDK_FUNC_ALL: all functions should be offered.
+ * @GDK_FUNC_RESIZE: the window should be resizable.
+ * @GDK_FUNC_MOVE: the window should be movable.
+ * @GDK_FUNC_MINIMIZE: the window should be minimizable.
+ * @GDK_FUNC_MAXIMIZE: the window should be maximizable.
+ * @GDK_FUNC_CLOSE: the window should be closable.
+ *
+ * These are hints originally defined by the Motif toolkit. The window manager
+ * can use them when determining the functions to offer for the window. The
+ * hint must be set before mapping the window.
+ */
+typedef enum
+{
+  GDK_FUNC_ALL         = 1 << 0,
+  GDK_FUNC_RESIZE      = 1 << 1,
+  GDK_FUNC_MOVE                = 1 << 2,
+  GDK_FUNC_MINIMIZE    = 1 << 3,
+  GDK_FUNC_MAXIMIZE    = 1 << 4,
+  GDK_FUNC_CLOSE       = 1 << 5
+} GdkWMFunction;
+
+/* Currently, these are the same values numerically as in the
+ * X protocol. If you change that, gdksurface-x11.c/gdk_surface_set_geometry_hints()
+ * will need fixing.
+ */
+/**
+ * GdkGravity:
+ * @GDK_GRAVITY_NORTH_WEST: the reference point is at the top left corner.
+ * @GDK_GRAVITY_NORTH: the reference point is in the middle of the top edge.
+ * @GDK_GRAVITY_NORTH_EAST: the reference point is at the top right corner.
+ * @GDK_GRAVITY_WEST: the reference point is at the middle of the left edge.
+ * @GDK_GRAVITY_CENTER: the reference point is at the center of the window.
+ * @GDK_GRAVITY_EAST: the reference point is at the middle of the right edge.
+ * @GDK_GRAVITY_SOUTH_WEST: the reference point is at the lower left corner.
+ * @GDK_GRAVITY_SOUTH: the reference point is at the middle of the lower edge.
+ * @GDK_GRAVITY_SOUTH_EAST: the reference point is at the lower right corner.
+ * @GDK_GRAVITY_STATIC: the reference point is at the top left corner of the
+ *  window itself, ignoring window manager decorations.
+ *
+ * Defines the reference point of a window and the meaning of coordinates
+ * passed to gtk_window_move(). See gtk_window_move() and the "implementation
+ * notes" section of the
+ * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec)
+ * specification for more details.
+ */
+typedef enum
+{
+  GDK_GRAVITY_NORTH_WEST = 1,
+  GDK_GRAVITY_NORTH,
+  GDK_GRAVITY_NORTH_EAST,
+  GDK_GRAVITY_WEST,
+  GDK_GRAVITY_CENTER,
+  GDK_GRAVITY_EAST,
+  GDK_GRAVITY_SOUTH_WEST,
+  GDK_GRAVITY_SOUTH,
+  GDK_GRAVITY_SOUTH_EAST,
+  GDK_GRAVITY_STATIC
+} GdkGravity;
+
+/**
+ * GdkAnchorHints:
+ * @GDK_ANCHOR_FLIP_X: allow flipping anchors horizontally
+ * @GDK_ANCHOR_FLIP_Y: allow flipping anchors vertically
+ * @GDK_ANCHOR_SLIDE_X: allow sliding window horizontally
+ * @GDK_ANCHOR_SLIDE_Y: allow sliding window vertically
+ * @GDK_ANCHOR_RESIZE_X: allow resizing window horizontally
+ * @GDK_ANCHOR_RESIZE_Y: allow resizing window vertically
+ * @GDK_ANCHOR_FLIP: allow flipping anchors on both axes
+ * @GDK_ANCHOR_SLIDE: allow sliding window on both axes
+ * @GDK_ANCHOR_RESIZE: allow resizing window on both axes
+ *
+ * Positioning hints for aligning a window relative to a rectangle.
+ *
+ * These hints determine how the window should be positioned in the case that
+ * the window would fall off-screen if placed in its ideal position.
+ *
+ * For example, %GDK_ANCHOR_FLIP_X will replace %GDK_GRAVITY_NORTH_WEST with
+ * %GDK_GRAVITY_NORTH_EAST and vice versa if the window extends beyond the left
+ * or right edges of the monitor.
+ *
+ * If %GDK_ANCHOR_SLIDE_X is set, the window can be shifted horizontally to fit
+ * on-screen. If %GDK_ANCHOR_RESIZE_X is set, the window can be shrunken
+ * horizontally to fit.
+ *
+ * In general, when multiple flags are set, flipping should take precedence over
+ * sliding, which should take precedence over resizing.
+ *
+ * Since: 3.22
+ * Stability: Unstable
+ */
+typedef enum
+{
+  GDK_ANCHOR_FLIP_X   = 1 << 0,
+  GDK_ANCHOR_FLIP_Y   = 1 << 1,
+  GDK_ANCHOR_SLIDE_X  = 1 << 2,
+  GDK_ANCHOR_SLIDE_Y  = 1 << 3,
+  GDK_ANCHOR_RESIZE_X = 1 << 4,
+  GDK_ANCHOR_RESIZE_Y = 1 << 5,
+  GDK_ANCHOR_FLIP     = GDK_ANCHOR_FLIP_X | GDK_ANCHOR_FLIP_Y,
+  GDK_ANCHOR_SLIDE    = GDK_ANCHOR_SLIDE_X | GDK_ANCHOR_SLIDE_Y,
+  GDK_ANCHOR_RESIZE   = GDK_ANCHOR_RESIZE_X | GDK_ANCHOR_RESIZE_Y
+} GdkAnchorHints;
+
+/**
+ * GdkSurfaceEdge:
+ * @GDK_SURFACE_EDGE_NORTH_WEST: the top left corner.
+ * @GDK_SURFACE_EDGE_NORTH: the top edge.
+ * @GDK_SURFACE_EDGE_NORTH_EAST: the top right corner.
+ * @GDK_SURFACE_EDGE_WEST: the left edge.
+ * @GDK_SURFACE_EDGE_EAST: the right edge.
+ * @GDK_SURFACE_EDGE_SOUTH_WEST: the lower left corner.
+ * @GDK_SURFACE_EDGE_SOUTH: the lower edge.
+ * @GDK_SURFACE_EDGE_SOUTH_EAST: the lower right corner.
+ *
+ * Determines a window edge or corner.
+ */
+typedef enum
+{
+  GDK_SURFACE_EDGE_NORTH_WEST,
+  GDK_SURFACE_EDGE_NORTH,
+  GDK_SURFACE_EDGE_NORTH_EAST,
+  GDK_SURFACE_EDGE_WEST,
+  GDK_SURFACE_EDGE_EAST,
+  GDK_SURFACE_EDGE_SOUTH_WEST,
+  GDK_SURFACE_EDGE_SOUTH,
+  GDK_SURFACE_EDGE_SOUTH_EAST  
+} GdkSurfaceEdge;
+
+/**
+ * GdkFullscreenMode:
+ * @GDK_FULLSCREEN_ON_CURRENT_MONITOR: Fullscreen on current monitor only.
+ * @GDK_FULLSCREEN_ON_ALL_MONITORS: Span across all monitors when fullscreen.
+ *
+ * Indicates which monitor (in a multi-head setup) a window should span over
+ * when in fullscreen mode.
+ *
+ * Since: 3.8
+ **/
+typedef enum
+{
+  GDK_FULLSCREEN_ON_CURRENT_MONITOR,
+  GDK_FULLSCREEN_ON_ALL_MONITORS
+} GdkFullscreenMode;
+
+/**
+ * GdkGeometry:
+ * @min_width: minimum width of window (or -1 to use requisition, with
+ *  #GtkWindow only)
+ * @min_height: minimum height of window (or -1 to use requisition, with
+ *  #GtkWindow only)
+ * @max_width: maximum width of window (or -1 to use requisition, with
+ *  #GtkWindow only)
+ * @max_height: maximum height of window (or -1 to use requisition, with
+ *  #GtkWindow only)
+ * @base_width: allowed window widths are @base_width + @width_inc * N where N
+ *  is any integer (-1 allowed with #GtkWindow)
+ * @base_height: allowed window widths are @base_height + @height_inc * N where
+ *  N is any integer (-1 allowed with #GtkWindow)
+ * @width_inc: width resize increment
+ * @height_inc: height resize increment
+ * @min_aspect: minimum width/height ratio
+ * @max_aspect: maximum width/height ratio
+ * @win_gravity: window gravity, see gtk_window_set_gravity()
+ *
+ * The #GdkGeometry struct gives the window manager information about
+ * a window’s geometry constraints. Normally you would set these on
+ * the GTK+ level using gtk_window_set_geometry_hints(). #GtkWindow
+ * then sets the hints on the #GdkSurface it creates.
+ *
+ * gdk_surface_set_geometry_hints() expects the hints to be fully valid already
+ * and simply passes them to the window manager; in contrast,
+ * gtk_window_set_geometry_hints() performs some interpretation. For example,
+ * #GtkWindow will apply the hints to the geometry widget instead of the
+ * toplevel window, if you set a geometry widget. Also, the
+ * @min_width/@min_height/@max_width/@max_height fields may be set to -1, and
+ * #GtkWindow will substitute the size request of the window or geometry widget.
+ * If the minimum size hint is not provided, #GtkWindow will use its requisition
+ * as the minimum size. If the minimum size is provided and a geometry widget is
+ * set, #GtkWindow will take the minimum size as the minimum size of the
+ * geometry widget rather than the entire window. The base size is treated
+ * similarly.
+ *
+ * The canonical use-case for gtk_window_set_geometry_hints() is to get a
+ * terminal widget to resize properly. Here, the terminal text area should be
+ * the geometry widget; #GtkWindow will then automatically set the base size to
+ * the size of other widgets in the terminal window, such as the menubar and
+ * scrollbar. Then, the @width_inc and @height_inc fields should be set to the
+ * size of one character in the terminal. Finally, the base size should be set
+ * to the size of one character. The net effect is that the minimum size of the
+ * terminal will have a 1x1 character terminal area, and only terminal sizes on
+ * the â€ścharacter grid” will be allowed.
+ *
+ * Here’s an example of how the terminal example would be implemented, assuming
+ * a terminal area widget called â€śterminal” and a toplevel window â€śtoplevel”:
+ *
+ * |[<!-- language="C" -->
+ *     GdkGeometry hints;
+ *
+ *     hints.base_width = terminal->char_width;
+ *         hints.base_height = terminal->char_height;
+ *         hints.min_width = terminal->char_width;
+ *         hints.min_height = terminal->char_height;
+ *         hints.width_inc = terminal->char_width;
+ *         hints.height_inc = terminal->char_height;
+ *
+ *  gtk_window_set_geometry_hints (GTK_WINDOW (toplevel),
+ *                                 GTK_WIDGET (terminal),
+ *                                 &hints,
+ *                                 GDK_HINT_RESIZE_INC |
+ *                                 GDK_HINT_MIN_SIZE |
+ *                                 GDK_HINT_BASE_SIZE);
+ * ]|
+ *
+ * The other useful fields are the @min_aspect and @max_aspect fields; these
+ * contain a width/height ratio as a floating point number. If a geometry widget
+ * is set, the aspect applies to the geometry widget rather than the entire
+ * window. The most common use of these hints is probably to set @min_aspect and
+ * @max_aspect to the same value, thus forcing the window to keep a constant
+ * aspect ratio.
+ */
+struct _GdkGeometry
+{
+  gint min_width;
+  gint min_height;
+  gint max_width;
+  gint max_height;
+  gint base_width;
+  gint base_height;
+  gint width_inc;
+  gint height_inc;
+  gdouble min_aspect;
+  gdouble max_aspect;
+  GdkGravity win_gravity;
+};
+
+/**
+ * GdkSurfaceState:
+ * @GDK_SURFACE_STATE_WITHDRAWN: the window is not shown.
+ * @GDK_SURFACE_STATE_ICONIFIED: the window is minimized.
+ * @GDK_SURFACE_STATE_MAXIMIZED: the window is maximized.
+ * @GDK_SURFACE_STATE_STICKY: the window is sticky.
+ * @GDK_SURFACE_STATE_FULLSCREEN: the window is maximized without
+ *   decorations.
+ * @GDK_SURFACE_STATE_ABOVE: the window is kept above other windows.
+ * @GDK_SURFACE_STATE_BELOW: the window is kept below other windows.
+ * @GDK_SURFACE_STATE_FOCUSED: the window is presented as focused (with active decorations).
+ * @GDK_SURFACE_STATE_TILED: the window is in a tiled state, Since 3.10. Since 3.91.2, this
+ *                          is deprecated in favor of per-edge information.
+ * @GDK_SURFACE_STATE_TOP_TILED: whether the top edge is tiled, Since 3.91.2
+ * @GDK_SURFACE_STATE_TOP_RESIZABLE: whether the top edge is resizable, Since 3.91.2
+ * @GDK_SURFACE_STATE_RIGHT_TILED: whether the right edge is tiled, Since 3.91.2
+ * @GDK_SURFACE_STATE_RIGHT_RESIZABLE: whether the right edge is resizable, Since 3.91.2
+ * @GDK_SURFACE_STATE_BOTTOM_TILED: whether the bottom edge is tiled, Since 3.91.2
+ * @GDK_SURFACE_STATE_BOTTOM_RESIZABLE: whether the bottom edge is resizable, Since 3.91.2
+ * @GDK_SURFACE_STATE_LEFT_TILED: whether the left edge is tiled, Since 3.91.2
+ * @GDK_SURFACE_STATE_LEFT_RESIZABLE: whether the left edge is resizable, Since 3.91.2
+ *
+ * Specifies the state of a toplevel window.
+ */
+typedef enum
+{
+  GDK_SURFACE_STATE_WITHDRAWN        = 1 << 0,
+  GDK_SURFACE_STATE_ICONIFIED        = 1 << 1,
+  GDK_SURFACE_STATE_MAXIMIZED        = 1 << 2,
+  GDK_SURFACE_STATE_STICKY           = 1 << 3,
+  GDK_SURFACE_STATE_FULLSCREEN       = 1 << 4,
+  GDK_SURFACE_STATE_ABOVE            = 1 << 5,
+  GDK_SURFACE_STATE_BELOW            = 1 << 6,
+  GDK_SURFACE_STATE_FOCUSED          = 1 << 7,
+  GDK_SURFACE_STATE_TILED            = 1 << 8,
+  GDK_SURFACE_STATE_TOP_TILED        = 1 << 9,
+  GDK_SURFACE_STATE_TOP_RESIZABLE    = 1 << 10,
+  GDK_SURFACE_STATE_RIGHT_TILED      = 1 << 11,
+  GDK_SURFACE_STATE_RIGHT_RESIZABLE  = 1 << 12,
+  GDK_SURFACE_STATE_BOTTOM_TILED     = 1 << 13,
+  GDK_SURFACE_STATE_BOTTOM_RESIZABLE = 1 << 14,
+  GDK_SURFACE_STATE_LEFT_TILED       = 1 << 15,
+  GDK_SURFACE_STATE_LEFT_RESIZABLE   = 1 << 16
+} GdkSurfaceState;
+
+
+typedef struct _GdkSurfaceClass GdkSurfaceClass;
+
+#define GDK_TYPE_SURFACE              (gdk_surface_get_type ())
+#define GDK_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE, GdkSurface))
+#define GDK_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE, GdkSurfaceClass))
+#define GDK_IS_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE))
+#define GDK_IS_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE))
+#define GDK_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE, GdkSurfaceClass))
+
+
+struct _GdkSurfaceClass
+{
+  GObjectClass      parent_class;
+
+  /* Padding for future expansion */
+  void (*_gdk_reserved1) (void);
+  void (*_gdk_reserved2) (void);
+  void (*_gdk_reserved3) (void);
+  void (*_gdk_reserved4) (void);
+  void (*_gdk_reserved5) (void);
+  void (*_gdk_reserved6) (void);
+  void (*_gdk_reserved7) (void);
+  void (*_gdk_reserved8) (void);
+};
+
+/* Windows
+ */
+GDK_AVAILABLE_IN_ALL
+GType         gdk_surface_get_type              (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GdkSurface *   gdk_surface_new_toplevel          (GdkDisplay    *display,
+                                                int            width,
+                                                int            height);
+GDK_AVAILABLE_IN_ALL
+GdkSurface *   gdk_surface_new_popup             (GdkDisplay    *display,
+                                                const GdkRectangle *position);
+GDK_AVAILABLE_IN_ALL
+GdkSurface *   gdk_surface_new_temp              (GdkDisplay    *display);
+GDK_AVAILABLE_IN_ALL
+GdkSurface *   gdk_surface_new_child             (GdkSurface     *parent,
+                                                const GdkRectangle *position);
+
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_destroy               (GdkSurface     *window);
+GDK_AVAILABLE_IN_ALL
+GdkSurfaceType gdk_surface_get_window_type       (GdkSurface     *window);
+GDK_AVAILABLE_IN_ALL
+gboolean      gdk_surface_is_destroyed          (GdkSurface     *window);
+
+GDK_AVAILABLE_IN_ALL
+GdkDisplay *  gdk_surface_get_display           (GdkSurface     *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_show                  (GdkSurface     *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_hide                  (GdkSurface     *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_withdraw              (GdkSurface     *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_show_unraised         (GdkSurface     *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_move                  (GdkSurface     *window,
+                                                gint           x,
+                                                gint           y);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_resize                (GdkSurface     *window,
+                                                gint           width,
+                                                gint           height);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_move_resize           (GdkSurface     *window,
+                                                gint           x,
+                                                gint           y,
+                                                gint           width,
+                                                gint           height);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_raise                 (GdkSurface     *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_lower                 (GdkSurface     *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_restack               (GdkSurface     *window,
+                                               GdkSurface     *sibling,
+                                               gboolean       above);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_focus                 (GdkSurface     *window,
+                                                guint32        timestamp);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_user_data         (GdkSurface     *window,
+                                                gpointer       user_data);
+GDK_AVAILABLE_IN_ALL
+gboolean      gdk_surface_get_accept_focus      (GdkSurface     *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_accept_focus      (GdkSurface     *window,
+                                               gboolean       accept_focus);
+GDK_AVAILABLE_IN_ALL
+gboolean      gdk_surface_get_focus_on_map      (GdkSurface     *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_focus_on_map      (GdkSurface     *window,
+                                               gboolean       focus_on_map);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_scroll                (GdkSurface     *window,
+                                                gint           dx,
+                                                gint           dy);
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_move_region           (GdkSurface       *window,
+                                               const cairo_region_t *region,
+                                               gint             dx,
+                                               gint             dy);
+
+/* 
+ * This allows for making shaped (partially transparent) windows
+ * - cool feature, needed for Drag and Drag for example.
+ */
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_shape_combine_region (GdkSurface            *window,
+                                      const cairo_region_t *shape_region,
+                                      gint            offset_x,
+                                      gint            offset_y);
+
+/*
+ * This routine allows you to quickly take the shapes of all the child windows
+ * of a window and use their shapes as the shape mask for this window - useful
+ * for container windows that dont want to look like a big box
+ * 
+ * - Raster
+ */
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_set_child_shapes (GdkSurface *window);
+
+/*
+ * This routine allows you to merge (ie ADD) child shapes to your
+ * own window’s shape keeping its current shape and ADDING the child
+ * shapes to it.
+ * 
+ * - Raster
+ */
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_merge_child_shapes         (GdkSurface       *window);
+
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_input_shape_combine_region (GdkSurface       *window,
+                                            const cairo_region_t *shape_region,
+                                            gint             offset_x,
+                                            gint             offset_y);
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_set_child_input_shapes     (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_merge_child_input_shapes   (GdkSurface       *window);
+
+
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_set_pass_through (GdkSurface *window,
+                                  gboolean   pass_through);
+GDK_AVAILABLE_IN_ALL
+gboolean gdk_surface_get_pass_through (GdkSurface *window);
+
+/*
+ * Check if a window has been shown, and whether all its
+ * parents up to a toplevel have been shown, respectively.
+ * Note that a window that is_viewable below is not necessarily
+ * viewable in the X sense.
+ */
+GDK_AVAILABLE_IN_ALL
+gboolean gdk_surface_is_visible     (GdkSurface *window);
+GDK_AVAILABLE_IN_ALL
+gboolean gdk_surface_is_viewable    (GdkSurface *window);
+GDK_AVAILABLE_IN_ALL
+gboolean gdk_surface_is_input_only  (GdkSurface *window);
+GDK_AVAILABLE_IN_ALL
+gboolean gdk_surface_is_shaped      (GdkSurface *window);
+
+GDK_AVAILABLE_IN_ALL
+GdkSurfaceState gdk_surface_get_state (GdkSurface *window);
+
+
+/* GdkSurface */
+
+GDK_AVAILABLE_IN_ALL
+gboolean      gdk_surface_has_native         (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void              gdk_surface_set_type_hint (GdkSurface        *window,
+                                            GdkSurfaceTypeHint hint);
+GDK_AVAILABLE_IN_ALL
+GdkSurfaceTypeHint gdk_surface_get_type_hint (GdkSurface        *window);
+
+GDK_AVAILABLE_IN_ALL
+gboolean      gdk_surface_get_modal_hint   (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_modal_hint   (GdkSurface       *window,
+                                           gboolean         modal);
+
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_set_skip_taskbar_hint (GdkSurface *window,
+                                       gboolean   skips_taskbar);
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_set_skip_pager_hint   (GdkSurface *window,
+                                       gboolean   skips_pager);
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_set_urgency_hint      (GdkSurface *window,
+                                      gboolean   urgent);
+
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_geometry_hints (GdkSurface          *window,
+                                            const GdkGeometry  *geometry,
+                                            GdkSurfaceHints      geom_mask);
+
+GDK_AVAILABLE_IN_ALL
+cairo_region_t *gdk_surface_get_clip_region  (GdkSurface          *window);
+GDK_AVAILABLE_IN_ALL
+cairo_region_t *gdk_surface_get_visible_region(GdkSurface         *window);
+
+GDK_AVAILABLE_IN_ALL
+GdkDrawingContext *gdk_surface_begin_draw_frame  (GdkSurface            *window,
+                                                 GdkDrawContext       *context,
+                                                 const cairo_region_t *region);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_end_draw_frame    (GdkSurface            *window,
+                                            GdkDrawingContext    *context);
+
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_set_title        (GdkSurface    *window,
+                                           const gchar   *title);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_role          (GdkSurface     *window,
+                                           const gchar   *role);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_startup_id    (GdkSurface     *window,
+                                           const gchar   *startup_id);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_transient_for (GdkSurface     *window,
+                                           GdkSurface     *parent);
+
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_set_cursor     (GdkSurface      *window,
+                                         GdkCursor       *cursor);
+GDK_AVAILABLE_IN_ALL
+GdkCursor    *gdk_surface_get_cursor      (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_set_device_cursor (GdkSurface   *window,
+                                            GdkDevice     *device,
+                                            GdkCursor    *cursor);
+GDK_AVAILABLE_IN_ALL
+GdkCursor    *gdk_surface_get_device_cursor (GdkSurface     *window,
+                                            GdkDevice     *device);
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_get_user_data  (GdkSurface      *window,
+                                         gpointer        *data);
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_get_geometry   (GdkSurface      *window,
+                                         gint            *x,
+                                         gint            *y,
+                                         gint            *width,
+                                         gint            *height);
+GDK_AVAILABLE_IN_ALL
+int           gdk_surface_get_width       (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+int           gdk_surface_get_height      (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_get_position   (GdkSurface      *window,
+                                         gint            *x,
+                                         gint            *y);
+GDK_AVAILABLE_IN_ALL
+gint         gdk_surface_get_origin     (GdkSurface      *window,
+                                         gint            *x,
+                                         gint            *y);
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_get_root_coords (GdkSurface     *window,
+                                         gint             x,
+                                         gint             y,
+                                         gint            *root_x,
+                                         gint            *root_y);
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_coords_to_parent   (GdkSurface       *window,
+                                          gdouble          x,
+                                          gdouble          y,
+                                          gdouble         *parent_x,
+                                          gdouble         *parent_y);
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_coords_from_parent (GdkSurface       *window,
+                                          gdouble          parent_x,
+                                          gdouble          parent_y,
+                                          gdouble         *x,
+                                          gdouble         *y);
+
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_get_root_origin (GdkSurface     *window,
+                                         gint            *x,
+                                         gint            *y);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_get_frame_extents (GdkSurface     *window,
+                                            GdkRectangle  *rect);
+
+GDK_AVAILABLE_IN_ALL
+gint          gdk_surface_get_scale_factor  (GdkSurface     *window);
+
+GDK_AVAILABLE_IN_ALL
+GdkSurface *   gdk_surface_get_device_position (GdkSurface       *window,
+                                              GdkDevice       *device,
+                                              gint            *x,
+                                              gint            *y,
+                                              GdkModifierType *mask);
+GDK_AVAILABLE_IN_ALL
+GdkSurface *   gdk_surface_get_device_position_double (GdkSurface       *window,
+                                                     GdkDevice       *device,
+                                                     gdouble         *x,
+                                                     gdouble         *y,
+                                                     GdkModifierType *mask);
+GDK_AVAILABLE_IN_ALL
+GdkSurface *   gdk_surface_get_parent      (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+GdkSurface *   gdk_surface_get_toplevel    (GdkSurface       *window);
+
+GDK_AVAILABLE_IN_ALL
+GList *              gdk_surface_get_children   (GdkSurface      *window);
+GDK_AVAILABLE_IN_ALL
+GList *       gdk_surface_peek_children   (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+GList *       gdk_surface_get_children_with_user_data (GdkSurface *window,
+                                                     gpointer   user_data);
+
+GDK_AVAILABLE_IN_ALL
+GdkEventMask  gdk_surface_get_events    (GdkSurface      *window);
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_set_events     (GdkSurface      *window,
+                                         GdkEventMask     event_mask);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_device_events (GdkSurface    *window,
+                                            GdkDevice    *device,
+                                            GdkEventMask  event_mask);
+GDK_AVAILABLE_IN_ALL
+GdkEventMask  gdk_surface_get_device_events (GdkSurface    *window,
+                                            GdkDevice    *device);
+
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_icon_list   (GdkSurface       *window,
+                                         GList           *surfaces);
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_set_icon_name  (GdkSurface      *window, 
+                                         const gchar     *name);
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_set_group      (GdkSurface      *window, 
+                                         GdkSurface      *leader);
+GDK_AVAILABLE_IN_ALL
+GdkSurface*    gdk_surface_get_group    (GdkSurface      *window);
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_set_decorations (GdkSurface     *window,
+                                         GdkWMDecoration  decorations);
+GDK_AVAILABLE_IN_ALL
+gboolean      gdk_surface_get_decorations (GdkSurface       *window,
+                                         GdkWMDecoration *decorations);
+GDK_AVAILABLE_IN_ALL
+void         gdk_surface_set_functions  (GdkSurface      *window,
+                                         GdkWMFunction    functions);
+
+GDK_AVAILABLE_IN_ALL
+cairo_surface_t *
+              gdk_surface_create_similar_surface (GdkSurface *window,
+                                          cairo_content_t  content,
+                                          int              width,
+                                          int              height);
+GDK_AVAILABLE_IN_ALL
+cairo_surface_t *
+              gdk_surface_create_similar_image_surface (GdkSurface *window,
+                                                      cairo_format_t format,
+                                                      int            width,
+                                                      int            height,
+                                                      int            scale);
+
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_beep            (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_iconify         (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_deiconify       (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_stick           (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_unstick         (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_maximize        (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_unmaximize      (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_fullscreen      (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_fullscreen_on_monitor (GdkSurface      *window,
+                                                GdkMonitor     *monitor);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_fullscreen_mode (GdkSurface   *window,
+                                          GdkFullscreenMode mode);
+GDK_AVAILABLE_IN_ALL
+GdkFullscreenMode
+              gdk_surface_get_fullscreen_mode (GdkSurface   *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_unfullscreen    (GdkSurface       *window);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_keep_above  (GdkSurface       *window,
+                                          gboolean         setting);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_keep_below  (GdkSurface       *window,
+                                          gboolean         setting);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_set_opacity     (GdkSurface       *window,
+                                          gdouble          opacity);
+GDK_AVAILABLE_IN_ALL
+void          gdk_surface_register_dnd    (GdkSurface       *window);
+
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_begin_resize_drag            (GdkSurface     *window,
+                                              GdkSurfaceEdge  edge,
+                                              gint           button,
+                                              gint           root_x,
+                                              gint           root_y,
+                                              guint32        timestamp);
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_begin_resize_drag_for_device (GdkSurface     *window,
+                                              GdkSurfaceEdge  edge,
+                                              GdkDevice     *device,
+                                              gint           button,
+                                              gint           root_x,
+                                              gint           root_y,
+                                              guint32        timestamp);
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_begin_move_drag              (GdkSurface     *window,
+                                              gint           button,
+                                              gint           root_x,
+                                              gint           root_y,
+                                              guint32        timestamp);
+GDK_AVAILABLE_IN_ALL
+void gdk_surface_begin_move_drag_for_device   (GdkSurface     *window,
+                                              GdkDevice     *device,
+                                              gint           button,
+                                              gint           root_x,
+                                              gint           root_y,
+                                              guint32        timestamp);
+
+/* Interface for dirty-region queueing */
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_invalidate_rect           (GdkSurface          *window,
+                                                const GdkRectangle *rect,
+                                                gboolean            invalidate_children);
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_invalidate_region         (GdkSurface          *window,
+                                                const cairo_region_t    *region,
+                                                gboolean            invalidate_children);
+
+/**
+ * GdkSurfaceChildFunc:
+ * @window: a #GdkSurface
+ * @user_data: user data
+ *
+ * A function of this type is passed to gdk_surface_invalidate_maybe_recurse().
+ * It gets called for each child of the window to determine whether to
+ * recursively invalidate it or now.
+ *
+ * Returns: %TRUE to invalidate @window recursively
+ */
+typedef gboolean (*GdkSurfaceChildFunc)          (GdkSurface *window,
+                                                 gpointer   user_data);
+
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_invalidate_maybe_recurse  (GdkSurface            *window,
+                                                const cairo_region_t *region,
+                                                GdkSurfaceChildFunc    child_func,
+                                                gpointer              user_data);
+GDK_AVAILABLE_IN_ALL
+cairo_region_t *gdk_surface_get_update_area      (GdkSurface            *window);
+
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_freeze_updates      (GdkSurface    *window);
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_thaw_updates        (GdkSurface    *window);
+
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_constrain_size      (GdkGeometry    *geometry,
+                                           GdkSurfaceHints  flags,
+                                           gint            width,
+                                           gint            height,
+                                           gint           *new_width,
+                                           gint           *new_height);
+
+/* Multidevice support */
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_set_support_multidevice (GdkSurface *window,
+                                               gboolean   support_multidevice);
+GDK_AVAILABLE_IN_ALL
+gboolean   gdk_surface_get_support_multidevice (GdkSurface *window);
+
+/* Frame clock */
+GDK_AVAILABLE_IN_ALL
+GdkFrameClock* gdk_surface_get_frame_clock      (GdkSurface     *window);
+
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_set_opaque_region        (GdkSurface      *window,
+                                                cairo_region_t *region);
+
+GDK_AVAILABLE_IN_ALL
+void       gdk_surface_set_shadow_width         (GdkSurface      *window,
+                                                gint            left,
+                                                gint            right,
+                                                gint            top,
+                                                gint            bottom);
+GDK_AVAILABLE_IN_ALL
+gboolean  gdk_surface_show_window_menu          (GdkSurface      *window,
+                                                GdkEvent       *event);
+
+GDK_AVAILABLE_IN_ALL
+GdkGLContext * gdk_surface_create_gl_context    (GdkSurface      *window,
+                                                GError        **error);
+GDK_AVAILABLE_IN_ALL
+GdkVulkanContext *
+               gdk_surface_create_vulkan_context(GdkSurface      *window,
+                                                GError        **error);
+
+G_END_DECLS
+
+#endif /* __GDK_SURFACE_H__ */
diff --git a/gdk/gdksurfaceimpl.c b/gdk/gdksurfaceimpl.c
new file mode 100644 (file)
index 0000000..f5c3296
--- /dev/null
@@ -0,0 +1,347 @@
+/* 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include "config.h"
+
+#include "gdksurfaceimpl.h"
+
+#include "gdkinternals.h"
+
+
+G_DEFINE_TYPE (GdkSurfaceImpl, gdk_surface_impl, G_TYPE_OBJECT);
+
+static gboolean
+gdk_surface_impl_beep (GdkSurface *window)
+{
+  /* FALSE means windows can't beep, so the display will be
+   * made to beep instead. */
+  return FALSE;
+}
+
+static GdkDisplay *
+get_display_for_window (GdkSurface *primary,
+                        GdkSurface *secondary)
+{
+  GdkDisplay *display = gdk_surface_get_display (primary);
+
+  if (display)
+    return display;
+
+  display = gdk_surface_get_display (secondary);
+
+  if (display)
+    return display;
+
+  g_warning ("no display for window, using default");
+  return gdk_display_get_default ();
+}
+
+static GdkMonitor *
+get_monitor_for_rect (GdkDisplay         *display,
+                      const GdkRectangle *rect)
+{
+  gint biggest_area = G_MININT;
+  GdkMonitor *best_monitor = NULL;
+  GdkMonitor *monitor;
+  GdkRectangle workarea;
+  GdkRectangle intersection;
+  gint x;
+  gint y;
+  gint i;
+
+  for (i = 0; i < gdk_display_get_n_monitors (display); i++)
+    {
+      monitor = gdk_display_get_monitor (display, i);
+      gdk_monitor_get_workarea (monitor, &workarea);
+
+      if (gdk_rectangle_intersect (&workarea, rect, &intersection))
+        {
+          if (intersection.width * intersection.height > biggest_area)
+            {
+              biggest_area = intersection.width * intersection.height;
+              best_monitor = monitor;
+            }
+        }
+    }
+
+  if (best_monitor)
+    return best_monitor;
+
+  x = rect->x + rect->width / 2;
+  y = rect->y + rect->height / 2;
+
+  return gdk_display_get_monitor_at_point (display, x, y);
+}
+
+static gint
+get_anchor_x_sign (GdkGravity anchor)
+{
+  switch (anchor)
+    {
+    case GDK_GRAVITY_STATIC:
+    case GDK_GRAVITY_NORTH_WEST:
+    case GDK_GRAVITY_WEST:
+    case GDK_GRAVITY_SOUTH_WEST:
+      return -1;
+
+    default:
+    case GDK_GRAVITY_NORTH:
+    case GDK_GRAVITY_CENTER:
+    case GDK_GRAVITY_SOUTH:
+      return 0;
+
+    case GDK_GRAVITY_NORTH_EAST:
+    case GDK_GRAVITY_EAST:
+    case GDK_GRAVITY_SOUTH_EAST:
+      return 1;
+    }
+}
+
+static gint
+get_anchor_y_sign (GdkGravity anchor)
+{
+  switch (anchor)
+    {
+    case GDK_GRAVITY_STATIC:
+    case GDK_GRAVITY_NORTH_WEST:
+    case GDK_GRAVITY_NORTH:
+    case GDK_GRAVITY_NORTH_EAST:
+      return -1;
+
+    default:
+    case GDK_GRAVITY_WEST:
+    case GDK_GRAVITY_CENTER:
+    case GDK_GRAVITY_EAST:
+      return 0;
+
+    case GDK_GRAVITY_SOUTH_WEST:
+    case GDK_GRAVITY_SOUTH:
+    case GDK_GRAVITY_SOUTH_EAST:
+      return 1;
+    }
+}
+
+static gint
+maybe_flip_position (gint      bounds_pos,
+                     gint      bounds_size,
+                     gint      rect_pos,
+                     gint      rect_size,
+                     gint      window_size,
+                     gint      rect_sign,
+                     gint      window_sign,
+                     gint      offset,
+                     gboolean  flip,
+                     gboolean *flipped)
+{
+  gint primary;
+  gint secondary;
+
+  *flipped = FALSE;
+  primary = rect_pos + (1 + rect_sign) * rect_size / 2 + offset - (1 + window_sign) * window_size / 2;
+
+  if (!flip || (primary >= bounds_pos && primary + window_size <= bounds_pos + bounds_size))
+    return primary;
+
+  *flipped = TRUE;
+  secondary = rect_pos + (1 - rect_sign) * rect_size / 2 - offset - (1 - window_sign) * window_size / 2;
+
+  if (secondary >= bounds_pos && secondary + window_size <= bounds_pos + bounds_size)
+    return secondary;
+
+  *flipped = FALSE;
+  return primary;
+}
+
+static GdkSurface *
+traverse_to_toplevel (GdkSurface *window,
+                      gint       x,
+                      gint       y,
+                      gint      *toplevel_x,
+                      gint      *toplevel_y)
+{
+  GdkSurface *parent;
+  gdouble xf = x;
+  gdouble yf = y;
+
+  while ((parent = window->parent) != NULL &&
+         (gdk_surface_get_window_type (parent) != GDK_SURFACE_ROOT))
+    {
+      gdk_surface_coords_to_parent (window, xf, yf, &xf, &yf);
+      window = parent;
+    }
+
+  *toplevel_x = (gint) xf;
+  *toplevel_y = (gint) yf;
+  return window;
+}
+
+static void
+gdk_surface_impl_move_to_rect (GdkSurface          *window,
+                              const GdkRectangle *rect,
+                              GdkGravity          rect_anchor,
+                              GdkGravity          window_anchor,
+                              GdkAnchorHints      anchor_hints,
+                              gint                rect_anchor_dx,
+                              gint                rect_anchor_dy)
+{
+  GdkSurface *transient_for_toplevel;
+  GdkDisplay *display;
+  GdkMonitor *monitor;
+  GdkRectangle bounds;
+  GdkRectangle root_rect = *rect;
+  GdkRectangle flipped_rect;
+  GdkRectangle final_rect;
+  gboolean flipped_x;
+  gboolean flipped_y;
+
+  /*
+   * First translate the anchor rect to toplevel coordinates. This is needed
+   * because not all backends will be able to get root coordinates for
+   * non-toplevel windows.
+   */
+  transient_for_toplevel = traverse_to_toplevel (window->transient_for,
+                                                 root_rect.x,
+                                                 root_rect.y,
+                                                 &root_rect.x,
+                                                 &root_rect.y);
+
+  gdk_surface_get_root_coords (transient_for_toplevel,
+                              root_rect.x,
+                              root_rect.y,
+                              &root_rect.x,
+                              &root_rect.y);
+
+  display = get_display_for_window (window, window->transient_for);
+  monitor = get_monitor_for_rect (display, &root_rect);
+  gdk_monitor_get_workarea (monitor, &bounds);
+
+  flipped_rect.width = window->width - window->shadow_left - window->shadow_right;
+  flipped_rect.height = window->height - window->shadow_top - window->shadow_bottom;
+  flipped_rect.x = maybe_flip_position (bounds.x,
+                                        bounds.width,
+                                        root_rect.x,
+                                        root_rect.width,
+                                        flipped_rect.width,
+                                        get_anchor_x_sign (rect_anchor),
+                                        get_anchor_x_sign (window_anchor),
+                                        rect_anchor_dx,
+                                        anchor_hints & GDK_ANCHOR_FLIP_X,
+                                        &flipped_x);
+  flipped_rect.y = maybe_flip_position (bounds.y,
+                                        bounds.height,
+                                        root_rect.y,
+                                        root_rect.height,
+                                        flipped_rect.height,
+                                        get_anchor_y_sign (rect_anchor),
+                                        get_anchor_y_sign (window_anchor),
+                                        rect_anchor_dy,
+                                        anchor_hints & GDK_ANCHOR_FLIP_Y,
+                                        &flipped_y);
+
+  final_rect = flipped_rect;
+
+  if (anchor_hints & GDK_ANCHOR_SLIDE_X)
+    {
+      if (final_rect.x + final_rect.width > bounds.x + bounds.width)
+        final_rect.x = bounds.x + bounds.width - final_rect.width;
+
+      if (final_rect.x < bounds.x)
+        final_rect.x = bounds.x;
+    }
+
+  if (anchor_hints & GDK_ANCHOR_SLIDE_Y)
+    {
+      if (final_rect.y + final_rect.height > bounds.y + bounds.height)
+        final_rect.y = bounds.y + bounds.height - final_rect.height;
+
+      if (final_rect.y < bounds.y)
+        final_rect.y = bounds.y;
+    }
+
+  if (anchor_hints & GDK_ANCHOR_RESIZE_X)
+    {
+      if (final_rect.x < bounds.x)
+        {
+          final_rect.width -= bounds.x - final_rect.x;
+          final_rect.x = bounds.x;
+        }
+
+      if (final_rect.x + final_rect.width > bounds.x + bounds.width)
+        final_rect.width = bounds.x + bounds.width - final_rect.x;
+    }
+
+  if (anchor_hints & GDK_ANCHOR_RESIZE_Y)
+    {
+      if (final_rect.y < bounds.y)
+        {
+          final_rect.height -= bounds.y - final_rect.y;
+          final_rect.y = bounds.y;
+        }
+
+      if (final_rect.y + final_rect.height > bounds.y + bounds.height)
+        final_rect.height = bounds.y + bounds.height - final_rect.y;
+    }
+
+  flipped_rect.x -= window->shadow_left;
+  flipped_rect.y -= window->shadow_top;
+  flipped_rect.width += window->shadow_left + window->shadow_right;
+  flipped_rect.height += window->shadow_top + window->shadow_bottom;
+
+  final_rect.x -= window->shadow_left;
+  final_rect.y -= window->shadow_top;
+  final_rect.width += window->shadow_left + window->shadow_right;
+  final_rect.height += window->shadow_top + window->shadow_bottom;
+
+  if (final_rect.width != window->width || final_rect.height != window->height)
+    gdk_surface_move_resize (window, final_rect.x, final_rect.y, final_rect.width, final_rect.height);
+  else
+    gdk_surface_move (window, final_rect.x, final_rect.y);
+
+  g_signal_emit_by_name (window,
+                         "moved-to-rect",
+                         &flipped_rect,
+                         &final_rect,
+                         flipped_x,
+                         flipped_y);
+}
+
+static void
+gdk_surface_impl_process_updates_recurse (GdkSurface      *window,
+                                         cairo_region_t *region)
+{
+  _gdk_surface_process_updates_recurse (window, region);
+}
+
+static void
+gdk_surface_impl_class_init (GdkSurfaceImplClass *impl_class)
+{
+  impl_class->beep = gdk_surface_impl_beep;
+  impl_class->move_to_rect = gdk_surface_impl_move_to_rect;
+  impl_class->process_updates_recurse = gdk_surface_impl_process_updates_recurse;
+}
+
+static void
+gdk_surface_impl_init (GdkSurfaceImpl *impl)
+{
+}
diff --git a/gdk/gdksurfaceimpl.h b/gdk/gdksurfaceimpl.h
new file mode 100644 (file)
index 0000000..7a1dcb4
--- /dev/null
@@ -0,0 +1,256 @@
+/* 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GDK_SURFACE_IMPL_H__
+#define __GDK_SURFACE_IMPL_H__
+
+#include <gdk/gdksurface.h>
+#include <gdk/gdkproperty.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_SURFACE_IMPL           (gdk_surface_impl_get_type ())
+#define GDK_SURFACE_IMPL(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL, GdkSurfaceImpl))
+#define GDK_SURFACE_IMPL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL, GdkSurfaceImplClass))
+#define GDK_IS_SURFACE_IMPL(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL))
+#define GDK_IS_SURFACE_IMPL_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL))
+#define GDK_SURFACE_IMPL_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL, GdkSurfaceImplClass))
+
+typedef struct _GdkSurfaceImpl       GdkSurfaceImpl;
+typedef struct _GdkSurfaceImplClass  GdkSurfaceImplClass;
+
+struct _GdkSurfaceImpl
+{
+  GObject parent;
+};
+
+struct _GdkSurfaceImplClass
+{
+  GObjectClass parent_class;
+
+  cairo_surface_t *
+               (* ref_cairo_surface)    (GdkSurface       *window);
+  cairo_surface_t *
+               (* create_similar_image_surface) (GdkSurface *     window,
+                                                 cairo_format_t  format,
+                                                 int             width,
+                                                 int             height);
+
+  void         (* show)                 (GdkSurface       *window,
+                                        gboolean         already_mapped);
+  void         (* hide)                 (GdkSurface       *window);
+  void         (* withdraw)             (GdkSurface       *window);
+  void         (* raise)                (GdkSurface       *window);
+  void         (* lower)                (GdkSurface       *window);
+  void         (* restack_toplevel)     (GdkSurface       *window,
+                                        GdkSurface       *sibling,
+                                        gboolean        above);
+
+  void         (* move_resize)          (GdkSurface       *window,
+                                         gboolean         with_move,
+                                         gint             x,
+                                         gint             y,
+                                         gint             width,
+                                         gint             height);
+  void         (* move_to_rect)         (GdkSurface       *window,
+                                         const GdkRectangle *rect,
+                                         GdkGravity       rect_anchor,
+                                         GdkGravity       window_anchor,
+                                         GdkAnchorHints   anchor_hints,
+                                         gint             rect_anchor_dx,
+                                         gint             rect_anchor_dy);
+
+  GdkEventMask (* get_events)           (GdkSurface       *window);
+  void         (* set_events)           (GdkSurface       *window,
+                                         GdkEventMask     event_mask);
+
+  void         (* get_geometry)         (GdkSurface       *window,
+                                         gint            *x,
+                                         gint            *y,
+                                         gint            *width,
+                                         gint            *height);
+  void         (* get_root_coords)      (GdkSurface       *window,
+                                        gint             x,
+                                        gint             y,
+                                         gint            *root_x,
+                                         gint            *root_y);
+  gboolean     (* get_device_state)     (GdkSurface       *window,
+                                         GdkDevice       *device,
+                                         gdouble         *x,
+                                         gdouble         *y,
+                                         GdkModifierType *mask);
+  gboolean    (* begin_paint)           (GdkSurface       *window);
+  void        (* end_paint)             (GdkSurface       *window);
+
+  void         (* shape_combine_region) (GdkSurface       *window,
+                                         const cairo_region_t *shape_region,
+                                         gint             offset_x,
+                                         gint             offset_y);
+  void         (* input_shape_combine_region) (GdkSurface       *window,
+                                              const cairo_region_t *shape_region,
+                                              gint             offset_x,
+                                              gint             offset_y);
+
+  /* Called before processing updates for a window. This gives the windowing
+   * layer a chance to save the region for later use in avoiding duplicate
+   * exposes.
+   */
+  void     (* queue_antiexpose)     (GdkSurface       *window,
+                                     cairo_region_t  *update_area);
+
+/* Called to do the windowing system specific part of gdk_surface_destroy(),
+ *
+ * window: The window being destroyed
+ * recursing: If TRUE, then this is being called because a parent
+ *     was destroyed. This generally means that the call to the windowing
+ *     system to destroy the window can be omitted, since it will be
+ *     destroyed as a result of the parent being destroyed.
+ *     Unless @foreign_destroy
+ * foreign_destroy: If TRUE, the window or a parent was destroyed by some
+ *     external agency. The window has already been destroyed and no
+ *     windowing system calls should be made. (This may never happen
+ *     for some windowing systems.)
+ */
+  void         (* destroy)              (GdkSurface       *window,
+                                        gboolean         recursing,
+                                        gboolean         foreign_destroy);
+
+
+  /* optional */
+  gboolean     (* beep)                 (GdkSurface       *window);
+
+  void         (* focus)                (GdkSurface       *window,
+                                        guint32          timestamp);
+  void         (* set_type_hint)        (GdkSurface       *window,
+                                        GdkSurfaceTypeHint hint);
+  GdkSurfaceTypeHint (* get_type_hint)   (GdkSurface       *window);
+  void         (* set_modal_hint)       (GdkSurface *window,
+                                        gboolean   modal);
+  void         (* set_skip_taskbar_hint) (GdkSurface *window,
+                                         gboolean   skips_taskbar);
+  void         (* set_skip_pager_hint)  (GdkSurface *window,
+                                        gboolean   skips_pager);
+  void         (* set_urgency_hint)     (GdkSurface *window,
+                                        gboolean   urgent);
+  void         (* set_geometry_hints)   (GdkSurface         *window,
+                                        const GdkGeometry *geometry,
+                                        GdkSurfaceHints     geom_mask);
+  void         (* set_title)            (GdkSurface   *window,
+                                        const gchar *title);
+  void         (* set_role)             (GdkSurface   *window,
+                                        const gchar *role);
+  void         (* set_startup_id)       (GdkSurface   *window,
+                                        const gchar *startup_id);
+  void         (* set_transient_for)    (GdkSurface *window,
+                                        GdkSurface *parent);
+  void         (* get_frame_extents)    (GdkSurface    *window,
+                                        GdkRectangle *rect);
+  void         (* set_accept_focus)     (GdkSurface *window,
+                                        gboolean accept_focus);
+  void         (* set_focus_on_map)     (GdkSurface *window,
+                                        gboolean focus_on_map);
+  void         (* set_icon_list)        (GdkSurface *window,
+                                        GList     *pixbufs);
+  void         (* set_icon_name)        (GdkSurface   *window,
+                                        const gchar *name);
+  void         (* iconify)              (GdkSurface *window);
+  void         (* deiconify)            (GdkSurface *window);
+  void         (* stick)                (GdkSurface *window);
+  void         (* unstick)              (GdkSurface *window);
+  void         (* maximize)             (GdkSurface *window);
+  void         (* unmaximize)           (GdkSurface *window);
+  void         (* fullscreen)           (GdkSurface *window);
+  void         (* fullscreen_on_monitor) (GdkSurface  *window,
+                                          GdkMonitor *monitor);
+  void         (* apply_fullscreen_mode) (GdkSurface *window);
+  void         (* unfullscreen)         (GdkSurface *window);
+  void         (* set_keep_above)       (GdkSurface *window,
+                                        gboolean   setting);
+  void         (* set_keep_below)       (GdkSurface *window,
+                                        gboolean   setting);
+  GdkSurface *  (* get_group)            (GdkSurface *window);
+  void         (* set_group)            (GdkSurface *window,
+                                        GdkSurface *leader);
+  void         (* set_decorations)      (GdkSurface      *window,
+                                        GdkWMDecoration decorations);
+  gboolean     (* get_decorations)      (GdkSurface       *window,
+                                        GdkWMDecoration *decorations);
+  void         (* set_functions)        (GdkSurface    *window,
+                                        GdkWMFunction functions);
+  void         (* begin_resize_drag)    (GdkSurface     *window,
+                                         GdkSurfaceEdge  edge,
+                                         GdkDevice     *device,
+                                         gint           button,
+                                         gint           root_x,
+                                         gint           root_y,
+                                         guint32        timestamp);
+  void         (* begin_move_drag)      (GdkSurface *window,
+                                         GdkDevice     *device,
+                                         gint       button,
+                                         gint       root_x,
+                                         gint       root_y,
+                                         guint32    timestamp);
+  void         (* enable_synchronized_configure) (GdkSurface *window);
+  void         (* configure_finished)   (GdkSurface *window);
+  void         (* set_opacity)          (GdkSurface *window,
+                                        gdouble    opacity);
+  void         (* destroy_notify)       (GdkSurface *window);
+  void         (* register_dnd)         (GdkSurface *window);
+  GdkDragContext * (*drag_begin)        (GdkSurface        *window,
+                                         GdkDevice        *device,
+                                         GdkContentProvider*content,
+                                         GdkDragAction     actions,
+                                         gint              dx,
+                                         gint              dy);
+
+  void         (*process_updates_recurse) (GdkSurface      *window,
+                                           cairo_region_t *region);
+
+  gint         (* get_scale_factor)       (GdkSurface      *window);
+  void         (* get_unscaled_size)      (GdkSurface      *window,
+                                           int            *unscaled_width,
+                                           int            *unscaled_height);
+
+  void         (* set_opaque_region)      (GdkSurface      *window,
+                                           cairo_region_t *region);
+  void         (* set_shadow_width)       (GdkSurface      *window,
+                                           gint            left,
+                                           gint            right,
+                                           gint            top,
+                                           gint            bottom);
+  gboolean     (* show_window_menu)       (GdkSurface      *window,
+                                           GdkEvent       *event);
+  GdkGLContext *(*create_gl_context)      (GdkSurface      *window,
+                                          gboolean        attached,
+                                           GdkGLContext   *share,
+                                           GError        **error);
+  gboolean     (* supports_edge_constraints)(GdkSurface    *window);
+};
+
+/* Interface Functions */
+GType gdk_surface_impl_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GDK_SURFACE_IMPL_H__ */
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
deleted file mode 100644 (file)
index 3eea491..0000000
+++ /dev/null
@@ -1,6957 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
- * Josh MacDonald, Ryan Lortie
- *
- * 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-#include "config.h"
-
-#include <cairo-gobject.h>
-
-#include "gdkwindow.h"
-
-#include "gdkrectangle.h"
-#include "gdkinternals.h"
-#include "gdkintl.h"
-#include "gdkdisplayprivate.h"
-#include "gdkdeviceprivate.h"
-#include "gdkmarshalers.h"
-#include "gdkframeclockidle.h"
-#include "gdkwindowimpl.h"
-#include "gdkglcontextprivate.h"
-#include "gdkdrawingcontextprivate.h"
-#include "gdk-private.h"
-
-#include <math.h>
-
-#include <epoxy/gl.h>
-
-/* for the use of round() */
-#include "fallback-c89.c"
-
-#ifdef GDK_WINDOWING_WAYLAND
-#include "wayland/gdkwayland.h"
-#endif
-
-#undef DEBUG_WINDOW_PRINTING
-
-
-/**
- * SECTION:windows
- * @Short_description: Onscreen display areas in the target window system
- * @Title: Windows
- *
- * A #GdkSurface is a (usually) rectangular region on the screen.
- * It’s a low-level object, used to implement high-level objects such as
- * #GtkWidget and #GtkWindow on the GTK+ level. A #GtkWindow is a toplevel
- * window, the thing a user might think of as a â€świndow” with a titlebar
- * and so on; a #GtkWindow may contain many sub-GdkSurfaces.
- */
-
-/**
- * GdkSurface:
- *
- * The GdkSurface struct contains only private fields and
- * should not be accessed directly.
- */
-
-/* Historically a GdkSurface always matches a platform native window,
- * be it a toplevel window or a child window. In this setup the
- * GdkSurface (and other GdkDrawables) were platform independent classes,
- * and the actual platform specific implementation was in a delegate
- * object available as â€śimpl” in the window object.
- *
- * With the addition of client side windows this changes a bit. The
- * application-visible GdkSurface object behaves as it did before, but
- * such windows now don't a corresponding native window. Instead subwindows
- * windows are â€śclient side”, i.e. emulated by the gdk code such
- * that clipping, drawing, moving, events etc work as expected.
- *
- * GdkSurfaces have a pointer to the â€śimpl window” they are in, i.e.
- * the topmost GdkSurface which have the same â€śimpl” value. This is stored
- * in impl_window, which is different from the window itself only for client
- * side windows.
- * All GdkSurfaces (native or not) track the position of the window in the parent
- * (x, y), the size of the window (width, height), the position of the window
- * with respect to the impl window (abs_x, abs_y). We also track the clip
- * region of the window wrt parent windows, in window-relative coordinates (clip_region).
- */
-
-enum {
-  MOVED_TO_RECT,
-  LAST_SIGNAL
-};
-
-enum {
-  PROP_0,
-  PROP_CURSOR,
-  PROP_DISPLAY,
-  PROP_STATE,
-  LAST_PROP
-};
-
-/* Global info */
-
-static void gdk_surface_finalize   (GObject              *object);
-
-static void gdk_surface_set_property (GObject      *object,
-                                     guint         prop_id,
-                                     const GValue *value,
-                                     GParamSpec   *pspec);
-static void gdk_surface_get_property (GObject      *object,
-                                     guint         prop_id,
-                                     GValue       *value,
-                                     GParamSpec   *pspec);
-
-static void gdk_surface_clear_backing_region (GdkSurface *window);
-
-static void recompute_visible_regions   (GdkSurface *private,
-                                        gboolean recalculate_children);
-static void gdk_surface_invalidate_in_parent (GdkSurface *private);
-static void update_cursor               (GdkDisplay *display,
-                                         GdkDevice  *device);
-static void impl_window_add_update_area (GdkSurface *impl_window,
-                                        cairo_region_t *region);
-static void gdk_surface_invalidate_region_full (GdkSurface       *window,
-                                              const cairo_region_t *region,
-                                              gboolean         invalidate_children);
-static void gdk_surface_invalidate_rect_full (GdkSurface          *window,
-                                            const GdkRectangle *rect,
-                                            gboolean            invalidate_children);
-static cairo_surface_t *gdk_surface_ref_impl_surface (GdkSurface *window);
-
-static void gdk_surface_set_frame_clock (GdkSurface      *window,
-                                        GdkFrameClock  *clock);
-
-
-static guint signals[LAST_SIGNAL] = { 0 };
-static GParamSpec *properties[LAST_PROP] = { NULL, };
-
-G_DEFINE_ABSTRACT_TYPE (GdkSurface, gdk_surface, G_TYPE_OBJECT)
-
-#ifdef DEBUG_WINDOW_PRINTING
-char *
-print_region (cairo_region_t *region)
-{
-  GString *s = g_string_new ("{");
-  if (cairo_region_is_empty (region))
-    {
-      g_string_append (s, "empty");
-    }
-  else
-    {
-      int num = cairo_region_num_rectangles (region);
-      cairo_rectangle_int_t r;
-
-      if (num == 1)
-       {
-         cairo_region_get_rectangle (region, 0, &r);
-         g_string_append_printf (s, "%dx%d @%d,%d", r.width, r.height, r.x, r.y);
-       }
-      else
-       {
-         int i;
-         cairo_region_get_extents (region, &r);
-         g_string_append_printf (s, "extent: %dx%d @%d,%d, details: ", r.width, r.height, r.x, r.y);
-         for (i = 0; i < num; i++)
-           {
-              cairo_region_get_rectangle (region, i, &r);
-             g_string_append_printf (s, "[%dx%d @%d,%d]", r.width, r.height, r.x, r.y);
-             if (i != num -1)
-               g_string_append (s, ", ");
-           }
-       }
-    }
-  g_string_append (s, "}");
-  return g_string_free (s, FALSE);
-}
-#endif
-
-static GList *
-list_insert_link_before (GList *list,
-                         GList *sibling,
-                         GList *link)
-{
-  if (list == NULL || sibling == list)
-    {
-      link->prev = NULL;
-      link->next = list;
-      if (list)
-        list->prev = link;
-      return link;
-    }
-  else if (sibling == NULL)
-    {
-      GList *last = g_list_last (list);
-
-      last->next = link;
-      link->prev = last;
-      link->next = NULL;
-
-      return list;
-    }
-  else
-    {
-      link->next = sibling;
-      link->prev = sibling->prev;
-      sibling->prev = link;
-
-      if (link->prev)
-        link->prev->next = link;
-
-      return list;
-    }
-}
-
-static void
-gdk_surface_init (GdkSurface *window)
-{
-  /* 0-initialization is good for all other fields. */
-
-  window->window_type = GDK_SURFACE_CHILD;
-
-  window->state = GDK_SURFACE_STATE_WITHDRAWN;
-  window->fullscreen_mode = GDK_FULLSCREEN_ON_CURRENT_MONITOR;
-  window->width = 1;
-  window->height = 1;
-  window->toplevel_window_type = -1;
-  window->children_list_node.data = window;
-
-  window->device_cursor = g_hash_table_new_full (NULL, NULL,
-                                                 NULL, g_object_unref);
-}
-
-static void
-gdk_surface_class_init (GdkSurfaceClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-  object_class->finalize = gdk_surface_finalize;
-  object_class->set_property = gdk_surface_set_property;
-  object_class->get_property = gdk_surface_get_property;
-
-  /* Properties */
-
-  /**
-   * GdkSurface:cursor:
-   *
-   * The mouse pointer for a #GdkSurface. See gdk_surface_set_cursor() and
-   * gdk_surface_get_cursor() for details.
-   */
-  properties[PROP_CURSOR] =
-      g_param_spec_object ("cursor",
-                           P_("Cursor"),
-                           P_("Cursor"),
-                           GDK_TYPE_CURSOR,
-                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-  /**
-   * GdkSurface:display:
-   *
-   * The #GdkDisplay connection of the window. See gdk_surface_get_display()
-   * for details.
-   */
-  properties[PROP_DISPLAY] =
-      g_param_spec_object ("display",
-                           P_("Display"),
-                           P_("Display"),
-                           GDK_TYPE_DISPLAY,
-                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
-  properties[PROP_STATE] =
-      g_param_spec_flags ("state",
-                          P_("State"),
-                          P_("State"),
-                          GDK_TYPE_SURFACE_STATE, GDK_SURFACE_STATE_WITHDRAWN,
-                          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-  g_object_class_install_properties (object_class, LAST_PROP, properties);
-
-  /**
-   * GdkSurface::moved-to-rect:
-   * @window: the #GdkSurface that moved
-   * @flipped_rect: (nullable): the position of @window after any possible
-   *                flipping or %NULL if the backend can't obtain it
-   * @final_rect: (nullable): the final position of @window or %NULL if the
-   *              backend can't obtain it
-   * @flipped_x: %TRUE if the anchors were flipped horizontally
-   * @flipped_y: %TRUE if the anchors were flipped vertically
-   *
-   * Emitted when the position of @window is finalized after being moved to a
-   * destination rectangle.
-   *
-   * @window might be flipped over the destination rectangle in order to keep
-   * it on-screen, in which case @flipped_x and @flipped_y will be set to %TRUE
-   * accordingly.
-   *
-   * @flipped_rect is the ideal position of @window after any possible
-   * flipping, but before any possible sliding. @final_rect is @flipped_rect,
-   * but possibly translated in the case that flipping is still ineffective in
-   * keeping @window on-screen.
-   * Stability: Private
-   */
-  signals[MOVED_TO_RECT] =
-    g_signal_new (g_intern_static_string ("moved-to-rect"),
-                  G_OBJECT_CLASS_TYPE (object_class),
-                  G_SIGNAL_RUN_FIRST,
-                  0,
-                  NULL,
-                  NULL,
-                  _gdk_marshal_VOID__POINTER_POINTER_BOOLEAN_BOOLEAN,
-                  G_TYPE_NONE,
-                  4,
-                  G_TYPE_POINTER,
-                  G_TYPE_POINTER,
-                  G_TYPE_BOOLEAN,
-                  G_TYPE_BOOLEAN);
-}
-
-static void
-seat_removed_cb (GdkDisplay *display,
-                 GdkSeat    *seat,
-                 GdkSurface  *window)
-{
-  GdkDevice *device = gdk_seat_get_pointer (seat);
-
-  window->devices_inside = g_list_remove (window->devices_inside, device);
-  g_hash_table_remove (window->device_cursor, device);
-
-  if (window->device_events)
-    g_hash_table_remove (window->device_events, device);
-}
-
-static void
-gdk_surface_finalize (GObject *object)
-{
-  GdkSurface *window = GDK_SURFACE (object);
-
-  g_signal_handlers_disconnect_by_func (gdk_surface_get_display (window),
-                                        seat_removed_cb, window);
-
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      if (GDK_SURFACE_TYPE (window) != GDK_SURFACE_FOREIGN)
-       {
-         g_warning ("losing last reference to undestroyed window");
-         _gdk_surface_destroy (window, FALSE);
-       }
-      else
-       /* We use TRUE here, to keep us from actually calling
-        * XDestroyWindow() on the window
-        */
-       _gdk_surface_destroy (window, TRUE);
-    }
-
-  if (window->impl)
-    {
-      g_object_unref (window->impl);
-      window->impl = NULL;
-    }
-
-  if (window->impl_window != window)
-    {
-      g_object_unref (window->impl_window);
-      window->impl_window = NULL;
-    }
-
-  if (window->shape)
-    cairo_region_destroy (window->shape);
-
-  if (window->input_shape)
-    cairo_region_destroy (window->input_shape);
-
-  if (window->cursor)
-    g_object_unref (window->cursor);
-
-  if (window->device_cursor)
-    g_hash_table_destroy (window->device_cursor);
-
-  if (window->device_events)
-    g_hash_table_destroy (window->device_events);
-
-  if (window->devices_inside)
-    g_list_free (window->devices_inside);
-
-  g_clear_object (&window->display);
-
-  if (window->opaque_region)
-    cairo_region_destroy (window->opaque_region);
-
-  G_OBJECT_CLASS (gdk_surface_parent_class)->finalize (object);
-}
-
-static void
-gdk_surface_set_property (GObject      *object,
-                         guint         prop_id,
-                         const GValue *value,
-                         GParamSpec   *pspec)
-{
-  GdkSurface *window = GDK_SURFACE (object);
-
-  switch (prop_id)
-    {
-    case PROP_CURSOR:
-      gdk_surface_set_cursor (window, g_value_get_object (value));
-      break;
-
-    case PROP_DISPLAY:
-      window->display = g_value_dup_object (value);
-      g_assert (window->display != NULL);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-gdk_surface_get_property (GObject    *object,
-                         guint       prop_id,
-                         GValue     *value,
-                         GParamSpec *pspec)
-{
-  GdkSurface *window = GDK_SURFACE (object);
-
-  switch (prop_id)
-    {
-    case PROP_CURSOR:
-      g_value_set_object (value, gdk_surface_get_cursor (window));
-      break;
-
-    case PROP_DISPLAY:
-      g_value_set_object (value, window->display);
-      break;
-
-    case PROP_STATE:
-      g_value_set_flags (value, window->state);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static gboolean
-gdk_surface_is_subsurface (GdkSurface *window)
-{
-   return window->window_type == GDK_SURFACE_SUBSURFACE;
-}
-
-static GdkSurface *
-gdk_surface_get_impl_window (GdkSurface *window)
-{
-  return window->impl_window;
-}
-
-GdkSurface *
-_gdk_surface_get_impl_window (GdkSurface *window)
-{
-  return gdk_surface_get_impl_window (window);
-}
-
-static gboolean
-gdk_surface_has_impl (GdkSurface *window)
-{
-  return window->impl_window == window;
-}
-
-static gboolean
-gdk_surface_is_toplevel (GdkSurface *window)
-{
-  return
-    window->parent == NULL ||
-    window->parent->window_type == GDK_SURFACE_ROOT;
-}
-
-gboolean
-_gdk_surface_has_impl (GdkSurface *window)
-{
-  return gdk_surface_has_impl (window);
-}
-
-static gboolean
-gdk_surface_has_no_impl (GdkSurface *window)
-{
-  return window->impl_window != window;
-}
-
-static void
-remove_sibling_overlapped_area (GdkSurface *window,
-                               cairo_region_t *region)
-{
-  GdkSurface *parent;
-  GdkSurface *sibling;
-  cairo_region_t *child_region;
-  GdkRectangle r;
-  GList *l;
-
-  parent = window->parent;
-
-  if (gdk_surface_is_toplevel (window))
-    return;
-
-  /* Convert from from window coords to parent coords */
-  cairo_region_translate (region, window->x, window->y);
-
-  for (l = parent->children; l; l = l->next)
-    {
-      sibling = l->data;
-
-      if (sibling == window)
-       break;
-
-      if (!GDK_SURFACE_IS_MAPPED (sibling) || sibling->input_only)
-       continue;
-
-      r.x = sibling->x;
-      r.y = sibling->y;
-      r.width = sibling->width;
-      r.height = sibling->height;
-
-      child_region = cairo_region_create_rectangle (&r);
-
-      if (sibling->shape)
-       {
-         /* Adjust shape region to parent window coords */
-         cairo_region_translate (sibling->shape, sibling->x, sibling->y);
-         cairo_region_intersect (child_region, sibling->shape);
-         cairo_region_translate (sibling->shape, -sibling->x, -sibling->y);
-       }
-
-      cairo_region_subtract (region, child_region);
-      cairo_region_destroy (child_region);
-    }
-
-  remove_sibling_overlapped_area (parent, region);
-
-  /* Convert back to window coords */
-  cairo_region_translate (region, -window->x, -window->y);
-}
-
-static void
-remove_child_area (GdkSurface *window,
-                  gboolean for_input,
-                  cairo_region_t *region)
-{
-  GdkSurface *child;
-  cairo_region_t *child_region;
-  GdkRectangle r;
-  GList *l;
-
-  for (l = window->children; l; l = l->next)
-    {
-      child = l->data;
-
-      /* If region is empty already, no need to do
-        anything potentially costly */
-      if (cairo_region_is_empty (region))
-       break;
-
-      if (!GDK_SURFACE_IS_MAPPED (child) || child->input_only)
-       continue;
-
-      r.x = child->x;
-      r.y = child->y;
-      r.width = child->width;
-      r.height = child->height;
-
-      /* Bail early if child totally outside region */
-      if (cairo_region_contains_rectangle (region, &r) == CAIRO_REGION_OVERLAP_OUT)
-       continue;
-
-      child_region = cairo_region_create_rectangle (&r);
-
-      if (child->shape)
-       {
-         /* Adjust shape region to parent window coords */
-         cairo_region_translate (child->shape, child->x, child->y);
-         cairo_region_intersect (child_region, child->shape);
-         cairo_region_translate (child->shape, -child->x, -child->y);
-       }
-
-      if (for_input)
-       {
-         if (child->input_shape)
-           cairo_region_intersect (child_region, child->input_shape);
-       }
-
-      cairo_region_subtract (region, child_region);
-      cairo_region_destroy (child_region);
-    }
-}
-
-static gboolean
-should_apply_clip_as_shape (GdkSurface *window)
-{
-  return
-    gdk_surface_has_impl (window) &&
-    /* Not for non-shaped toplevels */
-    (window->shape != NULL || window->applied_shape) &&
-    /* or for foreign windows */
-    window->window_type != GDK_SURFACE_FOREIGN &&
-    /* or for the root window */
-    window->window_type != GDK_SURFACE_ROOT;
-}
-
-static void
-apply_shape (GdkSurface *window,
-            cairo_region_t *region)
-{
-  GdkSurfaceImplClass *impl_class;
-
-  /* We trash whether we applied a shape so that
-     we can avoid unsetting it many times, which
-     could happen in e.g. apply_clip_as_shape as
-     windows get resized */
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-  if (region)
-    impl_class->shape_combine_region (window,
-                                     region, 0, 0);
-  else if (window->applied_shape)
-    impl_class->shape_combine_region (window,
-                                     NULL, 0, 0);
-
-  window->applied_shape = region != NULL;
-}
-
-static gboolean
-region_rect_equal (const cairo_region_t *region,
-                   const GdkRectangle *rect)
-{
-    GdkRectangle extents;
-
-    if (cairo_region_num_rectangles (region) != 1)
-        return FALSE;
-
-    cairo_region_get_extents (region, &extents);
-
-    return extents.x == rect->x &&
-        extents.y == rect->y &&
-        extents.width == rect->width &&
-        extents.height == rect->height;
-}
-
-static void
-apply_clip_as_shape (GdkSurface *window)
-{
-  GdkRectangle r;
-  cairo_region_t *region;
-
-  r.x = r.y = 0;
-  r.width = window->width;
-  r.height = window->height;
-
-  region = cairo_region_copy (window->clip_region);
-  remove_sibling_overlapped_area (window, region);
-
-  /* We only apply the clip region if would differ
-     from the actual clip region implied by the size
-     of the window. This is to avoid unneccessarily
-     adding meaningless shapes to all native subwindows */
-  if (!region_rect_equal (region, &r))
-    apply_shape (window, region);
-  else
-    apply_shape (window, NULL);
-
-  cairo_region_destroy (region);
-}
-
-static void
-recompute_visible_regions_internal (GdkSurface *private,
-                                   gboolean   recalculate_clip,
-                                   gboolean   recalculate_children)
-{
-  GdkRectangle r;
-  GList *l;
-  GdkSurface *child;
-  cairo_region_t *new_clip;
-  gboolean clip_region_changed;
-  gboolean abs_pos_changed;
-  int old_abs_x, old_abs_y;
-
-  old_abs_x = private->abs_x;
-  old_abs_y = private->abs_y;
-
-  /* Update absolute position */
-  if ((gdk_surface_has_impl (private) &&
-       private->window_type != GDK_SURFACE_SUBSURFACE) ||
-      (gdk_surface_is_toplevel (private) &&
-       private->window_type == GDK_SURFACE_SUBSURFACE))
-    {
-      /* Native windows and toplevel subsurfaces start here */
-      private->abs_x = 0;
-      private->abs_y = 0;
-    }
-  else
-    {
-      private->abs_x = private->parent->abs_x + private->x;
-      private->abs_y = private->parent->abs_y + private->y;
-    }
-
-  abs_pos_changed =
-    private->abs_x != old_abs_x ||
-    private->abs_y != old_abs_y;
-
-  /* Update clip region based on:
-   * parent clip
-   * window size/position
-   */
-  clip_region_changed = FALSE;
-  if (recalculate_clip)
-    {
-      if (private->viewable)
-       {
-         /* Calculate visible region (sans children) in parent window coords */
-         r.x = private->x;
-         r.y = private->y;
-         r.width = private->width;
-         r.height = private->height;
-         new_clip = cairo_region_create_rectangle (&r);
-
-         if (!gdk_surface_is_toplevel (private))
-           cairo_region_intersect (new_clip, private->parent->clip_region);
-
-         /* Convert from parent coords to window coords */
-         cairo_region_translate (new_clip, -private->x, -private->y);
-
-         if (should_apply_clip_as_shape (private) && private->shape)
-           cairo_region_intersect (new_clip, private->shape);
-       }
-      else
-         new_clip = cairo_region_create ();
-
-      if (private->clip_region == NULL ||
-         !cairo_region_equal (private->clip_region, new_clip))
-       clip_region_changed = TRUE;
-
-      if (private->clip_region)
-       cairo_region_destroy (private->clip_region);
-      private->clip_region = new_clip;
-    }
-
-  /* Update all children, recursively (except for root, where children are not exact). */
-  if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
-      private->window_type != GDK_SURFACE_ROOT)
-    {
-      for (l = private->children; l; l = l->next)
-       {
-         child = l->data;
-         /* Only recalculate clip if the the clip region changed, otherwise
-          * there is no way the child clip region could change (its has not e.g. moved)
-          * Except if recalculate_children is set to force child updates
-          */
-         recompute_visible_regions_internal (child,
-                                             recalculate_clip && (clip_region_changed || recalculate_children),
-                                             FALSE);
-       }
-    }
-}
-
-/* Call this when private has changed in one or more of these ways:
- *  size changed
- *  window moved
- *  new window added
- *  stacking order of window changed
- *  child deleted
- *
- * It will recalculate abs_x/y and the clip regions
- *
- * Unless the window didn’t change stacking order or size/pos, pass in TRUE
- * for recalculate_siblings. (Mostly used internally for the recursion)
- *
- * If a child window was removed (and you can’t use that child for
- * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
- */
-static void
-recompute_visible_regions (GdkSurface *private,
-                          gboolean recalculate_children)
-{
-  GdkSurface *toplevel;
-
-  toplevel = gdk_surface_get_toplevel (private);
-  toplevel->geometry_dirty = TRUE;
-
-  recompute_visible_regions_internal (private,
-                                     TRUE,
-                                     recalculate_children);
-}
-
-static void
-gdk_surface_clear_old_updated_area (GdkSurface *window)
-{
-  int i;
-
-  for (i = 0; i < 2; i++)
-    {
-      if (window->old_updated_area[i])
-        {
-          cairo_region_destroy (window->old_updated_area[i]);
-          window->old_updated_area[i] = NULL;
-        }
-    }
-}
-
-static void
-gdk_surface_append_old_updated_area (GdkSurface *window,
-                                    cairo_region_t *region)
-{
-  if (window->old_updated_area[1])
-    cairo_region_destroy (window->old_updated_area[1]);
-  window->old_updated_area[1] = window->old_updated_area[0];
-  window->old_updated_area[0] = cairo_region_reference (region);
-}
-
-void
-_gdk_surface_update_size (GdkSurface *window)
-{
-  gdk_surface_clear_old_updated_area (window);
-  recompute_visible_regions (window, FALSE);
-}
-
-static GdkEventMask
-get_native_device_event_mask (GdkSurface *private,
-                              GdkDevice *device)
-{
-  GdkEventMask event_mask;
-
-  if (device)
-    event_mask = GPOINTER_TO_INT (g_hash_table_lookup (private->device_events, device));
-  else
-    event_mask = private->event_mask;
-
-  if (private->window_type == GDK_SURFACE_ROOT ||
-      private->window_type == GDK_SURFACE_FOREIGN)
-    return event_mask;
-  else
-    {
-      GdkEventMask mask;
-
-      mask = private->event_mask;
-
-      /* We need thse for all native windows so we can
-        emulate events on children: */
-      mask |=
-       GDK_EXPOSURE_MASK |
-       GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
-        GDK_TOUCH_MASK |
-        GDK_POINTER_MOTION_MASK |
-        GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
-        GDK_SCROLL_MASK;
-
-      return mask;
-    }
-}
-
-static GdkEventMask
-get_native_event_mask (GdkSurface *private)
-{
-  return get_native_device_event_mask (private, NULL);
-}
-
-GdkSurface*
-gdk_surface_new (GdkDisplay    *display,
-                GdkSurface     *parent,
-               GdkSurfaceAttr *attributes)
-{
-  GdkSurface *window;
-  gboolean native;
-  GdkEventMask event_mask;
-
-  g_return_val_if_fail (attributes != NULL, NULL);
-
-  if (parent != NULL && GDK_SURFACE_DESTROYED (parent))
-    {
-      g_warning ("gdk_surface_new(): parent is destroyed");
-      return NULL;
-    }
-
-  window = _gdk_display_create_window (display);
-
-  window->parent = parent;
-
-  window->accept_focus = TRUE;
-  window->focus_on_map = TRUE;
-
-  window->x = attributes->x;
-  window->y = attributes->y;
-  window->width = (attributes->width > 1) ? (attributes->width) : (1);
-  window->height = (attributes->height > 1) ? (attributes->height) : (1);
-  window->alpha = 255;
-
-  if (attributes->wclass == GDK_INPUT_ONLY)
-    {
-      /* Backwards compatiblity - we've always ignored
-       * attributes->window_type for input-only windows
-       * before
-       */
-      if (parent == NULL)
-       window->window_type = GDK_SURFACE_TEMP;
-      else
-       window->window_type = GDK_SURFACE_CHILD;
-    }
-  else
-    window->window_type = attributes->window_type;
-
-  /* Sanity checks */
-  switch (window->window_type)
-    {
-    case GDK_SURFACE_TOPLEVEL:
-    case GDK_SURFACE_TEMP:
-      if (parent != NULL && GDK_SURFACE_TYPE (parent) != GDK_SURFACE_ROOT)
-       g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
-                  "a window of type GDK_SURFACE_ROOT");
-      break;
-    case GDK_SURFACE_SUBSURFACE:
-#ifdef GDK_WINDOWING_WAYLAND
-      if (!GDK_IS_WAYLAND_DISPLAY (display))
-        {
-          g_warning (G_STRLOC "Subsurface windows can only be used on Wayland");
-          return NULL;
-        }
-#endif
-      break;
-    case GDK_SURFACE_CHILD:
-      if (GDK_SURFACE_TYPE (parent) == GDK_SURFACE_ROOT ||
-          GDK_SURFACE_TYPE (parent) == GDK_SURFACE_FOREIGN)
-        {
-          g_warning (G_STRLOC "Child windows must not be created as children of\n"
-                     "a window of type GDK_SURFACE_ROOT or GDK_SURFACE_FOREIGN");
-          return NULL;
-        }
-      break;
-    default:
-      g_warning (G_STRLOC "cannot make windows of type %d", window->window_type);
-      return NULL;
-    }
-
-  window->event_mask = GDK_ALL_EVENTS_MASK;
-
-  if (attributes->wclass == GDK_INPUT_OUTPUT)
-    {
-      window->input_only = FALSE;
-    }
-  else
-    {
-      window->input_only = TRUE;
-    }
-
-  native = FALSE;
-
-  if (window->parent != NULL)
-    window->parent->children = g_list_concat (&window->children_list_node, window->parent->children);
-  else
-    {
-      GdkFrameClock *frame_clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
-      gdk_surface_set_frame_clock (window, frame_clock);
-      g_object_unref (frame_clock);
-
-      native = TRUE; /* Always use native windows for toplevels */
-    }
-
-#ifdef GDK_WINDOWING_WAYLAND
-  if (window->window_type == GDK_SURFACE_SUBSURFACE)
-    native = TRUE; /* Always use native windows for subsurfaces as well */
-#endif
-
-  if (native)
-    {
-      event_mask = get_native_event_mask (window);
-
-      /* Create the impl */
-      _gdk_display_create_window_impl (display, window, parent, event_mask, attributes);
-      window->impl_window = window;
-    }
-  else
-    {
-      window->impl_window = g_object_ref (window->parent->impl_window);
-      window->impl = g_object_ref (window->impl_window->impl);
-    }
-
-  recompute_visible_regions (window, FALSE);
-
-  g_signal_connect (display, "seat-removed", G_CALLBACK (seat_removed_cb), window);
-
-  return window;
-}
-
-/**
- * gdk_surface_new_toplevel: (constructor)
- * @display: the display to create the window on
- * @width: width of new window
- * @height: height of new window
- *
- * Creates a new toplevel window. The window will be managed by the window
- * manager.
- *
- * Returns: (transfer full): the new #GdkSurface
- **/
-GdkSurface *
-gdk_surface_new_toplevel (GdkDisplay *display,
-                         gint        width,
-                         gint        height)
-{
-  GdkSurfaceAttr attr;
-
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-
-  attr.wclass = GDK_INPUT_OUTPUT;
-  attr.x = 0;
-  attr.y = 0;
-  attr.width = width;
-  attr.height = height;
-  attr.window_type = GDK_SURFACE_TOPLEVEL;
-
-  return gdk_surface_new (display, NULL, &attr);
-}
-
-/**
- * gdk_surface_new_popup: (constructor)
- * @display: the display to create the window on
- * @position: position of the window on screen
- *
- * Creates a new toplevel popup window. The window will bypass window
- * management.
- *
- * Returns: (transfer full): the new #GdkSurface
- **/
-GdkSurface *
-gdk_surface_new_popup (GdkDisplay         *display,
-                      const GdkRectangle *position)
-{
-  GdkSurfaceAttr attr;
-
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-  g_return_val_if_fail (position != NULL, NULL);
-
-  attr.wclass = GDK_INPUT_OUTPUT;
-  attr.x = position->x;
-  attr.y = position->y;
-  attr.width = position->width;
-  attr.height = position->height;
-  attr.window_type = GDK_SURFACE_TEMP;
-
-  return gdk_surface_new (display, NULL, &attr);
-}
-
-/**
- * gdk_surface_new_temp: (constructor)
- * @display: the display to create the window on
- *
- * Creates a new toplevel temporary window. The window will be
- * situated off-screen and not handle output.
- *
- * You most likely do not want to use this function.
- *
- * Returns: (transfer full): the new #GdkSurface
- **/
-GdkSurface *
-gdk_surface_new_temp (GdkDisplay *display)
-{
-  GdkSurfaceAttr attr;
-
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-
-  attr.wclass = GDK_INPUT_ONLY;
-  attr.x = -100;
-  attr.y = -100;
-  attr.width = 10;
-  attr.height = 10;
-  attr.window_type = GDK_SURFACE_TEMP;
-
-  return gdk_surface_new (display, NULL, &attr);
-}
-
-/**
- * gdk_surface_new_child: (constructor)
- * @parent: the parent window
- * @position: placement of the window inside @parent
- *
- * Creates a new client-side child window.
- *
- * Returns: (transfer full): the new #GdkSurface
- **/
-GdkSurface *
-gdk_surface_new_child (GdkSurface          *parent,
-                      const GdkRectangle *position)
-{
-  GdkSurfaceAttr attr;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (parent), NULL);
-
-  attr.wclass = GDK_INPUT_OUTPUT;
-  attr.x = position->x;
-  attr.y = position->y;
-  attr.width = position->width;
-  attr.height = position->height;
-  attr.window_type = GDK_SURFACE_CHILD;
-
-  return gdk_surface_new (gdk_surface_get_display (parent), parent, &attr);
-}
-
-static void
-update_pointer_info_foreach (GdkDisplay           *display,
-                             GdkDevice            *device,
-                             GdkPointerSurfaceInfo *pointer_info,
-                             gpointer              user_data)
-{
-  GdkSurface *window = user_data;
-
-  if (pointer_info->window_under_pointer == window)
-    {
-      g_object_unref (pointer_info->window_under_pointer);
-      pointer_info->window_under_pointer = NULL;
-    }
-}
-
-static void
-window_remove_from_pointer_info (GdkSurface  *window,
-                                 GdkDisplay *display)
-{
-  _gdk_display_pointer_info_foreach (display,
-                                     update_pointer_info_foreach,
-                                     window);
-}
-
-static void
-gdk_surface_free_current_paint (GdkSurface *window)
-{
-  cairo_surface_destroy (window->current_paint.surface);
-  window->current_paint.surface = NULL;
-
-  cairo_region_destroy (window->current_paint.region);
-  window->current_paint.region = NULL;
-
-  window->current_paint.surface_needs_composite = FALSE;
-}
-
-/**
- * _gdk_surface_destroy_hierarchy:
- * @window: a #GdkSurface
- * @recursing: If %TRUE, then this is being called because a parent
- *            was destroyed.
- * @recursing_native: If %TRUE, then this is being called because a native parent
- *            was destroyed. This generally means that the call to the
- *            windowing system to destroy the window can be omitted, since
- *            it will be destroyed as a result of the parent being destroyed.
- *            Unless @foreign_destroy.
- * @foreign_destroy: If %TRUE, the window or a parent was destroyed by some
- *            external agency. The window has already been destroyed and no
- *            windowing system calls should be made. (This may never happen
- *            for some windowing systems.)
- *
- * Internal function to destroy a window. Like gdk_surface_destroy(),
- * but does not drop the reference count created by gdk_surface_new().
- **/
-static void
-_gdk_surface_destroy_hierarchy (GdkSurface *window,
-                              gboolean   recursing,
-                              gboolean   recursing_native,
-                              gboolean   foreign_destroy)
-{
-  GdkSurfaceImplClass *impl_class;
-  GdkSurface *temp_window;
-  GdkDisplay *display;
-  GList *tmp;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  display = gdk_surface_get_display (window);
-
-  switch (window->window_type)
-    {
-    default:
-      g_assert_not_reached ();
-      break;
-
-    case GDK_SURFACE_ROOT:
-      if (!gdk_display_is_closed (display))
-       {
-         g_error ("attempted to destroy root window");
-         break;
-       }
-      /* else fall thru */
-    case GDK_SURFACE_TOPLEVEL:
-    case GDK_SURFACE_CHILD:
-    case GDK_SURFACE_TEMP:
-    case GDK_SURFACE_FOREIGN:
-    case GDK_SURFACE_SUBSURFACE:
-      if (window->window_type == GDK_SURFACE_FOREIGN && !foreign_destroy)
-       {
-       }
-      else
-       {
-         if (window->parent)
-           {
-             if (window->parent->children)
-                window->parent->children = g_list_remove_link (window->parent->children, &window->children_list_node);
-
-             if (!recursing &&
-                 GDK_SURFACE_IS_MAPPED (window))
-               {
-                 recompute_visible_regions (window, FALSE);
-                 gdk_surface_invalidate_in_parent (window);
-               }
-           }
-
-          if (window->gl_paint_context)
-            {
-              /* Make sure to destroy if current */
-              g_object_run_dispose (G_OBJECT (window->gl_paint_context));
-              g_object_unref (window->gl_paint_context);
-              window->gl_paint_context = NULL;
-            }
-
-          if (window->frame_clock)
-            {
-              g_object_run_dispose (G_OBJECT (window->frame_clock));
-              gdk_surface_set_frame_clock (window, NULL);
-            }
-
-          gdk_surface_free_current_paint (window);
-
-         if (window->window_type == GDK_SURFACE_FOREIGN)
-           g_assert (window->children == NULL);
-         else
-           {
-             tmp = window->children;
-             window->children = NULL;
-             /* No need to free children list, its all made up of in-struct nodes */
-
-             while (tmp)
-               {
-                 temp_window = tmp->data;
-                 tmp = tmp->next;
-
-                 if (temp_window)
-                   _gdk_surface_destroy_hierarchy (temp_window,
-                                                  TRUE,
-                                                  recursing_native || gdk_surface_has_impl (window),
-                                                  foreign_destroy);
-               }
-           }
-
-         _gdk_surface_clear_update_area (window);
-
-         impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-         if (gdk_surface_has_impl (window))
-           impl_class->destroy (window, recursing_native, foreign_destroy);
-         else
-           {
-             /* hide to make sure we repaint and break grabs */
-             gdk_surface_hide (window);
-           }
-
-         window->state |= GDK_SURFACE_STATE_WITHDRAWN;
-         window->parent = NULL;
-         window->destroyed = TRUE;
-
-         window_remove_from_pointer_info (window, display);
-
-         if (window->clip_region)
-           {
-             cairo_region_destroy (window->clip_region);
-             window->clip_region = NULL;
-           }
-
-          g_object_notify_by_pspec (G_OBJECT (window), properties[PROP_STATE]);
-       }
-      break;
-    }
-}
-
-/**
- * _gdk_surface_destroy:
- * @window: a #GdkSurface
- * @foreign_destroy: If %TRUE, the window or a parent was destroyed by some
- *            external agency. The window has already been destroyed and no
- *            windowing system calls should be made. (This may never happen
- *            for some windowing systems.)
- *
- * Internal function to destroy a window. Like gdk_surface_destroy(),
- * but does not drop the reference count created by gdk_surface_new().
- **/
-void
-_gdk_surface_destroy (GdkSurface *window,
-                    gboolean   foreign_destroy)
-{
-  _gdk_surface_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
-}
-
-/**
- * gdk_surface_destroy:
- * @window: a #GdkSurface
- *
- * Destroys the window system resources associated with @window and decrements @window's
- * reference count. The window system resources for all children of @window are also
- * destroyed, but the children’s reference counts are not decremented.
- *
- * Note that a window will not be destroyed automatically when its reference count
- * reaches zero. You must call this function yourself before that happens.
- *
- **/
-void
-gdk_surface_destroy (GdkSurface *window)
-{
-  _gdk_surface_destroy_hierarchy (window, FALSE, FALSE, FALSE);
-  g_object_unref (window);
-}
-
-/**
- * gdk_surface_set_user_data:
- * @window: a #GdkSurface
- * @user_data: (allow-none) (type GObject.Object): user data
- *
- * For most purposes this function is deprecated in favor of
- * g_object_set_data(). However, for historical reasons GTK+ stores
- * the #GtkWidget that owns a #GdkSurface as user data on the
- * #GdkSurface. So, custom widget implementations should use
- * this function for that. If GTK+ receives an event for a #GdkSurface,
- * and the user data for the window is non-%NULL, GTK+ will assume the
- * user data is a #GtkWidget, and forward the event to that widget.
- *
- **/
-void
-gdk_surface_set_user_data (GdkSurface *window,
-                         gpointer   user_data)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  window->user_data = user_data;
-}
-
-/**
- * gdk_surface_get_user_data:
- * @window: a #GdkSurface
- * @data: (out): return location for user data
- *
- * Retrieves the user data for @window, which is normally the widget
- * that @window belongs to. See gdk_surface_set_user_data().
- *
- **/
-void
-gdk_surface_get_user_data (GdkSurface *window,
-                         gpointer  *data)
-{
-  *data = window->user_data;
-}
-
-/**
- * gdk_surface_get_window_type:
- * @window: a #GdkSurface
- *
- * Gets the type of the window. See #GdkSurfaceType.
- *
- * Returns: type of window
- **/
-GdkSurfaceType
-gdk_surface_get_window_type (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), (GdkSurfaceType) -1);
-
-  return GDK_SURFACE_TYPE (window);
-}
-
-/**
- * gdk_surface_get_display:
- * @window: a #GdkSurface
- * 
- * Gets the #GdkDisplay associated with a #GdkSurface.
- * 
- * Returns: (transfer none): the #GdkDisplay associated with @window
- **/
-GdkDisplay *
-gdk_surface_get_display (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  return window->display;
-}
-/**
- * gdk_surface_is_destroyed:
- * @window: a #GdkSurface
- *
- * Check to see if a window is destroyed..
- *
- * Returns: %TRUE if the window is destroyed
- **/
-gboolean
-gdk_surface_is_destroyed (GdkSurface *window)
-{
-  return GDK_SURFACE_DESTROYED (window);
-}
-
-/**
- * gdk_surface_has_native:
- * @window: a #GdkSurface
- *
- * Checks whether the window has a native window or not.
- *
- * Returns: %TRUE if the @window has a native window, %FALSE otherwise.
- */
-gboolean
-gdk_surface_has_native (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  return window->parent == NULL || window->parent->impl != window->impl;
-}
-
-/**
- * gdk_surface_get_position:
- * @window: a #GdkSurface
- * @x: (out) (allow-none): X coordinate of window
- * @y: (out) (allow-none): Y coordinate of window
- *
- * Obtains the position of the window as reported in the
- * most-recently-processed #GdkEventConfigure. Contrast with
- * gdk_surface_get_geometry() which queries the X server for the
- * current window position, regardless of which events have been
- * received or processed.
- *
- * The position coordinates are relative to the window’s parent window.
- *
- **/
-void
-gdk_surface_get_position (GdkSurface *window,
-                        gint      *x,
-                        gint      *y)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (x)
-    *x = window->x;
-  if (y)
-    *y = window->y;
-}
-
-/**
- * gdk_surface_get_parent:
- * @window: a #GdkSurface
- *
- * Obtains the parent of @window, as known to GDK. Does not query the
- * X server; thus this returns the parent as passed to gdk_surface_new(),
- * not the actual parent. This should never matter unless you’re using
- * Xlib calls mixed with GDK calls on the X11 platform. It may also
- * matter for toplevel windows, because the window manager may choose
- * to reparent them.
- *
- * Returns: (transfer none): parent of @window
- **/
-GdkSurface*
-gdk_surface_get_parent (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  if (gdk_surface_is_subsurface (window))
-    return window->transient_for;
-  else
-    return window->parent;
-}
-
-/**
- * gdk_surface_get_toplevel:
- * @window: a #GdkSurface
- *
- * Gets the toplevel window that’s an ancestor of @window.
- *
- * Any window type but %GDK_SURFACE_CHILD is considered a
- * toplevel window, as is a %GDK_SURFACE_CHILD window that
- * has a root window as parent.
- *
- * Returns: (transfer none): the toplevel window containing @window
- **/
-GdkSurface *
-gdk_surface_get_toplevel (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  while (window->window_type == GDK_SURFACE_CHILD ||
-         window->window_type == GDK_SURFACE_SUBSURFACE)
-    {
-      if (gdk_surface_is_toplevel (window))
-       break;
-      window = window->parent;
-    }
-
-  return window;
-}
-
-/**
- * gdk_surface_get_children:
- * @window: a #GdkSurface
- *
- * Gets the list of children of @window known to GDK.
- * This function only returns children created via GDK,
- * so for example it’s useless when used with the root window;
- * it only returns windows an application created itself.
- *
- * The returned list must be freed, but the elements in the
- * list need not be.
- *
- * Returns: (transfer container) (element-type GdkSurface):
- *     list of child windows inside @window
- **/
-GList*
-gdk_surface_get_children (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  return g_list_copy (window->children);
-}
-
-/**
- * gdk_surface_peek_children:
- * @window: a #GdkSurface
- *
- * Like gdk_surface_get_children(), but does not copy the list of
- * children, so the list does not need to be freed.
- *
- * Returns: (transfer none) (element-type GdkSurface):
- *     a reference to the list of child windows in @window
- **/
-GList *
-gdk_surface_peek_children (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  return window->children;
-}
-
-
-/**
- * gdk_surface_get_children_with_user_data:
- * @window: a #GdkSurface
- * @user_data: user data to look for
- *
- * Gets the list of children of @window known to GDK with a
- * particular @user_data set on it.
- *
- * The returned list must be freed, but the elements in the
- * list need not be.
- *
- * The list is returned in (relative) stacking order, i.e. the
- * lowest window is first.
- *
- * Returns: (transfer container) (element-type GdkSurface):
- *     list of child windows inside @window
- **/
-GList *
-gdk_surface_get_children_with_user_data (GdkSurface *window,
-                                        gpointer   user_data)
-{
-  GdkSurface *child;
-  GList *res, *l;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  res = NULL;
-  for (l = window->children; l != NULL; l = l->next)
-    {
-      child = l->data;
-
-      if (child->user_data == user_data)
-       res = g_list_prepend (res, child);
-    }
-
-  return res;
-}
-
-
-/**
- * gdk_surface_is_visible:
- * @window: a #GdkSurface
- *
- * Checks whether the window has been mapped (with gdk_surface_show() or
- * gdk_surface_show_unraised()).
- *
- * Returns: %TRUE if the window is mapped
- **/
-gboolean
-gdk_surface_is_visible (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  return GDK_SURFACE_IS_MAPPED (window);
-}
-
-/**
- * gdk_surface_is_viewable:
- * @window: a #GdkSurface
- *
- * Check if the window and all ancestors of the window are
- * mapped. (This is not necessarily "viewable" in the X sense, since
- * we only check as far as we have GDK window parents, not to the root
- * window.)
- *
- * Returns: %TRUE if the window is viewable
- **/
-gboolean
-gdk_surface_is_viewable (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  if (window->destroyed)
-    return FALSE;
-
-  return window->viewable;
-}
-
-/**
- * gdk_surface_get_state:
- * @window: a #GdkSurface
- *
- * Gets the bitwise OR of the currently active window state flags,
- * from the #GdkSurfaceState enumeration.
- *
- * Returns: window state bitfield
- **/
-GdkSurfaceState
-gdk_surface_get_state (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  return window->state;
-}
-
-static cairo_content_t
-gdk_surface_get_content (GdkSurface *window)
-{
-  cairo_surface_t *surface;
-  cairo_content_t content;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
-
-  surface = gdk_surface_ref_impl_surface (window);
-  content = cairo_surface_get_content (surface);
-  cairo_surface_destroy (surface);
-
-  return content;
-}
-
-static cairo_surface_t *
-gdk_surface_ref_impl_surface (GdkSurface *window)
-{
-  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->ref_cairo_surface (gdk_surface_get_impl_window (window));
-}
-
-GdkGLContext *
-gdk_surface_get_paint_gl_context (GdkSurface  *window,
-                                 GError    **error)
-{
-  GError *internal_error = NULL;
-
-  if (GDK_DISPLAY_DEBUG_CHECK (window->display, GL_DISABLE))
-    {
-      g_set_error_literal (error, GDK_GL_ERROR,
-                           GDK_GL_ERROR_NOT_AVAILABLE,
-                           _("GL support disabled via GDK_DEBUG"));
-      return NULL;
-    }
-
-  if (window->impl_window->gl_paint_context == NULL)
-    {
-      GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-      if (impl_class->create_gl_context == NULL)
-        {
-          g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
-                               _("The current backend does not support OpenGL"));
-          return NULL;
-        }
-
-      window->impl_window->gl_paint_context =
-        impl_class->create_gl_context (window->impl_window,
-                                       TRUE,
-                                       NULL,
-                                       &internal_error);
-    }
-
-  if (internal_error != NULL)
-    {
-      g_propagate_error (error, internal_error);
-      g_clear_object (&(window->impl_window->gl_paint_context));
-      return NULL;
-    }
-
-  gdk_gl_context_realize (window->impl_window->gl_paint_context, &internal_error);
-  if (internal_error != NULL)
-    {
-      g_propagate_error (error, internal_error);
-      g_clear_object (&(window->impl_window->gl_paint_context));
-      return NULL;
-    }
-
-  return window->impl_window->gl_paint_context;
-}
-
-/**
- * gdk_surface_create_gl_context:
- * @window: a #GdkSurface
- * @error: return location for an error
- *
- * Creates a new #GdkGLContext matching the
- * framebuffer format to the visual of the #GdkSurface. The context
- * is disconnected from any particular window or surface.
- *
- * If the creation of the #GdkGLContext failed, @error will be set.
- *
- * Before using the returned #GdkGLContext, you will need to
- * call gdk_gl_context_make_current() or gdk_gl_context_realize().
- *
- * Returns: (transfer full): the newly created #GdkGLContext, or
- * %NULL on error
- **/
-GdkGLContext *
-gdk_surface_create_gl_context (GdkSurface    *window,
-                              GError      **error)
-{
-  GdkGLContext *paint_context;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-  paint_context = gdk_surface_get_paint_gl_context (window, error);
-  if (paint_context == NULL)
-    return NULL;
-
-  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->create_gl_context (window->impl_window,
-                                                                     FALSE,
-                                                                      paint_context,
-                                                                      error);
-}
-
-/**
- * gdk_surface_create_vulkan_context:
- * @window: a #GdkSurface
- * @error: return location for an error
- *
- * Creates a new #GdkVulkanContext for rendering on @window.
- *
- * If the creation of the #GdkVulkanContext failed, @error will be set.
- *
- * Returns: (transfer full): the newly created #GdkVulkanContext, or
- * %NULL on error
- **/
-GdkVulkanContext *
-gdk_surface_create_vulkan_context (GdkSurface  *window,
-                                  GError    **error)
-{
-  GdkDisplay *display;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
-  if (GDK_DISPLAY_DEBUG_CHECK (window->display, VULKAN_DISABLE))
-    {
-      g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
-                           _("Vulkan support disabled via GDK_DEBUG"));
-      return NULL;
-    }
-
-  display = gdk_surface_get_display (window);
-
-  if (GDK_DISPLAY_GET_CLASS (display)->vk_extension_name == NULL)
-    {
-      g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
-                   "The %s backend has no Vulkan support.", G_OBJECT_TYPE_NAME (display));
-      return FALSE;
-    }
-
-  return g_initable_new (GDK_DISPLAY_GET_CLASS (display)->vk_context_type,
-                         NULL,
-                         error,
-                         "window", window,
-                         NULL);
-}
-
-static void
-gdk_surface_begin_paint_internal (GdkSurface            *window,
-                                const cairo_region_t *region)
-{
-  GdkRectangle clip_box;
-  GdkSurfaceImplClass *impl_class;
-  double sx, sy;
-  gboolean needs_surface;
-  cairo_content_t surface_content;
-
-  if (window->current_paint.surface != NULL)
-    {
-      g_warning ("A paint operation on the window is alredy in progress. "
-                 "This is not allowed.");
-      return;
-    }
-
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-  needs_surface = TRUE;
-  if (impl_class->begin_paint)
-    needs_surface = impl_class->begin_paint (window);
-
-  window->current_paint.region = cairo_region_copy (region);
-  cairo_region_intersect (window->current_paint.region, window->clip_region);
-  cairo_region_get_extents (window->current_paint.region, &clip_box);
-
-  surface_content = gdk_surface_get_content (window);
-
-  if (needs_surface)
-    {
-      window->current_paint.surface = gdk_surface_create_similar_surface (window,
-                                                                         surface_content,
-                                                                         MAX (clip_box.width, 1),
-                                                                         MAX (clip_box.height, 1));
-      sx = sy = 1;
-      cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy);
-      cairo_surface_set_device_offset (window->current_paint.surface, -clip_box.x*sx, -clip_box.y*sy);
-      gdk_cairo_surface_mark_as_direct (window->current_paint.surface, window);
-
-      window->current_paint.surface_needs_composite = TRUE;
-    }
-  else
-    {
-      window->current_paint.surface = gdk_surface_ref_impl_surface (window);
-      window->current_paint.surface_needs_composite = FALSE;
-    }
-
-  if (!cairo_region_is_empty (window->current_paint.region))
-    gdk_surface_clear_backing_region (window);
-}
-
-static void
-gdk_surface_end_paint_internal (GdkSurface *window)
-{
-  GdkSurfaceImplClass *impl_class;
-  cairo_t *cr;
-
-  if (window->current_paint.surface == NULL)
-    {
-      g_warning (G_STRLOC": no preceding call to gdk_surface_begin_draw_frame(), see documentation");
-      return;
-    }
-
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-  if (impl_class->end_paint)
-    impl_class->end_paint (window);
-
-  if (window->current_paint.surface_needs_composite)
-    {
-      cairo_surface_t *surface;
-
-      surface = gdk_surface_ref_impl_surface (window);
-      cr = cairo_create (surface);
-
-      cairo_set_source_surface (cr, window->current_paint.surface, 0, 0);
-      gdk_cairo_region (cr, window->current_paint.region);
-      cairo_clip (cr);
-
-      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-      cairo_paint (cr);
-
-      cairo_destroy (cr);
-
-      cairo_surface_flush (surface);
-      cairo_surface_destroy (surface);
-    }
-
-  gdk_surface_free_current_paint (window);
-}
-
-/**
- * gdk_surface_begin_draw_frame:
- * @window: a #GdkSurface
- * @context: (allow-none): the context used to draw the frame
- * @region: a Cairo region
- *
- * Indicates that you are beginning the process of redrawing @region
- * on @window, and provides you with a #GdkDrawingContext.
- *
- * If @window is a top level #GdkSurface, backed by a native window
- * implementation, a backing store (offscreen buffer) large enough to
- * contain @region will be created. The backing store will be initialized
- * with the background color or background surface for @window. Then, all
- * drawing operations performed on @window will be diverted to the
- * backing store. When you call gdk_surface_end_frame(), the contents of
- * the backing store will be copied to @window, making it visible
- * on screen. Only the part of @window contained in @region will be
- * modified; that is, drawing operations are clipped to @region.
- *
- * The net result of all this is to remove flicker, because the user
- * sees the finished product appear all at once when you call
- * gdk_surface_end_draw_frame(). If you draw to @window directly without
- * calling gdk_surface_begin_draw_frame(), the user may see flicker
- * as individual drawing operations are performed in sequence.
- *
- * When using GTK+, the widget system automatically places calls to
- * gdk_surface_begin_draw_frame() and gdk_surface_end_draw_frame() around
- * emissions of the `GtkWidget::draw` signal. That is, if you’re
- * drawing the contents of the widget yourself, you can assume that the
- * widget has a cleared background, is already set as the clip region,
- * and already has a backing store. Therefore in most cases, application
- * code in GTK does not need to call gdk_surface_begin_draw_frame()
- * explicitly.
- *
- * Returns: (transfer none): a #GdkDrawingContext context that should be
- *   used to draw the contents of the window; the returned context is owned
- *   by GDK.
- */
-GdkDrawingContext *
-gdk_surface_begin_draw_frame (GdkSurface            *window,
-                             GdkDrawContext       *draw_context,
-                             const cairo_region_t *region)
-{
-  GdkDrawingContext *context;
-  cairo_region_t *real_region;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-  g_return_val_if_fail (gdk_surface_has_native (window), NULL);
-  g_return_val_if_fail (gdk_surface_is_toplevel (window), NULL);
-  g_return_val_if_fail (region != NULL, NULL);
-  if (draw_context != NULL)
-    {
-      g_return_val_if_fail (GDK_IS_DRAW_CONTEXT (draw_context), NULL);
-      g_return_val_if_fail (gdk_draw_context_get_window (draw_context) == window, NULL);
-    }
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  if (window->drawing_context != NULL)
-    {
-      g_critical ("The window %p already has a drawing context. You cannot "
-                  "call gdk_surface_begin_draw_frame() without calling "
-                  "gdk_surface_end_draw_frame() first.", window);
-      return NULL;
-    }
-
-  real_region = cairo_region_copy (region);
-
-  if (draw_context)
-    gdk_draw_context_begin_frame (draw_context, real_region);
-  else
-    gdk_surface_begin_paint_internal (window, real_region);
-
-  context = g_object_new (GDK_TYPE_DRAWING_CONTEXT,
-                          "window", window,
-                          "paint-context", draw_context,
-                          "clip", real_region,
-                          NULL);
-
-  /* Do not take a reference, to avoid creating cycles */
-  window->drawing_context = context;
-
-  cairo_region_destroy (real_region);
-
-  return context;
-}
-
-/**
- * gdk_surface_end_draw_frame:
- * @window: a #GdkSurface
- * @context: the #GdkDrawingContext created by gdk_surface_begin_draw_frame()
- *
- * Indicates that the drawing of the contents of @window started with
- * gdk_surface_begin_frame() has been completed.
- *
- * This function will take care of destroying the #GdkDrawingContext.
- *
- * It is an error to call this function without a matching
- * gdk_surface_begin_frame() first.
- */
-void
-gdk_surface_end_draw_frame (GdkSurface         *window,
-                           GdkDrawingContext *context)
-{
-  GdkDrawContext *paint_context;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (window->drawing_context == NULL)
-    {
-      g_critical ("The window %p has no drawing context. You must call "
-                  "gdk_surface_begin_draw_frame() before calling "
-                  "gdk_surface_end_draw_frame().", window);
-      return;
-    }
-  g_return_if_fail (window->drawing_context == context);
-
-  paint_context = gdk_drawing_context_get_paint_context (context);
-  if (paint_context)
-    {
-      cairo_region_t *clip = gdk_drawing_context_get_clip (context);
-
-      gdk_draw_context_end_frame (paint_context,
-                                  clip,
-                                  window->active_update_area);
-
-      cairo_region_destroy (clip);
-    }
-  else
-    {
-      gdk_surface_end_paint_internal (window);
-    }
-
-  window->drawing_context = NULL;
-
-  g_object_unref (context);
-}
-
-/*< private >
- * gdk_surface_get_current_paint_region:
- * @window: a #GdkSurface
- *
- * Retrieves a copy of the current paint region.
- *
- * Returns: (transfer full): a Cairo region
- */
-cairo_region_t *
-gdk_surface_get_current_paint_region (GdkSurface *window)
-{
-  cairo_region_t *region;
-
-  if (window->impl_window->current_paint.region != NULL)
-    {
-      region = cairo_region_copy (window->impl_window->current_paint.region);
-      cairo_region_translate (region, -window->abs_x, -window->abs_y);
-    }
-  else
-    {
-      region = cairo_region_copy (window->clip_region);
-    }
-
-  return region;
-}
-
-/*< private >
- * gdk_surface_get_drawing_context:
- * @window: a #GdkSurface
- *
- * Retrieves the #GdkDrawingContext associated to @window by
- * gdk_surface_begin_draw_frame().
- *
- * Returns: (transfer none) (nullable): a #GdkDrawingContext, if any is set
- */
-GdkDrawingContext *
-gdk_surface_get_drawing_context (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  return window->drawing_context;
-}
-
-/**
- * gdk_surface_get_clip_region:
- * @window: a #GdkSurface
- * 
- * Computes the region of a window that potentially can be written
- * to by drawing primitives. This region may not take into account
- * other factors such as if the window is obscured by other windows,
- * but no area outside of this region will be affected by drawing
- * primitives.
- * 
- * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
- *          when you are done.
- **/
-cairo_region_t*
-gdk_surface_get_clip_region (GdkSurface *window)
-{
-  cairo_region_t *result;
-
-  g_return_val_if_fail (GDK_SURFACE (window), NULL);
-
-  result = cairo_region_copy (window->clip_region);
-
-  if (window->current_paint.region != NULL)
-    cairo_region_intersect (result, window->current_paint.region);
-
-  return result;
-}
-
-/**
- * gdk_surface_get_visible_region:
- * @window: a #GdkSurface
- * 
- * Computes the region of the @window that is potentially visible.
- * This does not necessarily take into account if the window is
- * obscured by other windows, but no area outside of this region
- * is visible.
- * 
- * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
- *          when you are done.
- **/
-cairo_region_t *
-gdk_surface_get_visible_region (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  return cairo_region_copy (window->clip_region);
-}
-
-static void
-gdk_surface_clear_backing_region (GdkSurface *window)
-{
-  cairo_t *cr;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  cr = cairo_create (window->current_paint.surface);
-
-  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
-  gdk_cairo_region (cr, window->current_paint.region);
-  cairo_fill (cr);
-
-  cairo_destroy (cr);
-}
-
-/* This returns either the current working surface on the paint stack
- * or the actual impl surface of the window. This should not be used
- * from very many places: be careful! */
-static cairo_surface_t *
-ref_window_surface (GdkSurface *window)
-{
-  if (window->impl_window->current_paint.surface)
-    return cairo_surface_reference (window->impl_window->current_paint.surface);
-  else
-    return gdk_surface_ref_impl_surface (window);
-}
-
-/* This is used in places like gdk_cairo_set_source_window and
- * other places to take "screenshots" of windows. Thus, we allow
- * it to be used outside of a begin_paint / end_paint. */
-cairo_surface_t *
-_gdk_surface_ref_cairo_surface (GdkSurface *window)
-{
-  cairo_surface_t *surface;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  surface = ref_window_surface (window);
-
-  if (gdk_surface_has_impl (window))
-    {
-      return surface;
-    }
-  else
-    {
-      cairo_surface_t *subsurface;
-      subsurface = cairo_surface_create_for_rectangle (surface,
-                                                       window->abs_x,
-                                                       window->abs_y,
-                                                       window->width,
-                                                       window->height);
-      cairo_surface_destroy (surface);
-      return subsurface;
-    }
-}
-
-/* Code for dirty-region queueing
- */
-static GSList *update_windows = NULL;
-
-static inline gboolean
-gdk_surface_is_ancestor (GdkSurface *window,
-                       GdkSurface *ancestor)
-{
-  while (window)
-    {
-      GdkSurface *parent = window->parent;
-
-      if (parent == ancestor)
-       return TRUE;
-
-      window = parent;
-    }
-
-  return FALSE;
-}
-
-static void
-gdk_surface_add_update_window (GdkSurface *window)
-{
-  GSList *tmp;
-  GSList *prev = NULL;
-  gboolean has_ancestor_in_list = FALSE;
-
-  /*  Check whether "window" is already in "update_windows" list.
-   *  It could be added during execution of gtk_widget_destroy() when
-   *  setting focus widget to NULL and redrawing old focus widget.
-   *  See bug 711552.
-   */
-  tmp = g_slist_find (update_windows, window);
-  if (tmp != NULL)
-    return;
-
-  for (tmp = update_windows; tmp; tmp = tmp->next)
-    {
-      GdkSurface *parent = window->parent;
-
-      /*  check if tmp is an ancestor of "window"; if it is, set a
-       *  flag indicating that all following windows are either
-       *  children of "window" or from a differen hierarchy
-       */
-      if (!has_ancestor_in_list && gdk_surface_is_ancestor (window, tmp->data))
-       has_ancestor_in_list = TRUE;
-
-      /* insert in reverse stacking order when adding around siblings,
-       * so processing updates properly paints over lower stacked windows
-       */
-      if (parent == GDK_SURFACE (tmp->data)->parent)
-       {
-          if (parent != NULL)
-            {
-              gint index = g_list_index (parent->children, window);
-              for (; tmp && parent == GDK_SURFACE (tmp->data)->parent; tmp = tmp->next)
-                {
-                  gint sibling_index = g_list_index (parent->children, tmp->data);
-                  if (index > sibling_index)
-                    break;
-                  prev = tmp;
-                }
-            }
-         /* here, tmp got advanced past all lower stacked siblings */
-         tmp = g_slist_prepend (tmp, g_object_ref (window));
-         if (prev)
-           prev->next = tmp;
-         else
-           update_windows = tmp;
-         return;
-       }
-
-      /*  if "window" has an ancestor in the list and tmp is one of
-       *  "window's" children, insert "window" before tmp
-       */
-      if (has_ancestor_in_list && gdk_surface_is_ancestor (tmp->data, window))
-       {
-         tmp = g_slist_prepend (tmp, g_object_ref (window));
-
-         if (prev)
-           prev->next = tmp;
-         else
-           update_windows = tmp;
-         return;
-       }
-
-      /*  if we're at the end of the list and had an ancestor it it,
-       *  append to the list
-       */
-      if (! tmp->next && has_ancestor_in_list)
-       {
-         tmp = g_slist_append (tmp, g_object_ref (window));
-         return;
-       }
-
-      prev = tmp;
-    }
-
-  /*  if all above checks failed ("window" is from a different
-   *  hierarchy than what is already in the list) or the list is
-   *  empty, prepend
-   */
-  update_windows = g_slist_prepend (update_windows, g_object_ref (window));
-}
-
-static void
-gdk_surface_remove_update_window (GdkSurface *window)
-{
-  GSList *link;
-
-  link = g_slist_find (update_windows, window);
-  if (link != NULL)
-    {
-      update_windows = g_slist_delete_link (update_windows, link);
-      g_object_unref (window);
-    }
-}
-
-static gboolean
-gdk_surface_is_toplevel_frozen (GdkSurface *window)
-{
-  GdkSurface *toplevel;
-
-  toplevel = gdk_surface_get_toplevel (window);
-
-  return toplevel->update_and_descendants_freeze_count > 0;
-}
-
-static void
-gdk_surface_schedule_update (GdkSurface *window)
-{
-  GdkFrameClock *frame_clock;
-
-  if (window &&
-      (window->update_freeze_count ||
-       gdk_surface_is_toplevel_frozen (window)))
-    return;
-
-  /* If there's no frame clock (a foreign window), then the invalid
-   * region will just stick around unless gdk_surface_process_updates()
-   * is called. */
-  frame_clock = gdk_surface_get_frame_clock (window);
-  if (frame_clock)
-    gdk_frame_clock_request_phase (gdk_surface_get_frame_clock (window),
-                                   GDK_FRAME_CLOCK_PHASE_PAINT);
-}
-
-void
-_gdk_surface_process_updates_recurse (GdkSurface *window,
-                                     cairo_region_t *expose_region)
-{
-  cairo_region_t *clipped_expose_region;
-  GdkEvent *event;
-
-  if (window->destroyed)
-    return;
-
-  clipped_expose_region = cairo_region_copy (expose_region);
-
-  cairo_region_intersect (clipped_expose_region, window->clip_region);
-
-  if (cairo_region_is_empty (clipped_expose_region))
-    goto out;
-
-  /* Paint the window before the children, clipped to the window region */
-
-  event = gdk_event_new (GDK_EXPOSE);
-  event->any.window = g_object_ref (window);
-  event->any.send_event = FALSE;
-  event->expose.count = 0;
-  event->expose.region = cairo_region_reference (clipped_expose_region);
-  cairo_region_get_extents (clipped_expose_region, &event->expose.area);
-
-  _gdk_event_emit (event);
-  gdk_event_free (event);
-
- out:
-  cairo_region_destroy (clipped_expose_region);
-}
-
-
-static void
-gdk_surface_update_native_shapes (GdkSurface *window)
-{
-  if (should_apply_clip_as_shape (window))
-    apply_clip_as_shape (window);
-}
-
-/* Process and remove any invalid area on the native window by creating
- * expose events for the window and all non-native descendants.
- */
-static void
-gdk_surface_process_updates_internal (GdkSurface *window)
-{
-  GdkSurfaceImplClass *impl_class;
-  GdkSurface *toplevel;
-
-  toplevel = gdk_surface_get_toplevel (window);
-  if (toplevel->geometry_dirty)
-    {
-      gdk_surface_update_native_shapes (toplevel);
-      toplevel->geometry_dirty = FALSE;
-    }
-
-  /* Ensure the window lives while updating it */
-  g_object_ref (window);
-
-  window->in_update = TRUE;
-
-  /* If an update got queued during update processing, we can get a
-   * window in the update queue that has an empty update_area.
-   * just ignore it.
-   */
-  if (window->update_area)
-    {
-      g_assert (window->active_update_area == NULL); /* No reentrancy */
-
-      window->active_update_area = window->update_area;
-      window->update_area = NULL;
-
-      if (gdk_surface_is_viewable (window))
-       {
-         cairo_region_t *expose_region;
-
-         expose_region = cairo_region_copy (window->active_update_area);
-
-         impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-         /* Clip to part visible in impl window */
-         cairo_region_intersect (expose_region, window->clip_region);
-
-          if (impl_class->queue_antiexpose)
-            impl_class->queue_antiexpose (window, expose_region);
-
-          impl_class->process_updates_recurse (window, expose_region);
-
-          gdk_surface_append_old_updated_area (window, window->active_update_area);
-
-          cairo_region_destroy (expose_region);
-        }
-
-      cairo_region_destroy (window->active_update_area);
-      window->active_update_area = NULL;
-    }
-
-  window->in_update = FALSE;
-
-  g_object_unref (window);
-}
-
-static void
-gdk_surface_paint_on_clock (GdkFrameClock *clock,
-                          void          *data)
-{
-  GdkSurface *window;
-
-  window = GDK_SURFACE (data);
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (window->impl_window == window);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  g_object_ref (window);
-
-  if (window->update_area &&
-      !window->update_freeze_count &&
-      !gdk_surface_is_toplevel_frozen (window) &&
-
-      /* Don't recurse into process_updates_internal, we'll
-       * do the update later when idle instead. */
-      !window->in_update)
-    {
-      gdk_surface_process_updates_internal (window);
-      gdk_surface_remove_update_window (window);
-    }
-
-  g_object_unref (window);
-}
-
-static void
-gdk_surface_invalidate_rect_full (GdkSurface          *window,
-                                 const GdkRectangle *rect,
-                                 gboolean            invalidate_children)
-{
-  GdkRectangle window_rect;
-  cairo_region_t *region;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (window->input_only || !window->viewable)
-    return;
-
-  if (!rect)
-    {
-      window_rect.x = 0;
-      window_rect.y = 0;
-      window_rect.width = window->width;
-      window_rect.height = window->height;
-      rect = &window_rect;
-    }
-
-  region = cairo_region_create_rectangle (rect);
-  gdk_surface_invalidate_region_full (window, region, invalidate_children);
-  cairo_region_destroy (region);
-}
-
-/**
- * gdk_surface_invalidate_rect:
- * @window: a #GdkSurface
- * @rect: (allow-none): rectangle to invalidate or %NULL to invalidate the whole
- *      window
- * @invalidate_children: whether to also invalidate child windows
- *
- * A convenience wrapper around gdk_surface_invalidate_region() which
- * invalidates a rectangular region. See
- * gdk_surface_invalidate_region() for details.
- **/
-void
-gdk_surface_invalidate_rect (GdkSurface          *window,
-                           const GdkRectangle *rect,
-                           gboolean            invalidate_children)
-{
-  gdk_surface_invalidate_rect_full (window, rect, invalidate_children);
-}
-
-static void
-impl_window_add_update_area (GdkSurface *impl_window,
-                            cairo_region_t *region)
-{
-  if (impl_window->update_area)
-    cairo_region_union (impl_window->update_area, region);
-  else
-    {
-      gdk_surface_add_update_window (impl_window);
-      impl_window->update_area = cairo_region_copy (region);
-      gdk_surface_schedule_update (impl_window);
-    }
-}
-
-static void
-gdk_surface_invalidate_maybe_recurse_full (GdkSurface            *window,
-                                         const cairo_region_t *region,
-                                          GdkSurfaceChildFunc    child_func,
-                                         gpointer              user_data)
-{
-  cairo_region_t *visible_region;
-  cairo_rectangle_int_t r;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (window->input_only ||
-      !window->viewable ||
-      cairo_region_is_empty (region) ||
-      window->window_type == GDK_SURFACE_ROOT)
-    return;
-
-  r.x = 0;
-  r.y = 0;
-
-  visible_region = cairo_region_copy (region);
-
-  while (window != NULL && 
-        !cairo_region_is_empty (visible_region))
-    {
-      r.width = window->width;
-      r.height = window->height;
-      cairo_region_intersect_rectangle (visible_region, &r);
-
-      if (gdk_surface_has_impl (window))
-       {
-         impl_window_add_update_area (window, visible_region);
-         break;
-       }
-      else
-       {
-         cairo_region_translate (visible_region,
-                                 window->x, window->y);
-         window = window->parent;
-       }
-    }
-
-  cairo_region_destroy (visible_region);
-}
-
-/**
- * gdk_surface_invalidate_maybe_recurse:
- * @window: a #GdkSurface
- * @region: a #cairo_region_t
- * @child_func: (scope call) (allow-none): function to use to decide if to
- *     recurse to a child, %NULL means never recurse.
- * @user_data: data passed to @child_func
- *
- * Adds @region to the update area for @window. The update area is the
- * region that needs to be redrawn, or â€śdirty region.”
- *
- * GDK will process all updates whenever the frame clock schedules a redraw,
- * so there’s no need to do forces redraws manually, you just need to
- * invalidate regions that you know should be redrawn.
- *
- * The @child_func parameter controls whether the region of
- * each child window that intersects @region will also be invalidated.
- * Only children for which @child_func returns #TRUE will have the area
- * invalidated.
- **/
-void
-gdk_surface_invalidate_maybe_recurse (GdkSurface            *window,
-                                    const cairo_region_t *region,
-                                     GdkSurfaceChildFunc    child_func,
-                                    gpointer              user_data)
-{
-  gdk_surface_invalidate_maybe_recurse_full (window, region,
-                                           child_func, user_data);
-}
-
-static gboolean
-true_predicate (GdkSurface *window,
-               gpointer   user_data)
-{
-  return TRUE;
-}
-
-static void
-gdk_surface_invalidate_region_full (GdkSurface       *window,
-                                   const cairo_region_t *region,
-                                   gboolean         invalidate_children)
-{
-  gdk_surface_invalidate_maybe_recurse_full (window, region,
-                                           invalidate_children ?
-                                           true_predicate : (gboolean (*) (GdkSurface *, gpointer))NULL,
-                                      NULL);
-}
-
-/**
- * gdk_surface_invalidate_region:
- * @window: a #GdkSurface
- * @region: a #cairo_region_t
- * @invalidate_children: %TRUE to also invalidate child windows
- *
- * Adds @region to the update area for @window. The update area is the
- * region that needs to be redrawn, or â€śdirty region.”
- *
- * GDK will process all updates whenever the frame clock schedules a redraw,
- * so there’s no need to do forces redraws manually, you just need to
- * invalidate regions that you know should be redrawn.
- *
- * The @invalidate_children parameter controls whether the region of
- * each child window that intersects @region will also be invalidated.
- * If %FALSE, then the update area for child windows will remain
- * unaffected. See gdk_surface_invalidate_maybe_recurse if you need
- * fine grained control over which children are invalidated.
- **/
-void
-gdk_surface_invalidate_region (GdkSurface       *window,
-                             const cairo_region_t *region,
-                             gboolean         invalidate_children)
-{
-  gdk_surface_invalidate_maybe_recurse (window, region,
-                                      invalidate_children ?
-                                        true_predicate : (gboolean (*) (GdkSurface *, gpointer))NULL,
-                                      NULL);
-}
-
-/**
- * _gdk_surface_invalidate_for_expose:
- * @window: a #GdkSurface
- * @region: a #cairo_region_t
- *
- * Adds @region to the update area for @window.
- *
- * GDK will process all updates whenever the frame clock schedules a redraw,
- * so there’s no need to do forces redraws manually, you just need to
- * invalidate regions that you know should be redrawn.
- *
- * This version of invalidation is used when you recieve expose events
- * from the native window system. It exposes the native window, plus
- * any non-native child windows.
- **/
-void
-_gdk_surface_invalidate_for_expose (GdkSurface       *window,
-                                  cairo_region_t       *region)
-{
-  gdk_surface_invalidate_maybe_recurse_full (window, region,
-                                           (gboolean (*) (GdkSurface *, gpointer))gdk_surface_has_no_impl,
-                                           NULL);
-}
-
-
-/**
- * gdk_surface_get_update_area:
- * @window: a #GdkSurface
- *
- * Transfers ownership of the update area from @window to the caller
- * of the function. That is, after calling this function, @window will
- * no longer have an invalid/dirty region; the update area is removed
- * from @window and handed to you. If a window has no update area,
- * gdk_surface_get_update_area() returns %NULL. You are responsible for
- * calling cairo_region_destroy() on the returned region if it’s non-%NULL.
- *
- * Returns: the update area for @window
- **/
-cairo_region_t *
-gdk_surface_get_update_area (GdkSurface *window)
-{
-  GdkSurface *impl_window;
-  cairo_region_t *tmp_region, *to_remove;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  impl_window = gdk_surface_get_impl_window (window);
-
-  if (impl_window->update_area)
-    {
-      tmp_region = cairo_region_copy (window->clip_region);
-      /* Convert to impl coords */
-      cairo_region_translate (tmp_region, window->abs_x, window->abs_y);
-      cairo_region_intersect (tmp_region, impl_window->update_area);
-
-      if (cairo_region_is_empty (tmp_region))
-       {
-         cairo_region_destroy (tmp_region);
-         return NULL;
-       }
-      else
-       {
-         /* Convert from impl coords */
-         cairo_region_translate (tmp_region, -window->abs_x, -window->abs_y);
-
-         /* Don't remove any update area that is overlapped by sibling windows
-            or child windows as these really need to be repainted independently of this window. */
-         to_remove = cairo_region_copy (tmp_region);
-
-         remove_child_area (window, FALSE, to_remove);
-         remove_sibling_overlapped_area (window, to_remove);
-
-         /* Remove from update_area */
-         cairo_region_translate (to_remove, window->abs_x, window->abs_y);
-         cairo_region_subtract (impl_window->update_area, to_remove);
-
-         cairo_region_destroy (to_remove);
-
-         if (cairo_region_is_empty (impl_window->update_area))
-           {
-             cairo_region_destroy (impl_window->update_area);
-             impl_window->update_area = NULL;
-
-             gdk_surface_remove_update_window ((GdkSurface *)impl_window);
-           }
-
-         return tmp_region;
-       }
-    }
-  else
-    return NULL;
-}
-
-/**
- * _gdk_surface_clear_update_area:
- * @window: a #GdkSurface.
- *
- * Internal function to clear the update area for a window. This
- * is called when the window is hidden or destroyed.
- **/
-void
-_gdk_surface_clear_update_area (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->update_area)
-    {
-      gdk_surface_remove_update_window (window);
-
-      cairo_region_destroy (window->update_area);
-      window->update_area = NULL;
-    }
-}
-
-/**
- * gdk_surface_freeze_updates:
- * @window: a #GdkSurface
- *
- * Temporarily freezes a window such that it won’t receive expose
- * events.  The window will begin receiving expose events again when
- * gdk_surface_thaw_updates() is called. If gdk_surface_freeze_updates()
- * has been called more than once, gdk_surface_thaw_updates() must be called
- * an equal number of times to begin processing exposes.
- **/
-void
-gdk_surface_freeze_updates (GdkSurface *window)
-{
-  GdkSurface *impl_window;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl_window = gdk_surface_get_impl_window (window);
-  impl_window->update_freeze_count++;
-}
-
-/**
- * gdk_surface_thaw_updates:
- * @window: a #GdkSurface
- *
- * Thaws a window frozen with gdk_surface_freeze_updates().
- **/
-void
-gdk_surface_thaw_updates (GdkSurface *window)
-{
-  GdkSurface *impl_window;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl_window = gdk_surface_get_impl_window (window);
-
-  g_return_if_fail (impl_window->update_freeze_count > 0);
-
-  if (--impl_window->update_freeze_count == 0)
-    gdk_surface_schedule_update (GDK_SURFACE (impl_window));
-}
-
-void
-gdk_surface_freeze_toplevel_updates (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (window->window_type != GDK_SURFACE_CHILD);
-
-  window->update_and_descendants_freeze_count++;
-  _gdk_frame_clock_freeze (gdk_surface_get_frame_clock (window));
-}
-
-void
-gdk_surface_thaw_toplevel_updates (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (window->window_type != GDK_SURFACE_CHILD);
-  g_return_if_fail (window->update_and_descendants_freeze_count > 0);
-
-  window->update_and_descendants_freeze_count--;
-  _gdk_frame_clock_thaw (gdk_surface_get_frame_clock (window));
-
-  gdk_surface_schedule_update (window);
-}
-
-/**
- * gdk_surface_constrain_size:
- * @geometry: a #GdkGeometry structure
- * @flags: a mask indicating what portions of @geometry are set
- * @width: desired width of window
- * @height: desired height of the window
- * @new_width: (out): location to store resulting width
- * @new_height: (out): location to store resulting height
- *
- * Constrains a desired width and height according to a
- * set of geometry hints (such as minimum and maximum size).
- */
-void
-gdk_surface_constrain_size (GdkGeometry    *geometry,
-                          GdkSurfaceHints  flags,
-                          gint            width,
-                          gint            height,
-                          gint           *new_width,
-                          gint           *new_height)
-{
-  /* This routine is partially borrowed from fvwm.
-   *
-   * Copyright 1993, Robert Nation
-   *     You may use this code for any purpose, as long as the original
-   *     copyright remains in the source code and all documentation
-   *
-   * which in turn borrows parts of the algorithm from uwm
-   */
-  gint min_width = 0;
-  gint min_height = 0;
-  gint base_width = 0;
-  gint base_height = 0;
-  gint xinc = 1;
-  gint yinc = 1;
-  gint max_width = G_MAXINT;
-  gint max_height = G_MAXINT;
-
-#define FLOOR(value, base)     ( ((gint) ((value) / (base))) * (base) )
-
-  if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
-    {
-      base_width = geometry->base_width;
-      base_height = geometry->base_height;
-      min_width = geometry->min_width;
-      min_height = geometry->min_height;
-    }
-  else if (flags & GDK_HINT_BASE_SIZE)
-    {
-      base_width = geometry->base_width;
-      base_height = geometry->base_height;
-      min_width = geometry->base_width;
-      min_height = geometry->base_height;
-    }
-  else if (flags & GDK_HINT_MIN_SIZE)
-    {
-      base_width = geometry->min_width;
-      base_height = geometry->min_height;
-      min_width = geometry->min_width;
-      min_height = geometry->min_height;
-    }
-
-  if (flags & GDK_HINT_MAX_SIZE)
-    {
-      max_width = geometry->max_width ;
-      max_height = geometry->max_height;
-    }
-
-  if (flags & GDK_HINT_RESIZE_INC)
-    {
-      xinc = MAX (xinc, geometry->width_inc);
-      yinc = MAX (yinc, geometry->height_inc);
-    }
-
-  /* clamp width and height to min and max values
-   */
-  width = CLAMP (width, min_width, max_width);
-  height = CLAMP (height, min_height, max_height);
-
-  /* shrink to base + N * inc
-   */
-  width = base_width + FLOOR (width - base_width, xinc);
-  height = base_height + FLOOR (height - base_height, yinc);
-
-  /* constrain aspect ratio, according to:
-   *
-   *                width
-   * min_aspect <= -------- <= max_aspect
-   *                height
-   */
-
-  if (flags & GDK_HINT_ASPECT &&
-      geometry->min_aspect > 0 &&
-      geometry->max_aspect > 0)
-    {
-      gint delta;
-
-      if (geometry->min_aspect * height > width)
-       {
-         delta = FLOOR (height - width / geometry->min_aspect, yinc);
-         if (height - delta >= min_height)
-           height -= delta;
-         else
-           {
-             delta = FLOOR (height * geometry->min_aspect - width, xinc);
-             if (width + delta <= max_width)
-               width += delta;
-           }
-       }
-
-      if (geometry->max_aspect * height < width)
-       {
-         delta = FLOOR (width - height * geometry->max_aspect, xinc);
-         if (width - delta >= min_width)
-           width -= delta;
-         else
-           {
-             delta = FLOOR (width / geometry->max_aspect - height, yinc);
-             if (height + delta <= max_height)
-               height += delta;
-           }
-       }
-    }
-
-#undef FLOOR
-
-  *new_width = width;
-  *new_height = height;
-}
-
-/**
- * gdk_surface_get_device_position_double:
- * @window: a #GdkSurface.
- * @device: pointer #GdkDevice to query to.
- * @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
- * @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
- * @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
- *
- * Obtains the current device position in doubles and modifier state.
- * The position is given in coordinates relative to the upper left
- * corner of @window.
- *
- * Returns: (nullable) (transfer none): The window underneath @device
- * (as with gdk_device_get_window_at_position()), or %NULL if the
- * window is not known to GDK.
- **/
-GdkSurface *
-gdk_surface_get_device_position_double (GdkSurface       *window,
-                                       GdkDevice       *device,
-                                       double          *x,
-                                       double          *y,
-                                       GdkModifierType *mask)
-{
-  gdouble tmp_x, tmp_y;
-  GdkModifierType tmp_mask;
-  gboolean normal_child;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
-  g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
-
-  tmp_x = tmp_y = 0;
-  tmp_mask = 0;
-  normal_child = GDK_SURFACE_IMPL_GET_CLASS (window->impl)->get_device_state (window,
-                                                                             device,
-                                                                             &tmp_x, &tmp_y,
-                                                                             &tmp_mask);
-  /* We got the coords on the impl, convert to the window */
-  tmp_x -= window->abs_x;
-  tmp_y -= window->abs_y;
-
-  if (x)
-    *x = tmp_x;
-  if (y)
-    *y = tmp_y;
-  if (mask)
-    *mask = tmp_mask;
-
-  if (normal_child)
-    return _gdk_surface_find_child_at (window, tmp_x, tmp_y);
-  return NULL;
-}
-
-/**
- * gdk_surface_get_device_position:
- * @window: a #GdkSurface.
- * @device: pointer #GdkDevice to query to.
- * @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
- * @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
- * @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
- *
- * Obtains the current device position and modifier state.
- * The position is given in coordinates relative to the upper left
- * corner of @window.
- *
- * Use gdk_surface_get_device_position_double() if you need subpixel precision.
- *
- * Returns: (nullable) (transfer none): The window underneath @device
- * (as with gdk_device_get_window_at_position()), or %NULL if the
- * window is not known to GDK.
- **/
-GdkSurface *
-gdk_surface_get_device_position (GdkSurface       *window,
-                                GdkDevice       *device,
-                                gint            *x,
-                                gint            *y,
-                                GdkModifierType *mask)
-{
-  gdouble tmp_x, tmp_y;
-
-  window = gdk_surface_get_device_position_double (window, device,
-                                                  &tmp_x, &tmp_y, mask);
-  if (x)
-    *x = round (tmp_x);
-  if (y)
-    *y = round (tmp_y);
-
-  return window;
-}
-
-static gboolean
-gdk_surface_raise_internal (GdkSurface *window)
-{
-  GdkSurface *parent = window->parent;
-  GdkSurfaceImplClass *impl_class;
-  gboolean did_raise = FALSE;
-
-  if (parent && parent->children->data != window)
-    {
-      parent->children = g_list_remove_link (parent->children, &window->children_list_node);
-      parent->children = g_list_concat (&window->children_list_node, parent->children);
-      did_raise = TRUE;
-    }
-
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-  /* Just do native raise for toplevels */
-  if (gdk_surface_has_impl (window))
-      impl_class->raise (window);
-
-  return did_raise;
-}
-
-/* Returns TRUE If the native window was mapped or unmapped */
-static gboolean
-set_viewable (GdkSurface *w,
-             gboolean val)
-{
-  GdkSurface *child;
-  GList *l;
-
-  if (w->viewable == val)
-    return FALSE;
-
-  w->viewable = val;
-
-  if (val)
-    recompute_visible_regions (w, FALSE);
-
-  for (l = w->children; l != NULL; l = l->next)
-    {
-      child = l->data;
-
-      if (GDK_SURFACE_IS_MAPPED (child))
-       set_viewable (child, val);
-    }
-
-  return FALSE;
-}
-
-/* Returns TRUE If the native window was mapped or unmapped */
-gboolean
-_gdk_surface_update_viewable (GdkSurface *window)
-{
-  gboolean viewable;
-
-  if (window->window_type == GDK_SURFACE_FOREIGN ||
-      window->window_type == GDK_SURFACE_ROOT)
-    viewable = TRUE;
-  else if (gdk_surface_is_toplevel (window) ||
-          window->parent->viewable)
-    viewable = GDK_SURFACE_IS_MAPPED (window);
-  else
-    viewable = FALSE;
-
-  return set_viewable (window, viewable);
-}
-
-static void
-gdk_surface_show_internal (GdkSurface *window, gboolean raise)
-{
-  GdkSurfaceImplClass *impl_class;
-  gboolean was_mapped, was_viewable;
-  gboolean did_show, did_raise = FALSE;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->destroyed)
-    return;
-
-  was_mapped = GDK_SURFACE_IS_MAPPED (window);
-  was_viewable = window->viewable;
-
-  if (raise)
-    {
-      /* Keep children in (reverse) stacking order */
-      did_raise = gdk_surface_raise_internal (window);
-    }
-
-  if (gdk_surface_has_impl (window))
-    {
-      if (!was_mapped)
-        gdk_synthesize_window_state (window,
-                                     GDK_SURFACE_STATE_WITHDRAWN,
-                                     0);
-    }
-  else
-    {
-      window->state = 0;
-      g_object_notify_by_pspec (G_OBJECT (window), properties[PROP_STATE]);
-    }
-
-  did_show = _gdk_surface_update_viewable (window);
-
-  /* If it was already viewable the backend show op won't be called, call it
-     again to ensure things happen right if the mapped tracking was not right
-     for e.g. a foreign window.
-     Dunno if this is strictly needed but its what happened pre-csw.
-     Also show if not done by gdk_surface_update_viewable. */
-  if (gdk_surface_has_impl (window) && (was_viewable || !did_show))
-    {
-      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-      impl_class->show (window, !did_show ? was_mapped : TRUE);
-    }
-
-  if (!was_mapped && !gdk_surface_has_impl (window))
-    {
-      if (window->event_mask & GDK_STRUCTURE_MASK)
-       _gdk_make_event (window, GDK_MAP, NULL, FALSE);
-
-      if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
-       _gdk_make_event (window, GDK_MAP, NULL, FALSE);
-    }
-
-  if (!was_mapped || did_raise)
-    {
-      recompute_visible_regions (window, FALSE);
-
-      if (gdk_surface_is_viewable (window))
-        gdk_surface_invalidate_rect_full (window, NULL, TRUE);
-    }
-}
-
-/**
- * gdk_surface_show_unraised:
- * @window: a #GdkSurface
- *
- * Shows a #GdkSurface onscreen, but does not modify its stacking
- * order. In contrast, gdk_surface_show() will raise the window
- * to the top of the window stack.
- *
- * On the X11 platform, in Xlib terms, this function calls
- * XMapWindow() (it also updates some internal GDK state, which means
- * that you can’t really use XMapWindow() directly on a GDK window).
- */
-void
-gdk_surface_show_unraised (GdkSurface *window)
-{
-  gdk_surface_show_internal (window, FALSE);
-}
-
-/**
- * gdk_surface_raise:
- * @window: a #GdkSurface
- *
- * Raises @window to the top of the Z-order (stacking order), so that
- * other windows with the same parent window appear below @window.
- * This is true whether or not the windows are visible.
- *
- * If @window is a toplevel, the window manager may choose to deny the
- * request to move the window in the Z-order, gdk_surface_raise() only
- * requests the restack, does not guarantee it.
- */
-void
-gdk_surface_raise (GdkSurface *window)
-{
-  gboolean did_raise;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->destroyed)
-    return;
-
-  /* Keep children in (reverse) stacking order */
-  did_raise = gdk_surface_raise_internal (window);
-
-  if (did_raise &&
-      !gdk_surface_is_toplevel (window) &&
-      gdk_surface_is_viewable (window) &&
-      !window->input_only)
-    gdk_surface_invalidate_region_full (window, window->clip_region, TRUE);
-}
-
-static void
-gdk_surface_lower_internal (GdkSurface *window)
-{
-  GdkSurface *parent = window->parent;
-  GdkSurfaceImplClass *impl_class;
-
-  if (parent)
-    {
-      parent->children = g_list_remove_link (parent->children, &window->children_list_node);
-      parent->children = g_list_concat (parent->children, &window->children_list_node);
-    }
-
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-  /* Just do native lower for toplevels */
-  if (gdk_surface_has_impl (window))
-    impl_class->lower (window);
-}
-
-static void
-gdk_surface_invalidate_in_parent (GdkSurface *private)
-{
-  GdkRectangle r, child;
-
-  if (gdk_surface_is_toplevel (private))
-    return;
-
-  /* get the visible rectangle of the parent */
-  r.x = r.y = 0;
-  r.width = private->parent->width;
-  r.height = private->parent->height;
-
-  child.x = private->x;
-  child.y = private->y;
-  child.width = private->width;
-  child.height = private->height;
-  gdk_rectangle_intersect (&r, &child, &r);
-
-  gdk_surface_invalidate_rect_full (private->parent, &r, TRUE);
-}
-
-
-/**
- * gdk_surface_lower:
- * @window: a #GdkSurface
- *
- * Lowers @window to the bottom of the Z-order (stacking order), so that
- * other windows with the same parent window appear above @window.
- * This is true whether or not the other windows are visible.
- *
- * If @window is a toplevel, the window manager may choose to deny the
- * request to move the window in the Z-order, gdk_surface_lower() only
- * requests the restack, does not guarantee it.
- *
- * Note that gdk_surface_show() raises the window again, so don’t call this
- * function before gdk_surface_show(). (Try gdk_surface_show_unraised().)
- */
-void
-gdk_surface_lower (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->destroyed)
-    return;
-
-  /* Keep children in (reverse) stacking order */
-  gdk_surface_lower_internal (window);
-
-  gdk_surface_invalidate_in_parent (window);
-}
-
-/**
- * gdk_surface_restack:
- * @window: a #GdkSurface
- * @sibling: (allow-none): a #GdkSurface that is a sibling of @window, or %NULL
- * @above: a boolean
- *
- * Changes the position of  @window in the Z-order (stacking order), so that
- * it is above @sibling (if @above is %TRUE) or below @sibling (if @above is
- * %FALSE).
- *
- * If @sibling is %NULL, then this either raises (if @above is %TRUE) or
- * lowers the window.
- *
- * If @window is a toplevel, the window manager may choose to deny the
- * request to move the window in the Z-order, gdk_surface_restack() only
- * requests the restack, does not guarantee it.
- */
-void
-gdk_surface_restack (GdkSurface     *window,
-                   GdkSurface     *sibling,
-                   gboolean       above)
-{
-  GdkSurfaceImplClass *impl_class;
-  GdkSurface *parent;
-  GList *sibling_link;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (sibling == NULL || GDK_IS_SURFACE (sibling));
-
-  if (window->destroyed)
-    return;
-
-  if (sibling == NULL)
-    {
-      if (above)
-       gdk_surface_raise (window);
-      else
-       gdk_surface_lower (window);
-      return;
-    }
-
-  if (gdk_surface_is_toplevel (window))
-    {
-      g_return_if_fail (gdk_surface_is_toplevel (sibling));
-      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-      impl_class->restack_toplevel (window, sibling, above);
-      return;
-    }
-
-  parent = window->parent;
-  if (parent)
-    {
-      sibling_link = g_list_find (parent->children, sibling);
-      g_return_if_fail (sibling_link != NULL);
-      if (sibling_link == NULL)
-       return;
-
-      parent->children = g_list_remove_link (parent->children, &window->children_list_node);
-      if (above)
-       parent->children = list_insert_link_before (parent->children,
-                                                    sibling_link,
-                                                    &window->children_list_node);
-      else
-       parent->children = list_insert_link_before (parent->children,
-                                                    sibling_link->next,
-                                                    &window->children_list_node);
-    }
-
-  gdk_surface_invalidate_in_parent (window);
-}
-
-
-/**
- * gdk_surface_show:
- * @window: a #GdkSurface
- *
- * Like gdk_surface_show_unraised(), but also raises the window to the
- * top of the window stack (moves the window to the front of the
- * Z-order).
- *
- * This function maps a window so it’s visible onscreen. Its opposite
- * is gdk_surface_hide().
- *
- * When implementing a #GtkWidget, you should call this function on the widget's
- * #GdkSurface as part of the â€śmap” method.
- */
-void
-gdk_surface_show (GdkSurface *window)
-{
-  gdk_surface_show_internal (window, TRUE);
-}
-
-/**
- * gdk_surface_hide:
- * @window: a #GdkSurface
- *
- * For toplevel windows, withdraws them, so they will no longer be
- * known to the window manager; for all windows, unmaps them, so
- * they won’t be displayed. Normally done automatically as
- * part of gtk_widget_hide().
- */
-void
-gdk_surface_hide (GdkSurface *window)
-{
-  GdkSurfaceImplClass *impl_class;
-  gboolean was_mapped, did_hide;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->destroyed)
-    return;
-
-  was_mapped = GDK_SURFACE_IS_MAPPED (window);
-
-  if (gdk_surface_has_impl (window))
-    {
-
-      if (GDK_SURFACE_IS_MAPPED (window))
-       gdk_synthesize_window_state (window,
-                                    0,
-                                    GDK_SURFACE_STATE_WITHDRAWN);
-    }
-  else if (was_mapped)
-    {
-      window->state = GDK_SURFACE_STATE_WITHDRAWN;
-      g_object_notify_by_pspec (G_OBJECT (window), properties[PROP_STATE]);
-    }
-
-  if (was_mapped)
-    {
-      GdkDisplay *display;
-      GdkSeat *seat;
-      GList *devices, *d;
-
-      /* May need to break grabs on children */
-      display = gdk_surface_get_display (window);
-      seat = gdk_display_get_default_seat (display);
-
-      devices = gdk_seat_get_slaves (seat, GDK_SEAT_CAPABILITY_ALL);
-      devices = g_list_prepend (devices, gdk_seat_get_keyboard (seat));
-      devices = g_list_prepend (devices, gdk_seat_get_pointer (seat));
-
-      for (d = devices; d; d = d->next)
-        {
-          GdkDevice *device = d->data;
-
-          if (_gdk_display_end_device_grab (display,
-                                            device,
-                                            _gdk_display_get_next_serial (display),
-                                            window,
-                                            TRUE))
-            {
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-              gdk_device_ungrab (device, GDK_CURRENT_TIME);
-G_GNUC_END_IGNORE_DEPRECATIONS
-            }
-        }
-
-      g_list_free (devices);
-    }
-
-  did_hide = _gdk_surface_update_viewable (window);
-
-  /* Hide foreign window as those are not handled by update_viewable. */
-  if (gdk_surface_has_impl (window) && (!did_hide))
-    {
-      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-      impl_class->hide (window);
-    }
-
-  gdk_surface_clear_old_updated_area (window);
-  recompute_visible_regions (window, FALSE);
-
-  if (was_mapped && !gdk_surface_has_impl (window))
-    {
-      if (window->event_mask & GDK_STRUCTURE_MASK)
-       _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
-
-      if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
-       _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
-    }
-
-  /* Invalidate the rect */
-  if (was_mapped)
-    gdk_surface_invalidate_in_parent (window);
-}
-
-/**
- * gdk_surface_withdraw:
- * @window: a toplevel #GdkSurface
- *
- * Withdraws a window (unmaps it and asks the window manager to forget about it).
- * This function is not really useful as gdk_surface_hide() automatically
- * withdraws toplevel windows before hiding them.
- **/
-void
-gdk_surface_withdraw (GdkSurface *window)
-{
-  GdkSurfaceImplClass *impl_class;
-  gboolean was_mapped;
-  GdkGLContext *current_context;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->destroyed)
-    return;
-
-  was_mapped = GDK_SURFACE_IS_MAPPED (window);
-
-  if (gdk_surface_has_impl (window))
-    {
-      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-      impl_class->withdraw (window);
-
-      if (was_mapped)
-       {
-         if (window->event_mask & GDK_STRUCTURE_MASK)
-           _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
-
-         if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
-           _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
-       }
-
-      current_context = gdk_gl_context_get_current ();
-      if (current_context != NULL && gdk_gl_context_get_window (current_context) == window)
-        gdk_gl_context_clear_current ();
-
-      recompute_visible_regions (window, FALSE);
-      gdk_surface_clear_old_updated_area (window);
-    }
-}
-
-/**
- * gdk_surface_set_events:
- * @window: a #GdkSurface
- * @event_mask: event mask for @window
- *
- * The event mask for a window determines which events will be reported
- * for that window from all master input devices. For example, an event mask
- * including #GDK_BUTTON_PRESS_MASK means the window should report button
- * press events. The event mask is the bitwise OR of values from the
- * #GdkEventMask enumeration.
- *
- * See the [input handling overview][event-masks] for details.
- **/
-void
-gdk_surface_set_events (GdkSurface       *window,
-                      GdkEventMask     event_mask)
-{
-  GdkSurfaceImplClass *impl_class;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->destroyed)
-    return;
-
-  window->event_mask = event_mask;
-
-  if (gdk_surface_has_impl (window))
-    {
-      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-      impl_class->set_events (window,
-                             get_native_event_mask (window));
-    }
-
-}
-
-/**
- * gdk_surface_get_events:
- * @window: a #GdkSurface
- *
- * Gets the event mask for @window for all master input devices. See
- * gdk_surface_set_events().
- *
- * Returns: event mask for @window
- **/
-GdkEventMask
-gdk_surface_get_events (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
-
-  if (window->destroyed)
-    return 0;
-
-  return window->event_mask;
-}
-
-/**
- * gdk_surface_set_device_events:
- * @window: a #GdkSurface
- * @device: #GdkDevice to enable events for.
- * @event_mask: event mask for @window
- *
- * Sets the event mask for a given device (Normally a floating device, not
- * attached to any visible pointer) to @window. For example, an event mask
- * including #GDK_BUTTON_PRESS_MASK means the window should report button
- * press events. The event mask is the bitwise OR of values from the
- * #GdkEventMask enumeration.
- *
- * See the [input handling overview][event-masks] for details.
- **/
-void
-gdk_surface_set_device_events (GdkSurface    *window,
-                              GdkDevice    *device,
-                              GdkEventMask  event_mask)
-{
-  GdkEventMask device_mask;
-  GdkSurface *native;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (GDK_IS_DEVICE (device));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (G_UNLIKELY (!window->device_events))
-    window->device_events = g_hash_table_new (NULL, NULL);
-
-  if (event_mask == 0)
-    {
-      /* FIXME: unsetting events on a master device
-       * would restore window->event_mask
-       */
-      g_hash_table_remove (window->device_events, device);
-    }
-  else
-    g_hash_table_insert (window->device_events, device,
-                         GINT_TO_POINTER (event_mask));
-
-  native = gdk_surface_get_toplevel (window);
-
-  device_mask = get_native_device_event_mask (window, device);
-  GDK_DEVICE_GET_CLASS (device)->select_window_events (device, native, device_mask);
-}
-
-/**
- * gdk_surface_get_device_events:
- * @window: a #GdkSurface.
- * @device: a #GdkDevice.
- *
- * Returns the event mask for @window corresponding to an specific device.
- *
- * Returns: device event mask for @window
- **/
-GdkEventMask
-gdk_surface_get_device_events (GdkSurface *window,
-                              GdkDevice *device)
-{
-  GdkEventMask mask;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
-  g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return 0;
-
-  if (!window->device_events)
-    return 0;
-
-  mask = GPOINTER_TO_INT (g_hash_table_lookup (window->device_events, device));
-
-  /* FIXME: device could be controlled by window->event_mask */
-
-  return mask;
-}
-
-static void
-gdk_surface_move_resize_toplevel (GdkSurface *window,
-                                 gboolean   with_move,
-                                 gint       x,
-                                 gint       y,
-                                 gint       width,
-                                 gint       height)
-{
-  cairo_region_t *old_region, *new_region;
-  GdkSurfaceImplClass *impl_class;
-  gboolean expose;
-  gboolean is_resize;
-
-  expose = FALSE;
-  old_region = NULL;
-
-  is_resize = (width != -1) || (height != -1);
-
-  if (gdk_surface_is_viewable (window) &&
-      !window->input_only)
-    {
-      expose = TRUE;
-      old_region = cairo_region_copy (window->clip_region);
-    }
-
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-  impl_class->move_resize (window, with_move, x, y, width, height);
-
-  /* Avoid recomputing for pure toplevel moves, for performance reasons */
-  if (is_resize)
-    recompute_visible_regions (window, FALSE);
-
-  if (expose)
-    {
-      new_region = cairo_region_copy (window->clip_region);
-
-      /* This is the newly exposed area (due to any resize),
-       * X will expose it, but lets do that without the roundtrip
-       */
-      cairo_region_subtract (new_region, old_region);
-      gdk_surface_invalidate_region_full (window, new_region, TRUE);
-
-      cairo_region_destroy (old_region);
-      cairo_region_destroy (new_region);
-    }
-}
-
-
-static void
-gdk_surface_move_resize_internal (GdkSurface *window,
-                                gboolean   with_move,
-                                gint       x,
-                                gint       y,
-                                gint       width,
-                                gint       height)
-{
-  cairo_region_t *old_region, *new_region;
-  gboolean expose;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->destroyed)
-    return;
-
-  if (gdk_surface_is_toplevel (window))
-    {
-      gdk_surface_move_resize_toplevel (window, with_move, x, y, width, height);
-      return;
-    }
-
-  if (width == 0)
-    width = 1;
-  if (height == 0)
-    height = 1;
-
-  /* Bail early if no change */
-  if (window->width == width &&
-      window->height == height &&
-      (!with_move ||
-       (window->x == x &&
-       window->y == y)))
-    return;
-
-  /* Handle child windows */
-
-  expose = FALSE;
-  old_region = NULL;
-
-  if (gdk_surface_is_viewable (window) &&
-      !window->input_only)
-    {
-      GdkRectangle r;
-
-      expose = TRUE;
-
-      r.x = window->x;
-      r.y = window->y;
-      r.width = window->width;
-      r.height = window->height;
-
-      old_region = cairo_region_create_rectangle (&r);
-    }
-
-  /* Set the new position and size */
-  if (with_move)
-    {
-      window->x = x;
-      window->y = y;
-    }
-  if (!(width < 0 && height < 0))
-    {
-      window->width = width;
-      window->height = height;
-    }
-
-  recompute_visible_regions (window, FALSE);
-
-  if (expose)
-    {
-      GdkRectangle r;
-
-      r.x = window->x;
-      r.y = window->y;
-      r.width = window->width;
-      r.height = window->height;
-
-      new_region = cairo_region_create_rectangle (&r);
-
-      cairo_region_union (new_region, old_region);
-
-      gdk_surface_invalidate_region_full (window->parent, new_region, TRUE);
-
-      cairo_region_destroy (old_region);
-      cairo_region_destroy (new_region);
-    }
-}
-
-
-
-/**
- * gdk_surface_move:
- * @window: a #GdkSurface
- * @x: X coordinate relative to window’s parent
- * @y: Y coordinate relative to window’s parent
- *
- * Repositions a window relative to its parent window.
- * For toplevel windows, window managers may ignore or modify the move;
- * you should probably use gtk_window_move() on a #GtkWindow widget
- * anyway, instead of using GDK functions. For child windows,
- * the move will reliably succeed.
- *
- * If you’re also planning to resize the window, use gdk_surface_move_resize()
- * to both move and resize simultaneously, for a nicer visual effect.
- **/
-void
-gdk_surface_move (GdkSurface *window,
-                gint       x,
-                gint       y)
-{
-  gdk_surface_move_resize_internal (window, TRUE, x, y, -1, -1);
-}
-
-/**
- * gdk_surface_resize:
- * @window: a #GdkSurface
- * @width: new width of the window
- * @height: new height of the window
- *
- * Resizes @window; for toplevel windows, asks the window manager to resize
- * the window. The window manager may not allow the resize. When using GTK+,
- * use gtk_window_resize() instead of this low-level GDK function.
- *
- * Windows may not be resized below 1x1.
- *
- * If you’re also planning to move the window, use gdk_surface_move_resize()
- * to both move and resize simultaneously, for a nicer visual effect.
- **/
-void
-gdk_surface_resize (GdkSurface *window,
-                  gint       width,
-                  gint       height)
-{
-  gdk_surface_move_resize_internal (window, FALSE, 0, 0, width, height);
-}
-
-
-/**
- * gdk_surface_move_resize:
- * @window: a #GdkSurface
- * @x: new X position relative to window’s parent
- * @y: new Y position relative to window’s parent
- * @width: new width
- * @height: new height
- *
- * Equivalent to calling gdk_surface_move() and gdk_surface_resize(),
- * except that both operations are performed at once, avoiding strange
- * visual effects. (i.e. the user may be able to see the window first
- * move, then resize, if you don’t use gdk_surface_move_resize().)
- **/
-void
-gdk_surface_move_resize (GdkSurface *window,
-                       gint       x,
-                       gint       y,
-                       gint       width,
-                       gint       height)
-{
-  gdk_surface_move_resize_internal (window, TRUE, x, y, width, height);
-}
-
-/**
- * gdk_surface_move_to_rect:
- * @window: the #GdkSurface to move
- * @rect: (not nullable): the destination #GdkRectangle to align @window with
- * @rect_anchor: the point on @rect to align with @window's anchor point
- * @window_anchor: the point on @window to align with @rect's anchor point
- * @anchor_hints: positioning hints to use when limited on space
- * @rect_anchor_dx: horizontal offset to shift @window, i.e. @rect's anchor
- *                  point
- * @rect_anchor_dy: vertical offset to shift @window, i.e. @rect's anchor point
- *
- * Moves @window to @rect, aligning their anchor points.
- *
- * @rect is relative to the top-left corner of the window that @window is
- * transient for. @rect_anchor and @window_anchor determine anchor points on
- * @rect and @window to pin together. @rect's anchor point can optionally be
- * offset by @rect_anchor_dx and @rect_anchor_dy, which is equivalent to
- * offsetting the position of @window.
- *
- * @anchor_hints determines how @window will be moved if the anchor points cause
- * it to move off-screen. For example, %GDK_ANCHOR_FLIP_X will replace
- * %GDK_GRAVITY_NORTH_WEST with %GDK_GRAVITY_NORTH_EAST and vice versa if
- * @window extends beyond the left or right edges of the monitor.
- *
- * Connect to the #GdkSurface::moved-to-rect signal to find out how it was
- * actually positioned.
- *
- * Stability: Private
- */
-void
-gdk_surface_move_to_rect (GdkSurface          *window,
-                         const GdkRectangle *rect,
-                         GdkGravity          rect_anchor,
-                         GdkGravity          window_anchor,
-                         GdkAnchorHints      anchor_hints,
-                         gint                rect_anchor_dx,
-                         gint                rect_anchor_dy)
-{
-  GdkSurfaceImplClass *impl_class;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (window->transient_for);
-  g_return_if_fail (rect);
-
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-  impl_class->move_to_rect (window,
-                            rect,
-                            rect_anchor,
-                            window_anchor,
-                            anchor_hints,
-                            rect_anchor_dx,
-                            rect_anchor_dy);
-}
-
-/**
- * gdk_surface_scroll:
- * @window: a #GdkSurface
- * @dx: Amount to scroll in the X direction
- * @dy: Amount to scroll in the Y direction
- *
- * Scroll the contents of @window, both pixels and children, by the
- * given amount. @window itself does not move. Portions of the window
- * that the scroll operation brings in from offscreen areas are
- * invalidated. The invalidated region may be bigger than what would
- * strictly be necessary.
- *
- * For X11, a minimum area will be invalidated if the window has no
- * subwindows, or if the edges of the window’s parent do not extend
- * beyond the edges of the window. In other cases, a multi-step process
- * is used to scroll the window which may produce temporary visual
- * artifacts and unnecessary invalidations.
- **/
-void
-gdk_surface_scroll (GdkSurface *window,
-                  gint       dx,
-                  gint       dy)
-{
-  GList *tmp_list;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (dx == 0 && dy == 0)
-    return;
-
-  if (window->destroyed)
-    return;
-
-  /* First move all child windows, without causing invalidation */
-
-  tmp_list = window->children;
-  while (tmp_list)
-    {
-      GdkSurface *child = GDK_SURFACE (tmp_list->data);
-
-      /* Just update the positions, the bits will move with the copy */
-      child->x += dx;
-      child->y += dy;
-
-      tmp_list = tmp_list->next;
-    }
-
-  recompute_visible_regions (window, TRUE);
-
-  gdk_surface_invalidate_rect_full (window, NULL, TRUE);
-}
-
-/**
- * gdk_surface_move_region:
- * @window: a #GdkSurface
- * @region: The #cairo_region_t to move
- * @dx: Amount to move in the X direction
- * @dy: Amount to move in the Y direction
- *
- * Move the part of @window indicated by @region by @dy pixels in the Y
- * direction and @dx pixels in the X direction. The portions of @region
- * that not covered by the new position of @region are invalidated.
- *
- * Child windows are not moved.
- */
-void
-gdk_surface_move_region (GdkSurface            *window,
-                        const cairo_region_t *region,
-                        gint                  dx,
-                        gint                  dy)
-{
-  cairo_region_t *expose_area;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (region != NULL);
-
-  if (dx == 0 && dy == 0)
-    return;
-
-  if (window->destroyed)
-    return;
-
-  expose_area = cairo_region_copy (region);
-  cairo_region_translate (expose_area, dx, dy);
-  cairo_region_union (expose_area, region);
-
-  gdk_surface_invalidate_region_full (window, expose_area, FALSE);
-  cairo_region_destroy (expose_area);
-}
-
-static void
-gdk_surface_set_cursor_internal (GdkSurface *window,
-                                GdkDevice *device,
-                                GdkCursor *cursor)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  g_assert (gdk_surface_get_display (window) == gdk_device_get_display (device));
-
-  if (window->window_type == GDK_SURFACE_ROOT ||
-      window->window_type == GDK_SURFACE_FOREIGN)
-    GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
-  else
-    {
-      GdkPointerSurfaceInfo *pointer_info;
-      GdkDisplay *display;
-
-      display = gdk_surface_get_display (window);
-      pointer_info = _gdk_display_get_pointer_info (display, device);
-
-      if (_gdk_surface_event_parent_of (window, pointer_info->window_under_pointer))
-        update_cursor (display, device);
-    }
-}
-
-/**
- * gdk_surface_get_cursor:
- * @window: a #GdkSurface
- *
- * Retrieves a #GdkCursor pointer for the cursor currently set on the
- * specified #GdkSurface, or %NULL.  If the return value is %NULL then
- * there is no custom cursor set on the specified window, and it is
- * using the cursor for its parent window.
- *
- * Returns: (nullable) (transfer none): a #GdkCursor, or %NULL. The
- *   returned object is owned by the #GdkSurface and should not be
- *   unreferenced directly. Use gdk_surface_set_cursor() to unset the
- *   cursor of the window
- */
-GdkCursor *
-gdk_surface_get_cursor (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  return window->cursor;
-}
-
-/**
- * gdk_surface_set_cursor:
- * @window: a #GdkSurface
- * @cursor: (allow-none): a cursor
- *
- * Sets the default mouse pointer for a #GdkSurface.
- *
- * Note that @cursor must be for the same display as @window.
- *
- * Use gdk_cursor_new_for_display() or gdk_cursor_new_from_texture() to
- * create the cursor. To make the cursor invisible, use %GDK_BLANK_CURSOR.
- * Passing %NULL for the @cursor argument to gdk_surface_set_cursor() means
- * that @window will use the cursor of its parent window. Most windows
- * should use this default.
- */
-void
-gdk_surface_set_cursor (GdkSurface *window,
-                      GdkCursor *cursor)
-{
-  GdkDisplay *display;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  display = gdk_surface_get_display (window);
-
-  if (window->cursor)
-    {
-      g_object_unref (window->cursor);
-      window->cursor = NULL;
-    }
-
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      GdkDevice *device;
-      GList *seats, *s;
-
-      if (cursor)
-       window->cursor = g_object_ref (cursor);
-
-      seats = gdk_display_list_seats (display);
-
-      for (s = seats; s; s = s->next)
-        {
-          GList *devices, *d;
-
-          device = gdk_seat_get_pointer (s->data);
-          gdk_surface_set_cursor_internal (window, device, window->cursor);
-
-          devices = gdk_seat_get_slaves (s->data, GDK_SEAT_CAPABILITY_TABLET_STYLUS);
-          for (d = devices; d; d = d->next)
-            {
-              device = gdk_device_get_associated_device (d->data);
-              gdk_surface_set_cursor_internal (window, device, window->cursor);
-            }
-          g_list_free (devices);
-        }
-
-      g_list_free (seats);
-      g_object_notify_by_pspec (G_OBJECT (window), properties[PROP_CURSOR]);
-    }
-}
-
-/**
- * gdk_surface_get_device_cursor:
- * @window: a #GdkSurface.
- * @device: a master, pointer #GdkDevice.
- *
- * Retrieves a #GdkCursor pointer for the @device currently set on the
- * specified #GdkSurface, or %NULL.  If the return value is %NULL then
- * there is no custom cursor set on the specified window, and it is
- * using the cursor for its parent window.
- *
- * Returns: (nullable) (transfer none): a #GdkCursor, or %NULL. The
- *   returned object is owned by the #GdkSurface and should not be
- *   unreferenced directly. Use gdk_surface_set_cursor() to unset the
- *   cursor of the window
- **/
-GdkCursor *
-gdk_surface_get_device_cursor (GdkSurface *window,
-                              GdkDevice *device)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
-  g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
-  g_return_val_if_fail (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER, NULL);
-
-  return g_hash_table_lookup (window->device_cursor, device);
-}
-
-/**
- * gdk_surface_set_device_cursor:
- * @window: a #GdkSurface
- * @device: a master, pointer #GdkDevice
- * @cursor: a #GdkCursor
- *
- * Sets a specific #GdkCursor for a given device when it gets inside @window.
- * Use gdk_cursor_new_for_display() or gdk_cursor_new_from_texture() to create
- * the cursor. To make the cursor invisible, use %GDK_BLANK_CURSOR. Passing
- * %NULL for the @cursor argument to gdk_surface_set_cursor() means that
- * @window will use the cursor of its parent window. Most windows should
- * use this default.
- **/
-void
-gdk_surface_set_device_cursor (GdkSurface *window,
-                              GdkDevice *device,
-                              GdkCursor *cursor)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (GDK_IS_DEVICE (device));
-  g_return_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD);
-  g_return_if_fail (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER);
-
-  if (!cursor)
-    g_hash_table_remove (window->device_cursor, device);
-  else
-    g_hash_table_replace (window->device_cursor, device, g_object_ref (cursor));
-
-  gdk_surface_set_cursor_internal (window, device, cursor);
-}
-
-/**
- * gdk_surface_get_geometry:
- * @window: a #GdkSurface
- * @x: (out) (allow-none): return location for X coordinate of window (relative to its parent)
- * @y: (out) (allow-none): return location for Y coordinate of window (relative to its parent)
- * @width: (out) (allow-none): return location for width of window
- * @height: (out) (allow-none): return location for height of window
- *
- * Any of the return location arguments to this function may be %NULL,
- * if you aren’t interested in getting the value of that field.
- *
- * The X and Y coordinates returned are relative to the parent window
- * of @window, which for toplevels usually means relative to the
- * window decorations (titlebar, etc.) rather than relative to the
- * root window (screen-size background window).
- *
- * On the X11 platform, the geometry is obtained from the X server,
- * so reflects the latest position of @window; this may be out-of-sync
- * with the position of @window delivered in the most-recently-processed
- * #GdkEventConfigure. gdk_surface_get_position() in contrast gets the
- * position from the most recent configure event.
- *
- * Note: If @window is not a toplevel, it is much better
- * to call gdk_surface_get_position(), gdk_surface_get_width() and
- * gdk_surface_get_height() instead, because it avoids the roundtrip to
- * the X server and because these functions support the full 32-bit
- * coordinate space, whereas gdk_surface_get_geometry() is restricted to
- * the 16-bit coordinates of X11.
- */
-void
-gdk_surface_get_geometry (GdkSurface *window,
-                        gint      *x,
-                        gint      *y,
-                        gint      *width,
-                        gint      *height)
-{
-  GdkSurface *parent;
-  GdkSurfaceImplClass *impl_class;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      if (gdk_surface_has_impl (window))
-       {
-         impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-         impl_class->get_geometry (window, x, y,
-                                   width, height);
-         /* This reports the position wrt to the native parent, we need to convert
-            it to be relative to the client side parent */
-         parent = window->parent;
-         if (parent && !gdk_surface_has_impl (parent))
-           {
-             if (x)
-               *x -= parent->abs_x;
-             if (y)
-               *y -= parent->abs_y;
-           }
-       }
-      else
-       {
-          if (x)
-            *x = window->x;
-          if (y)
-            *y = window->y;
-         if (width)
-           *width = window->width;
-         if (height)
-           *height = window->height;
-       }
-    }
-}
-
-/**
- * gdk_surface_get_width:
- * @window: a #GdkSurface
- *
- * Returns the width of the given @window.
- *
- * On the X11 platform the returned size is the size reported in the
- * most-recently-processed configure event, rather than the current
- * size on the X server.
- *
- * Returns: The width of @window
- */
-int
-gdk_surface_get_width (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
-
-  return window->width;
-}
-
-/**
- * gdk_surface_get_height:
- * @window: a #GdkSurface
- *
- * Returns the height of the given @window.
- *
- * On the X11 platform the returned size is the size reported in the
- * most-recently-processed configure event, rather than the current
- * size on the X server.
- *
- * Returns: The height of @window
- */
-int
-gdk_surface_get_height (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
-
-  return window->height;
-}
-
-/**
- * gdk_surface_get_origin:
- * @window: a #GdkSurface
- * @x: (out) (allow-none): return location for X coordinate
- * @y: (out) (allow-none): return location for Y coordinate
- *
- * Obtains the position of a window in root window coordinates.
- * (Compare with gdk_surface_get_position() and
- * gdk_surface_get_geometry() which return the position of a window
- * relative to its parent window.)
- *
- * Returns: not meaningful, ignore
- */
-gint
-gdk_surface_get_origin (GdkSurface *window,
-                      gint      *x,
-                      gint      *y)
-{
-  gint dummy_x, dummy_y;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
-
-  gdk_surface_get_root_coords (window,
-                              0, 0,
-                              x ? x : &dummy_x,
-                              y ? y : &dummy_y);
-
-  return TRUE;
-}
-
-/**
- * gdk_surface_get_root_coords:
- * @window: a #GdkSurface
- * @x: X coordinate in window
- * @y: Y coordinate in window
- * @root_x: (out): return location for X coordinate
- * @root_y: (out): return location for Y coordinate
- *
- * Obtains the position of a window position in root
- * window coordinates. This is similar to
- * gdk_surface_get_origin() but allows you to pass
- * in any position in the window, not just the origin.
- */
-void
-gdk_surface_get_root_coords (GdkSurface *window,
-                           gint       x,
-                           gint       y,
-                           gint      *root_x,
-                           gint      *root_y)
-{
-  GdkSurfaceImplClass *impl_class;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    {
-      *root_x = 0;
-      *root_y = 0;
-      return;
-    }
-  
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-  impl_class->get_root_coords (window->impl_window,
-                              x + window->abs_x,
-                              y + window->abs_y,
-                              root_x, root_y);
-}
-
-/**
- * gdk_surface_coords_to_parent:
- * @window: a child window
- * @x: X coordinate in child’s coordinate system
- * @y: Y coordinate in child’s coordinate system
- * @parent_x: (out) (allow-none): return location for X coordinate
- * in parent’s coordinate system, or %NULL
- * @parent_y: (out) (allow-none): return location for Y coordinate
- * in parent’s coordinate system, or %NULL
- *
- * Transforms window coordinates from a child window to its parent
- * window. Calling this function is equivalent to adding the return
- * values of gdk_surface_get_position() to the child coordinates.
- *
- * See also: gdk_surface_coords_from_parent()
- **/
-void
-gdk_surface_coords_to_parent (GdkSurface *window,
-                             gdouble    x,
-                             gdouble    y,
-                             gdouble   *parent_x,
-                             gdouble   *parent_y)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (parent_x)
-    *parent_x = x + window->x;
-
-  if (parent_y)
-    *parent_y = y + window->y;
-}
-
-/**
- * gdk_surface_coords_from_parent:
- * @window: a child window
- * @parent_x: X coordinate in parent’s coordinate system
- * @parent_y: Y coordinate in parent’s coordinate system
- * @x: (out) (allow-none): return location for X coordinate in child’s coordinate system
- * @y: (out) (allow-none): return location for Y coordinate in child’s coordinate system
- *
- * Transforms window coordinates from a parent window to a child
- * window.
- *
- * Calling this function is equivalent to subtracting the return
- * values of gdk_surface_get_position() from the parent coordinates.
- *
- * See also: gdk_surface_coords_to_parent()
- **/
-void
-gdk_surface_coords_from_parent (GdkSurface *window,
-                               gdouble    parent_x,
-                               gdouble    parent_y,
-                               gdouble   *x,
-                               gdouble   *y)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (x)
-    *x = parent_x - window->x;
-
-  if (y)
-    *y = parent_y - window->y;
-}
-
-/**
- * gdk_surface_shape_combine_region:
- * @window: a #GdkSurface
- * @shape_region: (allow-none): region of window to be non-transparent
- * @offset_x: X position of @shape_region in @window coordinates
- * @offset_y: Y position of @shape_region in @window coordinates
- *
- * Makes pixels in @window outside @shape_region be transparent,
- * so that the window may be nonrectangular.
- *
- * If @shape_region is %NULL, the shape will be unset, so the whole
- * window will be opaque again. @offset_x and @offset_y are ignored
- * if @shape_region is %NULL.
- *
- * On the X11 platform, this uses an X server extension which is
- * widely available on most common platforms, but not available on
- * very old X servers, and occasionally the implementation will be
- * buggy. On servers without the shape extension, this function
- * will do nothing.
- *
- * This function works on both toplevel and child windows.
- */
-void
-gdk_surface_shape_combine_region (GdkSurface       *window,
-                                const cairo_region_t *shape_region,
-                                gint             offset_x,
-                                gint             offset_y)
-{
-  cairo_region_t *old_region, *new_region, *diff;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (!window->shape && shape_region == NULL)
-    return;
-
-  window->shaped = (shape_region != NULL);
-
-  if (window->shape)
-    cairo_region_destroy (window->shape);
-
-  old_region = NULL;
-  if (GDK_SURFACE_IS_MAPPED (window))
-    old_region = cairo_region_copy (window->clip_region);
-
-  if (shape_region)
-    {
-      window->shape = cairo_region_copy (shape_region);
-      cairo_region_translate (window->shape, offset_x, offset_y);
-    }
-  else
-    window->shape = NULL;
-
-  recompute_visible_regions (window, FALSE);
-
-  if (old_region)
-    {
-      new_region = cairo_region_copy (window->clip_region);
-
-      /* New area in the window, needs invalidation */
-      diff = cairo_region_copy (new_region);
-      cairo_region_subtract (diff, old_region);
-
-      gdk_surface_invalidate_region_full (window, diff, TRUE);
-
-      cairo_region_destroy (diff);
-
-      if (!gdk_surface_is_toplevel (window))
-       {
-         /* New area in the non-root parent window, needs invalidation */
-         diff = cairo_region_copy (old_region);
-         cairo_region_subtract (diff, new_region);
-
-         /* Adjust region to parent window coords */
-         cairo_region_translate (diff, window->x, window->y);
-
-         gdk_surface_invalidate_region_full (window->parent, diff, TRUE);
-
-         cairo_region_destroy (diff);
-       }
-
-      cairo_region_destroy (new_region);
-      cairo_region_destroy (old_region);
-    }
-}
-
-static void
-do_child_shapes (GdkSurface *window,
-                gboolean merge)
-{
-  GdkRectangle r;
-  cairo_region_t *region;
-
-  r.x = 0;
-  r.y = 0;
-  r.width = window->width;
-  r.height = window->height;
-
-  region = cairo_region_create_rectangle (&r);
-  remove_child_area (window, FALSE, region);
-
-  if (merge && window->shape)
-    cairo_region_subtract (region, window->shape);
-
-  cairo_region_xor_rectangle (region, &r);
-
-  gdk_surface_shape_combine_region (window, region, 0, 0);
-
-  cairo_region_destroy (region);
-}
-
-/**
- * gdk_surface_set_child_shapes:
- * @window: a #GdkSurface
- *
- * Sets the shape mask of @window to the union of shape masks
- * for all children of @window, ignoring the shape mask of @window
- * itself. Contrast with gdk_surface_merge_child_shapes() which includes
- * the shape mask of @window in the masks to be merged.
- **/
-void
-gdk_surface_set_child_shapes (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  do_child_shapes (window, FALSE);
-}
-
-/**
- * gdk_surface_merge_child_shapes:
- * @window: a #GdkSurface
- *
- * Merges the shape masks for any child windows into the
- * shape mask for @window. i.e. the union of all masks
- * for @window and its children will become the new mask
- * for @window. See gdk_surface_shape_combine_region().
- *
- * This function is distinct from gdk_surface_set_child_shapes()
- * because it includes @window’s shape mask in the set of shapes to
- * be merged.
- */
-void
-gdk_surface_merge_child_shapes (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  do_child_shapes (window, TRUE);
-}
-
-/**
- * gdk_surface_input_shape_combine_region:
- * @window: a #GdkSurface
- * @shape_region: region of window to be non-transparent
- * @offset_x: X position of @shape_region in @window coordinates
- * @offset_y: Y position of @shape_region in @window coordinates
- *
- * Like gdk_surface_shape_combine_region(), but the shape applies
- * only to event handling. Mouse events which happen while
- * the pointer position corresponds to an unset bit in the
- * mask will be passed on the window below @window.
- *
- * An input shape is typically used with RGBA windows.
- * The alpha channel of the window defines which pixels are
- * invisible and allows for nicely antialiased borders,
- * and the input shape controls where the window is
- * â€śclickable”.
- *
- * On the X11 platform, this requires version 1.1 of the
- * shape extension.
- *
- * On the Win32 platform, this functionality is not present and the
- * function does nothing.
- */
-void
-gdk_surface_input_shape_combine_region (GdkSurface       *window,
-                                      const cairo_region_t *shape_region,
-                                      gint             offset_x,
-                                      gint             offset_y)
-{
-  GdkSurfaceImplClass *impl_class;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (window->input_shape)
-    cairo_region_destroy (window->input_shape);
-
-  if (shape_region)
-    {
-      window->input_shape = cairo_region_copy (shape_region);
-      cairo_region_translate (window->input_shape, offset_x, offset_y);
-    }
-  else
-    window->input_shape = NULL;
-
-  if (gdk_surface_has_impl (window))
-    {
-      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-      impl_class->input_shape_combine_region (window, window->input_shape, 0, 0);
-    }
-}
-
-static void
-do_child_input_shapes (GdkSurface *window,
-                      gboolean merge)
-{
-  GdkRectangle r;
-  cairo_region_t *region;
-
-  r.x = 0;
-  r.y = 0;
-  r.width = window->width;
-  r.height = window->height;
-
-  region = cairo_region_create_rectangle (&r);
-  remove_child_area (window, TRUE, region);
-
-  if (merge && window->shape)
-    cairo_region_subtract (region, window->shape);
-  if (merge && window->input_shape)
-    cairo_region_subtract (region, window->input_shape);
-
-  cairo_region_xor_rectangle (region, &r);
-
-  gdk_surface_input_shape_combine_region (window, region, 0, 0);
-}
-
-
-/**
- * gdk_surface_set_child_input_shapes:
- * @window: a #GdkSurface
- *
- * Sets the input shape mask of @window to the union of input shape masks
- * for all children of @window, ignoring the input shape mask of @window
- * itself. Contrast with gdk_surface_merge_child_input_shapes() which includes
- * the input shape mask of @window in the masks to be merged.
- **/
-void
-gdk_surface_set_child_input_shapes (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  do_child_input_shapes (window, FALSE);
-}
-
-/**
- * gdk_surface_set_pass_through:
- * @window: a #GdkSurface
- * @pass_through: a boolean
- *
- * Sets whether input to the window is passed through to the window
- * below.
- *
- * The default value of this is %FALSE, which means that pointer
- * events that happen inside the window are send first to the window,
- * but if the event is not selected by the event mask then the event
- * is sent to the parent window, and so on up the hierarchy.
- *
- * If @pass_through is %TRUE then such pointer events happen as if the
- * window wasn't there at all, and thus will be sent first to any
- * windows below @window. This is useful if the window is used in a
- * transparent fashion. In the terminology of the web this would be called
- * "pointer-events: none".
- *
- * Note that a window with @pass_through %TRUE can still have a subwindow
- * without pass through, so you can get events on a subset of a window. And in
- * that cases you would get the in-between related events such as the pointer
- * enter/leave events on its way to the destination window.
- **/
-void
-gdk_surface_set_pass_through (GdkSurface *window,
-                             gboolean   pass_through)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  window->pass_through = !!pass_through;
-}
-
-/**
- * gdk_surface_get_pass_through:
- * @window: a #GdkSurface
- *
- * Returns whether input to the window is passed through to the window
- * below.
- *
- * See gdk_surface_set_pass_through() for details
- **/
-gboolean
-gdk_surface_get_pass_through (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  return window->pass_through;
-}
-
-/**
- * gdk_surface_merge_child_input_shapes:
- * @window: a #GdkSurface
- *
- * Merges the input shape masks for any child windows into the
- * input shape mask for @window. i.e. the union of all input masks
- * for @window and its children will become the new input mask
- * for @window. See gdk_surface_input_shape_combine_region().
- *
- * This function is distinct from gdk_surface_set_child_input_shapes()
- * because it includes @window’s input shape mask in the set of
- * shapes to be merged.
- **/
-void
-gdk_surface_merge_child_input_shapes (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  do_child_input_shapes (window, TRUE);
-}
-
-
-/**
- * gdk_surface_get_modal_hint:
- * @window: A toplevel #GdkSurface.
- *
- * Determines whether or not the window manager is hinted that @window
- * has modal behaviour.
- *
- * Returns: whether or not the window has the modal hint set.
- */
-gboolean
-gdk_surface_get_modal_hint (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  return window->modal_hint;
-}
-
-/**
- * gdk_surface_get_accept_focus:
- * @window: a toplevel #GdkSurface.
- *
- * Determines whether or not the desktop environment shuld be hinted that
- * the window does not want to receive input focus.
- *
- * Returns: whether or not the window should receive input focus.
- */
-gboolean
-gdk_surface_get_accept_focus (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  return window->accept_focus;
-}
-
-/**
- * gdk_surface_get_focus_on_map:
- * @window: a toplevel #GdkSurface.
- *
- * Determines whether or not the desktop environment should be hinted that the
- * window does not want to receive input focus when it is mapped.
- *
- * Returns: whether or not the window wants to receive input focus when
- * it is mapped.
- */
-gboolean
-gdk_surface_get_focus_on_map (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  return window->focus_on_map;
-}
-
-/**
- * gdk_surface_is_input_only:
- * @window: a toplevel #GdkSurface
- *
- * Determines whether or not the window is an input only window.
- *
- * Returns: %TRUE if @window is input only
- */
-gboolean
-gdk_surface_is_input_only (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  return window->input_only;
-}
-
-/**
- * gdk_surface_is_shaped:
- * @window: a toplevel #GdkSurface
- *
- * Determines whether or not the window is shaped.
- *
- * Returns: %TRUE if @window is shaped
- */
-gboolean
-gdk_surface_is_shaped (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  return window->shaped;
-}
-
-/* Gets the toplevel for a window as used for events,
-   i.e. including offscreen parents going up to the native
-   toplevel */
-static GdkSurface *
-get_event_toplevel (GdkSurface *window)
-{
-  GdkSurface *parent;
-
-  while ((parent = window->parent) != NULL &&
-        (parent->window_type != GDK_SURFACE_ROOT))
-    window = parent;
-
-  return window;
-}
-
-gboolean
-_gdk_surface_event_parent_of (GdkSurface *parent,
-                            GdkSurface *child)
-{
-  GdkSurface *w;
-
-  w = child;
-  while (w != NULL)
-    {
-      if (w == parent)
-       return TRUE;
-
-      w = w->parent;
-    }
-
-  return FALSE;
-}
-
-static void
-update_cursor (GdkDisplay *display,
-               GdkDevice  *device)
-{
-  GdkSurface *cursor_window, *parent, *toplevel;
-  GdkSurface *pointer_window;
-  GdkPointerSurfaceInfo *pointer_info;
-  GdkDeviceGrabInfo *grab;
-  GdkCursor *cursor;
-
-  pointer_info = _gdk_display_get_pointer_info (display, device);
-  pointer_window = pointer_info->window_under_pointer;
-
-  /* We ignore the serials here and just pick the last grab
-     we've sent, as that would shortly be used anyway. */
-  grab = _gdk_display_get_last_device_grab (display, device);
-  if (/* have grab */
-      grab != NULL &&
-      /* the pointer is not in a descendant of the grab window */
-      !_gdk_surface_event_parent_of (grab->window, pointer_window))
-    {
-      /* use the cursor from the grab window */
-      cursor_window = grab->window;
-    }
-  else
-    {
-      /* otherwise use the cursor from the pointer window */
-      cursor_window = pointer_window;
-    }
-
-  /* Find the first window with the cursor actually set, as
-     the cursor is inherited from the parent */
-  while (cursor_window->cursor == NULL &&
-         !g_hash_table_contains (cursor_window->device_cursor, device) &&
-        (parent = cursor_window->parent) != NULL &&
-        parent->window_type != GDK_SURFACE_ROOT)
-    cursor_window = parent;
-
-  cursor = g_hash_table_lookup (cursor_window->device_cursor, device);
-
-  if (!cursor)
-    cursor = cursor_window->cursor;
-
-  /* Set all cursors on toplevel, otherwise its tricky to keep track of
-   * which native window has what cursor set. */
-  toplevel = get_event_toplevel (pointer_window);
-  GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, toplevel, cursor);
-}
-
-static gboolean
-point_in_window (GdkSurface *window,
-                gdouble    x,
-                 gdouble    y)
-{
-  return
-    x >= 0 && x < window->width &&
-    y >= 0 && y < window->height &&
-    (window->shape == NULL ||
-     cairo_region_contains_point (window->shape,
-                         x, y)) &&
-    (window->input_shape == NULL ||
-     cairo_region_contains_point (window->input_shape,
-                         x, y));
-}
-
-/* Same as point_in_window, except it also takes pass_through and its
-   interaction with child windows into account */
-static gboolean
-point_in_input_window (GdkSurface *window,
-                      gdouble    x,
-                      gdouble    y,
-                      GdkSurface **input_window,
-                      gdouble   *input_window_x,
-                      gdouble   *input_window_y)
-{
-  GdkSurface *sub;
-  double child_x, child_y;
-  GList *l;
-
-  if (!point_in_window (window, x, y))
-    return FALSE;
-
-  if (!window->pass_through)
-    {
-      if (input_window)
-       {
-         *input_window = window;
-         *input_window_x = x;
-         *input_window_y = y;
-       }
-      return TRUE;
-    }
-
-  /* For pass-through, must be over a child input window */
-
-  /* Children is ordered in reverse stack order, i.e. first is topmost */
-  for (l = window->children; l != NULL; l = l->next)
-    {
-      sub = l->data;
-
-      if (!GDK_SURFACE_IS_MAPPED (sub))
-       continue;
-
-      gdk_surface_coords_from_parent ((GdkSurface *)sub,
-                                    x, y,
-                                    &child_x, &child_y);
-      if (point_in_input_window (sub, child_x, child_y,
-                                input_window, input_window_x, input_window_y))
-       {
-         if (input_window)
-           gdk_surface_coords_to_parent (sub,
-                                        *input_window_x,
-                                        *input_window_y,
-                                        input_window_x,
-                                        input_window_y);
-         return TRUE;
-       }
-    }
-
-  return FALSE;
-}
-
-GdkSurface *
-_gdk_surface_find_child_at (GdkSurface *window,
-                          double     x,
-                           double     y)
-{
-  GdkSurface *sub;
-  double child_x, child_y;
-  GList *l;
-
-  if (point_in_window (window, x, y))
-    {
-      /* Children is ordered in reverse stack order, i.e. first is topmost */
-      for (l = window->children; l != NULL; l = l->next)
-       {
-         sub = l->data;
-
-         if (!GDK_SURFACE_IS_MAPPED (sub))
-           continue;
-
-         gdk_surface_coords_from_parent ((GdkSurface *)sub,
-                                         x, y,
-                                         &child_x, &child_y);
-         if (point_in_input_window (sub, child_x, child_y,
-                                    NULL, NULL, NULL))
-           return (GdkSurface *)sub;
-       }
-    }
-
-  return NULL;
-}
-
-GdkSurface *
-_gdk_surface_find_descendant_at (GdkSurface *window,
-                               gdouble    x,
-                                gdouble    y,
-                               gdouble   *found_x,
-                               gdouble   *found_y)
-{
-  GdkSurface *sub, *input_window;
-  gdouble child_x, child_y;
-  GList *l;
-  gboolean found;
-
-  if (point_in_window (window, x, y))
-    {
-      do
-       {
-         found = FALSE;
-         /* Children is ordered in reverse stack order, i.e. first is topmost */
-         for (l = window->children; l != NULL; l = l->next)
-           {
-             sub = l->data;
-
-             if (!GDK_SURFACE_IS_MAPPED (sub))
-               continue;
-
-             gdk_surface_coords_from_parent ((GdkSurface *)sub,
-                                             x, y,
-                                             &child_x, &child_y);
-             if (point_in_input_window (sub, child_x, child_y,
-                                        &input_window, &child_x, &child_y))
-               {
-                 x = child_x;
-                 y = child_y;
-                 window = input_window;
-                 found = TRUE;
-                 break;
-               }
-           }
-       }
-      while (found);
-    }
-  else
-    {
-      /* Not in window at all */
-      window = NULL;
-    }
-
-  if (found_x)
-    *found_x = x;
-  if (found_y)
-    *found_y = y;
-
-  return window;
-}
-
-/**
- * gdk_surface_beep:
- * @window: a toplevel #GdkSurface
- *
- * Emits a short beep associated to @window in the appropriate
- * display, if supported. Otherwise, emits a short beep on
- * the display just as gdk_display_beep().
- **/
-void
-gdk_surface_beep (GdkSurface *window)
-{
-  GdkDisplay *display;
-  GdkSurface *toplevel;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  toplevel = get_event_toplevel (window);
-  display = gdk_surface_get_display (window);
-
-  if (toplevel)
-    {
-      if (GDK_SURFACE_IMPL_GET_CLASS (toplevel->impl)->beep (toplevel))
-        return;
-    }
-  
-  /* If windows fail to beep, we beep the display. */
-  gdk_display_beep (display);
-}
-
-/**
- * gdk_surface_set_support_multidevice:
- * @window: a #GdkSurface.
- * @support_multidevice: %TRUE to enable multidevice support in @window.
- *
- * This function will enable multidevice features in @window.
- *
- * Multidevice aware windows will need to handle properly multiple,
- * per device enter/leave events, device grabs and grab ownerships.
- **/
-void
-gdk_surface_set_support_multidevice (GdkSurface *window,
-                                    gboolean   support_multidevice)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (window->support_multidevice == support_multidevice)
-    return;
-
-  window->support_multidevice = support_multidevice;
-
-  /* FIXME: What to do if called when some pointers are inside the window ? */
-}
-
-/**
- * gdk_surface_get_support_multidevice:
- * @window: a #GdkSurface.
- *
- * Returns %TRUE if the window is aware of the existence of multiple
- * devices.
- *
- * Returns: %TRUE if the window handles multidevice features.
- **/
-gboolean
-gdk_surface_get_support_multidevice (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return FALSE;
-
-  return window->support_multidevice;
-}
-
-/* send motion events if the right buttons are down */
-
-GdkEvent *
-_gdk_make_event (GdkSurface    *window,
-                GdkEventType  type,
-                GdkEvent     *event_in_queue,
-                gboolean      before_event)
-{
-  GdkEvent *event = gdk_event_new (type);
-  guint32 the_time;
-  GdkModifierType the_state;
-
-  the_time = gdk_event_get_time (event_in_queue);
-  gdk_event_get_state (event_in_queue, &the_state);
-
-  event->any.window = g_object_ref (window);
-  event->any.send_event = FALSE;
-  if (event_in_queue && event_in_queue->any.send_event)
-    event->any.send_event = TRUE;
-
-  switch ((guint) type)
-    {
-    case GDK_MOTION_NOTIFY:
-      event->motion.time = the_time;
-      event->motion.axes = NULL;
-      event->motion.state = the_state;
-      break;
-
-    case GDK_BUTTON_PRESS:
-    case GDK_BUTTON_RELEASE:
-      event->button.time = the_time;
-      event->button.axes = NULL;
-      event->button.state = the_state;
-      break;
-
-    case GDK_TOUCH_BEGIN:
-    case GDK_TOUCH_UPDATE:
-    case GDK_TOUCH_END:
-    case GDK_TOUCH_CANCEL:
-      event->touch.time = the_time;
-      event->touch.axes = NULL;
-      event->touch.state = the_state;
-      break;
-
-    case GDK_SCROLL:
-      event->scroll.time = the_time;
-      event->scroll.state = the_state;
-      break;
-
-    case GDK_KEY_PRESS:
-    case GDK_KEY_RELEASE:
-      event->key.time = the_time;
-      event->key.state = the_state;
-      break;
-
-    case GDK_ENTER_NOTIFY:
-    case GDK_LEAVE_NOTIFY:
-      event->crossing.time = the_time;
-      event->crossing.state = the_state;
-      break;
-
-    case GDK_PROXIMITY_IN:
-    case GDK_PROXIMITY_OUT:
-      event->proximity.time = the_time;
-      break;
-
-    case GDK_DRAG_ENTER:
-    case GDK_DRAG_LEAVE:
-    case GDK_DRAG_MOTION:
-    case GDK_DROP_START:
-      event->dnd.time = the_time;
-      break;
-
-    case GDK_TOUCHPAD_SWIPE:
-      event->touchpad_swipe.time = the_time;
-      event->touchpad_swipe.state = the_state;
-      break;
-
-    case GDK_TOUCHPAD_PINCH:
-      event->touchpad_pinch.time = the_time;
-      event->touchpad_pinch.state = the_state;
-      break;
-
-    case GDK_FOCUS_CHANGE:
-    case GDK_CONFIGURE:
-    case GDK_MAP:
-    case GDK_UNMAP:
-    case GDK_DELETE:
-    case GDK_DESTROY:
-    case GDK_EXPOSE:
-    default:
-      break;
-    }
-
-  if (event_in_queue)
-    {
-    if (before_event)
-      _gdk_event_queue_insert_before (gdk_surface_get_display (window), event_in_queue, event);
-    else
-      _gdk_event_queue_insert_after (gdk_surface_get_display (window), event_in_queue, event);
-    }
-  else
-    _gdk_event_queue_append (gdk_surface_get_display (window), event);
-
-  return event;
-}
-
-void
-_gdk_display_set_window_under_pointer (GdkDisplay *display,
-                                       GdkDevice  *device,
-                                      GdkSurface  *window)
-{
-  GdkPointerSurfaceInfo *device_info;
-
-  device_info = _gdk_display_get_pointer_info (display, device);
-
-  if (device_info->window_under_pointer)
-    g_object_unref (device_info->window_under_pointer);
-  device_info->window_under_pointer = window;
-
-  if (window)
-    {
-      g_object_ref (window);
-      update_cursor (display, device);
-    }
-}
-
-#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
-                            GDK_BUTTON2_MASK | \
-                            GDK_BUTTON3_MASK | \
-                            GDK_BUTTON4_MASK | \
-                            GDK_BUTTON5_MASK)
-
-#ifdef DEBUG_WINDOW_PRINTING
-
-#ifdef GDK_WINDOWING_X11
-#include "x11/gdkx.h"
-#endif
-
-static void
-gdk_surface_print (GdkSurface *window,
-                 int indent)
-{
-  char *s;
-  const char *window_types[] = {
-    "root",
-    "toplevel",
-    "child",
-    "dialog",
-    "temp",
-    "foreign",
-    "subsurface"
-  };
-
-  g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
-          window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
-          window->x, window->y,
-          window->width, window->height
-          );
-
-  if (gdk_surface_has_impl (window))
-    {
-#ifdef GDK_WINDOWING_X11
-      g_print (" impl(0x%lx)", gdk_x11_surface_get_xid (window));
-#endif
-    }
-
-  if (window->window_type != GDK_SURFACE_CHILD)
-    g_print (" %s", window_types[window->window_type]);
-
-  if (window->input_only)
-    g_print (" input-only");
-
-  if (window->shaped)
-    g_print (" shaped");
-
-  if (!gdk_surface_is_visible ((GdkSurface *)window))
-    g_print (" hidden");
-
-  g_print (" abs[%d,%d]",
-          window->abs_x, window->abs_y);
-
-  if (window->alpha != 255)
-    g_print (" alpha[%d]",
-          window->alpha);
-
-  s = print_region (window->clip_region);
-  g_print (" clipbox[%s]", s);
-
-  g_print ("\n");
-}
-
-
-static void
-gdk_surface_print_tree (GdkSurface *window,
-                      int indent,
-                      gboolean include_input_only)
-{
-  GList *l;
-
-  if (window->input_only && !include_input_only)
-    return;
-
-  gdk_surface_print (window, indent);
-
-  for (l = window->children; l != NULL; l = l->next)
-    gdk_surface_print_tree (l->data, indent + 4, include_input_only);
-}
-
-#endif /* DEBUG_WINDOW_PRINTING */
-
-void
-_gdk_windowing_got_event (GdkDisplay *display,
-                          GList      *event_link,
-                          GdkEvent   *event,
-                          gulong      serial)
-{
-  GdkSurface *event_window;
-  gboolean unlink_event = FALSE;
-  GdkDeviceGrabInfo *button_release_grab;
-  GdkPointerSurfaceInfo *pointer_info = NULL;
-  GdkDevice *device, *source_device;
-
-  _gdk_display_update_last_event (display, event);
-
-  device = gdk_event_get_device (event);
-  source_device = gdk_event_get_source_device (event);
-
-  if (device)
-    {
-      if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD &&
-          gdk_device_get_source (device) != GDK_SOURCE_TABLET_PAD)
-        {
-          pointer_info = _gdk_display_get_pointer_info (display, device);
-
-          if (source_device != pointer_info->last_slave &&
-              gdk_device_get_device_type (source_device) == GDK_DEVICE_TYPE_SLAVE)
-            pointer_info->last_slave = source_device;
-          else if (pointer_info->last_slave)
-            source_device = pointer_info->last_slave;
-        }
-
-      _gdk_display_device_grab_update (display, device, source_device, serial);
-
-      if (gdk_device_get_input_mode (device) == GDK_MODE_DISABLED ||
-          !_gdk_display_check_grab_ownership (display, device, serial))
-        {
-          /* Device events are blocked by another
-           * device grab, or the device is disabled
-           */
-          unlink_event = TRUE;
-          goto out;
-        }
-    }
-
-  event_window = event->any.window;
-  if (!event_window)
-    goto out;
-
-#ifdef DEBUG_WINDOW_PRINTING
-  if (event->any.type == GDK_KEY_PRESS &&
-      (event->key.keyval == 0xa7 ||
-       event->key.keyval == 0xbd))
-    {
-      gdk_surface_print_tree (event_window, 0, event->key.keyval == 0xbd);
-    }
-#endif
-
-  if (event_window->window_type == GDK_SURFACE_ROOT)
-    goto out;
-
-  if (event->any.type == GDK_ENTER_NOTIFY)
-    _gdk_display_set_window_under_pointer (display, device, event_window);
-  else if (event->any.type == GDK_LEAVE_NOTIFY)
-    _gdk_display_set_window_under_pointer (display, device, NULL);
-
-  if ((event->any.type == GDK_BUTTON_RELEASE ||
-       event->any.type == GDK_TOUCH_CANCEL ||
-       event->any.type == GDK_TOUCH_END) &&
-      !event->any.send_event)
-    {
-      if (event->any.type == GDK_BUTTON_RELEASE ||
-          gdk_event_get_pointer_emulated (event))
-        {
-          button_release_grab =
-            _gdk_display_has_device_grab (display, device, serial);
-
-          if (button_release_grab &&
-              button_release_grab->implicit &&
-              (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
-            {
-              button_release_grab->serial_end = serial;
-              button_release_grab->implicit_ungrab = FALSE;
-              _gdk_display_device_grab_update (display, device, source_device, serial);
-            }
-        }
-    }
-
- out:
-  if (unlink_event)
-    {
-      _gdk_event_queue_remove_link (display, event_link);
-      g_list_free_1 (event_link);
-      gdk_event_free (event);
-    }
-
-  /* This does two things - first it sees if there are motions at the
-   * end of the queue that can be compressed. Second, if there is just
-   * a single motion that won't be dispatched because it is a compression
-   * candidate it queues up flushing the event queue.
-   */
-  _gdk_event_queue_handle_motion_compression (display);
-}
-
-/**
- * gdk_surface_create_similar_surface:
- * @window: window to make new surface similar to
- * @content: the content for the new surface
- * @width: width of the new surface
- * @height: height of the new surface
- *
- * Create a new surface that is as compatible as possible with the
- * given @window. For example the new surface will have the same
- * fallback resolution and font options as @window. Generally, the new
- * surface will also use the same backend as @window, unless that is
- * not possible for some reason. The type of the returned surface may
- * be examined with cairo_surface_get_type().
- *
- * Initially the surface contents are all 0 (transparent if contents
- * have transparency, black otherwise.)
- *
- * Returns: a pointer to the newly allocated surface. The caller
- * owns the surface and should call cairo_surface_destroy() when done
- * with it.
- *
- * This function always returns a valid pointer, but it will return a
- * pointer to a â€śnil” surface if @other is already in an error state
- * or any other error occurs.
- **/
-cairo_surface_t *
-gdk_surface_create_similar_surface (GdkSurface *     window,
-                                   cairo_content_t content,
-                                   int             width,
-                                   int             height)
-{
-  cairo_surface_t *window_surface, *surface;
-  double sx, sy;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  window_surface = gdk_surface_ref_impl_surface (window);
-  sx = sy = 1;
-  cairo_surface_get_device_scale (window_surface, &sx, &sy);
-
-  if (GDK_DISPLAY_DEBUG_CHECK (window->display, CAIRO_IMAGE))
-    {
-      surface = cairo_image_surface_create (content == CAIRO_CONTENT_COLOR ? CAIRO_FORMAT_RGB24 :
-                                            content == CAIRO_CONTENT_ALPHA ? CAIRO_FORMAT_A8 : CAIRO_FORMAT_ARGB32,
-                                            width * sx, height * sy);
-      cairo_surface_set_device_scale (surface, sx, sy);
-    }
-  else
-    {
-      surface = cairo_surface_create_similar (window_surface,
-                                              content,
-                                              width, height);
-    }
-
-  cairo_surface_destroy (window_surface);
-
-  return surface;
-}
-
-
-/**
- * gdk_surface_create_similar_image_surface:
- * @window: (nullable): window to make new surface similar to, or
- *   %NULL if none
- * @format: (type int): the format for the new surface
- * @width: width of the new surface
- * @height: height of the new surface
- * @scale: the scale of the new surface, or 0 to use same as @window
- *
- * Create a new image surface that is efficient to draw on the
- * given @window.
- *
- * Initially the surface contents are all 0 (transparent if contents
- * have transparency, black otherwise.)
- *
- * The @width and @height of the new surface are not affected by
- * the scaling factor of the @window, or by the @scale argument; they
- * are the size of the surface in device pixels. If you wish to create
- * an image surface capable of holding the contents of @window you can
- * use:
- *
- * |[<!-- language="C" -->
- *   int scale = gdk_surface_get_scale_factor (window);
- *   int width = gdk_surface_get_width (window) * scale;
- *   int height = gdk_surface_get_height (window) * scale;
- *
- *   // format is set elsewhere
- *   cairo_surface_t *surface =
- *     gdk_surface_create_similar_image_surface (window,
- *                                              format,
- *                                              width, height,
- *                                              scale);
- * ]|
- *
- * Note that unlike cairo_surface_create_similar_image(), the new
- * surface's device scale is set to @scale, or to the scale factor of
- * @window if @scale is 0.
- *
- * Returns: a pointer to the newly allocated surface. The caller
- * owns the surface and should call cairo_surface_destroy() when done
- * with it.
- *
- * This function always returns a valid pointer, but it will return a
- * pointer to a â€śnil” surface if @other is already in an error state
- * or any other error occurs.
- **/
-cairo_surface_t *
-gdk_surface_create_similar_image_surface (GdkSurface *     window,
-                                        cairo_format_t  format,
-                                        int             width,
-                                        int             height,
-                                        int             scale)
-{
-  cairo_surface_t *surface;
-
-  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), NULL);
-
-  if (window == NULL)
-    {
-      surface = cairo_image_surface_create (format, width, height);
-    }
-  else if (GDK_SURFACE_IMPL_GET_CLASS (window->impl)->create_similar_image_surface)
-    {
-      surface =
-        GDK_SURFACE_IMPL_GET_CLASS (window->impl)->create_similar_image_surface (window, format, width, height);
-    }
-  else
-    {
-      cairo_surface_t *window_surface;
-
-      window_surface = gdk_surface_ref_impl_surface (window);
-      surface =
-        cairo_surface_create_similar_image (window_surface,
-                                            format,
-                                            width,
-                                            height);
-      cairo_surface_destroy (window_surface);
-    }
-
-  if (scale == 0)
-    scale = gdk_surface_get_scale_factor (window);
-
-  cairo_surface_set_device_scale (surface, scale, scale);
-
-  return surface;
-}
-
-
-/**
- * gdk_surface_focus:
- * @window: a #GdkSurface
- * @timestamp: timestamp of the event triggering the window focus
- *
- * Sets keyboard focus to @window. In most cases, gtk_window_present()
- * should be used on a #GtkWindow, rather than calling this function.
- *
- **/
-void
-gdk_surface_focus (GdkSurface *window,
-                  guint32    timestamp)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->focus (window, timestamp);
-}
-
-/**
- * gdk_surface_set_type_hint:
- * @window: A toplevel #GdkSurface
- * @hint: A hint of the function this window will have
- *
- * The application can use this call to provide a hint to the window
- * manager about the functionality of a window. The window manager
- * can use this information when determining the decoration and behaviour
- * of the window.
- *
- * The hint must be set before the window is mapped.
- **/
-void
-gdk_surface_set_type_hint (GdkSurface        *window,
-                         GdkSurfaceTypeHint hint)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_type_hint (window, hint);
-}
-
-/**
- * gdk_surface_get_type_hint:
- * @window: A toplevel #GdkSurface
- *
- * This function returns the type hint set for a window.
- *
- * Returns: The type hint set for @window
- **/
-GdkSurfaceTypeHint
-gdk_surface_get_type_hint (GdkSurface *window)
-{
-  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->get_type_hint (window);
-}
-
-/**
- * gdk_surface_set_modal_hint:
- * @window: A toplevel #GdkSurface
- * @modal: %TRUE if the window is modal, %FALSE otherwise.
- *
- * The application can use this hint to tell the window manager
- * that a certain window has modal behaviour. The window manager
- * can use this information to handle modal windows in a special
- * way.
- *
- * You should only use this on windows for which you have
- * previously called gdk_surface_set_transient_for()
- **/
-void
-gdk_surface_set_modal_hint (GdkSurface *window,
-                          gboolean   modal)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_modal_hint (window, modal);
-}
-
-/**
- * gdk_surface_set_skip_taskbar_hint:
- * @window: a toplevel #GdkSurface
- * @skips_taskbar: %TRUE to skip the taskbar
- *
- * Toggles whether a window should appear in a task list or window
- * list. If a window’s semantic type as specified with
- * gdk_surface_set_type_hint() already fully describes the window, this
- * function should not be called in addition,
- * instead you should allow the window to be treated according to
- * standard policy for its semantic type.
- **/
-void
-gdk_surface_set_skip_taskbar_hint (GdkSurface *window,
-                                  gboolean   skips_taskbar)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_skip_taskbar_hint (window, skips_taskbar);
-}
-
-/**
- * gdk_surface_set_skip_pager_hint:
- * @window: a toplevel #GdkSurface
- * @skips_pager: %TRUE to skip the pager
- *
- * Toggles whether a window should appear in a pager (workspace
- * switcher, or other desktop utility program that displays a small
- * thumbnail representation of the windows on the desktop). If a
- * window’s semantic type as specified with gdk_surface_set_type_hint()
- * already fully describes the window, this function should
- * not be called in addition, instead you should
- * allow the window to be treated according to standard policy for
- * its semantic type.
- **/
-void
-gdk_surface_set_skip_pager_hint (GdkSurface *window,
-                                gboolean   skips_pager)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_skip_pager_hint (window, skips_pager);
-}
-
-/**
- * gdk_surface_set_urgency_hint:
- * @window: a toplevel #GdkSurface
- * @urgent: %TRUE if the window is urgent
- *
- * Toggles whether a window needs the user's
- * urgent attention.
- **/
-void
-gdk_surface_set_urgency_hint (GdkSurface *window,
-                            gboolean   urgent)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_urgency_hint (window, urgent);
-}
-
-/**
- * gdk_surface_set_geometry_hints:
- * @window: a toplevel #GdkSurface
- * @geometry: geometry hints
- * @geom_mask: bitmask indicating fields of @geometry to pay attention to
- *
- * Sets the geometry hints for @window. Hints flagged in @geom_mask
- * are set, hints not flagged in @geom_mask are unset.
- * To unset all hints, use a @geom_mask of 0 and a @geometry of %NULL.
- *
- * This function provides hints to the windowing system about
- * acceptable sizes for a toplevel window. The purpose of
- * this is to constrain user resizing, but the windowing system
- * will typically  (but is not required to) also constrain the
- * current size of the window to the provided values and
- * constrain programatic resizing via gdk_surface_resize() or
- * gdk_surface_move_resize().
- *
- * Note that on X11, this effect has no effect on windows
- * of type %GDK_SURFACE_TEMP since these windows are not resizable
- * by the user.
- *
- * Since you can’t count on the windowing system doing the
- * constraints for programmatic resizes, you should generally
- * call gdk_surface_constrain_size() yourself to determine
- * appropriate sizes.
- *
- **/
-void
-gdk_surface_set_geometry_hints (GdkSurface         *window,
-                              const GdkGeometry *geometry,
-                              GdkSurfaceHints     geom_mask)
-{
-  g_return_if_fail (geometry != NULL || geom_mask == 0);
-
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_geometry_hints (window, geometry, geom_mask);
-}
-
-/**
- * gdk_surface_set_title:
- * @window: a toplevel #GdkSurface
- * @title: title of @window
- *
- * Sets the title of a toplevel window, to be displayed in the titlebar.
- * If you haven’t explicitly set the icon name for the window
- * (using gdk_surface_set_icon_name()), the icon name will be set to
- * @title as well. @title must be in UTF-8 encoding (as with all
- * user-readable strings in GDK/GTK+). @title may not be %NULL.
- **/
-void
-gdk_surface_set_title (GdkSurface   *window,
-                     const gchar *title)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_title (window, title);
-}
-
-/**
- * gdk_surface_set_role:
- * @window: a toplevel #GdkSurface
- * @role: a string indicating its role
- *
- * When using GTK+, typically you should use gtk_window_set_role() instead
- * of this low-level function.
- *
- * The window manager and session manager use a window’s role to
- * distinguish it from other kinds of window in the same application.
- * When an application is restarted after being saved in a previous
- * session, all windows with the same title and role are treated as
- * interchangeable.  So if you have two windows with the same title
- * that should be distinguished for session management purposes, you
- * should set the role on those windows. It doesn’t matter what string
- * you use for the role, as long as you have a different role for each
- * non-interchangeable kind of window.
- *
- **/
-void
-gdk_surface_set_role (GdkSurface   *window,
-                    const gchar *role)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_role (window, role);
-}
-
-/**
- * gdk_surface_set_startup_id:
- * @window: a toplevel #GdkSurface
- * @startup_id: a string with startup-notification identifier
- *
- * When using GTK+, typically you should use gtk_window_set_startup_id()
- * instead of this low-level function.
- **/
-void
-gdk_surface_set_startup_id (GdkSurface   *window,
-                          const gchar *startup_id)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_startup_id (window, startup_id);
-}
-
-/**
- * gdk_surface_set_transient_for:
- * @window: a toplevel #GdkSurface
- * @parent: another toplevel #GdkSurface
- *
- * Indicates to the window manager that @window is a transient dialog
- * associated with the application window @parent. This allows the
- * window manager to do things like center @window on @parent and
- * keep @window above @parent.
- *
- * See gtk_window_set_transient_for() if you’re using #GtkWindow or
- * #GtkDialog.
- **/
-void
-gdk_surface_set_transient_for (GdkSurface *window,
-                             GdkSurface *parent)
-{
-  window->transient_for = parent;
-
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_transient_for (window, parent);
-}
-
-/**
- * gdk_surface_get_root_origin:
- * @window: a toplevel #GdkSurface
- * @x: (out): return location for X position of window frame
- * @y: (out): return location for Y position of window frame
- *
- * Obtains the top-left corner of the window manager frame in root
- * window coordinates.
- *
- **/
-void
-gdk_surface_get_root_origin (GdkSurface *window,
-                           gint      *x,
-                           gint      *y)
-{
-  GdkRectangle rect;
-
-  gdk_surface_get_frame_extents (window, &rect);
-
-  if (x)
-    *x = rect.x;
-
-  if (y)
-    *y = rect.y;
-}
-
-/**
- * gdk_surface_get_frame_extents:
- * @window: a toplevel #GdkSurface
- * @rect: (out): rectangle to fill with bounding box of the window frame
- *
- * Obtains the bounding box of the window, including window manager
- * titlebar/borders if any. The frame position is given in root window
- * coordinates. To get the position of the window itself (rather than
- * the frame) in root window coordinates, use gdk_surface_get_origin().
- *
- **/
-void
-gdk_surface_get_frame_extents (GdkSurface    *window,
-                              GdkRectangle *rect)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->get_frame_extents (window, rect);
-}
-
-/**
- * gdk_surface_set_accept_focus:
- * @window: a toplevel #GdkSurface
- * @accept_focus: %TRUE if the window should receive input focus
- *
- * Setting @accept_focus to %FALSE hints the desktop environment that the
- * window doesn’t want to receive input focus.
- *
- * On X, it is the responsibility of the window manager to interpret this
- * hint. ICCCM-compliant window manager usually respect it.
- **/
-void
-gdk_surface_set_accept_focus (GdkSurface *window,
-                            gboolean accept_focus)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_accept_focus (window, accept_focus);
-}
-
-/**
- * gdk_surface_set_focus_on_map:
- * @window: a toplevel #GdkSurface
- * @focus_on_map: %TRUE if the window should receive input focus when mapped
- *
- * Setting @focus_on_map to %FALSE hints the desktop environment that the
- * window doesn’t want to receive input focus when it is mapped.
- * focus_on_map should be turned off for windows that aren’t triggered
- * interactively (such as popups from network activity).
- *
- * On X, it is the responsibility of the window manager to interpret
- * this hint. Window managers following the freedesktop.org window
- * manager extension specification should respect it.
- **/
-void
-gdk_surface_set_focus_on_map (GdkSurface *window,
-                            gboolean focus_on_map)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_focus_on_map (window, focus_on_map);
-}
-
-/**
- * gdk_surface_set_icon_list:
- * @window: The #GdkSurface toplevel window to set the icon of.
- * @surfaces: (transfer none) (element-type GdkTexture):
- *     A list of image surfaces, of different sizes.
- *
- * Sets a list of icons for the window. One of these will be used
- * to represent the window when it has been iconified. The icon is
- * usually shown in an icon box or some sort of task bar. Which icon
- * size is shown depends on the window manager. The window manager
- * can scale the icon  but setting several size icons can give better
- * image quality since the window manager may only need to scale the
- * icon by a small amount or not at all.
- *
- * Note that some platforms don't support window icons.
- */
-void
-gdk_surface_set_icon_list (GdkSurface *window,
-                          GList     *textures)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_icon_list (window, textures);
-}
-
-/**
- * gdk_surface_set_icon_name:
- * @window: a toplevel #GdkSurface
- * @name: (allow-none): name of window while iconified (minimized)
- *
- * Windows may have a name used while minimized, distinct from the
- * name they display in their titlebar. Most of the time this is a bad
- * idea from a user interface standpoint. But you can set such a name
- * with this function, if you like.
- *
- * After calling this with a non-%NULL @name, calls to gdk_surface_set_title()
- * will not update the icon title.
- *
- * Using %NULL for @name unsets the icon title; further calls to
- * gdk_surface_set_title() will again update the icon title as well.
- *
- * Note that some platforms don't support window icons.
- **/
-void
-gdk_surface_set_icon_name (GdkSurface   *window,
-                         const gchar *name)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_icon_name (window, name);
-}
-
-/**
- * gdk_surface_iconify:
- * @window: a toplevel #GdkSurface
- *
- * Asks to iconify (minimize) @window. The window manager may choose
- * to ignore the request, but normally will honor it. Using
- * gtk_window_iconify() is preferred, if you have a #GtkWindow widget.
- *
- * This function only makes sense when @window is a toplevel window.
- *
- **/
-void
-gdk_surface_iconify (GdkSurface *window)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->iconify (window);
-}
-
-/**
- * gdk_surface_deiconify:
- * @window: a toplevel #GdkSurface
- *
- * Attempt to deiconify (unminimize) @window. On X11 the window manager may
- * choose to ignore the request to deiconify. When using GTK+,
- * use gtk_window_deiconify() instead of the #GdkSurface variant. Or better yet,
- * you probably want to use gtk_window_present(), which raises the window, focuses it,
- * unminimizes it, and puts it on the current desktop.
- *
- **/
-void
-gdk_surface_deiconify (GdkSurface *window)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->deiconify (window);
-}
-
-/**
- * gdk_surface_stick:
- * @window: a toplevel #GdkSurface
- *
- * â€śPins” a window such that it’s on all workspaces and does not scroll
- * with viewports, for window managers that have scrollable viewports.
- * (When using #GtkWindow, gtk_window_stick() may be more useful.)
- *
- * On the X11 platform, this function depends on window manager
- * support, so may have no effect with many window managers. However,
- * GDK will do the best it can to convince the window manager to stick
- * the window. For window managers that don’t support this operation,
- * there’s nothing you can do to force it to happen.
- *
- **/
-void
-gdk_surface_stick (GdkSurface *window)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->stick (window);
-}
-
-/**
- * gdk_surface_unstick:
- * @window: a toplevel #GdkSurface
- *
- * Reverse operation for gdk_surface_stick(); see gdk_surface_stick(),
- * and gtk_window_unstick().
- *
- **/
-void
-gdk_surface_unstick (GdkSurface *window)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->unstick (window);
-}
-
-/**
- * gdk_surface_maximize:
- * @window: a toplevel #GdkSurface
- *
- * Maximizes the window. If the window was already maximized, then
- * this function does nothing.
- *
- * On X11, asks the window manager to maximize @window, if the window
- * manager supports this operation. Not all window managers support
- * this, and some deliberately ignore it or don’t have a concept of
- * â€śmaximized”; so you can’t rely on the maximization actually
- * happening. But it will happen with most standard window managers,
- * and GDK makes a best effort to get it to happen.
- *
- * On Windows, reliably maximizes the window.
- *
- **/
-void
-gdk_surface_maximize (GdkSurface *window)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->maximize (window);
-}
-
-/**
- * gdk_surface_unmaximize:
- * @window: a toplevel #GdkSurface
- *
- * Unmaximizes the window. If the window wasn’t maximized, then this
- * function does nothing.
- *
- * On X11, asks the window manager to unmaximize @window, if the
- * window manager supports this operation. Not all window managers
- * support this, and some deliberately ignore it or don’t have a
- * concept of â€śmaximized”; so you can’t rely on the unmaximization
- * actually happening. But it will happen with most standard window
- * managers, and GDK makes a best effort to get it to happen.
- *
- * On Windows, reliably unmaximizes the window.
- *
- **/
-void
-gdk_surface_unmaximize (GdkSurface *window)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->unmaximize (window);
-}
-
-/**
- * gdk_surface_fullscreen:
- * @window: a toplevel #GdkSurface
- *
- * Moves the window into fullscreen mode. This means the
- * window covers the entire screen and is above any panels
- * or task bars.
- *
- * If the window was already fullscreen, then this function does nothing.
- *
- * On X11, asks the window manager to put @window in a fullscreen
- * state, if the window manager supports this operation. Not all
- * window managers support this, and some deliberately ignore it or
- * don’t have a concept of â€śfullscreen”; so you can’t rely on the
- * fullscreenification actually happening. But it will happen with
- * most standard window managers, and GDK makes a best effort to get
- * it to happen.
- **/
-void
-gdk_surface_fullscreen (GdkSurface *window)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->fullscreen (window);
-}
-
-/**
- * gdk_surface_fullscreen_on_monitor:
- * @window: a toplevel #GdkSurface
- * @monitor: Which monitor to display fullscreen on.
- *
- * Moves the window into fullscreen mode on the given monitor. This means
- * the window covers the entire screen and is above any panels or task bars.
- *
- * If the window was already fullscreen, then this function does nothing.
- **/
-void
-gdk_surface_fullscreen_on_monitor (GdkSurface  *window,
-                                  GdkMonitor *monitor)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (GDK_IS_MONITOR (monitor));
-  g_return_if_fail (gdk_monitor_get_display (monitor) == gdk_surface_get_display (window));
-  g_return_if_fail (gdk_monitor_is_valid (monitor));
-
-  if (GDK_SURFACE_IMPL_GET_CLASS (window->impl)->fullscreen_on_monitor != NULL)
-    GDK_SURFACE_IMPL_GET_CLASS (window->impl)->fullscreen_on_monitor (window, monitor);
-  else
-    GDK_SURFACE_IMPL_GET_CLASS (window->impl)->fullscreen (window);
-}
-
-/**
- * gdk_surface_set_fullscreen_mode:
- * @window: a toplevel #GdkSurface
- * @mode: fullscreen mode
- *
- * Specifies whether the @window should span over all monitors (in a multi-head
- * setup) or only the current monitor when in fullscreen mode.
- *
- * The @mode argument is from the #GdkFullscreenMode enumeration.
- * If #GDK_FULLSCREEN_ON_ALL_MONITORS is specified, the fullscreen @window will
- * span over all monitors of the display.
- *
- * On X11, searches through the list of monitors display the ones
- * which delimit the 4 edges of the entire display and will ask the window
- * manager to span the @window over these monitors.
- *
- * If the XINERAMA extension is not available or not usable, this function
- * has no effect.
- *
- * Not all window managers support this, so you can’t rely on the fullscreen
- * window to span over the multiple monitors when #GDK_FULLSCREEN_ON_ALL_MONITORS
- * is specified.
- **/
-void
-gdk_surface_set_fullscreen_mode (GdkSurface        *window,
-                                GdkFullscreenMode mode)
-{
-  GdkSurfaceImplClass *impl_class;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->fullscreen_mode != mode)
-    {
-      window->fullscreen_mode = mode;
-
-      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-      if (impl_class->apply_fullscreen_mode != NULL)
-        impl_class->apply_fullscreen_mode (window);
-    }
-}
-
-/**
- * gdk_surface_get_fullscreen_mode:
- * @window: a toplevel #GdkSurface
- *
- * Obtains the #GdkFullscreenMode of the @window.
- *
- * Returns: The #GdkFullscreenMode applied to the window when fullscreen.
- **/
-GdkFullscreenMode
-gdk_surface_get_fullscreen_mode (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), GDK_FULLSCREEN_ON_CURRENT_MONITOR);
-
-  return window->fullscreen_mode;
-}
-
-/**
- * gdk_surface_unfullscreen:
- * @window: a toplevel #GdkSurface
- *
- * Moves the window out of fullscreen mode. If the window was not
- * fullscreen, does nothing.
- *
- * On X11, asks the window manager to move @window out of the fullscreen
- * state, if the window manager supports this operation. Not all
- * window managers support this, and some deliberately ignore it or
- * don’t have a concept of â€śfullscreen”; so you can’t rely on the
- * unfullscreenification actually happening. But it will happen with
- * most standard window managers, and GDK makes a best effort to get
- * it to happen.
- **/
-void
-gdk_surface_unfullscreen (GdkSurface *window)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->unfullscreen (window);
-}
-
-/**
- * gdk_surface_set_keep_above:
- * @window: a toplevel #GdkSurface
- * @setting: whether to keep @window above other windows
- *
- * Set if @window must be kept above other windows. If the
- * window was already above, then this function does nothing.
- *
- * On X11, asks the window manager to keep @window above, if the window
- * manager supports this operation. Not all window managers support
- * this, and some deliberately ignore it or don’t have a concept of
- * â€śkeep above”; so you can’t rely on the window being kept above.
- * But it will happen with most standard window managers,
- * and GDK makes a best effort to get it to happen.
- **/
-void
-gdk_surface_set_keep_above (GdkSurface *window,
-                           gboolean   setting)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_keep_above (window, setting);
-}
-
-/**
- * gdk_surface_set_keep_below:
- * @window: a toplevel #GdkSurface
- * @setting: whether to keep @window below other windows
- *
- * Set if @window must be kept below other windows. If the
- * window was already below, then this function does nothing.
- *
- * On X11, asks the window manager to keep @window below, if the window
- * manager supports this operation. Not all window managers support
- * this, and some deliberately ignore it or don’t have a concept of
- * â€śkeep below”; so you can’t rely on the window being kept below.
- * But it will happen with most standard window managers,
- * and GDK makes a best effort to get it to happen.
- **/
-void
-gdk_surface_set_keep_below (GdkSurface *window, gboolean setting)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_keep_below (window, setting);
-}
-
-/**
- * gdk_surface_get_group:
- * @window: a toplevel #GdkSurface
- *
- * Returns the group leader window for @window. See gdk_surface_set_group().
- *
- * Returns: (transfer none): the group leader window for @window
- **/
-GdkSurface *
-gdk_surface_get_group (GdkSurface *window)
-{
-  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->get_group (window);
-}
-
-/**
- * gdk_surface_set_group:
- * @window: a toplevel #GdkSurface
- * @leader: (allow-none): group leader window, or %NULL to restore the default group leader window
- *
- * Sets the group leader window for @window. By default,
- * GDK sets the group leader for all toplevel windows
- * to a global window implicitly created by GDK. With this function
- * you can override this default.
- *
- * The group leader window allows the window manager to distinguish
- * all windows that belong to a single application. It may for example
- * allow users to minimize/unminimize all windows belonging to an
- * application at once. You should only set a non-default group window
- * if your application pretends to be multiple applications.
- **/
-void
-gdk_surface_set_group (GdkSurface *window,
-                     GdkSurface *leader)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_group (window, leader);
-}
-
-/**
- * gdk_surface_set_decorations:
- * @window: a toplevel #GdkSurface
- * @decorations: decoration hint mask
- *
- * â€śDecorations” are the features the window manager adds to a toplevel #GdkSurface.
- * This function sets the traditional Motif window manager hints that tell the
- * window manager which decorations you would like your window to have.
- * Usually you should use gtk_window_set_decorated() on a #GtkWindow instead of
- * using the GDK function directly.
- *
- * The @decorations argument is the logical OR of the fields in
- * the #GdkWMDecoration enumeration. If #GDK_DECOR_ALL is included in the
- * mask, the other bits indicate which decorations should be turned off.
- * If #GDK_DECOR_ALL is not included, then the other bits indicate
- * which decorations should be turned on.
- *
- * Most window managers honor a decorations hint of 0 to disable all decorations,
- * but very few honor all possible combinations of bits.
- *
- **/
-void
-gdk_surface_set_decorations (GdkSurface      *window,
-                           GdkWMDecoration decorations)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_decorations (window, decorations);
-}
-
-/**
- * gdk_surface_get_decorations:
- * @window: The toplevel #GdkSurface to get the decorations from
- * @decorations: (out): The window decorations will be written here
- *
- * Returns the decorations set on the GdkSurface with
- * gdk_surface_set_decorations().
- *
- * Returns: %TRUE if the window has decorations set, %FALSE otherwise.
- **/
-gboolean
-gdk_surface_get_decorations(GdkSurface       *window,
-                          GdkWMDecoration *decorations)
-{
-  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->get_decorations (window, decorations);
-}
-
-/**
- * gdk_surface_set_functions:
- * @window: a toplevel #GdkSurface
- * @functions: bitmask of operations to allow on @window
- *
- * Sets hints about the window management functions to make available
- * via buttons on the window frame.
- *
- * On the X backend, this function sets the traditional Motif window
- * manager hint for this purpose. However, few window managers do
- * anything reliable or interesting with this hint. Many ignore it
- * entirely.
- *
- * The @functions argument is the logical OR of values from the
- * #GdkWMFunction enumeration. If the bitmask includes #GDK_FUNC_ALL,
- * then the other bits indicate which functions to disable; if
- * it doesn’t include #GDK_FUNC_ALL, it indicates which functions to
- * enable.
- *
- **/
-void
-gdk_surface_set_functions (GdkSurface    *window,
-                         GdkWMFunction functions)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_functions (window, functions);
-}
-
-/**
- * gdk_surface_begin_resize_drag_for_device:
- * @window: a toplevel #GdkSurface
- * @edge: the edge or corner from which the drag is started
- * @device: the device used for the operation
- * @button: the button being used to drag, or 0 for a keyboard-initiated drag
- * @root_x: root window X coordinate of mouse click that began the drag
- * @root_y: root window Y coordinate of mouse click that began the drag
- * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
- *
- * Begins a window resize operation (for a toplevel window).
- * You might use this function to implement a â€świndow resize grip,” for
- * example; in fact #GtkStatusbar uses it. The function works best
- * with window managers that support the
- * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec)
- * but has a fallback implementation for other window managers.
- */
-void
-gdk_surface_begin_resize_drag_for_device (GdkSurface     *window,
-                                         GdkSurfaceEdge  edge,
-                                         GdkDevice     *device,
-                                         gint           button,
-                                         gint           root_x,
-                                         gint           root_y,
-                                         guint32        timestamp)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->begin_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
-}
-
-/**
- * gdk_surface_begin_resize_drag:
- * @window: a toplevel #GdkSurface
- * @edge: the edge or corner from which the drag is started
- * @button: the button being used to drag, or 0 for a keyboard-initiated drag
- * @root_x: root window X coordinate of mouse click that began the drag
- * @root_y: root window Y coordinate of mouse click that began the drag
- * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
- *
- * Begins a window resize operation (for a toplevel window).
- *
- * This function assumes that the drag is controlled by the
- * client pointer device, use gdk_surface_begin_resize_drag_for_device()
- * to begin a drag with a different device.
- */
-void
-gdk_surface_begin_resize_drag (GdkSurface     *window,
-                              GdkSurfaceEdge  edge,
-                              gint           button,
-                              gint           root_x,
-                              gint           root_y,
-                              guint32        timestamp)
-{
-  GdkDisplay *display;
-  GdkDevice *device;
-
-  display = gdk_surface_get_display (window);
-  device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
-  gdk_surface_begin_resize_drag_for_device (window, edge,
-                                           device, button, root_x, root_y, timestamp);
-}
-
-/**
- * gdk_surface_begin_move_drag_for_device:
- * @window: a toplevel #GdkSurface
- * @device: the device used for the operation
- * @button: the button being used to drag, or 0 for a keyboard-initiated drag
- * @root_x: root window X coordinate of mouse click that began the drag
- * @root_y: root window Y coordinate of mouse click that began the drag
- * @timestamp: timestamp of mouse click that began the drag
- *
- * Begins a window move operation (for a toplevel window).
- * You might use this function to implement a â€świndow move grip,” for
- * example. The function works best with window managers that support the
- * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec)
- * but has a fallback implementation for other window managers.
- */
-void
-gdk_surface_begin_move_drag_for_device (GdkSurface *window,
-                                       GdkDevice *device,
-                                       gint       button,
-                                       gint       root_x,
-                                       gint       root_y,
-                                       guint32    timestamp)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->begin_move_drag (window,
-                                                             device, button, root_x, root_y, timestamp);
-}
-
-/**
- * gdk_surface_begin_move_drag:
- * @window: a toplevel #GdkSurface
- * @button: the button being used to drag, or 0 for a keyboard-initiated drag
- * @root_x: root window X coordinate of mouse click that began the drag
- * @root_y: root window Y coordinate of mouse click that began the drag
- * @timestamp: timestamp of mouse click that began the drag
- *
- * Begins a window move operation (for a toplevel window).
- *
- * This function assumes that the drag is controlled by the
- * client pointer device, use gdk_surface_begin_move_drag_for_device()
- * to begin a drag with a different device.
- */
-void
-gdk_surface_begin_move_drag (GdkSurface *window,
-                            gint       button,
-                            gint       root_x,
-                            gint       root_y,
-                            guint32    timestamp)
-{
-  GdkDisplay *display;
-  GdkDevice *device;
-
-  display = gdk_surface_get_display (window);
-  device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
-  gdk_surface_begin_move_drag_for_device (window, device, button, root_x, root_y, timestamp);
-}
-
-/**
- * gdk_surface_set_opacity:
- * @window: a top-level or non-native #GdkSurface
- * @opacity: opacity
- *
- * Set @window to render as partially transparent,
- * with opacity 0 being fully transparent and 1 fully opaque. (Values
- * of the opacity parameter are clamped to the [0,1] range.) 
- *
- * For toplevel windows this depends on support from the windowing system
- * that may not always be there. For instance, On X11, this works only on
- * X screens with a compositing manager running. On Wayland, there is no
- * per-window opacity value that the compositor would apply. Instead, use
- * `gdk_surface_set_opaque_region (window, NULL)` to tell the compositor
- * that the entire window is (potentially) non-opaque, and draw your content
- * with alpha, or use gtk_widget_set_opacity() to set an overall opacity
- * for your widgets.
- *
- * Support for non-toplevel windows was added in 3.8.
- */
-void
-gdk_surface_set_opacity (GdkSurface *window,
-                       gdouble    opacity)
-{
-  if (opacity < 0)
-    opacity = 0;
-  else if (opacity > 1)
-    opacity = 1;
-
-  window->alpha = round (opacity * 255);
-
-  if (window->destroyed)
-    return;
-
-  if (gdk_surface_has_impl (window))
-    GDK_SURFACE_IMPL_GET_CLASS (window->impl)->set_opacity (window, opacity);
-  else
-    {
-      recompute_visible_regions (window, FALSE);
-      gdk_surface_invalidate_rect_full (window, NULL, TRUE);
-    }
-}
-
-/* This function is called when the XWindow is really gone.
- */
-void
-gdk_surface_destroy_notify (GdkSurface *window)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->destroy_notify (window);
-}
-
-/**
- * gdk_surface_register_dnd:
- * @window: a #GdkSurface.
- *
- * Registers a window as a potential drop destination.
- */
-void
-gdk_surface_register_dnd (GdkSurface *window)
-{
-  GDK_SURFACE_IMPL_GET_CLASS (window->impl)->register_dnd (window);
-}
-
-/**
- * gdk_drag_begin:
- * @window: the source window for this drag
- * @device: the device that controls this drag
- * @content: (transfer none): the offered content
- * @actions: the actions supported by this drag
- * @dx: the x offset to @device's position where the drag nominally started
- * @dy: the y offset to @device's position where the drag nominally started
- *
- * Starts a drag and creates a new drag context for it.
- *
- * This function is called by the drag source.
- *
- * Returns: (transfer full) (nullable): a newly created #GdkDragContext or
- *     %NULL on error.
- */
-GdkDragContext *
-gdk_drag_begin (GdkSurface          *window,
-                GdkDevice          *device,
-                GdkContentProvider *content,
-                GdkDragAction       actions,
-                gint                dx,
-                gint                dy)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-  g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
-  g_return_val_if_fail (gdk_surface_get_display (window) == gdk_device_get_display (device), NULL);
-  g_return_val_if_fail (GDK_IS_CONTENT_PROVIDER (content), NULL);
-
-  return GDK_SURFACE_IMPL_GET_CLASS (window->impl)->drag_begin (window, device, content, actions, dx, dy);
-}
-
-static void
-gdk_surface_flush_events (GdkFrameClock *clock,
-                         void          *data)
-{
-  GdkSurface *window;
-  GdkDisplay *display;
-
-  window = GDK_SURFACE (data);
-
-  display = gdk_surface_get_display (window);
-  _gdk_event_queue_flush (display);
-  _gdk_display_pause_events (display);
-
-  gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_RESUME_EVENTS);
-
-  window->frame_clock_events_paused = TRUE;
-}
-
-static void
-gdk_surface_resume_events (GdkFrameClock *clock,
-                          void          *data)
-{
-  GdkSurface *window;
-  GdkDisplay *display;
-
-  window = GDK_SURFACE (data);
-
-  display = gdk_surface_get_display (window);
-  _gdk_display_unpause_events (display);
-
-  window->frame_clock_events_paused = FALSE;
-}
-
-static void
-gdk_surface_set_frame_clock (GdkSurface     *window,
-                            GdkFrameClock *clock)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (clock == NULL || GDK_IS_FRAME_CLOCK (clock));
-  g_return_if_fail (clock == NULL || gdk_surface_is_toplevel (window));
-
-  if (clock == window->frame_clock)
-    return;
-
-  if (clock)
-    {
-      g_object_ref (clock);
-      g_signal_connect (G_OBJECT (clock),
-                        "flush-events",
-                        G_CALLBACK (gdk_surface_flush_events),
-                        window);
-      g_signal_connect (G_OBJECT (clock),
-                        "paint",
-                        G_CALLBACK (gdk_surface_paint_on_clock),
-                        window);
-      g_signal_connect (G_OBJECT (clock),
-                        "resume-events",
-                        G_CALLBACK (gdk_surface_resume_events),
-                        window);
-    }
-
-  if (window->frame_clock)
-    {
-      if (window->frame_clock_events_paused)
-        gdk_surface_resume_events (window->frame_clock, G_OBJECT (window));
-
-      g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),
-                                            G_CALLBACK (gdk_surface_flush_events),
-                                            window);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),
-                                            G_CALLBACK (gdk_surface_paint_on_clock),
-                                            window);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),
-                                            G_CALLBACK (gdk_surface_resume_events),
-                                            window);
-      g_object_unref (window->frame_clock);
-    }
-
-  window->frame_clock = clock;
-}
-
-/**
- * gdk_surface_get_frame_clock:
- * @window: window to get frame clock for
- *
- * Gets the frame clock for the window. The frame clock for a window
- * never changes unless the window is reparented to a new toplevel
- * window.
- *
- * Returns: (transfer none): the frame clock
- */
-GdkFrameClock*
-gdk_surface_get_frame_clock (GdkSurface *window)
-{
-  GdkSurface *toplevel;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  toplevel = gdk_surface_get_toplevel (window);
-
-  return toplevel->frame_clock;
-}
-
-/**
- * gdk_surface_get_scale_factor:
- * @window: window to get scale factor for
- *
- * Returns the internal scale factor that maps from window coordiantes
- * to the actual device pixels. On traditional systems this is 1, but
- * on very high density outputs this can be a higher value (often 2).
- *
- * A higher value means that drawing is automatically scaled up to
- * a higher resolution, so any code doing drawing will automatically look
- * nicer. However, if you are supplying pixel-based data the scale
- * value can be used to determine whether to use a pixel resource
- * with higher resolution data.
- *
- * The scale of a window may change during runtime, if this happens
- * a configure event will be sent to the toplevel window.
- *
- * Returns: the scale factor
- */
-gint
-gdk_surface_get_scale_factor (GdkSurface *window)
-{
-  GdkSurfaceImplClass *impl_class;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), 1);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return 1;
-
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-  if (impl_class->get_scale_factor)
-    return impl_class->get_scale_factor (window);
-
-  return 1;
-}
-
-/* Returns the *real* unscaled size, which may be a fractional size
-   in window scale coordinates. We need this to properly handle GL
-   coordinates which are y-flipped in the real coordinates. */
-void
-gdk_surface_get_unscaled_size (GdkSurface *window,
-                              int *unscaled_width,
-                              int *unscaled_height)
-{
-  GdkSurfaceImplClass *impl_class;
-  gint scale;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->impl_window == window)
-    {
-      impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-      if (impl_class->get_unscaled_size)
-        {
-          impl_class->get_unscaled_size (window, unscaled_width, unscaled_height);
-          return;
-        }
-    }
-
-  scale = gdk_surface_get_scale_factor (window);
-
-  if (unscaled_width)
-    *unscaled_width = window->width * scale;
-
-  if (unscaled_height)
-    *unscaled_height = window->height * scale;
-}
-
-
-/**
- * gdk_surface_set_opaque_region:
- * @window: a top-level or non-native #GdkSurface
- * @region: (allow-none):  a region, or %NULL
- *
- * For optimisation purposes, compositing window managers may
- * like to not draw obscured regions of windows, or turn off blending
- * during for these regions. With RGB windows with no transparency,
- * this is just the shape of the window, but with ARGB32 windows, the
- * compositor does not know what regions of the window are transparent
- * or not.
- *
- * This function only works for toplevel windows.
- *
- * GTK+ will update this property automatically if
- * the @window background is opaque, as we know where the opaque regions
- * are. If your window background is not opaque, please update this
- * property in your #GtkWidget::style-updated handler.
- */
-void
-gdk_surface_set_opaque_region (GdkSurface      *window,
-                              cairo_region_t *region)
-{
-  GdkSurfaceImplClass *impl_class;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (!GDK_SURFACE_DESTROYED (window));
-
-  if (cairo_region_equal (window->opaque_region, region))
-    return;
-
-  g_clear_pointer (&window->opaque_region, cairo_region_destroy);
-
-  if (region != NULL)
-    window->opaque_region = cairo_region_reference (region);
-
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-  if (impl_class->set_opaque_region)
-    impl_class->set_opaque_region (window, region);
-}
-
-/**
- * gdk_surface_set_shadow_width:
- * @window: a #GdkSurface
- * @left: The left extent
- * @right: The right extent
- * @top: The top extent
- * @bottom: The bottom extent
- *
- * Newer GTK+ windows using client-side decorations use extra geometry
- * around their frames for effects like shadows and invisible borders.
- * Window managers that want to maximize windows or snap to edges need
- * to know where the extents of the actual frame lie, so that users
- * don’t feel like windows are snapping against random invisible edges.
- *
- * Note that this property is automatically updated by GTK+, so this
- * function should only be used by applications which do not use GTK+
- * to create toplevel windows.
- */
-void
-gdk_surface_set_shadow_width (GdkSurface *window,
-                             gint       left,
-                             gint       right,
-                             gint       top,
-                             gint       bottom)
-{
-  GdkSurfaceImplClass *impl_class;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (!GDK_SURFACE_DESTROYED (window));
-  g_return_if_fail (left >= 0 && right >= 0 && top >= 0 && bottom >= 0);
-
-  window->shadow_top = top;
-  window->shadow_left = left;
-  window->shadow_right = right;
-  window->shadow_bottom = bottom;
-
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-  if (impl_class->set_shadow_width)
-    impl_class->set_shadow_width (window, left, right, top, bottom);
-}
-
-/**
- * gdk_surface_show_window_menu:
- * @window: a #GdkSurface
- * @event: a #GdkEvent to show the menu for
- *
- * Asks the windowing system to show the window menu. The window menu
- * is the menu shown when right-clicking the titlebar on traditional
- * windows managed by the window manager. This is useful for windows
- * using client-side decorations, activating it with a right-click
- * on the window decorations.
- *
- * Returns: %TRUE if the window menu was shown and %FALSE otherwise.
- */
-gboolean
-gdk_surface_show_window_menu (GdkSurface *window,
-                             GdkEvent  *event)
-{
-  GdkSurfaceImplClass *impl_class;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-  g_return_val_if_fail (!GDK_SURFACE_DESTROYED (window), FALSE);
-
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-  if (impl_class->show_window_menu)
-    return impl_class->show_window_menu (window, event);
-  else
-    return FALSE;
-}
-
-gboolean
-gdk_surface_supports_edge_constraints (GdkSurface *window)
-{
-  GdkSurfaceImplClass *impl_class;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-  g_return_val_if_fail (!GDK_SURFACE_DESTROYED (window), FALSE);
-
-  impl_class = GDK_SURFACE_IMPL_GET_CLASS (window->impl);
-
-  if (impl_class->supports_edge_constraints)
-    return impl_class->supports_edge_constraints (window);
-  else
-    return FALSE;
-}
-
-void
-gdk_surface_set_state (GdkSurface      *window,
-                      GdkSurfaceState  new_state)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (new_state == window->state)
-    return; /* No actual work to do, nothing changed. */
-
-  /* Actually update the field in GdkSurface, this is sort of an odd
-   * place to do it, but seems like the safest since it ensures we expose no
-   * inconsistent state to the user.
-   */
-
-  window->state = new_state;
-
-  _gdk_surface_update_viewable (window);
-
-  /* We only really send the event to toplevels, since
-   * all the window states don't apply to non-toplevels.
-   * Non-toplevels do use the GDK_SURFACE_STATE_WITHDRAWN flag
-   * internally so we needed to update window->state.
-   */
-  switch (window->window_type)
-    {
-    case GDK_SURFACE_TOPLEVEL:
-    case GDK_SURFACE_TEMP: /* ? */
-      g_object_notify (G_OBJECT (window), "state");
-      break;
-    case GDK_SURFACE_FOREIGN:
-    case GDK_SURFACE_ROOT:
-    case GDK_SURFACE_CHILD:
-    default:
-      break;
-    }
-}
-
-void
-gdk_synthesize_window_state (GdkSurface     *window,
-                             GdkSurfaceState unset_flags,
-                             GdkSurfaceState set_flags)
-{
-  gdk_surface_set_state (window, (window->state | set_flags) & ~unset_flags);
-}
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
deleted file mode 100644 (file)
index ea5ca92..0000000
+++ /dev/null
@@ -1,933 +0,0 @@
-/* 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-#ifndef __GDK_SURFACE_H__
-#define __GDK_SURFACE_H__
-
-#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
-#error "Only <gdk/gdk.h> can be included directly."
-#endif
-
-#include <gdk/gdkversionmacros.h>
-#include <gdk/gdktypes.h>
-#include <gdk/gdkdrawingcontext.h>
-#include <gdk/gdkevents.h>
-#include <gdk/gdkframeclock.h>
-#include <gdk/gdkmonitor.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GdkGeometry          GdkGeometry;
-
-/**
- * GdkSurfaceType:
- * @GDK_SURFACE_ROOT: root window; this window has no parent, covers the entire
- *  screen, and is created by the window system
- * @GDK_SURFACE_TOPLEVEL: toplevel window (used to implement #GtkWindow)
- * @GDK_SURFACE_CHILD: child window (used to implement e.g. #GtkEntry)
- * @GDK_SURFACE_TEMP: override redirect temporary window (used to implement
- *  #GtkMenu)
- * @GDK_SURFACE_FOREIGN: foreign window (see gdk_surface_foreign_new())
- * @GDK_SURFACE_SUBSURFACE: subsurface-based window; This window is visually
- *  tied to a toplevel, and is moved/stacked with it. Currently this window
- *  type is only implemented in Wayland. Since 3.14
- *
- * Describes the kind of window.
- */
-typedef enum
-{
-  GDK_SURFACE_ROOT,
-  GDK_SURFACE_TOPLEVEL,
-  GDK_SURFACE_CHILD,
-  GDK_SURFACE_TEMP,
-  GDK_SURFACE_FOREIGN,
-  GDK_SURFACE_SUBSURFACE
-} GdkSurfaceType;
-
-/* Size restriction enumeration.
- */
-/**
- * GdkSurfaceHints:
- * @GDK_HINT_POS: indicates that the program has positioned the window
- * @GDK_HINT_MIN_SIZE: min size fields are set
- * @GDK_HINT_MAX_SIZE: max size fields are set
- * @GDK_HINT_BASE_SIZE: base size fields are set
- * @GDK_HINT_ASPECT: aspect ratio fields are set
- * @GDK_HINT_RESIZE_INC: resize increment fields are set
- * @GDK_HINT_WIN_GRAVITY: window gravity field is set
- * @GDK_HINT_USER_POS: indicates that the window’s position was explicitly set
- *  by the user
- * @GDK_HINT_USER_SIZE: indicates that the window’s size was explicitly set by
- *  the user
- *
- * Used to indicate which fields of a #GdkGeometry struct should be paid
- * attention to. Also, the presence/absence of @GDK_HINT_POS,
- * @GDK_HINT_USER_POS, and @GDK_HINT_USER_SIZE is significant, though they don't
- * directly refer to #GdkGeometry fields. @GDK_HINT_USER_POS will be set
- * automatically by #GtkWindow if you call gtk_window_move().
- * @GDK_HINT_USER_POS and @GDK_HINT_USER_SIZE should be set if the user
- * specified a size/position using a --geometry command-line argument;
- * gtk_window_parse_geometry() automatically sets these flags.
- */
-typedef enum
-{
-  GDK_HINT_POS        = 1 << 0,
-  GDK_HINT_MIN_SIZE    = 1 << 1,
-  GDK_HINT_MAX_SIZE    = 1 << 2,
-  GDK_HINT_BASE_SIZE   = 1 << 3,
-  GDK_HINT_ASPECT      = 1 << 4,
-  GDK_HINT_RESIZE_INC  = 1 << 5,
-  GDK_HINT_WIN_GRAVITY = 1 << 6,
-  GDK_HINT_USER_POS    = 1 << 7,
-  GDK_HINT_USER_SIZE   = 1 << 8
-} GdkSurfaceHints;
-
-/* The next two enumeration values current match the
- * Motif constants. If this is changed, the implementation
- * of gdk_surface_set_decorations/gdk_surface_set_functions
- * will need to change as well.
- */
-/**
- * GdkWMDecoration:
- * @GDK_DECOR_ALL: all decorations should be applied.
- * @GDK_DECOR_BORDER: a frame should be drawn around the window.
- * @GDK_DECOR_RESIZEH: the frame should have resize handles.
- * @GDK_DECOR_TITLE: a titlebar should be placed above the window.
- * @GDK_DECOR_MENU: a button for opening a menu should be included.
- * @GDK_DECOR_MINIMIZE: a minimize button should be included.
- * @GDK_DECOR_MAXIMIZE: a maximize button should be included.
- *
- * These are hints originally defined by the Motif toolkit.
- * The window manager can use them when determining how to decorate
- * the window. The hint must be set before mapping the window.
- */
-typedef enum
-{
-  GDK_DECOR_ALL                = 1 << 0,
-  GDK_DECOR_BORDER     = 1 << 1,
-  GDK_DECOR_RESIZEH    = 1 << 2,
-  GDK_DECOR_TITLE      = 1 << 3,
-  GDK_DECOR_MENU       = 1 << 4,
-  GDK_DECOR_MINIMIZE   = 1 << 5,
-  GDK_DECOR_MAXIMIZE   = 1 << 6
-} GdkWMDecoration;
-
-/**
- * GdkWMFunction:
- * @GDK_FUNC_ALL: all functions should be offered.
- * @GDK_FUNC_RESIZE: the window should be resizable.
- * @GDK_FUNC_MOVE: the window should be movable.
- * @GDK_FUNC_MINIMIZE: the window should be minimizable.
- * @GDK_FUNC_MAXIMIZE: the window should be maximizable.
- * @GDK_FUNC_CLOSE: the window should be closable.
- *
- * These are hints originally defined by the Motif toolkit. The window manager
- * can use them when determining the functions to offer for the window. The
- * hint must be set before mapping the window.
- */
-typedef enum
-{
-  GDK_FUNC_ALL         = 1 << 0,
-  GDK_FUNC_RESIZE      = 1 << 1,
-  GDK_FUNC_MOVE                = 1 << 2,
-  GDK_FUNC_MINIMIZE    = 1 << 3,
-  GDK_FUNC_MAXIMIZE    = 1 << 4,
-  GDK_FUNC_CLOSE       = 1 << 5
-} GdkWMFunction;
-
-/* Currently, these are the same values numerically as in the
- * X protocol. If you change that, gdkwindow-x11.c/gdk_surface_set_geometry_hints()
- * will need fixing.
- */
-/**
- * GdkGravity:
- * @GDK_GRAVITY_NORTH_WEST: the reference point is at the top left corner.
- * @GDK_GRAVITY_NORTH: the reference point is in the middle of the top edge.
- * @GDK_GRAVITY_NORTH_EAST: the reference point is at the top right corner.
- * @GDK_GRAVITY_WEST: the reference point is at the middle of the left edge.
- * @GDK_GRAVITY_CENTER: the reference point is at the center of the window.
- * @GDK_GRAVITY_EAST: the reference point is at the middle of the right edge.
- * @GDK_GRAVITY_SOUTH_WEST: the reference point is at the lower left corner.
- * @GDK_GRAVITY_SOUTH: the reference point is at the middle of the lower edge.
- * @GDK_GRAVITY_SOUTH_EAST: the reference point is at the lower right corner.
- * @GDK_GRAVITY_STATIC: the reference point is at the top left corner of the
- *  window itself, ignoring window manager decorations.
- *
- * Defines the reference point of a window and the meaning of coordinates
- * passed to gtk_window_move(). See gtk_window_move() and the "implementation
- * notes" section of the
- * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec)
- * specification for more details.
- */
-typedef enum
-{
-  GDK_GRAVITY_NORTH_WEST = 1,
-  GDK_GRAVITY_NORTH,
-  GDK_GRAVITY_NORTH_EAST,
-  GDK_GRAVITY_WEST,
-  GDK_GRAVITY_CENTER,
-  GDK_GRAVITY_EAST,
-  GDK_GRAVITY_SOUTH_WEST,
-  GDK_GRAVITY_SOUTH,
-  GDK_GRAVITY_SOUTH_EAST,
-  GDK_GRAVITY_STATIC
-} GdkGravity;
-
-/**
- * GdkAnchorHints:
- * @GDK_ANCHOR_FLIP_X: allow flipping anchors horizontally
- * @GDK_ANCHOR_FLIP_Y: allow flipping anchors vertically
- * @GDK_ANCHOR_SLIDE_X: allow sliding window horizontally
- * @GDK_ANCHOR_SLIDE_Y: allow sliding window vertically
- * @GDK_ANCHOR_RESIZE_X: allow resizing window horizontally
- * @GDK_ANCHOR_RESIZE_Y: allow resizing window vertically
- * @GDK_ANCHOR_FLIP: allow flipping anchors on both axes
- * @GDK_ANCHOR_SLIDE: allow sliding window on both axes
- * @GDK_ANCHOR_RESIZE: allow resizing window on both axes
- *
- * Positioning hints for aligning a window relative to a rectangle.
- *
- * These hints determine how the window should be positioned in the case that
- * the window would fall off-screen if placed in its ideal position.
- *
- * For example, %GDK_ANCHOR_FLIP_X will replace %GDK_GRAVITY_NORTH_WEST with
- * %GDK_GRAVITY_NORTH_EAST and vice versa if the window extends beyond the left
- * or right edges of the monitor.
- *
- * If %GDK_ANCHOR_SLIDE_X is set, the window can be shifted horizontally to fit
- * on-screen. If %GDK_ANCHOR_RESIZE_X is set, the window can be shrunken
- * horizontally to fit.
- *
- * In general, when multiple flags are set, flipping should take precedence over
- * sliding, which should take precedence over resizing.
- *
- * Since: 3.22
- * Stability: Unstable
- */
-typedef enum
-{
-  GDK_ANCHOR_FLIP_X   = 1 << 0,
-  GDK_ANCHOR_FLIP_Y   = 1 << 1,
-  GDK_ANCHOR_SLIDE_X  = 1 << 2,
-  GDK_ANCHOR_SLIDE_Y  = 1 << 3,
-  GDK_ANCHOR_RESIZE_X = 1 << 4,
-  GDK_ANCHOR_RESIZE_Y = 1 << 5,
-  GDK_ANCHOR_FLIP     = GDK_ANCHOR_FLIP_X | GDK_ANCHOR_FLIP_Y,
-  GDK_ANCHOR_SLIDE    = GDK_ANCHOR_SLIDE_X | GDK_ANCHOR_SLIDE_Y,
-  GDK_ANCHOR_RESIZE   = GDK_ANCHOR_RESIZE_X | GDK_ANCHOR_RESIZE_Y
-} GdkAnchorHints;
-
-/**
- * GdkSurfaceEdge:
- * @GDK_SURFACE_EDGE_NORTH_WEST: the top left corner.
- * @GDK_SURFACE_EDGE_NORTH: the top edge.
- * @GDK_SURFACE_EDGE_NORTH_EAST: the top right corner.
- * @GDK_SURFACE_EDGE_WEST: the left edge.
- * @GDK_SURFACE_EDGE_EAST: the right edge.
- * @GDK_SURFACE_EDGE_SOUTH_WEST: the lower left corner.
- * @GDK_SURFACE_EDGE_SOUTH: the lower edge.
- * @GDK_SURFACE_EDGE_SOUTH_EAST: the lower right corner.
- *
- * Determines a window edge or corner.
- */
-typedef enum
-{
-  GDK_SURFACE_EDGE_NORTH_WEST,
-  GDK_SURFACE_EDGE_NORTH,
-  GDK_SURFACE_EDGE_NORTH_EAST,
-  GDK_SURFACE_EDGE_WEST,
-  GDK_SURFACE_EDGE_EAST,
-  GDK_SURFACE_EDGE_SOUTH_WEST,
-  GDK_SURFACE_EDGE_SOUTH,
-  GDK_SURFACE_EDGE_SOUTH_EAST  
-} GdkSurfaceEdge;
-
-/**
- * GdkFullscreenMode:
- * @GDK_FULLSCREEN_ON_CURRENT_MONITOR: Fullscreen on current monitor only.
- * @GDK_FULLSCREEN_ON_ALL_MONITORS: Span across all monitors when fullscreen.
- *
- * Indicates which monitor (in a multi-head setup) a window should span over
- * when in fullscreen mode.
- *
- * Since: 3.8
- **/
-typedef enum
-{
-  GDK_FULLSCREEN_ON_CURRENT_MONITOR,
-  GDK_FULLSCREEN_ON_ALL_MONITORS
-} GdkFullscreenMode;
-
-/**
- * GdkGeometry:
- * @min_width: minimum width of window (or -1 to use requisition, with
- *  #GtkWindow only)
- * @min_height: minimum height of window (or -1 to use requisition, with
- *  #GtkWindow only)
- * @max_width: maximum width of window (or -1 to use requisition, with
- *  #GtkWindow only)
- * @max_height: maximum height of window (or -1 to use requisition, with
- *  #GtkWindow only)
- * @base_width: allowed window widths are @base_width + @width_inc * N where N
- *  is any integer (-1 allowed with #GtkWindow)
- * @base_height: allowed window widths are @base_height + @height_inc * N where
- *  N is any integer (-1 allowed with #GtkWindow)
- * @width_inc: width resize increment
- * @height_inc: height resize increment
- * @min_aspect: minimum width/height ratio
- * @max_aspect: maximum width/height ratio
- * @win_gravity: window gravity, see gtk_window_set_gravity()
- *
- * The #GdkGeometry struct gives the window manager information about
- * a window’s geometry constraints. Normally you would set these on
- * the GTK+ level using gtk_window_set_geometry_hints(). #GtkWindow
- * then sets the hints on the #GdkSurface it creates.
- *
- * gdk_surface_set_geometry_hints() expects the hints to be fully valid already
- * and simply passes them to the window manager; in contrast,
- * gtk_window_set_geometry_hints() performs some interpretation. For example,
- * #GtkWindow will apply the hints to the geometry widget instead of the
- * toplevel window, if you set a geometry widget. Also, the
- * @min_width/@min_height/@max_width/@max_height fields may be set to -1, and
- * #GtkWindow will substitute the size request of the window or geometry widget.
- * If the minimum size hint is not provided, #GtkWindow will use its requisition
- * as the minimum size. If the minimum size is provided and a geometry widget is
- * set, #GtkWindow will take the minimum size as the minimum size of the
- * geometry widget rather than the entire window. The base size is treated
- * similarly.
- *
- * The canonical use-case for gtk_window_set_geometry_hints() is to get a
- * terminal widget to resize properly. Here, the terminal text area should be
- * the geometry widget; #GtkWindow will then automatically set the base size to
- * the size of other widgets in the terminal window, such as the menubar and
- * scrollbar. Then, the @width_inc and @height_inc fields should be set to the
- * size of one character in the terminal. Finally, the base size should be set
- * to the size of one character. The net effect is that the minimum size of the
- * terminal will have a 1x1 character terminal area, and only terminal sizes on
- * the â€ścharacter grid” will be allowed.
- *
- * Here’s an example of how the terminal example would be implemented, assuming
- * a terminal area widget called â€śterminal” and a toplevel window â€śtoplevel”:
- *
- * |[<!-- language="C" -->
- *     GdkGeometry hints;
- *
- *     hints.base_width = terminal->char_width;
- *         hints.base_height = terminal->char_height;
- *         hints.min_width = terminal->char_width;
- *         hints.min_height = terminal->char_height;
- *         hints.width_inc = terminal->char_width;
- *         hints.height_inc = terminal->char_height;
- *
- *  gtk_window_set_geometry_hints (GTK_WINDOW (toplevel),
- *                                 GTK_WIDGET (terminal),
- *                                 &hints,
- *                                 GDK_HINT_RESIZE_INC |
- *                                 GDK_HINT_MIN_SIZE |
- *                                 GDK_HINT_BASE_SIZE);
- * ]|
- *
- * The other useful fields are the @min_aspect and @max_aspect fields; these
- * contain a width/height ratio as a floating point number. If a geometry widget
- * is set, the aspect applies to the geometry widget rather than the entire
- * window. The most common use of these hints is probably to set @min_aspect and
- * @max_aspect to the same value, thus forcing the window to keep a constant
- * aspect ratio.
- */
-struct _GdkGeometry
-{
-  gint min_width;
-  gint min_height;
-  gint max_width;
-  gint max_height;
-  gint base_width;
-  gint base_height;
-  gint width_inc;
-  gint height_inc;
-  gdouble min_aspect;
-  gdouble max_aspect;
-  GdkGravity win_gravity;
-};
-
-/**
- * GdkSurfaceState:
- * @GDK_SURFACE_STATE_WITHDRAWN: the window is not shown.
- * @GDK_SURFACE_STATE_ICONIFIED: the window is minimized.
- * @GDK_SURFACE_STATE_MAXIMIZED: the window is maximized.
- * @GDK_SURFACE_STATE_STICKY: the window is sticky.
- * @GDK_SURFACE_STATE_FULLSCREEN: the window is maximized without
- *   decorations.
- * @GDK_SURFACE_STATE_ABOVE: the window is kept above other windows.
- * @GDK_SURFACE_STATE_BELOW: the window is kept below other windows.
- * @GDK_SURFACE_STATE_FOCUSED: the window is presented as focused (with active decorations).
- * @GDK_SURFACE_STATE_TILED: the window is in a tiled state, Since 3.10. Since 3.91.2, this
- *                          is deprecated in favor of per-edge information.
- * @GDK_SURFACE_STATE_TOP_TILED: whether the top edge is tiled, Since 3.91.2
- * @GDK_SURFACE_STATE_TOP_RESIZABLE: whether the top edge is resizable, Since 3.91.2
- * @GDK_SURFACE_STATE_RIGHT_TILED: whether the right edge is tiled, Since 3.91.2
- * @GDK_SURFACE_STATE_RIGHT_RESIZABLE: whether the right edge is resizable, Since 3.91.2
- * @GDK_SURFACE_STATE_BOTTOM_TILED: whether the bottom edge is tiled, Since 3.91.2
- * @GDK_SURFACE_STATE_BOTTOM_RESIZABLE: whether the bottom edge is resizable, Since 3.91.2
- * @GDK_SURFACE_STATE_LEFT_TILED: whether the left edge is tiled, Since 3.91.2
- * @GDK_SURFACE_STATE_LEFT_RESIZABLE: whether the left edge is resizable, Since 3.91.2
- *
- * Specifies the state of a toplevel window.
- */
-typedef enum
-{
-  GDK_SURFACE_STATE_WITHDRAWN        = 1 << 0,
-  GDK_SURFACE_STATE_ICONIFIED        = 1 << 1,
-  GDK_SURFACE_STATE_MAXIMIZED        = 1 << 2,
-  GDK_SURFACE_STATE_STICKY           = 1 << 3,
-  GDK_SURFACE_STATE_FULLSCREEN       = 1 << 4,
-  GDK_SURFACE_STATE_ABOVE            = 1 << 5,
-  GDK_SURFACE_STATE_BELOW            = 1 << 6,
-  GDK_SURFACE_STATE_FOCUSED          = 1 << 7,
-  GDK_SURFACE_STATE_TILED            = 1 << 8,
-  GDK_SURFACE_STATE_TOP_TILED        = 1 << 9,
-  GDK_SURFACE_STATE_TOP_RESIZABLE    = 1 << 10,
-  GDK_SURFACE_STATE_RIGHT_TILED      = 1 << 11,
-  GDK_SURFACE_STATE_RIGHT_RESIZABLE  = 1 << 12,
-  GDK_SURFACE_STATE_BOTTOM_TILED     = 1 << 13,
-  GDK_SURFACE_STATE_BOTTOM_RESIZABLE = 1 << 14,
-  GDK_SURFACE_STATE_LEFT_TILED       = 1 << 15,
-  GDK_SURFACE_STATE_LEFT_RESIZABLE   = 1 << 16
-} GdkSurfaceState;
-
-
-typedef struct _GdkSurfaceClass GdkSurfaceClass;
-
-#define GDK_TYPE_SURFACE              (gdk_surface_get_type ())
-#define GDK_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE, GdkSurface))
-#define GDK_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE, GdkSurfaceClass))
-#define GDK_IS_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE))
-#define GDK_IS_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE))
-#define GDK_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE, GdkSurfaceClass))
-
-
-struct _GdkSurfaceClass
-{
-  GObjectClass      parent_class;
-
-  /* Padding for future expansion */
-  void (*_gdk_reserved1) (void);
-  void (*_gdk_reserved2) (void);
-  void (*_gdk_reserved3) (void);
-  void (*_gdk_reserved4) (void);
-  void (*_gdk_reserved5) (void);
-  void (*_gdk_reserved6) (void);
-  void (*_gdk_reserved7) (void);
-  void (*_gdk_reserved8) (void);
-};
-
-/* Windows
- */
-GDK_AVAILABLE_IN_ALL
-GType         gdk_surface_get_type              (void) G_GNUC_CONST;
-GDK_AVAILABLE_IN_ALL
-GdkSurface *   gdk_surface_new_toplevel          (GdkDisplay    *display,
-                                                int            width,
-                                                int            height);
-GDK_AVAILABLE_IN_ALL
-GdkSurface *   gdk_surface_new_popup             (GdkDisplay    *display,
-                                                const GdkRectangle *position);
-GDK_AVAILABLE_IN_ALL
-GdkSurface *   gdk_surface_new_temp              (GdkDisplay    *display);
-GDK_AVAILABLE_IN_ALL
-GdkSurface *   gdk_surface_new_child             (GdkSurface     *parent,
-                                                const GdkRectangle *position);
-
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_destroy               (GdkSurface     *window);
-GDK_AVAILABLE_IN_ALL
-GdkSurfaceType gdk_surface_get_window_type       (GdkSurface     *window);
-GDK_AVAILABLE_IN_ALL
-gboolean      gdk_surface_is_destroyed          (GdkSurface     *window);
-
-GDK_AVAILABLE_IN_ALL
-GdkDisplay *  gdk_surface_get_display           (GdkSurface     *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_show                  (GdkSurface     *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_hide                  (GdkSurface     *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_withdraw              (GdkSurface     *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_show_unraised         (GdkSurface     *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_move                  (GdkSurface     *window,
-                                                gint           x,
-                                                gint           y);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_resize                (GdkSurface     *window,
-                                                gint           width,
-                                                gint           height);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_move_resize           (GdkSurface     *window,
-                                                gint           x,
-                                                gint           y,
-                                                gint           width,
-                                                gint           height);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_raise                 (GdkSurface     *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_lower                 (GdkSurface     *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_restack               (GdkSurface     *window,
-                                               GdkSurface     *sibling,
-                                               gboolean       above);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_focus                 (GdkSurface     *window,
-                                                guint32        timestamp);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_user_data         (GdkSurface     *window,
-                                                gpointer       user_data);
-GDK_AVAILABLE_IN_ALL
-gboolean      gdk_surface_get_accept_focus      (GdkSurface     *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_accept_focus      (GdkSurface     *window,
-                                               gboolean       accept_focus);
-GDK_AVAILABLE_IN_ALL
-gboolean      gdk_surface_get_focus_on_map      (GdkSurface     *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_focus_on_map      (GdkSurface     *window,
-                                               gboolean       focus_on_map);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_scroll                (GdkSurface     *window,
-                                                gint           dx,
-                                                gint           dy);
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_move_region           (GdkSurface       *window,
-                                               const cairo_region_t *region,
-                                               gint             dx,
-                                               gint             dy);
-
-/* 
- * This allows for making shaped (partially transparent) windows
- * - cool feature, needed for Drag and Drag for example.
- */
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_shape_combine_region (GdkSurface            *window,
-                                      const cairo_region_t *shape_region,
-                                      gint            offset_x,
-                                      gint            offset_y);
-
-/*
- * This routine allows you to quickly take the shapes of all the child windows
- * of a window and use their shapes as the shape mask for this window - useful
- * for container windows that dont want to look like a big box
- * 
- * - Raster
- */
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_set_child_shapes (GdkSurface *window);
-
-/*
- * This routine allows you to merge (ie ADD) child shapes to your
- * own window’s shape keeping its current shape and ADDING the child
- * shapes to it.
- * 
- * - Raster
- */
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_merge_child_shapes         (GdkSurface       *window);
-
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_input_shape_combine_region (GdkSurface       *window,
-                                            const cairo_region_t *shape_region,
-                                            gint             offset_x,
-                                            gint             offset_y);
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_set_child_input_shapes     (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_merge_child_input_shapes   (GdkSurface       *window);
-
-
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_set_pass_through (GdkSurface *window,
-                                  gboolean   pass_through);
-GDK_AVAILABLE_IN_ALL
-gboolean gdk_surface_get_pass_through (GdkSurface *window);
-
-/*
- * Check if a window has been shown, and whether all its
- * parents up to a toplevel have been shown, respectively.
- * Note that a window that is_viewable below is not necessarily
- * viewable in the X sense.
- */
-GDK_AVAILABLE_IN_ALL
-gboolean gdk_surface_is_visible     (GdkSurface *window);
-GDK_AVAILABLE_IN_ALL
-gboolean gdk_surface_is_viewable    (GdkSurface *window);
-GDK_AVAILABLE_IN_ALL
-gboolean gdk_surface_is_input_only  (GdkSurface *window);
-GDK_AVAILABLE_IN_ALL
-gboolean gdk_surface_is_shaped      (GdkSurface *window);
-
-GDK_AVAILABLE_IN_ALL
-GdkSurfaceState gdk_surface_get_state (GdkSurface *window);
-
-
-/* GdkSurface */
-
-GDK_AVAILABLE_IN_ALL
-gboolean      gdk_surface_has_native         (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void              gdk_surface_set_type_hint (GdkSurface        *window,
-                                            GdkSurfaceTypeHint hint);
-GDK_AVAILABLE_IN_ALL
-GdkSurfaceTypeHint gdk_surface_get_type_hint (GdkSurface        *window);
-
-GDK_AVAILABLE_IN_ALL
-gboolean      gdk_surface_get_modal_hint   (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_modal_hint   (GdkSurface       *window,
-                                           gboolean         modal);
-
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_set_skip_taskbar_hint (GdkSurface *window,
-                                       gboolean   skips_taskbar);
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_set_skip_pager_hint   (GdkSurface *window,
-                                       gboolean   skips_pager);
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_set_urgency_hint      (GdkSurface *window,
-                                      gboolean   urgent);
-
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_geometry_hints (GdkSurface          *window,
-                                            const GdkGeometry  *geometry,
-                                            GdkSurfaceHints      geom_mask);
-
-GDK_AVAILABLE_IN_ALL
-cairo_region_t *gdk_surface_get_clip_region  (GdkSurface          *window);
-GDK_AVAILABLE_IN_ALL
-cairo_region_t *gdk_surface_get_visible_region(GdkSurface         *window);
-
-GDK_AVAILABLE_IN_ALL
-GdkDrawingContext *gdk_surface_begin_draw_frame  (GdkSurface            *window,
-                                                 GdkDrawContext       *context,
-                                                 const cairo_region_t *region);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_end_draw_frame    (GdkSurface            *window,
-                                            GdkDrawingContext    *context);
-
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_set_title        (GdkSurface    *window,
-                                           const gchar   *title);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_role          (GdkSurface     *window,
-                                           const gchar   *role);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_startup_id    (GdkSurface     *window,
-                                           const gchar   *startup_id);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_transient_for (GdkSurface     *window,
-                                           GdkSurface     *parent);
-
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_set_cursor     (GdkSurface      *window,
-                                         GdkCursor       *cursor);
-GDK_AVAILABLE_IN_ALL
-GdkCursor    *gdk_surface_get_cursor      (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_set_device_cursor (GdkSurface   *window,
-                                            GdkDevice     *device,
-                                            GdkCursor    *cursor);
-GDK_AVAILABLE_IN_ALL
-GdkCursor    *gdk_surface_get_device_cursor (GdkSurface     *window,
-                                            GdkDevice     *device);
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_get_user_data  (GdkSurface      *window,
-                                         gpointer        *data);
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_get_geometry   (GdkSurface      *window,
-                                         gint            *x,
-                                         gint            *y,
-                                         gint            *width,
-                                         gint            *height);
-GDK_AVAILABLE_IN_ALL
-int           gdk_surface_get_width       (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-int           gdk_surface_get_height      (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_get_position   (GdkSurface      *window,
-                                         gint            *x,
-                                         gint            *y);
-GDK_AVAILABLE_IN_ALL
-gint         gdk_surface_get_origin     (GdkSurface      *window,
-                                         gint            *x,
-                                         gint            *y);
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_get_root_coords (GdkSurface     *window,
-                                         gint             x,
-                                         gint             y,
-                                         gint            *root_x,
-                                         gint            *root_y);
-GDK_AVAILABLE_IN_ALL
-void       gdk_surface_coords_to_parent   (GdkSurface       *window,
-                                          gdouble          x,
-                                          gdouble          y,
-                                          gdouble         *parent_x,
-                                          gdouble         *parent_y);
-GDK_AVAILABLE_IN_ALL
-void       gdk_surface_coords_from_parent (GdkSurface       *window,
-                                          gdouble          parent_x,
-                                          gdouble          parent_y,
-                                          gdouble         *x,
-                                          gdouble         *y);
-
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_get_root_origin (GdkSurface     *window,
-                                         gint            *x,
-                                         gint            *y);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_get_frame_extents (GdkSurface     *window,
-                                            GdkRectangle  *rect);
-
-GDK_AVAILABLE_IN_ALL
-gint          gdk_surface_get_scale_factor  (GdkSurface     *window);
-
-GDK_AVAILABLE_IN_ALL
-GdkSurface *   gdk_surface_get_device_position (GdkSurface       *window,
-                                              GdkDevice       *device,
-                                              gint            *x,
-                                              gint            *y,
-                                              GdkModifierType *mask);
-GDK_AVAILABLE_IN_ALL
-GdkSurface *   gdk_surface_get_device_position_double (GdkSurface       *window,
-                                                     GdkDevice       *device,
-                                                     gdouble         *x,
-                                                     gdouble         *y,
-                                                     GdkModifierType *mask);
-GDK_AVAILABLE_IN_ALL
-GdkSurface *   gdk_surface_get_parent      (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-GdkSurface *   gdk_surface_get_toplevel    (GdkSurface       *window);
-
-GDK_AVAILABLE_IN_ALL
-GList *              gdk_surface_get_children   (GdkSurface      *window);
-GDK_AVAILABLE_IN_ALL
-GList *       gdk_surface_peek_children   (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-GList *       gdk_surface_get_children_with_user_data (GdkSurface *window,
-                                                     gpointer   user_data);
-
-GDK_AVAILABLE_IN_ALL
-GdkEventMask  gdk_surface_get_events    (GdkSurface      *window);
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_set_events     (GdkSurface      *window,
-                                         GdkEventMask     event_mask);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_device_events (GdkSurface    *window,
-                                            GdkDevice    *device,
-                                            GdkEventMask  event_mask);
-GDK_AVAILABLE_IN_ALL
-GdkEventMask  gdk_surface_get_device_events (GdkSurface    *window,
-                                            GdkDevice    *device);
-
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_icon_list   (GdkSurface       *window,
-                                         GList           *surfaces);
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_set_icon_name  (GdkSurface      *window, 
-                                         const gchar     *name);
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_set_group      (GdkSurface      *window, 
-                                         GdkSurface      *leader);
-GDK_AVAILABLE_IN_ALL
-GdkSurface*    gdk_surface_get_group    (GdkSurface      *window);
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_set_decorations (GdkSurface     *window,
-                                         GdkWMDecoration  decorations);
-GDK_AVAILABLE_IN_ALL
-gboolean      gdk_surface_get_decorations (GdkSurface       *window,
-                                         GdkWMDecoration *decorations);
-GDK_AVAILABLE_IN_ALL
-void         gdk_surface_set_functions  (GdkSurface      *window,
-                                         GdkWMFunction    functions);
-
-GDK_AVAILABLE_IN_ALL
-cairo_surface_t *
-              gdk_surface_create_similar_surface (GdkSurface *window,
-                                          cairo_content_t  content,
-                                          int              width,
-                                          int              height);
-GDK_AVAILABLE_IN_ALL
-cairo_surface_t *
-              gdk_surface_create_similar_image_surface (GdkSurface *window,
-                                                      cairo_format_t format,
-                                                      int            width,
-                                                      int            height,
-                                                      int            scale);
-
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_beep            (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_iconify         (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_deiconify       (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_stick           (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_unstick         (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_maximize        (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_unmaximize      (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_fullscreen      (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_fullscreen_on_monitor (GdkSurface      *window,
-                                                GdkMonitor     *monitor);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_fullscreen_mode (GdkSurface   *window,
-                                          GdkFullscreenMode mode);
-GDK_AVAILABLE_IN_ALL
-GdkFullscreenMode
-              gdk_surface_get_fullscreen_mode (GdkSurface   *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_unfullscreen    (GdkSurface       *window);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_keep_above  (GdkSurface       *window,
-                                          gboolean         setting);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_keep_below  (GdkSurface       *window,
-                                          gboolean         setting);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_set_opacity     (GdkSurface       *window,
-                                          gdouble          opacity);
-GDK_AVAILABLE_IN_ALL
-void          gdk_surface_register_dnd    (GdkSurface       *window);
-
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_begin_resize_drag            (GdkSurface     *window,
-                                              GdkSurfaceEdge  edge,
-                                              gint           button,
-                                              gint           root_x,
-                                              gint           root_y,
-                                              guint32        timestamp);
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_begin_resize_drag_for_device (GdkSurface     *window,
-                                              GdkSurfaceEdge  edge,
-                                              GdkDevice     *device,
-                                              gint           button,
-                                              gint           root_x,
-                                              gint           root_y,
-                                              guint32        timestamp);
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_begin_move_drag              (GdkSurface     *window,
-                                              gint           button,
-                                              gint           root_x,
-                                              gint           root_y,
-                                              guint32        timestamp);
-GDK_AVAILABLE_IN_ALL
-void gdk_surface_begin_move_drag_for_device   (GdkSurface     *window,
-                                              GdkDevice     *device,
-                                              gint           button,
-                                              gint           root_x,
-                                              gint           root_y,
-                                              guint32        timestamp);
-
-/* Interface for dirty-region queueing */
-GDK_AVAILABLE_IN_ALL
-void       gdk_surface_invalidate_rect           (GdkSurface          *window,
-                                                const GdkRectangle *rect,
-                                                gboolean            invalidate_children);
-GDK_AVAILABLE_IN_ALL
-void       gdk_surface_invalidate_region         (GdkSurface          *window,
-                                                const cairo_region_t    *region,
-                                                gboolean            invalidate_children);
-
-/**
- * GdkSurfaceChildFunc:
- * @window: a #GdkSurface
- * @user_data: user data
- *
- * A function of this type is passed to gdk_surface_invalidate_maybe_recurse().
- * It gets called for each child of the window to determine whether to
- * recursively invalidate it or now.
- *
- * Returns: %TRUE to invalidate @window recursively
- */
-typedef gboolean (*GdkSurfaceChildFunc)          (GdkSurface *window,
-                                                 gpointer   user_data);
-
-GDK_AVAILABLE_IN_ALL
-void       gdk_surface_invalidate_maybe_recurse  (GdkSurface            *window,
-                                                const cairo_region_t *region,
-                                                GdkSurfaceChildFunc    child_func,
-                                                gpointer              user_data);
-GDK_AVAILABLE_IN_ALL
-cairo_region_t *gdk_surface_get_update_area      (GdkSurface            *window);
-
-GDK_AVAILABLE_IN_ALL
-void       gdk_surface_freeze_updates      (GdkSurface    *window);
-GDK_AVAILABLE_IN_ALL
-void       gdk_surface_thaw_updates        (GdkSurface    *window);
-
-GDK_AVAILABLE_IN_ALL
-void       gdk_surface_constrain_size      (GdkGeometry    *geometry,
-                                           GdkSurfaceHints  flags,
-                                           gint            width,
-                                           gint            height,
-                                           gint           *new_width,
-                                           gint           *new_height);
-
-/* Multidevice support */
-GDK_AVAILABLE_IN_ALL
-void       gdk_surface_set_support_multidevice (GdkSurface *window,
-                                               gboolean   support_multidevice);
-GDK_AVAILABLE_IN_ALL
-gboolean   gdk_surface_get_support_multidevice (GdkSurface *window);
-
-/* Frame clock */
-GDK_AVAILABLE_IN_ALL
-GdkFrameClock* gdk_surface_get_frame_clock      (GdkSurface     *window);
-
-GDK_AVAILABLE_IN_ALL
-void       gdk_surface_set_opaque_region        (GdkSurface      *window,
-                                                cairo_region_t *region);
-
-GDK_AVAILABLE_IN_ALL
-void       gdk_surface_set_shadow_width         (GdkSurface      *window,
-                                                gint            left,
-                                                gint            right,
-                                                gint            top,
-                                                gint            bottom);
-GDK_AVAILABLE_IN_ALL
-gboolean  gdk_surface_show_window_menu          (GdkSurface      *window,
-                                                GdkEvent       *event);
-
-GDK_AVAILABLE_IN_ALL
-GdkGLContext * gdk_surface_create_gl_context    (GdkSurface      *window,
-                                                GError        **error);
-GDK_AVAILABLE_IN_ALL
-GdkVulkanContext *
-               gdk_surface_create_vulkan_context(GdkSurface      *window,
-                                                GError        **error);
-
-G_END_DECLS
-
-#endif /* __GDK_SURFACE_H__ */
diff --git a/gdk/gdkwindowimpl.c b/gdk/gdkwindowimpl.c
deleted file mode 100644 (file)
index d182a40..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-/* 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-#include "config.h"
-
-#include "gdkwindowimpl.h"
-
-#include "gdkinternals.h"
-
-
-G_DEFINE_TYPE (GdkSurfaceImpl, gdk_surface_impl, G_TYPE_OBJECT);
-
-static gboolean
-gdk_surface_impl_beep (GdkSurface *window)
-{
-  /* FALSE means windows can't beep, so the display will be
-   * made to beep instead. */
-  return FALSE;
-}
-
-static GdkDisplay *
-get_display_for_window (GdkSurface *primary,
-                        GdkSurface *secondary)
-{
-  GdkDisplay *display = gdk_surface_get_display (primary);
-
-  if (display)
-    return display;
-
-  display = gdk_surface_get_display (secondary);
-
-  if (display)
-    return display;
-
-  g_warning ("no display for window, using default");
-  return gdk_display_get_default ();
-}
-
-static GdkMonitor *
-get_monitor_for_rect (GdkDisplay         *display,
-                      const GdkRectangle *rect)
-{
-  gint biggest_area = G_MININT;
-  GdkMonitor *best_monitor = NULL;
-  GdkMonitor *monitor;
-  GdkRectangle workarea;
-  GdkRectangle intersection;
-  gint x;
-  gint y;
-  gint i;
-
-  for (i = 0; i < gdk_display_get_n_monitors (display); i++)
-    {
-      monitor = gdk_display_get_monitor (display, i);
-      gdk_monitor_get_workarea (monitor, &workarea);
-
-      if (gdk_rectangle_intersect (&workarea, rect, &intersection))
-        {
-          if (intersection.width * intersection.height > biggest_area)
-            {
-              biggest_area = intersection.width * intersection.height;
-              best_monitor = monitor;
-            }
-        }
-    }
-
-  if (best_monitor)
-    return best_monitor;
-
-  x = rect->x + rect->width / 2;
-  y = rect->y + rect->height / 2;
-
-  return gdk_display_get_monitor_at_point (display, x, y);
-}
-
-static gint
-get_anchor_x_sign (GdkGravity anchor)
-{
-  switch (anchor)
-    {
-    case GDK_GRAVITY_STATIC:
-    case GDK_GRAVITY_NORTH_WEST:
-    case GDK_GRAVITY_WEST:
-    case GDK_GRAVITY_SOUTH_WEST:
-      return -1;
-
-    default:
-    case GDK_GRAVITY_NORTH:
-    case GDK_GRAVITY_CENTER:
-    case GDK_GRAVITY_SOUTH:
-      return 0;
-
-    case GDK_GRAVITY_NORTH_EAST:
-    case GDK_GRAVITY_EAST:
-    case GDK_GRAVITY_SOUTH_EAST:
-      return 1;
-    }
-}
-
-static gint
-get_anchor_y_sign (GdkGravity anchor)
-{
-  switch (anchor)
-    {
-    case GDK_GRAVITY_STATIC:
-    case GDK_GRAVITY_NORTH_WEST:
-    case GDK_GRAVITY_NORTH:
-    case GDK_GRAVITY_NORTH_EAST:
-      return -1;
-
-    default:
-    case GDK_GRAVITY_WEST:
-    case GDK_GRAVITY_CENTER:
-    case GDK_GRAVITY_EAST:
-      return 0;
-
-    case GDK_GRAVITY_SOUTH_WEST:
-    case GDK_GRAVITY_SOUTH:
-    case GDK_GRAVITY_SOUTH_EAST:
-      return 1;
-    }
-}
-
-static gint
-maybe_flip_position (gint      bounds_pos,
-                     gint      bounds_size,
-                     gint      rect_pos,
-                     gint      rect_size,
-                     gint      window_size,
-                     gint      rect_sign,
-                     gint      window_sign,
-                     gint      offset,
-                     gboolean  flip,
-                     gboolean *flipped)
-{
-  gint primary;
-  gint secondary;
-
-  *flipped = FALSE;
-  primary = rect_pos + (1 + rect_sign) * rect_size / 2 + offset - (1 + window_sign) * window_size / 2;
-
-  if (!flip || (primary >= bounds_pos && primary + window_size <= bounds_pos + bounds_size))
-    return primary;
-
-  *flipped = TRUE;
-  secondary = rect_pos + (1 - rect_sign) * rect_size / 2 - offset - (1 - window_sign) * window_size / 2;
-
-  if (secondary >= bounds_pos && secondary + window_size <= bounds_pos + bounds_size)
-    return secondary;
-
-  *flipped = FALSE;
-  return primary;
-}
-
-static GdkSurface *
-traverse_to_toplevel (GdkSurface *window,
-                      gint       x,
-                      gint       y,
-                      gint      *toplevel_x,
-                      gint      *toplevel_y)
-{
-  GdkSurface *parent;
-  gdouble xf = x;
-  gdouble yf = y;
-
-  while ((parent = window->parent) != NULL &&
-         (gdk_surface_get_window_type (parent) != GDK_SURFACE_ROOT))
-    {
-      gdk_surface_coords_to_parent (window, xf, yf, &xf, &yf);
-      window = parent;
-    }
-
-  *toplevel_x = (gint) xf;
-  *toplevel_y = (gint) yf;
-  return window;
-}
-
-static void
-gdk_surface_impl_move_to_rect (GdkSurface          *window,
-                              const GdkRectangle *rect,
-                              GdkGravity          rect_anchor,
-                              GdkGravity          window_anchor,
-                              GdkAnchorHints      anchor_hints,
-                              gint                rect_anchor_dx,
-                              gint                rect_anchor_dy)
-{
-  GdkSurface *transient_for_toplevel;
-  GdkDisplay *display;
-  GdkMonitor *monitor;
-  GdkRectangle bounds;
-  GdkRectangle root_rect = *rect;
-  GdkRectangle flipped_rect;
-  GdkRectangle final_rect;
-  gboolean flipped_x;
-  gboolean flipped_y;
-
-  /*
-   * First translate the anchor rect to toplevel coordinates. This is needed
-   * because not all backends will be able to get root coordinates for
-   * non-toplevel windows.
-   */
-  transient_for_toplevel = traverse_to_toplevel (window->transient_for,
-                                                 root_rect.x,
-                                                 root_rect.y,
-                                                 &root_rect.x,
-                                                 &root_rect.y);
-
-  gdk_surface_get_root_coords (transient_for_toplevel,
-                              root_rect.x,
-                              root_rect.y,
-                              &root_rect.x,
-                              &root_rect.y);
-
-  display = get_display_for_window (window, window->transient_for);
-  monitor = get_monitor_for_rect (display, &root_rect);
-  gdk_monitor_get_workarea (monitor, &bounds);
-
-  flipped_rect.width = window->width - window->shadow_left - window->shadow_right;
-  flipped_rect.height = window->height - window->shadow_top - window->shadow_bottom;
-  flipped_rect.x = maybe_flip_position (bounds.x,
-                                        bounds.width,
-                                        root_rect.x,
-                                        root_rect.width,
-                                        flipped_rect.width,
-                                        get_anchor_x_sign (rect_anchor),
-                                        get_anchor_x_sign (window_anchor),
-                                        rect_anchor_dx,
-                                        anchor_hints & GDK_ANCHOR_FLIP_X,
-                                        &flipped_x);
-  flipped_rect.y = maybe_flip_position (bounds.y,
-                                        bounds.height,
-                                        root_rect.y,
-                                        root_rect.height,
-                                        flipped_rect.height,
-                                        get_anchor_y_sign (rect_anchor),
-                                        get_anchor_y_sign (window_anchor),
-                                        rect_anchor_dy,
-                                        anchor_hints & GDK_ANCHOR_FLIP_Y,
-                                        &flipped_y);
-
-  final_rect = flipped_rect;
-
-  if (anchor_hints & GDK_ANCHOR_SLIDE_X)
-    {
-      if (final_rect.x + final_rect.width > bounds.x + bounds.width)
-        final_rect.x = bounds.x + bounds.width - final_rect.width;
-
-      if (final_rect.x < bounds.x)
-        final_rect.x = bounds.x;
-    }
-
-  if (anchor_hints & GDK_ANCHOR_SLIDE_Y)
-    {
-      if (final_rect.y + final_rect.height > bounds.y + bounds.height)
-        final_rect.y = bounds.y + bounds.height - final_rect.height;
-
-      if (final_rect.y < bounds.y)
-        final_rect.y = bounds.y;
-    }
-
-  if (anchor_hints & GDK_ANCHOR_RESIZE_X)
-    {
-      if (final_rect.x < bounds.x)
-        {
-          final_rect.width -= bounds.x - final_rect.x;
-          final_rect.x = bounds.x;
-        }
-
-      if (final_rect.x + final_rect.width > bounds.x + bounds.width)
-        final_rect.width = bounds.x + bounds.width - final_rect.x;
-    }
-
-  if (anchor_hints & GDK_ANCHOR_RESIZE_Y)
-    {
-      if (final_rect.y < bounds.y)
-        {
-          final_rect.height -= bounds.y - final_rect.y;
-          final_rect.y = bounds.y;
-        }
-
-      if (final_rect.y + final_rect.height > bounds.y + bounds.height)
-        final_rect.height = bounds.y + bounds.height - final_rect.y;
-    }
-
-  flipped_rect.x -= window->shadow_left;
-  flipped_rect.y -= window->shadow_top;
-  flipped_rect.width += window->shadow_left + window->shadow_right;
-  flipped_rect.height += window->shadow_top + window->shadow_bottom;
-
-  final_rect.x -= window->shadow_left;
-  final_rect.y -= window->shadow_top;
-  final_rect.width += window->shadow_left + window->shadow_right;
-  final_rect.height += window->shadow_top + window->shadow_bottom;
-
-  if (final_rect.width != window->width || final_rect.height != window->height)
-    gdk_surface_move_resize (window, final_rect.x, final_rect.y, final_rect.width, final_rect.height);
-  else
-    gdk_surface_move (window, final_rect.x, final_rect.y);
-
-  g_signal_emit_by_name (window,
-                         "moved-to-rect",
-                         &flipped_rect,
-                         &final_rect,
-                         flipped_x,
-                         flipped_y);
-}
-
-static void
-gdk_surface_impl_process_updates_recurse (GdkSurface      *window,
-                                         cairo_region_t *region)
-{
-  _gdk_surface_process_updates_recurse (window, region);
-}
-
-static void
-gdk_surface_impl_class_init (GdkSurfaceImplClass *impl_class)
-{
-  impl_class->beep = gdk_surface_impl_beep;
-  impl_class->move_to_rect = gdk_surface_impl_move_to_rect;
-  impl_class->process_updates_recurse = gdk_surface_impl_process_updates_recurse;
-}
-
-static void
-gdk_surface_impl_init (GdkSurfaceImpl *impl)
-{
-}
diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h
deleted file mode 100644 (file)
index 076feff..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/* 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-#ifndef __GDK_SURFACE_IMPL_H__
-#define __GDK_SURFACE_IMPL_H__
-
-#include <gdk/gdkwindow.h>
-#include <gdk/gdkproperty.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_SURFACE_IMPL           (gdk_surface_impl_get_type ())
-#define GDK_SURFACE_IMPL(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL, GdkSurfaceImpl))
-#define GDK_SURFACE_IMPL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL, GdkSurfaceImplClass))
-#define GDK_IS_SURFACE_IMPL(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL))
-#define GDK_IS_SURFACE_IMPL_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL))
-#define GDK_SURFACE_IMPL_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL, GdkSurfaceImplClass))
-
-typedef struct _GdkSurfaceImpl       GdkSurfaceImpl;
-typedef struct _GdkSurfaceImplClass  GdkSurfaceImplClass;
-
-struct _GdkSurfaceImpl
-{
-  GObject parent;
-};
-
-struct _GdkSurfaceImplClass
-{
-  GObjectClass parent_class;
-
-  cairo_surface_t *
-               (* ref_cairo_surface)    (GdkSurface       *window);
-  cairo_surface_t *
-               (* create_similar_image_surface) (GdkSurface *     window,
-                                                 cairo_format_t  format,
-                                                 int             width,
-                                                 int             height);
-
-  void         (* show)                 (GdkSurface       *window,
-                                        gboolean         already_mapped);
-  void         (* hide)                 (GdkSurface       *window);
-  void         (* withdraw)             (GdkSurface       *window);
-  void         (* raise)                (GdkSurface       *window);
-  void         (* lower)                (GdkSurface       *window);
-  void         (* restack_toplevel)     (GdkSurface       *window,
-                                        GdkSurface       *sibling,
-                                        gboolean        above);
-
-  void         (* move_resize)          (GdkSurface       *window,
-                                         gboolean         with_move,
-                                         gint             x,
-                                         gint             y,
-                                         gint             width,
-                                         gint             height);
-  void         (* move_to_rect)         (GdkSurface       *window,
-                                         const GdkRectangle *rect,
-                                         GdkGravity       rect_anchor,
-                                         GdkGravity       window_anchor,
-                                         GdkAnchorHints   anchor_hints,
-                                         gint             rect_anchor_dx,
-                                         gint             rect_anchor_dy);
-
-  GdkEventMask (* get_events)           (GdkSurface       *window);
-  void         (* set_events)           (GdkSurface       *window,
-                                         GdkEventMask     event_mask);
-
-  void         (* get_geometry)         (GdkSurface       *window,
-                                         gint            *x,
-                                         gint            *y,
-                                         gint            *width,
-                                         gint            *height);
-  void         (* get_root_coords)      (GdkSurface       *window,
-                                        gint             x,
-                                        gint             y,
-                                         gint            *root_x,
-                                         gint            *root_y);
-  gboolean     (* get_device_state)     (GdkSurface       *window,
-                                         GdkDevice       *device,
-                                         gdouble         *x,
-                                         gdouble         *y,
-                                         GdkModifierType *mask);
-  gboolean    (* begin_paint)           (GdkSurface       *window);
-  void        (* end_paint)             (GdkSurface       *window);
-
-  void         (* shape_combine_region) (GdkSurface       *window,
-                                         const cairo_region_t *shape_region,
-                                         gint             offset_x,
-                                         gint             offset_y);
-  void         (* input_shape_combine_region) (GdkSurface       *window,
-                                              const cairo_region_t *shape_region,
-                                              gint             offset_x,
-                                              gint             offset_y);
-
-  /* Called before processing updates for a window. This gives the windowing
-   * layer a chance to save the region for later use in avoiding duplicate
-   * exposes.
-   */
-  void     (* queue_antiexpose)     (GdkSurface       *window,
-                                     cairo_region_t  *update_area);
-
-/* Called to do the windowing system specific part of gdk_surface_destroy(),
- *
- * window: The window being destroyed
- * recursing: If TRUE, then this is being called because a parent
- *     was destroyed. This generally means that the call to the windowing
- *     system to destroy the window can be omitted, since it will be
- *     destroyed as a result of the parent being destroyed.
- *     Unless @foreign_destroy
- * foreign_destroy: If TRUE, the window or a parent was destroyed by some
- *     external agency. The window has already been destroyed and no
- *     windowing system calls should be made. (This may never happen
- *     for some windowing systems.)
- */
-  void         (* destroy)              (GdkSurface       *window,
-                                        gboolean         recursing,
-                                        gboolean         foreign_destroy);
-
-
-  /* optional */
-  gboolean     (* beep)                 (GdkSurface       *window);
-
-  void         (* focus)                (GdkSurface       *window,
-                                        guint32          timestamp);
-  void         (* set_type_hint)        (GdkSurface       *window,
-                                        GdkSurfaceTypeHint hint);
-  GdkSurfaceTypeHint (* get_type_hint)   (GdkSurface       *window);
-  void         (* set_modal_hint)       (GdkSurface *window,
-                                        gboolean   modal);
-  void         (* set_skip_taskbar_hint) (GdkSurface *window,
-                                         gboolean   skips_taskbar);
-  void         (* set_skip_pager_hint)  (GdkSurface *window,
-                                        gboolean   skips_pager);
-  void         (* set_urgency_hint)     (GdkSurface *window,
-                                        gboolean   urgent);
-  void         (* set_geometry_hints)   (GdkSurface         *window,
-                                        const GdkGeometry *geometry,
-                                        GdkSurfaceHints     geom_mask);
-  void         (* set_title)            (GdkSurface   *window,
-                                        const gchar *title);
-  void         (* set_role)             (GdkSurface   *window,
-                                        const gchar *role);
-  void         (* set_startup_id)       (GdkSurface   *window,
-                                        const gchar *startup_id);
-  void         (* set_transient_for)    (GdkSurface *window,
-                                        GdkSurface *parent);
-  void         (* get_frame_extents)    (GdkSurface    *window,
-                                        GdkRectangle *rect);
-  void         (* set_accept_focus)     (GdkSurface *window,
-                                        gboolean accept_focus);
-  void         (* set_focus_on_map)     (GdkSurface *window,
-                                        gboolean focus_on_map);
-  void         (* set_icon_list)        (GdkSurface *window,
-                                        GList     *pixbufs);
-  void         (* set_icon_name)        (GdkSurface   *window,
-                                        const gchar *name);
-  void         (* iconify)              (GdkSurface *window);
-  void         (* deiconify)            (GdkSurface *window);
-  void         (* stick)                (GdkSurface *window);
-  void         (* unstick)              (GdkSurface *window);
-  void         (* maximize)             (GdkSurface *window);
-  void         (* unmaximize)           (GdkSurface *window);
-  void         (* fullscreen)           (GdkSurface *window);
-  void         (* fullscreen_on_monitor) (GdkSurface  *window,
-                                          GdkMonitor *monitor);
-  void         (* apply_fullscreen_mode) (GdkSurface *window);
-  void         (* unfullscreen)         (GdkSurface *window);
-  void         (* set_keep_above)       (GdkSurface *window,
-                                        gboolean   setting);
-  void         (* set_keep_below)       (GdkSurface *window,
-                                        gboolean   setting);
-  GdkSurface *  (* get_group)            (GdkSurface *window);
-  void         (* set_group)            (GdkSurface *window,
-                                        GdkSurface *leader);
-  void         (* set_decorations)      (GdkSurface      *window,
-                                        GdkWMDecoration decorations);
-  gboolean     (* get_decorations)      (GdkSurface       *window,
-                                        GdkWMDecoration *decorations);
-  void         (* set_functions)        (GdkSurface    *window,
-                                        GdkWMFunction functions);
-  void         (* begin_resize_drag)    (GdkSurface     *window,
-                                         GdkSurfaceEdge  edge,
-                                         GdkDevice     *device,
-                                         gint           button,
-                                         gint           root_x,
-                                         gint           root_y,
-                                         guint32        timestamp);
-  void         (* begin_move_drag)      (GdkSurface *window,
-                                         GdkDevice     *device,
-                                         gint       button,
-                                         gint       root_x,
-                                         gint       root_y,
-                                         guint32    timestamp);
-  void         (* enable_synchronized_configure) (GdkSurface *window);
-  void         (* configure_finished)   (GdkSurface *window);
-  void         (* set_opacity)          (GdkSurface *window,
-                                        gdouble    opacity);
-  void         (* destroy_notify)       (GdkSurface *window);
-  void         (* register_dnd)         (GdkSurface *window);
-  GdkDragContext * (*drag_begin)        (GdkSurface        *window,
-                                         GdkDevice        *device,
-                                         GdkContentProvider*content,
-                                         GdkDragAction     actions,
-                                         gint              dx,
-                                         gint              dy);
-
-  void         (*process_updates_recurse) (GdkSurface      *window,
-                                           cairo_region_t *region);
-
-  gint         (* get_scale_factor)       (GdkSurface      *window);
-  void         (* get_unscaled_size)      (GdkSurface      *window,
-                                           int            *unscaled_width,
-                                           int            *unscaled_height);
-
-  void         (* set_opaque_region)      (GdkSurface      *window,
-                                           cairo_region_t *region);
-  void         (* set_shadow_width)       (GdkSurface      *window,
-                                           gint            left,
-                                           gint            right,
-                                           gint            top,
-                                           gint            bottom);
-  gboolean     (* show_window_menu)       (GdkSurface      *window,
-                                           GdkEvent       *event);
-  GdkGLContext *(*create_gl_context)      (GdkSurface      *window,
-                                          gboolean        attached,
-                                           GdkGLContext   *share,
-                                           GError        **error);
-  gboolean     (* supports_edge_constraints)(GdkSurface    *window);
-};
-
-/* Interface Functions */
-GType gdk_surface_impl_get_type (void) G_GNUC_CONST;
-
-G_END_DECLS
-
-#endif /* __GDK_SURFACE_IMPL_H__ */
index 8f69e1ca24e80112848998d390ca871ba134ec14..d562d6c84f0aada19abc70e128ba5919ad20307e 100644 (file)
@@ -42,8 +42,8 @@ gdk_public_sources = files([
   'gdksnapshot.c',
   'gdktexture.c',
   'gdkvulkancontext.c',
-  'gdkwindow.c',
-  'gdkwindowimpl.c',
+  'gdksurface.c',
+  'gdksurfaceimpl.c',
 ])
 
 gdk_public_headers = files([
@@ -86,7 +86,7 @@ gdk_public_headers = files([
   'gdktexture.h',
   'gdktypes.h',
   'gdkvulkancontext.h',
-  'gdkwindow.h',
+  'gdksurface.h',
 ])
 install_headers(gdk_public_headers, subdir: 'gtk-4.0/gdk/')
 
index bdb86011ab13e6fd4cf0c6021d966f919934c526..60067f5c7a8487849f7e21c4132a954bc50f5304 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "config.h"
 #import "GdkQuartzNSWindow.h"
-#include "gdkquartzwindow.h"
+#include "gdkquartzsurface.h"
 #include "gdkdnd-quartz.h"
 #include "gdkprivate-quartz.h"
 
index fc2f13458eb1f332727c2e5a46ef6226ba746cda..39d38214060cbc5a33518fa036b917375980a9e3 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "config.h"
 #import "GdkQuartzView.h"
-#include "gdkquartzwindow.h"
+#include "gdkquartzsurface.h"
 #include "gdkprivate-quartz.h"
 #include "gdkquartz.h"
 
index 9a2e270e08859627246550ea53bf17aec9302cd7..c42680e3ac6875b0934ea4d732d3c2d388fd55c2 100644 (file)
@@ -22,7 +22,7 @@
 #include <gdk/gdkdisplayprivate.h>
 
 #import "GdkQuartzView.h"
-#include "gdkquartzwindow.h"
+#include "gdkquartzsurface.h"
 #include "gdkquartzcursor.h"
 #include "gdkprivate-quartz.h"
 #include "gdkquartzdevice-core.h"
index 781437d1c040076f5632fe22a82dc75e44348c88..1bfb4459dd1abdb02a6f13c2ba39ea5fa0f68951 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "gdkprivate-quartz.h"
 #include "gdkquartzscreen.h"
-#include "gdkquartzwindow.h"
+#include "gdkquartzsurface.h"
 #include "gdkquartzdisplay.h"
 #include "gdkquartzdevicemanager-core.h"
 #include "gdkmonitorprivate.h"
index 10d249e5a30f01ee09fff8e26249ff1516165baa..4e25106879b437c162448163b81e3b5f6bc73b88 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "gdkdisplayprivate.h"
 #include "gdkkeys.h"
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkinternals.h"
 
 G_BEGIN_DECLS
index d1f520b9ccd657923192efc7865b4e3202e56797..c85f071c18271f77e6c663fc307e9411f0fddb4c 100644 (file)
@@ -624,7 +624,7 @@ find_toplevel_under_pointer (GdkDisplay *display,
        * under the pointer and we thus return NULL. This can occur when
        * toplevel under pointer has not yet been updated due to a very recent
        * window resize. Alternatively, we should no longer be relying on
-       * the toplevel_under_pointer value which is maintained in gdkwindow.c.
+       * the toplevel_under_pointer value which is maintained in gdksurface.c.
        */
       if (*x < 0 || *y < 0 || *x >= toplevel->width || *y >= toplevel->height)
         return NULL;
index 86946a1df81b4869e8f48aa519dc07d177bed50a..080316e5bc871aea48501a64e6db1831e3003116 100644 (file)
@@ -24,7 +24,7 @@
 #define __GDK_QUARTZ_GL_CONTEXT__
 
 #include "gdkglcontextprivate.h"
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkinternals.h"
 
 G_BEGIN_DECLS
index 48f5950d4c9651d665b3f249025198e181466a92..e65a5f227ff879c72da8ca7cfcf3785bc9a56886 100644 (file)
@@ -1,4 +1,4 @@
-/* gdkwindow-quartz.c
+/* gdksurface-quartz.c
  *
  * Copyright (C) 2005-2007 Imendio AB
  *
@@ -26,7 +26,7 @@
 #include <gdk/quartz/gdkdevicemanager-core-quartz.h>
 #include <gdk/quartz/gdkdnd-quartz.h>
 #include <gdk/quartz/gdkscreen-quartz.h>
-#include <gdk/quartz/gdkwindow-quartz.h>
+#include <gdk/quartz/gdksurface-quartz.h>
 
 #include <gdk/gdk.h>
 
index 0479c72303e95f34daf470755ffbbe3e6429c814..132245d09f780cca62433286a283d9036722a4a2 100644 (file)
@@ -80,7 +80,7 @@ G_END_DECLS
 #include <gdk/quartz/gdkquartzmonitor.h>
 #include <gdk/quartz/gdkquartzscreen.h>
 #include <gdk/quartz/gdkquartzutils.h>
-#include <gdk/quartz/gdkquartzwindow.h>
+#include <gdk/quartz/gdkquartzsurface.h>
 
 #undef __GDKQUARTZ_H_INSIDE__
 
diff --git a/gdk/quartz/gdkquartzsurface.h b/gdk/quartz/gdkquartzsurface.h
new file mode 100644 (file)
index 0000000..a37cb37
--- /dev/null
@@ -0,0 +1,55 @@
+/* gdkquartzsurface.h
+ *
+ * Copyright (C) 2005  Imendio AB
+ * Copyright (C) 2010  Kristian Rietveld  <kris@gtk.org>
+ *
+ * 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_QUARTZ_SURFACE_H__
+#define __GDK_QUARTZ_SURFACE_H__
+
+#if !defined (__GDKQUARTZ_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdkquartz.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_QUARTZ_SURFACE              (gdk_quartz_surface_get_type ())
+#define GDK_QUARTZ_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurface))
+#define GDK_QUARTZ_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurfaceClass))
+#define GDK_IS_QUARTZ_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_SURFACE))
+#define GDK_IS_QUARTZ_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_SURFACE))
+#define GDK_QUARTZ_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurfaceClass))
+
+#ifdef GDK_COMPILATION
+typedef struct _GdkQuartzSurface GdkQuartzSurface;
+#else
+typedef GdkSurface GdkQuartzSurface;
+#endif
+typedef struct _GdkQuartzSurfaceClass GdkQuartzSurfaceClass;
+
+GDK_AVAILABLE_IN_ALL
+GType     gdk_quartz_surface_get_type     (void);
+
+GDK_AVAILABLE_IN_ALL
+NSWindow *gdk_quartz_surface_get_nswindow (GdkSurface *window);
+GDK_AVAILABLE_IN_ALL
+NSView   *gdk_quartz_surface_get_nsview   (GdkSurface *window);
+
+G_END_DECLS
+
+#endif /* __GDK_QUARTZ_SURFACE_H__ */
diff --git a/gdk/quartz/gdkquartzwindow.h b/gdk/quartz/gdkquartzwindow.h
deleted file mode 100644 (file)
index 56ff424..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* gdkquartzwindow.h
- *
- * Copyright (C) 2005  Imendio AB
- * Copyright (C) 2010  Kristian Rietveld  <kris@gtk.org>
- *
- * 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_QUARTZ_SURFACE_H__
-#define __GDK_QUARTZ_SURFACE_H__
-
-#if !defined (__GDKQUARTZ_H_INSIDE__) && !defined (GDK_COMPILATION)
-#error "Only <gdk/gdkquartz.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_QUARTZ_SURFACE              (gdk_quartz_surface_get_type ())
-#define GDK_QUARTZ_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurface))
-#define GDK_QUARTZ_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurfaceClass))
-#define GDK_IS_QUARTZ_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_SURFACE))
-#define GDK_IS_QUARTZ_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_SURFACE))
-#define GDK_QUARTZ_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurfaceClass))
-
-#ifdef GDK_COMPILATION
-typedef struct _GdkQuartzSurface GdkQuartzSurface;
-#else
-typedef GdkSurface GdkQuartzSurface;
-#endif
-typedef struct _GdkQuartzSurfaceClass GdkQuartzSurfaceClass;
-
-GDK_AVAILABLE_IN_ALL
-GType     gdk_quartz_surface_get_type     (void);
-
-GDK_AVAILABLE_IN_ALL
-NSWindow *gdk_quartz_surface_get_nswindow (GdkSurface *window);
-GDK_AVAILABLE_IN_ALL
-NSView   *gdk_quartz_surface_get_nsview   (GdkSurface *window);
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_SURFACE_H__ */
index e9d2d6b0945ac05e71e27e104b3d37ee441663da..f8094354a094afd6fae9951e2c28bc8da6478220 100644 (file)
@@ -55,7 +55,7 @@
  * coordinate space.  Such coordinates are mapped to their respective
  * position in the GdkScreen root window (_gdk_quartz_surface_xy_to_gdk_xy)
  * and vice versa (_gdk_quartz_surface_gdk_xy_to_xy).  Both functions can
- * be found in gdkwindow-quartz.c.  Note that Cocoa coordinates can have
+ * be found in gdksurface-quartz.c.  Note that Cocoa coordinates can have
  * negative values (in case a monitor is located left or below of screen 0),
  * but GDK coordinates can *not*!
  */
diff --git a/gdk/quartz/gdksurface-quartz.c b/gdk/quartz/gdksurface-quartz.c
new file mode 100644 (file)
index 0000000..f3676ce
--- /dev/null
@@ -0,0 +1,2958 @@
+/* gdksurface-quartz.c
+ *
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 2005-2007 Imendio AB
+ *
+ * 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 <gdk/gdk.h>
+#include <gdk/gdkdeviceprivate.h>
+#include <gdk/gdkdisplayprivate.h>
+
+#include "gdksurfaceimpl.h"
+#include "gdkprivate-quartz.h"
+#include "gdkglcontext-quartz.h"
+#include "gdkquartzscreen.h"
+#include "gdkquartzcursor.h"
+
+#include <Carbon/Carbon.h>
+#include <AvailabilityMacros.h>
+
+#include <sys/time.h>
+#include <cairo-quartz.h>
+
+static gpointer parent_class;
+static gpointer root_window_parent_class;
+
+static GSList   *update_nswindows;
+static gboolean  in_process_all_updates = FALSE;
+
+static GSList *main_window_stack;
+
+void _gdk_quartz_surface_flush (GdkSurfaceImplQuartz *window_impl);
+
+typedef struct
+{
+  gint            x, y;
+  gint            width, height;
+  GdkWMDecoration decor;
+} FullscreenSavedGeometry;
+
+
+#ifndef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
+static FullscreenSavedGeometry *get_fullscreen_geometry (GdkSurface *window);
+#endif
+
+#define FULLSCREEN_DATA "fullscreen-data"
+
+static void update_toplevel_order (void);
+static void clear_toplevel_order  (void);
+
+#define WINDOW_IS_TOPLEVEL(window)      (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD)
+
+/*
+ * GdkQuartzSurface
+ */
+
+struct _GdkQuartzSurface
+{
+  GdkSurface parent;
+};
+
+struct _GdkQuartzSurfaceClass
+{
+  GdkSurfaceClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkQuartzSurface, gdk_quartz_surface, GDK_TYPE_SURFACE);
+
+static void
+gdk_quartz_surface_class_init (GdkQuartzSurfaceClass *quartz_surface_class)
+{
+}
+
+static void
+gdk_quartz_surface_init (GdkQuartzSurface *quartz_surface)
+{
+}
+
+
+/*
+ * GdkQuartzSurfaceImpl
+ */
+
+NSView *
+gdk_quartz_surface_get_nsview (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window))
+    return NULL;
+
+  return ((GdkSurfaceImplQuartz *)window->impl)->view;
+}
+
+NSWindow *
+gdk_quartz_surface_get_nswindow (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window))
+    return NULL;
+
+  return ((GdkSurfaceImplQuartz *)window->impl)->toplevel;
+}
+
+static CGContextRef
+gdk_surface_impl_quartz_get_context (GdkSurfaceImplQuartz *window_impl,
+                                   gboolean             antialias)
+{
+  CGContextRef cg_context;
+  CGSize scale;
+
+  if (GDK_SURFACE_DESTROYED (window_impl->wrapper))
+    return NULL;
+
+  /* Lock focus when not called as part of a drawRect call. This
+   * is needed when called from outside "real" expose events, for
+   * example for synthesized expose events when realizing windows
+   * and for widgets that send fake expose events like the arrow
+   * buttons in spinbuttons or the position marker in rulers.
+   */
+  if (window_impl->in_paint_rect_count == 0)
+    {
+      if (![window_impl->view lockFocusIfCanDraw])
+        return NULL;
+    }
+
+  cg_context = [[NSGraphicsContext currentContext] graphicsPort];
+  CGContextSaveGState (cg_context);
+  CGContextSetAllowsAntialiasing (cg_context, antialias);
+
+  /* Undo the default scaling transform, since we apply our own
+   * in gdk_quartz_ref_cairo_surface () */
+  scale = CGContextConvertSizeToDeviceSpace (cg_context,
+                                             CGSizeMake (1.0, 1.0));
+  CGContextScaleCTM (cg_context, 1.0 / scale.width, 1.0 / scale.height);
+
+  return cg_context;
+}
+
+static void
+gdk_surface_impl_quartz_release_context (GdkSurfaceImplQuartz *window_impl,
+                                        CGContextRef         cg_context)
+{
+  CGContextRestoreGState (cg_context);
+  CGContextSetAllowsAntialiasing (cg_context, TRUE);
+
+  /* See comment in gdk_quartz_surface_get_context(). */
+  if (window_impl->in_paint_rect_count == 0)
+    {
+      _gdk_quartz_surface_flush (window_impl);
+      [window_impl->view unlockFocus];
+    }
+}
+
+static void
+check_grab_destroy (GdkSurface *window)
+{
+  GList *devices = NULL, *l;
+  GdkDisplay *display = gdk_surface_get_display (window);
+  GdkSeat *seat;
+
+  seat = gdk_display_get_default_seat (display);
+
+  devices = g_list_prepend (devices, gdk_seat_get_keyboard (seat));
+  devices = g_list_prepend (devices, gdk_seat_get_pointer (seat));
+
+  for (l = devices; l; l = l->next)
+    {
+      GdkDeviceGrabInfo *grab;
+
+      grab = _gdk_display_get_last_device_grab (display, l->data);
+      if (grab && grab->native_window == window)
+        {
+          /* Serials are always 0 in quartz, but for clarity: */
+          grab->serial_end = grab->serial_start;
+          grab->implicit_ungrab = TRUE;
+        }
+    }
+
+  g_list_free (devices);
+}
+
+static void
+gdk_surface_impl_quartz_finalize (GObject *object)
+{
+  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (object);
+
+  check_grab_destroy (GDK_SURFACE_IMPL_QUARTZ (object)->wrapper);
+
+  if (impl->transient_for)
+    g_object_unref (impl->transient_for);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/* Help preventing "beam sync penalty" where CG makes all graphics code
+ * block until the next vsync if we try to flush (including call display on
+ * a view) too often. We do this by limiting the manual flushing done
+ * outside of expose calls to less than some frequency when measured over
+ * the last 4 flushes. This is a bit arbitray, but seems to make it possible
+ * for some quick manual flushes (such as gtkruler or gimp’s marching ants)
+ * without hitting the max flush frequency.
+ *
+ * If drawable NULL, no flushing is done, only registering that a flush was
+ * done externally.
+ */
+void
+_gdk_quartz_surface_flush (GdkSurfaceImplQuartz *window_impl)
+{
+  static struct timeval prev_tv;
+  static gint intervals[4];
+  static gint index;
+  struct timeval tv;
+  gint ms;
+
+  gettimeofday (&tv, NULL);
+  ms = (tv.tv_sec - prev_tv.tv_sec) * 1000 + (tv.tv_usec - prev_tv.tv_usec) / 1000;
+  intervals[index++ % 4] = ms;
+
+  if (window_impl)
+    {
+      ms = intervals[0] + intervals[1] + intervals[2] + intervals[3];
+
+      /* ~25Hz on average. */
+      if (ms > 4*40)
+        {
+          if (window_impl)
+            [window_impl->toplevel flushWindow];
+
+          prev_tv = tv;
+        }
+    }
+  else
+    prev_tv = tv;
+}
+
+static cairo_user_data_key_t gdk_quartz_cairo_key;
+
+typedef struct {
+  GdkSurfaceImplQuartz  *window_impl;
+  CGContextRef  cg_context;
+} GdkQuartzCairoSurfaceData;
+
+static void
+gdk_quartz_cairo_surface_destroy (void *data)
+{
+  GdkQuartzCairoSurfaceData *surface_data = data;
+
+  surface_data->window_impl->cairo_surface = NULL;
+
+  gdk_quartz_surface_release_context (surface_data->window_impl,
+                                     surface_data->cg_context);
+
+  g_free (surface_data);
+}
+
+static cairo_surface_t *
+gdk_quartz_create_cairo_surface (GdkSurfaceImplQuartz *impl,
+                                int                  width,
+                                int                  height)
+{
+  CGContextRef cg_context;
+  GdkQuartzCairoSurfaceData *surface_data;
+  cairo_surface_t *surface;
+
+  cg_context = gdk_quartz_surface_get_context (impl, TRUE);
+
+  if (!cg_context)
+    return NULL;
+
+  surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
+  surface_data->window_impl = impl;
+  surface_data->cg_context = cg_context;
+
+  surface = cairo_quartz_surface_create_for_cg_context (cg_context,
+                                                        width, height);
+
+  cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
+                               surface_data,
+                               gdk_quartz_cairo_surface_destroy);
+
+  return surface;
+}
+
+static cairo_surface_t *
+gdk_quartz_ref_cairo_surface (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return NULL;
+
+  if (!impl->cairo_surface)
+    {
+      gint scale = gdk_surface_get_scale_factor (impl->wrapper);
+
+      impl->cairo_surface = 
+          gdk_quartz_create_cairo_surface (impl,
+                                           gdk_surface_get_width (impl->wrapper) * scale,
+                                           gdk_surface_get_height (impl->wrapper) * scale);
+
+      cairo_surface_set_device_scale (impl->cairo_surface, scale, scale);
+    }
+  else
+    cairo_surface_reference (impl->cairo_surface);
+
+  return impl->cairo_surface;
+}
+
+static void
+gdk_surface_impl_quartz_init (GdkSurfaceImplQuartz *impl)
+{
+  impl->type_hint = GDK_SURFACE_TYPE_HINT_NORMAL;
+}
+
+static gboolean
+gdk_surface_impl_quartz_begin_paint (GdkSurface *window)
+{
+  return FALSE;
+}
+
+static void
+gdk_quartz_surface_set_needs_display_in_region (GdkSurface    *window,
+                                               cairo_region_t    *region)
+{
+  GdkSurfaceImplQuartz *impl;
+  int i, n_rects;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (!impl->needs_display_region)
+    impl->needs_display_region = cairo_region_create ();
+
+  cairo_region_union (impl->needs_display_region, region);
+
+  n_rects = cairo_region_num_rectangles (region);
+  for (i = 0; i < n_rects; i++)
+    {
+      cairo_rectangle_int_t rect;
+      cairo_region_get_rectangle (region, i, &rect);
+      [impl->view setNeedsDisplayInRect:NSMakeRect (rect.x, rect.y,
+                                                    rect.width, rect.height)];
+    }
+}
+
+void
+_gdk_quartz_surface_process_updates_recurse (GdkSurface *window,
+                                            cairo_region_t *region)
+{
+  /* Make sure to only flush each toplevel at most once if we're called
+   * from process_all_updates.
+   */
+  if (in_process_all_updates)
+    {
+      GdkSurface *toplevel;
+
+      toplevel = gdk_surface_get_toplevel (window);
+      if (toplevel && WINDOW_IS_TOPLEVEL (toplevel))
+        {
+          GdkSurfaceImplQuartz *toplevel_impl;
+          NSWindow *nswindow;
+
+          toplevel_impl = (GdkSurfaceImplQuartz *)toplevel->impl;
+          nswindow = toplevel_impl->toplevel;
+
+          /* In theory, we could skip the flush disabling, since we only
+           * have one NSView.
+           */
+          if (nswindow && ![nswindow isFlushWindowDisabled]) 
+            {
+              [nswindow retain];
+              [nswindow disableFlushWindow];
+              update_nswindows = g_slist_prepend (update_nswindows, nswindow);
+            }
+        }
+    }
+
+  if (WINDOW_IS_TOPLEVEL (window))
+    gdk_quartz_surface_set_needs_display_in_region (window, region);
+  else
+    _gdk_surface_process_updates_recurse (window, region);
+
+  /* NOTE: I'm not sure if we should displayIfNeeded here. It slows down a
+   * lot (since it triggers the beam syncing) and things seem to work
+   * without it.
+   */
+}
+
+static const gchar *
+get_default_title (void)
+{
+  const char *title;
+
+  title = g_get_application_name ();
+  if (!title)
+    title = g_get_prgname ();
+
+  return title;
+}
+
+static void
+get_ancestor_coordinates_from_child (GdkSurface *child_window,
+                                    gint       child_x,
+                                    gint       child_y,
+                                    GdkSurface *ancestor_window, 
+                                    gint      *ancestor_x, 
+                                    gint      *ancestor_y)
+{
+  while (child_window != ancestor_window)
+    {
+      child_x += child_window->x;
+      child_y += child_window->y;
+
+      child_window = child_window->parent;
+    }
+
+  *ancestor_x = child_x;
+  *ancestor_y = child_y;
+}
+
+void
+_gdk_quartz_surface_debug_highlight (GdkSurface *window, gint number)
+{
+  gint x, y;
+  gint gx, gy;
+  GdkSurface *toplevel;
+  gint tx, ty;
+  static NSWindow *debug_window[10];
+  static NSRect old_rect[10];
+  NSRect rect;
+  NSColor *color;
+
+  g_return_if_fail (number >= 0 && number <= 9);
+
+  if (window == _gdk_root)
+    return;
+
+  if (window == NULL)
+    {
+      if (debug_window[number])
+        [debug_window[number] close];
+      debug_window[number] = NULL;
+
+      return;
+    }
+
+  toplevel = gdk_surface_get_toplevel (window);
+  get_ancestor_coordinates_from_child (window, 0, 0, toplevel, &x, &y);
+
+  gdk_surface_get_origin (toplevel, &tx, &ty);
+  x += tx;
+  y += ty;
+
+  _gdk_quartz_surface_gdk_xy_to_xy (x, y + window->height,
+                                   &gx, &gy);
+
+  rect = NSMakeRect (gx, gy, window->width, window->height);
+
+  if (debug_window[number] && NSEqualRects (rect, old_rect[number]))
+    return;
+
+  old_rect[number] = rect;
+
+  if (debug_window[number])
+    [debug_window[number] close];
+
+  debug_window[number] = [[NSWindow alloc] initWithContentRect:rect
+                                                     styleMask:NSBorderlessWindowMask
+                                                      backing:NSBackingStoreBuffered
+                                                        defer:NO];
+
+  switch (number)
+    {
+    case 0:
+      color = [NSColor redColor];
+      break;
+    case 1:
+      color = [NSColor blueColor];
+      break;
+    case 2:
+      color = [NSColor greenColor];
+      break;
+    case 3:
+      color = [NSColor yellowColor];
+      break;
+    case 4:
+      color = [NSColor brownColor];
+      break;
+    case 5:
+      color = [NSColor purpleColor];
+      break;
+    default:
+      color = [NSColor blackColor];
+      break;
+    }
+
+  [debug_window[number] setBackgroundColor:color];
+  [debug_window[number] setAlphaValue:0.4];
+  [debug_window[number] setOpaque:NO];
+  [debug_window[number] setReleasedWhenClosed:YES];
+  [debug_window[number] setIgnoresMouseEvents:YES];
+  [debug_window[number] setLevel:NSFloatingWindowLevel];
+
+  [debug_window[number] orderFront:nil];
+}
+
+gboolean
+_gdk_quartz_surface_is_ancestor (GdkSurface *ancestor,
+                                GdkSurface *window)
+{
+  if (ancestor == NULL || window == NULL)
+    return FALSE;
+
+  return (gdk_surface_get_parent (window) == ancestor ||
+          _gdk_quartz_surface_is_ancestor (ancestor, 
+                                          gdk_surface_get_parent (window)));
+}
+
+
+/* See notes on top of gdkscreen-quartz.c */
+void
+_gdk_quartz_surface_gdk_xy_to_xy (gint  gdk_x,
+                                 gint  gdk_y,
+                                 gint *ns_x,
+                                 gint *ns_y)
+{
+  GdkQuartzScreen *screen_quartz = GDK_QUARTZ_SCREEN (_gdk_screen);
+
+  if (ns_y)
+    *ns_y = screen_quartz->height - gdk_y + screen_quartz->min_y;
+
+  if (ns_x)
+    *ns_x = gdk_x + screen_quartz->min_x;
+}
+
+void
+_gdk_quartz_surface_xy_to_gdk_xy (gint  ns_x,
+                                 gint  ns_y,
+                                 gint *gdk_x,
+                                 gint *gdk_y)
+{
+  GdkQuartzScreen *screen_quartz = GDK_QUARTZ_SCREEN (_gdk_screen);
+
+  if (gdk_y)
+    *gdk_y = screen_quartz->height - ns_y + screen_quartz->min_y;
+
+  if (gdk_x)
+    *gdk_x = ns_x - screen_quartz->min_x;
+}
+
+void
+_gdk_quartz_surface_nspoint_to_gdk_xy (NSPoint  point,
+                                      gint    *x,
+                                      gint    *y)
+{
+  _gdk_quartz_surface_xy_to_gdk_xy (point.x, point.y,
+                                   x, y);
+}
+
+static GdkSurface *
+find_child_window_helper (GdkSurface *window,
+                         gint       x,
+                         gint       y,
+                         gint       x_offset,
+                         gint       y_offset,
+                          gboolean   get_toplevel)
+{
+  GdkSurfaceImplQuartz *impl;
+  GList *l;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (window == _gdk_root)
+    update_toplevel_order ();
+
+  for (l = impl->sorted_children; l; l = l->next)
+    {
+      GdkSurface *child = l->data;
+      GdkSurfaceImplQuartz *child_impl = GDK_SURFACE_IMPL_QUARTZ (child->impl);
+      int temp_x, temp_y;
+
+      if (!GDK_SURFACE_IS_MAPPED (child))
+       continue;
+
+      temp_x = x_offset + child->x;
+      temp_y = y_offset + child->y;
+
+      /* Special-case the root window. We have to include the title
+       * bar in the checks, otherwise the window below the title bar
+       * will be found i.e. events punch through. (If we can find a
+       * better way to deal with the events in gdkevents-quartz, this
+       * might not be needed.)
+       */
+      if (window == _gdk_root)
+        {
+          NSRect frame = NSMakeRect (0, 0, 100, 100);
+          NSRect content;
+          NSUInteger mask;
+          int titlebar_height;
+
+          mask = [child_impl->toplevel styleMask];
+
+          /* Get the title bar height. */
+          content = [NSWindow contentRectForFrameRect:frame
+                                            styleMask:mask];
+          titlebar_height = frame.size.height - content.size.height;
+
+          if (titlebar_height > 0 &&
+              x >= temp_x && y >= temp_y - titlebar_height &&
+              x < temp_x + child->width && y < temp_y)
+            {
+              /* The root means "unknown" i.e. a window not managed by
+               * GDK.
+               */
+              return (GdkSurface *)_gdk_root;
+            }
+        }
+
+      if ((!get_toplevel || (get_toplevel && window == _gdk_root)) &&
+          x >= temp_x && y >= temp_y &&
+         x < temp_x + child->width && y < temp_y + child->height)
+       {
+         /* Look for child windows. */
+         return find_child_window_helper (l->data,
+                                          x, y,
+                                          temp_x, temp_y,
+                                           get_toplevel);
+       }
+    }
+  
+  return window;
+}
+
+/* Given a GdkSurface and coordinates relative to it, returns the
+ * innermost subwindow that contains the point. If the coordinates are
+ * outside the passed in window, NULL is returned.
+ */
+GdkSurface *
+_gdk_quartz_surface_find_child (GdkSurface *window,
+                              gint       x,
+                              gint       y,
+                               gboolean   get_toplevel)
+{
+  if (x >= 0 && y >= 0 && x < window->width && y < window->height)
+    return find_child_window_helper (window, x, y, 0, 0, get_toplevel);
+
+  return NULL;
+}
+
+
+void
+_gdk_quartz_surface_did_become_main (GdkSurface *window)
+{
+  main_window_stack = g_slist_remove (main_window_stack, window);
+
+  if (window->window_type != GDK_SURFACE_TEMP)
+    main_window_stack = g_slist_prepend (main_window_stack, window);
+
+  clear_toplevel_order ();
+}
+
+void
+_gdk_quartz_surface_did_resign_main (GdkSurface *window)
+{
+  GdkSurface *new_window = NULL;
+
+  if (main_window_stack)
+    new_window = main_window_stack->data;
+  else
+    {
+      GList *toplevels;
+
+      toplevels = get_toplevels ();
+      if (toplevels)
+        new_window = toplevels->data;
+    }
+
+  if (new_window &&
+      new_window != window &&
+      GDK_SURFACE_IS_MAPPED (new_window) &&
+      WINDOW_IS_TOPLEVEL (new_window))
+    {
+      GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (new_window->impl);
+
+      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
+    }
+
+  clear_toplevel_order ();
+}
+
+static NSScreen *
+get_nsscreen_for_point (gint x, gint y)
+{
+  int i;
+  NSArray *screens;
+  NSScreen *screen = NULL;
+
+  GDK_QUARTZ_ALLOC_POOL;
+
+  screens = [NSScreen screens];
+
+  for (i = 0; i < [screens count]; i++)
+    {
+      NSRect rect = [[screens objectAtIndex:i] frame];
+
+      if (x >= rect.origin.x && x <= rect.origin.x + rect.size.width &&
+          y >= rect.origin.y && y <= rect.origin.y + rect.size.height)
+        {
+          screen = [screens objectAtIndex:i];
+          break;
+        }
+    }
+
+  GDK_QUARTZ_RELEASE_POOL;
+
+  return screen;
+}
+
+void
+_gdk_quartz_display_create_window_impl (GdkDisplay    *display,
+                                        GdkSurface     *window,
+                                        GdkSurface     *real_parent,
+                                        GdkEventMask   event_mask,
+                                        GdkSurfaceAttr *attributes)
+{
+  GdkSurfaceImplQuartz *impl;
+  GdkSurfaceImplQuartz *parent_impl;
+
+  GDK_QUARTZ_ALLOC_POOL;
+
+  impl = g_object_new (GDK_TYPE_SURFACE_IMPL_QUARTZ, NULL);
+  window->impl = GDK_SURFACE_IMPL (impl);
+  impl->wrapper = window;
+
+  parent_impl = GDK_SURFACE_IMPL_QUARTZ (window->parent->impl);
+
+  switch (window->window_type)
+    {
+    case GDK_SURFACE_TOPLEVEL:
+    case GDK_SURFACE_TEMP:
+      if (GDK_SURFACE_TYPE (window->parent) != GDK_SURFACE_ROOT)
+       {
+         /* The common code warns for this case */
+          parent_impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
+       }
+    }
+
+  /* Maintain the z-ordered list of children. */
+  if (window->parent != _gdk_root)
+    parent_impl->sorted_children = g_list_prepend (parent_impl->sorted_children, window);
+  else
+    clear_toplevel_order ();
+
+  impl->view = NULL;
+
+  switch (window->window_type)
+    {
+    case GDK_SURFACE_TOPLEVEL:
+    case GDK_SURFACE_TEMP:
+      {
+        NSScreen *screen;
+        NSRect screen_rect;
+        NSRect content_rect;
+        NSUInteger style_mask;
+        int nx, ny;
+
+        /* initWithContentRect will place on the mainScreen by default.
+         * We want to select the screen to place on ourselves.  We need
+         * to find the screen the window will be on and correct the
+         * content_rect coordinates to be relative to that screen.
+         */
+        _gdk_quartz_surface_gdk_xy_to_xy (window->x, window->y, &nx, &ny);
+
+        screen = get_nsscreen_for_point (nx, ny);
+        screen_rect = [screen frame];
+        nx -= screen_rect.origin.x;
+        ny -= screen_rect.origin.y;
+
+        content_rect = NSMakeRect (nx, ny - window->height,
+                                   window->width,
+                                   window->height);
+
+        if (window->window_type == GDK_SURFACE_TEMP)
+          {
+            style_mask = NSBorderlessWindowMask;
+          }
+        else
+          {
+            style_mask = (NSTitledWindowMask |
+                          NSClosableWindowMask |
+                          NSMiniaturizableWindowMask |
+                          NSResizableWindowMask);
+          }
+
+       impl->toplevel = [[GdkQuartzNSWindow alloc] initWithContentRect:content_rect 
+                                                             styleMask:style_mask
+                                                               backing:NSBackingStoreBuffered
+                                                                 defer:NO
+                                                                  screen:screen];
+
+       gdk_surface_set_title (window, get_default_title ());
+  
+        [impl->toplevel setOpaque:NO];
+        [impl->toplevel setBackgroundColor:[NSColor clearColor]];
+
+        content_rect.origin.x = 0;
+        content_rect.origin.y = 0;
+
+       impl->view = [[GdkQuartzView alloc] initWithFrame:content_rect];
+       [impl->view setGdkSurface:window];
+       [impl->toplevel setContentView:impl->view];
+       [impl->view release];
+      }
+      break;
+
+    case GDK_SURFACE_CHILD:
+      {
+       GdkSurfaceImplQuartz *parent_impl = GDK_SURFACE_IMPL_QUARTZ (window->parent->impl);
+
+       if (!window->input_only)
+         {
+           NSRect frame_rect = NSMakeRect (window->x + window->parent->abs_x,
+                                            window->y + window->parent->abs_y,
+                                            window->width,
+                                            window->height);
+       
+           impl->view = [[GdkQuartzView alloc] initWithFrame:frame_rect];
+           
+           [impl->view setGdkSurface:window];
+
+           /* GdkSurfaces should be hidden by default */
+           [impl->view setHidden:YES];
+           [parent_impl->view addSubview:impl->view];
+           [impl->view release];
+         }
+      }
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  GDK_QUARTZ_RELEASE_POOL;
+}
+
+void
+_gdk_quartz_surface_update_position (GdkSurface *window)
+{
+  NSRect frame_rect;
+  NSRect content_rect;
+  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  GDK_QUARTZ_ALLOC_POOL;
+
+  frame_rect = [impl->toplevel frame];
+  content_rect = [impl->toplevel contentRectForFrameRect:frame_rect];
+
+  _gdk_quartz_surface_xy_to_gdk_xy (content_rect.origin.x,
+                                   content_rect.origin.y + content_rect.size.height,
+                                   &window->x, &window->y);
+
+
+  GDK_QUARTZ_RELEASE_POOL;
+}
+
+void
+_gdk_quartz_surface_init_windowing (GdkDisplay *display)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  g_assert (_gdk_root == NULL);
+
+  _gdk_root = _gdk_display_create_window (display);
+
+  _gdk_root->impl = g_object_new (_gdk_root_window_impl_quartz_get_type (), NULL);
+  _gdk_root->impl_window = _gdk_root;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
+
+  _gdk_quartz_screen_update_window_sizes (screen);
+
+  _gdk_root->state = 0; /* We don't want GDK_SURFACE_STATE_WITHDRAWN here */
+  _gdk_root->window_type = GDK_SURFACE_ROOT;
+  _gdk_root->viewable = TRUE;
+
+  impl->wrapper = _gdk_root;
+}
+
+static void
+gdk_quartz_surface_destroy (GdkSurface *window,
+                           gboolean   recursing,
+                           gboolean   foreign_destroy)
+{
+  GdkSurfaceImplQuartz *impl;
+  GdkSurface *parent;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  main_window_stack = g_slist_remove (main_window_stack, window);
+
+  g_list_free (impl->sorted_children);
+  impl->sorted_children = NULL;
+
+  parent = window->parent;
+  if (parent)
+    {
+      GdkSurfaceImplQuartz *parent_impl = GDK_SURFACE_IMPL_QUARTZ (parent->impl);
+
+      parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window);
+    }
+
+  if (impl->cairo_surface)
+    {
+      cairo_surface_finish (impl->cairo_surface);
+      cairo_surface_set_user_data (impl->cairo_surface, &gdk_quartz_cairo_key,
+                                  NULL, NULL);
+      impl->cairo_surface = NULL;
+    }
+
+  if (!recursing && !foreign_destroy)
+    {
+      GDK_QUARTZ_ALLOC_POOL;
+
+      if (impl->toplevel)
+       [impl->toplevel close];
+      else if (impl->view)
+       [impl->view removeFromSuperview];
+
+      GDK_QUARTZ_RELEASE_POOL;
+    }
+}
+
+/* FIXME: This might be possible to simplify with client-side windows. Also
+ * note that already_mapped is not used yet, see the x11 backend.
+*/
+static void
+gdk_surface_quartz_show (GdkSurface *window, gboolean already_mapped)
+{
+  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  gboolean focus_on_map;
+
+  GDK_QUARTZ_ALLOC_POOL;
+
+  if (!GDK_SURFACE_IS_MAPPED (window))
+    focus_on_map = window->focus_on_map;
+  else
+    focus_on_map = TRUE;
+
+  if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel)
+    {
+      gboolean make_key;
+
+      make_key = (window->accept_focus && focus_on_map &&
+                  window->window_type != GDK_SURFACE_TEMP);
+
+      [(GdkQuartzNSWindow*)impl->toplevel showAndMakeKey:make_key];
+      clear_toplevel_order ();
+
+      _gdk_quartz_events_send_map_event (window);
+    }
+  else
+    {
+      [impl->view setHidden:NO];
+    }
+
+  [impl->view setNeedsDisplay:YES];
+
+  gdk_synthesize_window_state (window, GDK_SURFACE_STATE_WITHDRAWN, 0);
+
+  if (window->state & GDK_SURFACE_STATE_MAXIMIZED)
+    gdk_surface_maximize (window);
+
+  if (window->state & GDK_SURFACE_STATE_ICONIFIED)
+    gdk_surface_iconify (window);
+
+  if (impl->transient_for && !GDK_SURFACE_DESTROYED (impl->transient_for))
+    _gdk_quartz_surface_attach_to_parent (window);
+
+  GDK_QUARTZ_RELEASE_POOL;
+}
+
+/* Temporarily unsets the parent window, if the window is a
+ * transient. 
+ */
+void
+_gdk_quartz_surface_detach_from_parent (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  
+  g_return_if_fail (impl->toplevel != NULL);
+
+  if (impl->transient_for && !GDK_SURFACE_DESTROYED (impl->transient_for))
+    {
+      GdkSurfaceImplQuartz *parent_impl;
+
+      parent_impl = GDK_SURFACE_IMPL_QUARTZ (impl->transient_for->impl);
+      [parent_impl->toplevel removeChildWindow:impl->toplevel];
+      clear_toplevel_order ();
+    }
+}
+
+/* Re-sets the parent window, if the window is a transient. */
+void
+_gdk_quartz_surface_attach_to_parent (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  
+  g_return_if_fail (impl->toplevel != NULL);
+
+  if (impl->transient_for && !GDK_SURFACE_DESTROYED (impl->transient_for))
+    {
+      GdkSurfaceImplQuartz *parent_impl;
+
+      parent_impl = GDK_SURFACE_IMPL_QUARTZ (impl->transient_for->impl);
+      [parent_impl->toplevel addChildWindow:impl->toplevel ordered:NSWindowAbove];
+      clear_toplevel_order ();
+    }
+}
+
+void
+gdk_surface_quartz_hide (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  /* Make sure we're not stuck in fullscreen mode. */
+#ifndef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
+  if (get_fullscreen_geometry (window))
+    SetSystemUIMode (kUIModeNormal, 0);
+#endif
+
+  _gdk_surface_clear_update_area (window);
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (WINDOW_IS_TOPLEVEL (window)) 
+    {
+     /* Update main window. */
+      main_window_stack = g_slist_remove (main_window_stack, window);
+      if ([NSApp mainWindow] == impl->toplevel)
+        _gdk_quartz_surface_did_resign_main (window);
+
+      if (impl->transient_for)
+        _gdk_quartz_surface_detach_from_parent (window);
+
+      [(GdkQuartzNSWindow*)impl->toplevel hide];
+    }
+  else if (impl->view)
+    {
+      [impl->view setHidden:YES];
+    }
+}
+
+void
+gdk_surface_quartz_withdraw (GdkSurface *window)
+{
+  gdk_surface_hide (window);
+}
+
+static void
+move_resize_window_internal (GdkSurface *window,
+                            gint       x,
+                            gint       y,
+                            gint       width,
+                            gint       height)
+{
+  GdkSurfaceImplQuartz *impl;
+  GdkRectangle old_visible;
+  GdkRectangle new_visible;
+  GdkRectangle scroll_rect;
+  cairo_region_t *old_region;
+  cairo_region_t *expose_region;
+  NSSize delta;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if ((x == -1 || (x == window->x)) &&
+      (y == -1 || (y == window->y)) &&
+      (width == -1 || (width == window->width)) &&
+      (height == -1 || (height == window->height)))
+    {
+      return;
+    }
+
+  if (!impl->toplevel)
+    {
+      /* The previously visible area of this window in a coordinate
+       * system rooted at the origin of this window.
+       */
+      old_visible.x = -window->x;
+      old_visible.y = -window->y;
+
+      old_visible.width = window->width;
+      old_visible.height = window->height;
+    }
+
+  if (x != -1)
+    {
+      delta.width = x - window->x;
+      window->x = x;
+    }
+  else
+    {
+      delta.width = 0;
+    }
+
+  if (y != -1)
+    {
+      delta.height = y - window->y;
+      window->y = y;
+    }
+  else
+    {
+      delta.height = 0;
+    }
+
+  if (width != -1)
+    window->width = width;
+
+  if (height != -1)
+    window->height = height;
+
+  GDK_QUARTZ_ALLOC_POOL;
+
+  if (impl->toplevel)
+    {
+      NSRect content_rect;
+      NSRect frame_rect;
+      gint gx, gy;
+
+      _gdk_quartz_surface_gdk_xy_to_xy (window->x, window->y + window->height,
+                                       &gx, &gy);
+
+      content_rect = NSMakeRect (gx, gy, window->width, window->height);
+
+      frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
+      [impl->toplevel setFrame:frame_rect display:YES];
+    }
+  else 
+    {
+      if (!window->input_only)
+        {
+          NSRect nsrect;
+
+          nsrect = NSMakeRect (window->x, window->y, window->width, window->height);
+
+          /* The newly visible area of this window in a coordinate
+           * system rooted at the origin of this window.
+           */
+          new_visible.x = -window->x;
+          new_visible.y = -window->y;
+          new_visible.width = old_visible.width;   /* parent has not changed size */
+          new_visible.height = old_visible.height; /* parent has not changed size */
+
+          expose_region = cairo_region_create_rectangle (&new_visible);
+          old_region = cairo_region_create_rectangle (&old_visible);
+          cairo_region_subtract (expose_region, old_region);
+
+          /* Determine what (if any) part of the previously visible
+           * part of the window can be copied without a redraw
+           */
+          scroll_rect = old_visible;
+          scroll_rect.x -= delta.width;
+          scroll_rect.y -= delta.height;
+          gdk_rectangle_intersect (&scroll_rect, &old_visible, &scroll_rect);
+
+          if (!cairo_region_is_empty (expose_region))
+            {
+              if (scroll_rect.width != 0 && scroll_rect.height != 0)
+                {
+                  [impl->view scrollRect:NSMakeRect (scroll_rect.x,
+                                                     scroll_rect.y,
+                                                     scroll_rect.width,
+                                                     scroll_rect.height)
+                                     by:delta];
+                }
+
+              [impl->view setFrame:nsrect];
+
+              gdk_quartz_surface_set_needs_display_in_region (window, expose_region);
+            }
+          else
+            {
+              [impl->view setFrame:nsrect];
+              [impl->view setNeedsDisplay:YES];
+            }
+
+          cairo_region_destroy (expose_region);
+          cairo_region_destroy (old_region);
+        }
+    }
+
+  GDK_QUARTZ_RELEASE_POOL;
+}
+
+static inline void
+window_quartz_move (GdkSurface *window,
+                    gint       x,
+                    gint       y)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
+    return;
+
+  move_resize_window_internal (window, x, y, -1, -1);
+}
+
+static inline void
+window_quartz_resize (GdkSurface *window,
+                      gint       width,
+                      gint       height)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
+    return;
+
+  if (width < 1)
+    width = 1;
+  if (height < 1)
+    height = 1;
+
+  move_resize_window_internal (window, -1, -1, width, height);
+}
+
+static inline void
+window_quartz_move_resize (GdkSurface *window,
+                           gint       x,
+                           gint       y,
+                           gint       width,
+                           gint       height)
+{
+  if (width < 1)
+    width = 1;
+  if (height < 1)
+    height = 1;
+
+  move_resize_window_internal (window, x, y, width, height);
+}
+
+static void
+gdk_surface_quartz_move_resize (GdkSurface *window,
+                               gboolean   with_move,
+                               gint       x,
+                               gint       y,
+                               gint       width,
+                               gint       height)
+{
+  if (with_move && (width < 0 && height < 0))
+    window_quartz_move (window, x, y);
+  else
+    {
+      if (with_move)
+        window_quartz_move_resize (window, x, y, width, height);
+      else
+        window_quartz_resize (window, width, height);
+    }
+}
+
+/* Get the toplevel ordering from NSApp and update our own list. We do
+ * this on demand since the NSApp’s list is not up to date directly
+ * after we get windowDidBecomeMain.
+ */
+static void
+update_toplevel_order (void)
+{
+  GdkSurfaceImplQuartz *root_impl;
+  NSEnumerator *enumerator;
+  id nswindow;
+  GList *toplevels = NULL;
+
+  root_impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
+
+  if (root_impl->sorted_children)
+    return;
+
+  GDK_QUARTZ_ALLOC_POOL;
+
+  enumerator = [[NSApp orderedWindows] objectEnumerator];
+  while ((nswindow = [enumerator nextObject]))
+    {
+      GdkSurface *window;
+
+      if (![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
+        continue;
+
+      window = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
+      toplevels = g_list_prepend (toplevels, window);
+    }
+
+  GDK_QUARTZ_RELEASE_POOL;
+
+  root_impl->sorted_children = g_list_reverse (toplevels);
+}
+
+static void
+clear_toplevel_order (void)
+{
+  GdkSurfaceImplQuartz *root_impl;
+
+  root_impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
+
+  g_list_free (root_impl->sorted_children);
+  root_impl->sorted_children = NULL;
+}
+
+static void
+gdk_surface_quartz_raise (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (WINDOW_IS_TOPLEVEL (window))
+    {
+      GdkSurfaceImplQuartz *impl;
+
+      impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+      [impl->toplevel orderFront:impl->toplevel];
+
+      clear_toplevel_order ();
+    }
+  else
+    {
+      GdkSurface *parent = window->parent;
+
+      if (parent)
+        {
+          GdkSurfaceImplQuartz *impl;
+
+          impl = (GdkSurfaceImplQuartz *)parent->impl;
+
+          impl->sorted_children = g_list_remove (impl->sorted_children, window);
+          impl->sorted_children = g_list_prepend (impl->sorted_children, window);
+        }
+    }
+}
+
+static void
+gdk_surface_quartz_lower (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (WINDOW_IS_TOPLEVEL (window))
+    {
+      GdkSurfaceImplQuartz *impl;
+
+      impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+      [impl->toplevel orderBack:impl->toplevel];
+
+      clear_toplevel_order ();
+    }
+  else
+    {
+      GdkSurface *parent = window->parent;
+
+      if (parent)
+        {
+          GdkSurfaceImplQuartz *impl;
+
+          impl = (GdkSurfaceImplQuartz *)parent->impl;
+
+          impl->sorted_children = g_list_remove (impl->sorted_children, window);
+          impl->sorted_children = g_list_append (impl->sorted_children, window);
+        }
+    }
+}
+
+static void
+gdk_surface_quartz_restack_toplevel (GdkSurface *window,
+                                   GdkSurface *sibling,
+                                   gboolean   above)
+{
+  GdkSurfaceImplQuartz *impl;
+  gint sibling_num;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (sibling->impl);
+  sibling_num = [impl->toplevel windowNumber];
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (above)
+    [impl->toplevel orderWindow:NSWindowAbove relativeTo:sibling_num];
+  else
+    [impl->toplevel orderWindow:NSWindowBelow relativeTo:sibling_num];
+}
+
+static void
+gdk_surface_quartz_get_geometry (GdkSurface *window,
+                                gint      *x,
+                                gint      *y,
+                                gint      *width,
+                                gint      *height)
+{
+  GdkSurfaceImplQuartz *impl;
+  NSRect ns_rect;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  if (window == _gdk_root)
+    {
+      if (x) 
+        *x = 0;
+      if (y) 
+        *y = 0;
+
+      if (width) 
+        *width = window->width;
+      if (height)
+        *height = window->height;
+    }
+  else if (WINDOW_IS_TOPLEVEL (window))
+    {
+      ns_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
+
+      /* This doesn't work exactly as in X. There doesn't seem to be a
+       * way to get the coords relative to the parent window (usually
+       * the window frame), but that seems useless except for
+       * borderless windows where it's relative to the root window. So
+       * we return (0, 0) (should be something like (0, 22)) for
+       * windows with borders and the root relative coordinates
+       * otherwise.
+       */
+      if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
+        {
+          _gdk_quartz_surface_xy_to_gdk_xy (ns_rect.origin.x,
+                                           ns_rect.origin.y + ns_rect.size.height,
+                                           x, y);
+        }
+      else 
+        {
+          if (x)
+            *x = 0;
+          if (y)
+            *y = 0;
+        }
+
+      if (width)
+        *width = ns_rect.size.width;
+      if (height)
+        *height = ns_rect.size.height;
+    }
+  else
+    {
+      ns_rect = [impl->view frame];
+      
+      if (x)
+        *x = ns_rect.origin.x;
+      if (y)
+        *y = ns_rect.origin.y;
+      if (width)
+        *width  = ns_rect.size.width;
+      if (height)
+        *height = ns_rect.size.height;
+    }
+}
+
+static void
+gdk_surface_quartz_get_root_coords (GdkSurface *window,
+                                   gint       x,
+                                   gint       y,
+                                   gint      *root_x,
+                                   gint      *root_y)
+{
+  int tmp_x = 0, tmp_y = 0;
+  GdkSurface *toplevel;
+  NSRect content_rect;
+  GdkSurfaceImplQuartz *impl;
+
+  if (GDK_SURFACE_DESTROYED (window)) 
+    {
+      if (root_x)
+       *root_x = 0;
+      if (root_y)
+       *root_y = 0;
+      
+      return;
+    }
+
+  if (window == _gdk_root)
+    {
+      if (root_x)
+        *root_x = x;
+      if (root_y)
+        *root_y = y;
+
+      return;
+    }
+  
+  toplevel = gdk_surface_get_toplevel (window);
+  impl = GDK_SURFACE_IMPL_QUARTZ (toplevel->impl);
+
+  content_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
+
+  _gdk_quartz_surface_xy_to_gdk_xy (content_rect.origin.x,
+                                   content_rect.origin.y + content_rect.size.height,
+                                   &tmp_x, &tmp_y);
+
+  tmp_x += x;
+  tmp_y += y;
+
+  while (window != toplevel)
+    {
+      if (_gdk_surface_has_impl ((GdkSurface *)window))
+        {
+          tmp_x += window->x;
+          tmp_y += window->y;
+        }
+
+      window = window->parent;
+    }
+
+  if (root_x)
+    *root_x = tmp_x;
+  if (root_y)
+    *root_y = tmp_y;
+}
+
+/* Returns coordinates relative to the passed in window. */
+static GdkSurface *
+gdk_surface_quartz_get_device_state_helper (GdkSurface       *window,
+                                           GdkDevice       *device,
+                                           gdouble         *x,
+                                           gdouble         *y,
+                                           GdkModifierType *mask)
+{
+  NSPoint point;
+  gint x_tmp, y_tmp;
+  GdkSurface *toplevel;
+  GdkSurface *found_window;
+
+  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), NULL);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    {
+      *x = 0;
+      *y = 0;
+      *mask = 0;
+      return NULL;
+    }
+  
+  toplevel = gdk_surface_get_toplevel (window);
+
+  *mask = _gdk_quartz_events_get_current_keyboard_modifiers () |
+      _gdk_quartz_events_get_current_mouse_modifiers ();
+
+  /* Get the y coordinate, needs to be flipped. */
+  if (window == _gdk_root)
+    {
+      point = [NSEvent mouseLocation];
+      _gdk_quartz_surface_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
+    }
+  else
+    {
+      GdkSurfaceImplQuartz *impl;
+      NSWindow *nswindow;
+
+      impl = GDK_SURFACE_IMPL_QUARTZ (toplevel->impl);
+      nswindow = impl->toplevel;
+
+      point = [nswindow mouseLocationOutsideOfEventStream];
+
+      x_tmp = point.x;
+      y_tmp = toplevel->height - point.y;
+
+      window = (GdkSurface *)toplevel;
+    }
+
+  found_window = _gdk_quartz_surface_find_child (window, x_tmp, y_tmp,
+                                                FALSE);
+
+  /* We never return the root window. */
+  if (found_window == _gdk_root)
+    found_window = NULL;
+
+  *x = x_tmp;
+  *y = y_tmp;
+
+  return found_window;
+}
+
+static gboolean
+gdk_surface_quartz_get_device_state (GdkSurface       *window,
+                                    GdkDevice       *device,
+                                    gdouble          *x,
+                                    gdouble          *y,
+                                    GdkModifierType *mask)
+{
+  return gdk_surface_quartz_get_device_state_helper (window,
+                                                    device,
+                                                    x, y, mask) != NULL;
+}
+
+static GdkEventMask
+gdk_surface_quartz_get_events (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window))
+    return 0;
+  else
+    return window->event_mask;
+}
+
+static void
+gdk_surface_quartz_set_events (GdkSurface       *window,
+                              GdkEventMask     event_mask)
+{
+  /* The mask is set in the common code. */
+}
+
+static void
+gdk_quartz_surface_set_urgency_hint (GdkSurface *window,
+                                    gboolean   urgent)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  /* FIXME: Implement */
+}
+
+static void
+gdk_quartz_surface_set_geometry_hints (GdkSurface         *window,
+                                      const GdkGeometry *geometry,
+                                      GdkSurfaceHints     geom_mask)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  g_return_if_fail (geometry != NULL);
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+  
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  if (!impl->toplevel)
+    return;
+
+  if (geom_mask & GDK_HINT_POS)
+    {
+      /* FIXME: Implement */
+    }
+
+  if (geom_mask & GDK_HINT_USER_POS)
+    {
+      /* FIXME: Implement */
+    }
+
+  if (geom_mask & GDK_HINT_USER_SIZE)
+    {
+      /* FIXME: Implement */
+    }
+  
+  if (geom_mask & GDK_HINT_MIN_SIZE)
+    {
+      NSSize size;
+
+      size.width = geometry->min_width;
+      size.height = geometry->min_height;
+
+      [impl->toplevel setContentMinSize:size];
+    }
+  
+  if (geom_mask & GDK_HINT_MAX_SIZE)
+    {
+      NSSize size;
+
+      size.width = geometry->max_width;
+      size.height = geometry->max_height;
+
+      [impl->toplevel setContentMaxSize:size];
+    }
+  
+  if (geom_mask & GDK_HINT_BASE_SIZE)
+    {
+      /* FIXME: Implement */
+    }
+  
+  if (geom_mask & GDK_HINT_RESIZE_INC)
+    {
+      NSSize size;
+
+      size.width = geometry->width_inc;
+      size.height = geometry->height_inc;
+
+      [impl->toplevel setContentResizeIncrements:size];
+    }
+  
+  if (geom_mask & GDK_HINT_ASPECT)
+    {
+      NSSize size;
+
+      if (geometry->min_aspect != geometry->max_aspect)
+        {
+          g_warning ("Only equal minimum and maximum aspect ratios are supported on Mac OS. Using minimum aspect ratio...");
+        }
+
+      size.width = geometry->min_aspect;
+      size.height = 1.0;
+
+      [impl->toplevel setContentAspectRatio:size];
+    }
+
+  if (geom_mask & GDK_HINT_WIN_GRAVITY)
+    {
+      /* FIXME: Implement */
+    }
+}
+
+static void
+gdk_quartz_surface_set_title (GdkSurface   *window,
+                             const gchar *title)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  g_return_if_fail (title != NULL);
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (impl->toplevel)
+    {
+      GDK_QUARTZ_ALLOC_POOL;
+      [impl->toplevel setTitle:[NSString stringWithUTF8String:title]];
+      GDK_QUARTZ_RELEASE_POOL;
+    }
+}
+
+static void
+gdk_quartz_surface_set_role (GdkSurface   *window,
+                            const gchar *role)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  /* FIXME: Implement */
+}
+
+static void
+gdk_quartz_surface_set_startup_id (GdkSurface   *window,
+                                  const gchar *startup_id)
+{
+  /* FIXME: Implement? */
+}
+
+static void
+gdk_quartz_surface_set_transient_for (GdkSurface *window,
+                                     GdkSurface *parent)
+{
+  GdkSurfaceImplQuartz *window_impl;
+  GdkSurfaceImplQuartz *parent_impl;
+
+  if (GDK_SURFACE_DESTROYED (window)  || GDK_SURFACE_DESTROYED (parent) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  window_impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  if (!window_impl->toplevel)
+    return;
+
+  GDK_QUARTZ_ALLOC_POOL;
+
+  if (window_impl->transient_for)
+    {
+      _gdk_quartz_surface_detach_from_parent (window);
+
+      g_object_unref (window_impl->transient_for);
+      window_impl->transient_for = NULL;
+    }
+
+  parent_impl = GDK_SURFACE_IMPL_QUARTZ (parent->impl);
+  if (parent_impl->toplevel)
+    {
+      /* We save the parent because it needs to be unset/reset when
+       * hiding and showing the window. 
+       */
+
+      /* We don't set transients for tooltips, they are already
+       * handled by the window level being the top one. If we do, then
+       * the parent window will be brought to the top just because the
+       * tooltip is, which is not what we want.
+       */
+      if (gdk_surface_get_type_hint (window) != GDK_SURFACE_TYPE_HINT_TOOLTIP)
+        {
+          window_impl->transient_for = g_object_ref (parent);
+
+          /* We only add the window if it is shown, otherwise it will
+           * be shown unconditionally here. If it is not shown, the
+           * window will be added in show() instead.
+           */
+          if (!(window->state & GDK_SURFACE_STATE_WITHDRAWN))
+            _gdk_quartz_surface_attach_to_parent (window);
+        }
+    }
+  
+  GDK_QUARTZ_RELEASE_POOL;
+}
+
+static void
+gdk_surface_quartz_shape_combine_region (GdkSurface       *window,
+                                        const cairo_region_t *shape,
+                                        gint             x,
+                                        gint             y)
+{
+  /* FIXME: Implement */
+}
+
+static void
+gdk_surface_quartz_input_shape_combine_region (GdkSurface       *window,
+                                              const cairo_region_t *shape_region,
+                                              gint             offset_x,
+                                              gint             offset_y)
+{
+  /* FIXME: Implement */
+}
+
+static void
+gdk_quartz_surface_set_accept_focus (GdkSurface *window,
+                                    gboolean accept_focus)
+{
+  window->accept_focus = accept_focus != FALSE;
+}
+
+static void
+gdk_quartz_surface_set_focus_on_map (GdkSurface *window,
+                                    gboolean focus_on_map)
+{
+  window->focus_on_map = focus_on_map != FALSE;
+}
+
+static void
+gdk_quartz_surface_set_icon_name (GdkSurface   *window,
+                                 const gchar *name)
+{
+  /* FIXME: Implement */
+}
+
+static void
+gdk_quartz_surface_focus (GdkSurface *window,
+                         guint32    timestamp)
+{
+  GdkSurfaceImplQuartz *impl;
+       
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  if (window->accept_focus && window->window_type != GDK_SURFACE_TEMP)
+    {
+      GDK_QUARTZ_ALLOC_POOL;
+      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
+      clear_toplevel_order ();
+      GDK_QUARTZ_RELEASE_POOL;
+    }
+}
+
+static gint
+window_type_hint_to_level (GdkSurfaceTypeHint hint)
+{
+  /*  the order in this switch statement corresponds to the actual
+   *  stacking order: the first group is top, the last group is bottom
+   */
+  switch (hint)
+    {
+    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
+    case GDK_SURFACE_TYPE_HINT_COMBO:
+    case GDK_SURFACE_TYPE_HINT_DND:
+    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
+      return NSPopUpMenuWindowLevel;
+
+    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
+    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
+      return NSStatusWindowLevel;
+
+    case GDK_SURFACE_TYPE_HINT_MENU: /* Torn-off menu */
+    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
+      return NSTornOffMenuWindowLevel;
+
+    case GDK_SURFACE_TYPE_HINT_DOCK:
+      return NSFloatingWindowLevel; /* NSDockWindowLevel is deprecated, and not replaced */
+
+    case GDK_SURFACE_TYPE_HINT_UTILITY:
+    case GDK_SURFACE_TYPE_HINT_DIALOG:  /* Dialog window */
+    case GDK_SURFACE_TYPE_HINT_NORMAL:  /* Normal toplevel window */
+    case GDK_SURFACE_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
+      return NSNormalWindowLevel;
+
+    case GDK_SURFACE_TYPE_HINT_DESKTOP:
+      return kCGDesktopWindowLevelKey; /* doesn't map to any real Cocoa model */
+
+    default:
+      break;
+    }
+
+  return NSNormalWindowLevel;
+}
+
+static gboolean
+window_type_hint_to_shadow (GdkSurfaceTypeHint hint)
+{
+  switch (hint)
+    {
+    case GDK_SURFACE_TYPE_HINT_NORMAL:  /* Normal toplevel window */
+    case GDK_SURFACE_TYPE_HINT_DIALOG:  /* Dialog window */
+    case GDK_SURFACE_TYPE_HINT_DOCK:
+    case GDK_SURFACE_TYPE_HINT_UTILITY:
+    case GDK_SURFACE_TYPE_HINT_MENU: /* Torn-off menu */
+    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
+    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
+    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
+    case GDK_SURFACE_TYPE_HINT_COMBO:
+    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
+    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
+      return TRUE;
+
+    case GDK_SURFACE_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
+    case GDK_SURFACE_TYPE_HINT_DESKTOP: /* N/A */
+    case GDK_SURFACE_TYPE_HINT_DND:
+      break;
+
+    default:
+      break;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+window_type_hint_to_hides_on_deactivate (GdkSurfaceTypeHint hint)
+{
+  switch (hint)
+    {
+    case GDK_SURFACE_TYPE_HINT_UTILITY:
+    case GDK_SURFACE_TYPE_HINT_MENU: /* Torn-off menu */
+    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
+    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
+    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
+      return TRUE;
+
+    default:
+      break;
+    }
+
+  return FALSE;
+}
+
+static void
+_gdk_quartz_surface_update_has_shadow (GdkSurfaceImplQuartz *impl)
+{
+    gboolean has_shadow;
+
+    /* In case there is any shadow set we have to turn off the
+     * NSWindow setHasShadow as the system drawn ones wont match our
+     * window boundary anymore */
+    has_shadow = (window_type_hint_to_shadow (impl->type_hint) && !impl->shadow_max);
+
+    [impl->toplevel setHasShadow: has_shadow];
+}
+
+static void
+gdk_quartz_surface_set_type_hint (GdkSurface        *window,
+                                 GdkSurfaceTypeHint hint)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  impl->type_hint = hint;
+
+  /* Match the documentation, only do something if we're not mapped yet. */
+  if (GDK_SURFACE_IS_MAPPED (window))
+    return;
+
+  _gdk_quartz_surface_update_has_shadow (impl);
+  [impl->toplevel setLevel: window_type_hint_to_level (hint)];
+  [impl->toplevel setHidesOnDeactivate: window_type_hint_to_hides_on_deactivate (hint)];
+}
+
+static GdkSurfaceTypeHint
+gdk_quartz_surface_get_type_hint (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return GDK_SURFACE_TYPE_HINT_NORMAL;
+  
+  return GDK_SURFACE_IMPL_QUARTZ (window->impl)->type_hint;
+}
+
+static void
+gdk_quartz_surface_set_modal_hint (GdkSurface *window,
+                                  gboolean   modal)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  /* FIXME: Implement */
+}
+
+static void
+gdk_quartz_surface_set_skip_taskbar_hint (GdkSurface *window,
+                                         gboolean   skips_taskbar)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  /* FIXME: Implement */
+}
+
+static void
+gdk_quartz_surface_set_skip_pager_hint (GdkSurface *window,
+                                       gboolean   skips_pager)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  /* FIXME: Implement */
+}
+
+static void
+gdk_quartz_surface_begin_resize_drag (GdkSurface     *window,
+                                     GdkSurfaceEdge  edge,
+                                     GdkDevice     *device,
+                                     gint           button,
+                                     gint           root_x,
+                                     gint           root_y,
+                                     guint32        timestamp)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (!impl->toplevel)
+    {
+      g_warning ("Can't call gdk_surface_begin_resize_drag on non-toplevel window");
+      return;
+    }
+
+  [(GdkQuartzNSWindow *)impl->toplevel beginManualResize:edge];
+}
+
+static void
+gdk_quartz_surface_begin_move_drag (GdkSurface *window,
+                                   GdkDevice *device,
+                                   gint       button,
+                                   gint       root_x,
+                                   gint       root_y,
+                                   guint32    timestamp)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (!impl->toplevel)
+    {
+      g_warning ("Can't call gdk_surface_begin_move_drag on non-toplevel window");
+      return;
+    }
+
+  [(GdkQuartzNSWindow *)impl->toplevel beginManualMove];
+}
+
+static void
+gdk_quartz_surface_set_icon_list (GdkSurface *window,
+                                 GList     *surfaces)
+{
+  /* FIXME: Implement */
+}
+
+static void
+gdk_quartz_surface_get_frame_extents (GdkSurface    *window,
+                                     GdkRectangle *rect)
+{
+  GdkSurface *toplevel;
+  GdkSurfaceImplQuartz *impl;
+  NSRect ns_rect;
+
+  g_return_if_fail (rect != NULL);
+
+
+  rect->x = 0;
+  rect->y = 0;
+  rect->width = 1;
+  rect->height = 1;
+  
+  toplevel = gdk_surface_get_toplevel (window);
+  impl = GDK_SURFACE_IMPL_QUARTZ (toplevel->impl);
+
+  ns_rect = [impl->toplevel frame];
+
+  _gdk_quartz_surface_xy_to_gdk_xy (ns_rect.origin.x,
+                                   ns_rect.origin.y + ns_rect.size.height,
+                                   &rect->x, &rect->y);
+
+  rect->width = ns_rect.size.width;
+  rect->height = ns_rect.size.height;
+}
+
+/* Fake protocol to make gcc think that it's OK to call setStyleMask
+   even if it isn't. We check to make sure before actually calling
+   it. */
+
+@protocol CanSetStyleMask
+- (void)setStyleMask:(int)mask;
+@end
+
+static void
+gdk_quartz_surface_set_decorations (GdkSurface       *window,
+                           GdkWMDecoration  decorations)
+{
+  GdkSurfaceImplQuartz *impl;
+  NSUInteger old_mask, new_mask;
+  NSView *old_view;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (decorations == 0 || GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP ||
+      impl->type_hint == GDK_SURFACE_TYPE_HINT_SPLASHSCREEN )
+    {
+      new_mask = NSBorderlessWindowMask;
+    }
+  else
+    {
+      /* FIXME: Honor other GDK_DECOR_* flags. */
+      new_mask = (NSTitledWindowMask | NSClosableWindowMask |
+                    NSMiniaturizableWindowMask | NSResizableWindowMask);
+    }
+
+  GDK_QUARTZ_ALLOC_POOL;
+
+  old_mask = [impl->toplevel styleMask];
+
+  if (old_mask != new_mask)
+    {
+      NSRect rect;
+
+      old_view = [[impl->toplevel contentView] retain];
+
+      rect = [impl->toplevel frame];
+
+      /* Properly update the size of the window when the titlebar is
+       * added or removed.
+       */
+      if (old_mask == NSBorderlessWindowMask &&
+          new_mask != NSBorderlessWindowMask)
+        {
+          rect = [NSWindow frameRectForContentRect:rect styleMask:new_mask];
+
+        }
+      else if (old_mask != NSBorderlessWindowMask &&
+               new_mask == NSBorderlessWindowMask)
+        {
+          rect = [NSWindow contentRectForFrameRect:rect styleMask:old_mask];
+        }
+
+      /* Note, before OS 10.6 there doesn't seem to be a way to change this
+       * without recreating the toplevel. From 10.6 onward, a simple call to
+       * setStyleMask takes care of most of this, except for ensuring that the
+       * title is set.
+       */
+      if ([impl->toplevel respondsToSelector:@selector(setStyleMask:)])
+        {
+          NSString *title = [impl->toplevel title];
+
+          [(id<CanSetStyleMask>)impl->toplevel setStyleMask:new_mask];
+
+          /* It appears that unsetting and then resetting NSTitledWindowMask
+           * does not reset the title in the title bar as might be expected.
+           *
+           * In theory we only need to set this if new_mask includes
+           * NSTitledWindowMask. This behaved extremely oddly when
+           * conditionalized upon that and since it has no side effects (i.e.
+           * if NSTitledWindowMask is not requested, the title will not be
+           * displayed) just do it unconditionally. We also must null check
+           * 'title' before setting it to avoid crashing.
+           */
+          if (title)
+            [impl->toplevel setTitle:title];
+        }
+      else
+        {
+          NSString *title = [impl->toplevel title];
+          NSColor *bg = [impl->toplevel backgroundColor];
+          NSScreen *screen = [impl->toplevel screen];
+
+          /* Make sure the old window is closed, recall that releasedWhenClosed
+           * is set on GdkQuartzSurfaces.
+           */
+          [impl->toplevel close];
+
+          impl->toplevel = [[GdkQuartzNSWindow alloc] initWithContentRect:rect
+                                                                styleMask:new_mask
+                                                                  backing:NSBackingStoreBuffered
+                                                                    defer:NO
+                                                                   screen:screen];
+          _gdk_quartz_surface_update_has_shadow (impl);
+
+          [impl->toplevel setLevel: window_type_hint_to_level (impl->type_hint)];
+          if (title)
+            [impl->toplevel setTitle:title];
+          [impl->toplevel setBackgroundColor:bg];
+          [impl->toplevel setHidesOnDeactivate: window_type_hint_to_hides_on_deactivate (impl->type_hint)];
+          [impl->toplevel setContentView:old_view];
+        }
+
+      if (new_mask == NSBorderlessWindowMask)
+        {
+          [impl->toplevel setContentSize:rect.size];
+          [impl->toplevel setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+        }
+      else
+        [impl->toplevel setFrame:rect display:YES];
+
+      /* Invalidate the window shadow for non-opaque views that have shadow
+       * enabled, to get the shadow shape updated.
+       */
+      if (![old_view isOpaque] && [impl->toplevel hasShadow])
+        [(GdkQuartzView*)old_view setNeedsInvalidateShadow:YES];
+
+      [old_view release];
+    }
+
+  GDK_QUARTZ_RELEASE_POOL;
+}
+
+static gboolean
+gdk_quartz_surface_get_decorations (GdkSurface       *window,
+                                   GdkWMDecoration *decorations)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return FALSE;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (decorations)
+    {
+      /* Borderless is 0, so we can't check it as a bit being set. */
+      if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
+        {
+          *decorations = 0;
+        }
+      else
+        {
+          /* FIXME: Honor the other GDK_DECOR_* flags. */
+          *decorations = GDK_DECOR_ALL;
+        }
+    }
+
+  return TRUE;
+}
+
+static void
+gdk_quartz_surface_set_functions (GdkSurface    *window,
+                                 GdkWMFunction functions)
+{
+  GdkSurfaceImplQuartz *impl;
+  gboolean min, max, close;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (functions & GDK_FUNC_ALL)
+    {
+      min = !(functions & GDK_FUNC_MINIMIZE);
+      max = !(functions & GDK_FUNC_MAXIMIZE);
+      close = !(functions & GDK_FUNC_CLOSE);
+    }
+  else
+    {
+      min = (functions & GDK_FUNC_MINIMIZE);
+      max = (functions & GDK_FUNC_MAXIMIZE);
+      close = (functions & GDK_FUNC_CLOSE);
+    }
+
+  if (impl->toplevel)
+    {
+      NSUInteger mask = [impl->toplevel styleMask];
+
+      if (min)
+        mask = mask | NSMiniaturizableWindowMask;
+      else
+        mask = mask & ~NSMiniaturizableWindowMask;
+
+      if (max)
+        mask = mask | NSResizableWindowMask;
+      else
+        mask = mask & ~NSResizableWindowMask;
+
+      if (close)
+        mask = mask | NSClosableWindowMask;
+      else
+        mask = mask & ~NSClosableWindowMask;
+
+      [impl->toplevel setStyleMask:mask];
+    }
+}
+
+static void
+gdk_quartz_surface_stick (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+}
+
+static void
+gdk_quartz_surface_unstick (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+}
+
+static void
+gdk_quartz_surface_maximize (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl;
+  gboolean maximized;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      GDK_QUARTZ_ALLOC_POOL;
+
+      if (impl->toplevel && !maximized)
+        [impl->toplevel zoom:nil];
+
+      GDK_QUARTZ_RELEASE_POOL;
+    }
+}
+
+static void
+gdk_quartz_surface_unmaximize (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl;
+  gboolean maximized;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      GDK_QUARTZ_ALLOC_POOL;
+
+      if (impl->toplevel && maximized)
+        [impl->toplevel zoom:nil];
+
+      GDK_QUARTZ_RELEASE_POOL;
+    }
+}
+
+static void
+gdk_quartz_surface_iconify (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      GDK_QUARTZ_ALLOC_POOL;
+
+      if (impl->toplevel)
+       [impl->toplevel miniaturize:nil];
+
+      GDK_QUARTZ_RELEASE_POOL;
+    }
+  else
+    {
+      gdk_synthesize_window_state (window,
+                                  0,
+                                  GDK_SURFACE_STATE_ICONIFIED);
+    }
+}
+
+static void
+gdk_quartz_surface_deiconify (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      GDK_QUARTZ_ALLOC_POOL;
+
+      if (impl->toplevel)
+       [impl->toplevel deminiaturize:nil];
+
+      GDK_QUARTZ_RELEASE_POOL;
+    }
+  else
+    {
+      gdk_synthesize_window_state (window,
+                                  GDK_SURFACE_STATE_ICONIFIED,
+                                  0);
+    }
+}
+
+#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
+
+static gboolean
+window_is_fullscreen (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  return ([impl->toplevel styleMask] & NSFullScreenWindowMask) != 0;
+}
+
+static void
+gdk_quartz_surface_fullscreen (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (!window_is_fullscreen (window))
+    [impl->toplevel toggleFullScreen:nil];
+}
+
+static void
+gdk_quartz_surface_unfullscreen (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (window_is_fullscreen (window))
+    [impl->toplevel toggleFullScreen:nil];
+}
+
+void
+_gdk_quartz_surface_update_fullscreen_state (GdkSurface *window)
+{
+  gboolean is_fullscreen;
+  gboolean was_fullscreen;
+
+  is_fullscreen = window_is_fullscreen (window);
+  was_fullscreen = (gdk_surface_get_state (window) & GDK_SURFACE_STATE_FULLSCREEN) != 0;
+
+  if (is_fullscreen != was_fullscreen)
+    {
+      if (is_fullscreen)
+        gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
+      else
+        gdk_synthesize_window_state (window, GDK_SURFACE_STATE_FULLSCREEN, 0);
+    }
+}
+
+#else
+
+static FullscreenSavedGeometry *
+get_fullscreen_geometry (GdkSurface *window)
+{
+  return g_object_get_data (G_OBJECT (window), FULLSCREEN_DATA);
+}
+
+static void
+gdk_quartz_surface_fullscreen (GdkSurface *window)
+{
+  FullscreenSavedGeometry *geometry;
+  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  NSRect frame;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  geometry = get_fullscreen_geometry (window);
+  if (!geometry)
+    {
+      geometry = g_new (FullscreenSavedGeometry, 1);
+
+      geometry->x = window->x;
+      geometry->y = window->y;
+      geometry->width = window->width;
+      geometry->height = window->height;
+
+      if (!gdk_surface_get_decorations (window, &geometry->decor))
+        geometry->decor = GDK_DECOR_ALL;
+
+      g_object_set_data_full (G_OBJECT (window),
+                              FULLSCREEN_DATA, geometry, 
+                              g_free);
+
+      gdk_surface_set_decorations (window, 0);
+
+      frame = [[impl->toplevel screen] frame];
+      move_resize_window_internal (window,
+                                   0, 0, 
+                                   frame.size.width, frame.size.height);
+      [impl->toplevel setContentSize:frame.size];
+      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
+
+      clear_toplevel_order ();
+    }
+
+  SetSystemUIMode (kUIModeAllHidden, kUIOptionAutoShowMenuBar);
+
+  gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
+}
+
+static void
+gdk_quartz_surface_unfullscreen (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  FullscreenSavedGeometry *geometry;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  geometry = get_fullscreen_geometry (window);
+  if (geometry)
+    {
+      SetSystemUIMode (kUIModeNormal, 0);
+
+      move_resize_window_internal (window,
+                                   geometry->x,
+                                   geometry->y,
+                                   geometry->width,
+                                   geometry->height);
+      
+      gdk_surface_set_decorations (window, geometry->decor);
+
+      g_object_set_data (G_OBJECT (window), FULLSCREEN_DATA, NULL);
+
+      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
+      clear_toplevel_order ();
+
+      gdk_synthesize_window_state (window, GDK_SURFACE_STATE_FULLSCREEN, 0);
+    }
+}
+
+#endif
+
+static void
+gdk_quartz_surface_set_keep_above (GdkSurface *window,
+                                  gboolean   setting)
+{
+  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  gint level;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  level = window_type_hint_to_level (gdk_surface_get_type_hint (window));
+  
+  /* Adjust normal window level by one if necessary. */
+  [impl->toplevel setLevel: level + (setting ? 1 : 0)];
+}
+
+static void
+gdk_quartz_surface_set_keep_below (GdkSurface *window,
+                                  gboolean   setting)
+{
+  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+  gint level;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+  
+  level = window_type_hint_to_level (gdk_surface_get_type_hint (window));
+  
+  /* Adjust normal window level by one if necessary. */
+  [impl->toplevel setLevel: level - (setting ? 1 : 0)];
+}
+
+static GdkSurface *
+gdk_quartz_surface_get_group (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD, NULL);
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return NULL;
+
+  /* FIXME: Implement */
+
+  return NULL;
+}
+
+static void
+gdk_quartz_surface_set_group (GdkSurface *window,
+                             GdkSurface *leader)
+{
+  /* FIXME: Implement */       
+}
+
+static void
+gdk_quartz_surface_destroy_notify (GdkSurface *window)
+{
+  check_grab_destroy (window);
+}
+
+static void
+gdk_quartz_surface_set_opacity (GdkSurface *window,
+                               gdouble    opacity)
+{
+  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  if (opacity < 0)
+    opacity = 0;
+  else if (opacity > 1)
+    opacity = 1;
+
+  [impl->toplevel setAlphaValue: opacity];
+}
+
+static void
+gdk_quartz_surface_set_shadow_width (GdkSurface *window,
+                                    gint       left,
+                                    gint       right,
+                                    gint       top,
+                                    gint       bottom)
+{
+  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl->shadow_top = top;
+  impl->shadow_max = MAX (MAX (left, right), MAX (top, bottom));
+  _gdk_quartz_surface_update_has_shadow (impl);
+}
+
+/* Protocol to build cleanly for OSX < 10.7 */
+@protocol ScaleFactor
+- (CGFloat) backingScaleFactor;
+@end
+
+static gint
+gdk_quartz_surface_get_scale_factor (GdkSurface *window)
+{
+  GdkSurfaceImplQuartz *impl;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return 1;
+
+  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
+
+  if (impl->toplevel != NULL && gdk_quartz_osx_version() >= GDK_OSX_LION)
+    return [(id <ScaleFactor>) impl->toplevel backingScaleFactor];
+
+  return 1;
+}
+
+static void
+gdk_surface_impl_quartz_class_init (GdkSurfaceImplQuartzClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_CLASS (klass);
+  GdkSurfaceImplQuartzClass *impl_quartz_class = GDK_SURFACE_IMPL_QUARTZ_CLASS (klass);
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  object_class->finalize = gdk_surface_impl_quartz_finalize;
+
+  impl_class->ref_cairo_surface = gdk_quartz_ref_cairo_surface;
+  impl_class->show = gdk_surface_quartz_show;
+  impl_class->hide = gdk_surface_quartz_hide;
+  impl_class->withdraw = gdk_surface_quartz_withdraw;
+  impl_class->set_events = gdk_surface_quartz_set_events;
+  impl_class->get_events = gdk_surface_quartz_get_events;
+  impl_class->raise = gdk_surface_quartz_raise;
+  impl_class->lower = gdk_surface_quartz_lower;
+  impl_class->restack_toplevel = gdk_surface_quartz_restack_toplevel;
+  impl_class->move_resize = gdk_surface_quartz_move_resize;
+  impl_class->get_geometry = gdk_surface_quartz_get_geometry;
+  impl_class->get_root_coords = gdk_surface_quartz_get_root_coords;
+  impl_class->get_device_state = gdk_surface_quartz_get_device_state;
+  impl_class->shape_combine_region = gdk_surface_quartz_shape_combine_region;
+  impl_class->input_shape_combine_region = gdk_surface_quartz_input_shape_combine_region;
+  impl_class->destroy = gdk_quartz_surface_destroy;
+  impl_class->begin_paint = gdk_surface_impl_quartz_begin_paint;
+  impl_class->get_scale_factor = gdk_quartz_surface_get_scale_factor;
+
+  impl_class->focus = gdk_quartz_surface_focus;
+  impl_class->set_type_hint = gdk_quartz_surface_set_type_hint;
+  impl_class->get_type_hint = gdk_quartz_surface_get_type_hint;
+  impl_class->set_modal_hint = gdk_quartz_surface_set_modal_hint;
+  impl_class->set_skip_taskbar_hint = gdk_quartz_surface_set_skip_taskbar_hint;
+  impl_class->set_skip_pager_hint = gdk_quartz_surface_set_skip_pager_hint;
+  impl_class->set_urgency_hint = gdk_quartz_surface_set_urgency_hint;
+  impl_class->set_geometry_hints = gdk_quartz_surface_set_geometry_hints;
+  impl_class->set_title = gdk_quartz_surface_set_title;
+  impl_class->set_role = gdk_quartz_surface_set_role;
+  impl_class->set_startup_id = gdk_quartz_surface_set_startup_id;
+  impl_class->set_transient_for = gdk_quartz_surface_set_transient_for;
+  impl_class->get_frame_extents = gdk_quartz_surface_get_frame_extents;
+  impl_class->set_accept_focus = gdk_quartz_surface_set_accept_focus;
+  impl_class->set_focus_on_map = gdk_quartz_surface_set_focus_on_map;
+  impl_class->set_icon_list = gdk_quartz_surface_set_icon_list;
+  impl_class->set_icon_name = gdk_quartz_surface_set_icon_name;
+  impl_class->iconify = gdk_quartz_surface_iconify;
+  impl_class->deiconify = gdk_quartz_surface_deiconify;
+  impl_class->stick = gdk_quartz_surface_stick;
+  impl_class->unstick = gdk_quartz_surface_unstick;
+  impl_class->maximize = gdk_quartz_surface_maximize;
+  impl_class->unmaximize = gdk_quartz_surface_unmaximize;
+  impl_class->fullscreen = gdk_quartz_surface_fullscreen;
+  impl_class->unfullscreen = gdk_quartz_surface_unfullscreen;
+  impl_class->set_keep_above = gdk_quartz_surface_set_keep_above;
+  impl_class->set_keep_below = gdk_quartz_surface_set_keep_below;
+  impl_class->get_group = gdk_quartz_surface_get_group;
+  impl_class->set_group = gdk_quartz_surface_set_group;
+  impl_class->set_decorations = gdk_quartz_surface_set_decorations;
+  impl_class->get_decorations = gdk_quartz_surface_get_decorations;
+  impl_class->set_functions = gdk_quartz_surface_set_functions;
+  impl_class->set_functions = gdk_quartz_surface_set_functions;
+  impl_class->begin_resize_drag = gdk_quartz_surface_begin_resize_drag;
+  impl_class->begin_move_drag = gdk_quartz_surface_begin_move_drag;
+  impl_class->set_opacity = gdk_quartz_surface_set_opacity;
+  impl_class->set_shadow_width = gdk_quartz_surface_set_shadow_width;
+  impl_class->destroy_notify = gdk_quartz_surface_destroy_notify;
+  impl_class->register_dnd = _gdk_quartz_surface_register_dnd;
+  impl_class->drag_begin = _gdk_quartz_surface_drag_begin;
+  impl_class->process_updates_recurse = _gdk_quartz_surface_process_updates_recurse;
+
+  impl_class->create_gl_context = gdk_quartz_surface_create_gl_context;
+
+  impl_quartz_class->get_context = gdk_surface_impl_quartz_get_context;
+  impl_quartz_class->release_context = gdk_surface_impl_quartz_release_context;
+}
+
+GType
+_gdk_surface_impl_quartz_get_type (void)
+{
+  static GType object_type = 0;
+
+  if (!object_type)
+    {
+      const GTypeInfo object_info =
+       {
+         sizeof (GdkSurfaceImplQuartzClass),
+         (GBaseInitFunc) NULL,
+         (GBaseFinalizeFunc) NULL,
+         (GClassInitFunc) gdk_surface_impl_quartz_class_init,
+         NULL,           /* class_finalize */
+         NULL,           /* class_data */
+         sizeof (GdkSurfaceImplQuartz),
+         0,              /* n_preallocs */
+         (GInstanceInitFunc) gdk_surface_impl_quartz_init,
+       };
+
+      object_type = g_type_register_static (GDK_TYPE_SURFACE_IMPL,
+                                            "GdkSurfaceImplQuartz",
+                                            &object_info, 0);
+    }
+
+  return object_type;
+}
+
+CGContextRef
+gdk_quartz_surface_get_context (GdkSurfaceImplQuartz  *window,
+                               gboolean             antialias)
+{
+  if (!GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->get_context)
+    {
+      g_warning ("%s doesn't implement GdkSurfaceImplQuartzClass::get_context()",
+                 G_OBJECT_TYPE_NAME (window));
+      return NULL;
+    }
+
+  return GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->get_context (window, antialias);
+}
+
+void
+gdk_quartz_surface_release_context (GdkSurfaceImplQuartz  *window,
+                                   CGContextRef          cg_context)
+{
+  if (!GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->release_context)
+    {
+      g_warning ("%s doesn't implement GdkSurfaceImplQuartzClass::release_context()",
+                 G_OBJECT_TYPE_NAME (window));
+      return;
+    }
+
+  GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->release_context (window, cg_context);
+}
+
+
+
+static CGContextRef
+gdk_root_window_impl_quartz_get_context (GdkSurfaceImplQuartz *window,
+                                         gboolean             antialias)
+{
+  CGColorSpaceRef colorspace;
+  CGContextRef cg_context;
+  GdkSurfaceImplQuartz *window_impl = GDK_SURFACE_IMPL_QUARTZ (window);
+
+  if (GDK_SURFACE_DESTROYED (window_impl->wrapper))
+    return NULL;
+
+  /* We do not have the notion of a root window on OS X.  We fake this
+   * by creating a 1x1 bitmap and return a context to that.
+   */
+  colorspace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
+  cg_context = CGBitmapContextCreate (NULL,
+                                      1, 1, 8, 4, colorspace,
+                                      kCGImageAlphaPremultipliedLast);
+  CGColorSpaceRelease (colorspace);
+
+  return cg_context;
+}
+
+static void
+gdk_root_window_impl_quartz_release_context (GdkSurfaceImplQuartz *window,
+                                             CGContextRef         cg_context)
+{
+  CGContextRelease (cg_context);
+}
+
+static void
+gdk_root_window_impl_quartz_class_init (GdkRootWindowImplQuartzClass *klass)
+{
+  GdkSurfaceImplQuartzClass *window_quartz_class = GDK_SURFACE_IMPL_QUARTZ_CLASS (klass);
+
+  root_window_parent_class = g_type_class_peek_parent (klass);
+
+  window_quartz_class->get_context = gdk_root_window_impl_quartz_get_context;
+  window_quartz_class->release_context = gdk_root_window_impl_quartz_release_context;
+}
+
+static void
+gdk_root_window_impl_quartz_init (GdkRootWindowImplQuartz *impl)
+{
+}
+
+GType
+_gdk_root_window_impl_quartz_get_type (void)
+{
+  static GType object_type = 0;
+
+  if (!object_type)
+    {
+      const GTypeInfo object_info =
+        {
+          sizeof (GdkRootWindowImplQuartzClass),
+          (GBaseInitFunc) NULL,
+          (GBaseFinalizeFunc) NULL,
+          (GClassInitFunc) gdk_root_window_impl_quartz_class_init,
+          NULL,           /* class_finalize */
+          NULL,           /* class_data */
+          sizeof (GdkRootWindowImplQuartz),
+          0,              /* n_preallocs */
+          (GInstanceInitFunc) gdk_root_window_impl_quartz_init,
+        };
+
+      object_type = g_type_register_static (GDK_TYPE_SURFACE_IMPL_QUARTZ,
+                                            "GdkRootWindowQuartz",
+                                            &object_info, 0);
+    }
+
+  return object_type;
+}
+
+GList *
+get_toplevels (void)
+{
+  update_toplevel_order ();
+  return GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl)->sorted_children;
+}
diff --git a/gdk/quartz/gdksurface-quartz.h b/gdk/quartz/gdksurface-quartz.h
new file mode 100644 (file)
index 0000000..ca4dd0d
--- /dev/null
@@ -0,0 +1,115 @@
+/* gdkdrawable-quartz.h
+ *
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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_SURFACE_QUARTZ_H__
+#define __GDK_SURFACE_QUARTZ_H__
+
+#import <gdk/quartz/GdkQuartzView.h>
+#import <gdk/quartz/GdkQuartzNSWindow.h>
+#include "gdk/gdksurfaceimpl.h"
+
+G_BEGIN_DECLS
+
+/* Window implementation for Quartz
+ */
+
+typedef struct _GdkSurfaceImplQuartz GdkSurfaceImplQuartz;
+typedef struct _GdkSurfaceImplQuartzClass GdkSurfaceImplQuartzClass;
+
+#define GDK_TYPE_SURFACE_IMPL_QUARTZ              (_gdk_surface_impl_quartz_get_type ())
+#define GDK_SURFACE_IMPL_QUARTZ(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartz))
+#define GDK_SURFACE_IMPL_QUARTZ_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartzClass))
+#define GDK_IS_SURFACE_IMPL_QUARTZ(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_QUARTZ))
+#define GDK_IS_SURFACE_IMPL_QUARTZ_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_QUARTZ))
+#define GDK_SURFACE_IMPL_QUARTZ_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartzClass))
+
+struct _GdkSurfaceImplQuartz
+{
+  GdkSurfaceImpl parent_instance;
+
+  GdkSurface *wrapper;
+
+  NSWindow *toplevel;
+  NSTrackingRectTag tracking_rect;
+  GdkQuartzView *view;
+
+  GdkSurfaceTypeHint type_hint;
+
+  gint in_paint_rect_count;
+
+  GdkSurface *transient_for;
+
+  /* Sorted by z-order */
+  GList *sorted_children;
+
+  cairo_region_t *needs_display_region;
+
+  cairo_surface_t *cairo_surface;
+
+  gint shadow_top;
+
+  gint shadow_max;
+};
+struct _GdkSurfaceImplQuartzClass 
+{
+  GdkSurfaceImplClass parent_class;
+
+  CGContextRef  (* get_context)     (GdkSurfaceImplQuartz *window,
+                                     gboolean             antialias);
+  void          (* release_context) (GdkSurfaceImplQuartz *window,
+                                     CGContextRef         cg_context);
+};
+
+GType _gdk_surface_impl_quartz_get_type (void);
+
+CGContextRef gdk_quartz_surface_get_context     (GdkSurfaceImplQuartz *window,
+                                                gboolean             antialias);
+void         gdk_quartz_surface_release_context (GdkSurfaceImplQuartz *window,
+                                                CGContextRef         context);
+
+/* Root window implementation for Quartz
+ */
+
+typedef struct _GdkRootWindowImplQuartz GdkRootWindowImplQuartz;
+typedef struct _GdkRootWindowImplQuartzClass GdkRootWindowImplQuartzClass;
+
+#define GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ              (_gdk_root_window_impl_quartz_get_type ())
+#define GDK_ROOT_WINDOW_IMPL_QUARTZ(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartz))
+#define GDK_ROOT_WINDOW_IMPL_QUARTZ_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartzClass))
+#define GDK_IS_ROOT_WINDOW_IMPL_QUARTZ(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ))
+#define GDK_IS_ROOT_WINDOW_IMPL_QUARTZ_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ))
+#define GDK_ROOT_WINDOW_IMPL_QUARTZ_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartzClass))
+
+struct _GdkRootWindowImplQuartz
+{
+  GdkSurfaceImplQuartz parent_instance;
+};
+struct _GdkRootWindowImplQuartzClass 
+{
+  GdkSurfaceImplQuartzClass parent_class;
+};
+
+GType _gdk_root_window_impl_quartz_get_type (void);
+
+GList *get_toplevels (void);
+
+G_END_DECLS
+
+#endif /* __GDK_SURFACE_QUARTZ_H__ */
diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c
deleted file mode 100644 (file)
index 170950a..0000000
+++ /dev/null
@@ -1,2958 +0,0 @@
-/* gdkwindow-quartz.c
- *
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 2005-2007 Imendio AB
- *
- * 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 <gdk/gdk.h>
-#include <gdk/gdkdeviceprivate.h>
-#include <gdk/gdkdisplayprivate.h>
-
-#include "gdkwindowimpl.h"
-#include "gdkprivate-quartz.h"
-#include "gdkglcontext-quartz.h"
-#include "gdkquartzscreen.h"
-#include "gdkquartzcursor.h"
-
-#include <Carbon/Carbon.h>
-#include <AvailabilityMacros.h>
-
-#include <sys/time.h>
-#include <cairo-quartz.h>
-
-static gpointer parent_class;
-static gpointer root_window_parent_class;
-
-static GSList   *update_nswindows;
-static gboolean  in_process_all_updates = FALSE;
-
-static GSList *main_window_stack;
-
-void _gdk_quartz_surface_flush (GdkSurfaceImplQuartz *window_impl);
-
-typedef struct
-{
-  gint            x, y;
-  gint            width, height;
-  GdkWMDecoration decor;
-} FullscreenSavedGeometry;
-
-
-#ifndef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
-static FullscreenSavedGeometry *get_fullscreen_geometry (GdkSurface *window);
-#endif
-
-#define FULLSCREEN_DATA "fullscreen-data"
-
-static void update_toplevel_order (void);
-static void clear_toplevel_order  (void);
-
-#define WINDOW_IS_TOPLEVEL(window)      (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD)
-
-/*
- * GdkQuartzSurface
- */
-
-struct _GdkQuartzSurface
-{
-  GdkSurface parent;
-};
-
-struct _GdkQuartzSurfaceClass
-{
-  GdkSurfaceClass parent_class;
-};
-
-G_DEFINE_TYPE (GdkQuartzSurface, gdk_quartz_surface, GDK_TYPE_SURFACE);
-
-static void
-gdk_quartz_surface_class_init (GdkQuartzSurfaceClass *quartz_surface_class)
-{
-}
-
-static void
-gdk_quartz_surface_init (GdkQuartzSurface *quartz_surface)
-{
-}
-
-
-/*
- * GdkQuartzSurfaceImpl
- */
-
-NSView *
-gdk_quartz_surface_get_nsview (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  return ((GdkSurfaceImplQuartz *)window->impl)->view;
-}
-
-NSWindow *
-gdk_quartz_surface_get_nswindow (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  return ((GdkSurfaceImplQuartz *)window->impl)->toplevel;
-}
-
-static CGContextRef
-gdk_surface_impl_quartz_get_context (GdkSurfaceImplQuartz *window_impl,
-                                   gboolean             antialias)
-{
-  CGContextRef cg_context;
-  CGSize scale;
-
-  if (GDK_SURFACE_DESTROYED (window_impl->wrapper))
-    return NULL;
-
-  /* Lock focus when not called as part of a drawRect call. This
-   * is needed when called from outside "real" expose events, for
-   * example for synthesized expose events when realizing windows
-   * and for widgets that send fake expose events like the arrow
-   * buttons in spinbuttons or the position marker in rulers.
-   */
-  if (window_impl->in_paint_rect_count == 0)
-    {
-      if (![window_impl->view lockFocusIfCanDraw])
-        return NULL;
-    }
-
-  cg_context = [[NSGraphicsContext currentContext] graphicsPort];
-  CGContextSaveGState (cg_context);
-  CGContextSetAllowsAntialiasing (cg_context, antialias);
-
-  /* Undo the default scaling transform, since we apply our own
-   * in gdk_quartz_ref_cairo_surface () */
-  scale = CGContextConvertSizeToDeviceSpace (cg_context,
-                                             CGSizeMake (1.0, 1.0));
-  CGContextScaleCTM (cg_context, 1.0 / scale.width, 1.0 / scale.height);
-
-  return cg_context;
-}
-
-static void
-gdk_surface_impl_quartz_release_context (GdkSurfaceImplQuartz *window_impl,
-                                        CGContextRef         cg_context)
-{
-  CGContextRestoreGState (cg_context);
-  CGContextSetAllowsAntialiasing (cg_context, TRUE);
-
-  /* See comment in gdk_quartz_surface_get_context(). */
-  if (window_impl->in_paint_rect_count == 0)
-    {
-      _gdk_quartz_surface_flush (window_impl);
-      [window_impl->view unlockFocus];
-    }
-}
-
-static void
-check_grab_destroy (GdkSurface *window)
-{
-  GList *devices = NULL, *l;
-  GdkDisplay *display = gdk_surface_get_display (window);
-  GdkSeat *seat;
-
-  seat = gdk_display_get_default_seat (display);
-
-  devices = g_list_prepend (devices, gdk_seat_get_keyboard (seat));
-  devices = g_list_prepend (devices, gdk_seat_get_pointer (seat));
-
-  for (l = devices; l; l = l->next)
-    {
-      GdkDeviceGrabInfo *grab;
-
-      grab = _gdk_display_get_last_device_grab (display, l->data);
-      if (grab && grab->native_window == window)
-        {
-          /* Serials are always 0 in quartz, but for clarity: */
-          grab->serial_end = grab->serial_start;
-          grab->implicit_ungrab = TRUE;
-        }
-    }
-
-  g_list_free (devices);
-}
-
-static void
-gdk_surface_impl_quartz_finalize (GObject *object)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (object);
-
-  check_grab_destroy (GDK_SURFACE_IMPL_QUARTZ (object)->wrapper);
-
-  if (impl->transient_for)
-    g_object_unref (impl->transient_for);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-/* Help preventing "beam sync penalty" where CG makes all graphics code
- * block until the next vsync if we try to flush (including call display on
- * a view) too often. We do this by limiting the manual flushing done
- * outside of expose calls to less than some frequency when measured over
- * the last 4 flushes. This is a bit arbitray, but seems to make it possible
- * for some quick manual flushes (such as gtkruler or gimp’s marching ants)
- * without hitting the max flush frequency.
- *
- * If drawable NULL, no flushing is done, only registering that a flush was
- * done externally.
- */
-void
-_gdk_quartz_surface_flush (GdkSurfaceImplQuartz *window_impl)
-{
-  static struct timeval prev_tv;
-  static gint intervals[4];
-  static gint index;
-  struct timeval tv;
-  gint ms;
-
-  gettimeofday (&tv, NULL);
-  ms = (tv.tv_sec - prev_tv.tv_sec) * 1000 + (tv.tv_usec - prev_tv.tv_usec) / 1000;
-  intervals[index++ % 4] = ms;
-
-  if (window_impl)
-    {
-      ms = intervals[0] + intervals[1] + intervals[2] + intervals[3];
-
-      /* ~25Hz on average. */
-      if (ms > 4*40)
-        {
-          if (window_impl)
-            [window_impl->toplevel flushWindow];
-
-          prev_tv = tv;
-        }
-    }
-  else
-    prev_tv = tv;
-}
-
-static cairo_user_data_key_t gdk_quartz_cairo_key;
-
-typedef struct {
-  GdkSurfaceImplQuartz  *window_impl;
-  CGContextRef  cg_context;
-} GdkQuartzCairoSurfaceData;
-
-static void
-gdk_quartz_cairo_surface_destroy (void *data)
-{
-  GdkQuartzCairoSurfaceData *surface_data = data;
-
-  surface_data->window_impl->cairo_surface = NULL;
-
-  gdk_quartz_surface_release_context (surface_data->window_impl,
-                                     surface_data->cg_context);
-
-  g_free (surface_data);
-}
-
-static cairo_surface_t *
-gdk_quartz_create_cairo_surface (GdkSurfaceImplQuartz *impl,
-                                int                  width,
-                                int                  height)
-{
-  CGContextRef cg_context;
-  GdkQuartzCairoSurfaceData *surface_data;
-  cairo_surface_t *surface;
-
-  cg_context = gdk_quartz_surface_get_context (impl, TRUE);
-
-  if (!cg_context)
-    return NULL;
-
-  surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
-  surface_data->window_impl = impl;
-  surface_data->cg_context = cg_context;
-
-  surface = cairo_quartz_surface_create_for_cg_context (cg_context,
-                                                        width, height);
-
-  cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
-                               surface_data,
-                               gdk_quartz_cairo_surface_destroy);
-
-  return surface;
-}
-
-static cairo_surface_t *
-gdk_quartz_ref_cairo_surface (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  if (!impl->cairo_surface)
-    {
-      gint scale = gdk_surface_get_scale_factor (impl->wrapper);
-
-      impl->cairo_surface = 
-          gdk_quartz_create_cairo_surface (impl,
-                                           gdk_surface_get_width (impl->wrapper) * scale,
-                                           gdk_surface_get_height (impl->wrapper) * scale);
-
-      cairo_surface_set_device_scale (impl->cairo_surface, scale, scale);
-    }
-  else
-    cairo_surface_reference (impl->cairo_surface);
-
-  return impl->cairo_surface;
-}
-
-static void
-gdk_surface_impl_quartz_init (GdkSurfaceImplQuartz *impl)
-{
-  impl->type_hint = GDK_SURFACE_TYPE_HINT_NORMAL;
-}
-
-static gboolean
-gdk_surface_impl_quartz_begin_paint (GdkSurface *window)
-{
-  return FALSE;
-}
-
-static void
-gdk_quartz_surface_set_needs_display_in_region (GdkSurface    *window,
-                                               cairo_region_t    *region)
-{
-  GdkSurfaceImplQuartz *impl;
-  int i, n_rects;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (!impl->needs_display_region)
-    impl->needs_display_region = cairo_region_create ();
-
-  cairo_region_union (impl->needs_display_region, region);
-
-  n_rects = cairo_region_num_rectangles (region);
-  for (i = 0; i < n_rects; i++)
-    {
-      cairo_rectangle_int_t rect;
-      cairo_region_get_rectangle (region, i, &rect);
-      [impl->view setNeedsDisplayInRect:NSMakeRect (rect.x, rect.y,
-                                                    rect.width, rect.height)];
-    }
-}
-
-void
-_gdk_quartz_surface_process_updates_recurse (GdkSurface *window,
-                                            cairo_region_t *region)
-{
-  /* Make sure to only flush each toplevel at most once if we're called
-   * from process_all_updates.
-   */
-  if (in_process_all_updates)
-    {
-      GdkSurface *toplevel;
-
-      toplevel = gdk_surface_get_toplevel (window);
-      if (toplevel && WINDOW_IS_TOPLEVEL (toplevel))
-        {
-          GdkSurfaceImplQuartz *toplevel_impl;
-          NSWindow *nswindow;
-
-          toplevel_impl = (GdkSurfaceImplQuartz *)toplevel->impl;
-          nswindow = toplevel_impl->toplevel;
-
-          /* In theory, we could skip the flush disabling, since we only
-           * have one NSView.
-           */
-          if (nswindow && ![nswindow isFlushWindowDisabled]) 
-            {
-              [nswindow retain];
-              [nswindow disableFlushWindow];
-              update_nswindows = g_slist_prepend (update_nswindows, nswindow);
-            }
-        }
-    }
-
-  if (WINDOW_IS_TOPLEVEL (window))
-    gdk_quartz_surface_set_needs_display_in_region (window, region);
-  else
-    _gdk_surface_process_updates_recurse (window, region);
-
-  /* NOTE: I'm not sure if we should displayIfNeeded here. It slows down a
-   * lot (since it triggers the beam syncing) and things seem to work
-   * without it.
-   */
-}
-
-static const gchar *
-get_default_title (void)
-{
-  const char *title;
-
-  title = g_get_application_name ();
-  if (!title)
-    title = g_get_prgname ();
-
-  return title;
-}
-
-static void
-get_ancestor_coordinates_from_child (GdkSurface *child_window,
-                                    gint       child_x,
-                                    gint       child_y,
-                                    GdkSurface *ancestor_window, 
-                                    gint      *ancestor_x, 
-                                    gint      *ancestor_y)
-{
-  while (child_window != ancestor_window)
-    {
-      child_x += child_window->x;
-      child_y += child_window->y;
-
-      child_window = child_window->parent;
-    }
-
-  *ancestor_x = child_x;
-  *ancestor_y = child_y;
-}
-
-void
-_gdk_quartz_surface_debug_highlight (GdkSurface *window, gint number)
-{
-  gint x, y;
-  gint gx, gy;
-  GdkSurface *toplevel;
-  gint tx, ty;
-  static NSWindow *debug_window[10];
-  static NSRect old_rect[10];
-  NSRect rect;
-  NSColor *color;
-
-  g_return_if_fail (number >= 0 && number <= 9);
-
-  if (window == _gdk_root)
-    return;
-
-  if (window == NULL)
-    {
-      if (debug_window[number])
-        [debug_window[number] close];
-      debug_window[number] = NULL;
-
-      return;
-    }
-
-  toplevel = gdk_surface_get_toplevel (window);
-  get_ancestor_coordinates_from_child (window, 0, 0, toplevel, &x, &y);
-
-  gdk_surface_get_origin (toplevel, &tx, &ty);
-  x += tx;
-  y += ty;
-
-  _gdk_quartz_surface_gdk_xy_to_xy (x, y + window->height,
-                                   &gx, &gy);
-
-  rect = NSMakeRect (gx, gy, window->width, window->height);
-
-  if (debug_window[number] && NSEqualRects (rect, old_rect[number]))
-    return;
-
-  old_rect[number] = rect;
-
-  if (debug_window[number])
-    [debug_window[number] close];
-
-  debug_window[number] = [[NSWindow alloc] initWithContentRect:rect
-                                                     styleMask:NSBorderlessWindowMask
-                                                      backing:NSBackingStoreBuffered
-                                                        defer:NO];
-
-  switch (number)
-    {
-    case 0:
-      color = [NSColor redColor];
-      break;
-    case 1:
-      color = [NSColor blueColor];
-      break;
-    case 2:
-      color = [NSColor greenColor];
-      break;
-    case 3:
-      color = [NSColor yellowColor];
-      break;
-    case 4:
-      color = [NSColor brownColor];
-      break;
-    case 5:
-      color = [NSColor purpleColor];
-      break;
-    default:
-      color = [NSColor blackColor];
-      break;
-    }
-
-  [debug_window[number] setBackgroundColor:color];
-  [debug_window[number] setAlphaValue:0.4];
-  [debug_window[number] setOpaque:NO];
-  [debug_window[number] setReleasedWhenClosed:YES];
-  [debug_window[number] setIgnoresMouseEvents:YES];
-  [debug_window[number] setLevel:NSFloatingWindowLevel];
-
-  [debug_window[number] orderFront:nil];
-}
-
-gboolean
-_gdk_quartz_surface_is_ancestor (GdkSurface *ancestor,
-                                GdkSurface *window)
-{
-  if (ancestor == NULL || window == NULL)
-    return FALSE;
-
-  return (gdk_surface_get_parent (window) == ancestor ||
-          _gdk_quartz_surface_is_ancestor (ancestor, 
-                                          gdk_surface_get_parent (window)));
-}
-
-
-/* See notes on top of gdkscreen-quartz.c */
-void
-_gdk_quartz_surface_gdk_xy_to_xy (gint  gdk_x,
-                                 gint  gdk_y,
-                                 gint *ns_x,
-                                 gint *ns_y)
-{
-  GdkQuartzScreen *screen_quartz = GDK_QUARTZ_SCREEN (_gdk_screen);
-
-  if (ns_y)
-    *ns_y = screen_quartz->height - gdk_y + screen_quartz->min_y;
-
-  if (ns_x)
-    *ns_x = gdk_x + screen_quartz->min_x;
-}
-
-void
-_gdk_quartz_surface_xy_to_gdk_xy (gint  ns_x,
-                                 gint  ns_y,
-                                 gint *gdk_x,
-                                 gint *gdk_y)
-{
-  GdkQuartzScreen *screen_quartz = GDK_QUARTZ_SCREEN (_gdk_screen);
-
-  if (gdk_y)
-    *gdk_y = screen_quartz->height - ns_y + screen_quartz->min_y;
-
-  if (gdk_x)
-    *gdk_x = ns_x - screen_quartz->min_x;
-}
-
-void
-_gdk_quartz_surface_nspoint_to_gdk_xy (NSPoint  point,
-                                      gint    *x,
-                                      gint    *y)
-{
-  _gdk_quartz_surface_xy_to_gdk_xy (point.x, point.y,
-                                   x, y);
-}
-
-static GdkSurface *
-find_child_window_helper (GdkSurface *window,
-                         gint       x,
-                         gint       y,
-                         gint       x_offset,
-                         gint       y_offset,
-                          gboolean   get_toplevel)
-{
-  GdkSurfaceImplQuartz *impl;
-  GList *l;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (window == _gdk_root)
-    update_toplevel_order ();
-
-  for (l = impl->sorted_children; l; l = l->next)
-    {
-      GdkSurface *child = l->data;
-      GdkSurfaceImplQuartz *child_impl = GDK_SURFACE_IMPL_QUARTZ (child->impl);
-      int temp_x, temp_y;
-
-      if (!GDK_SURFACE_IS_MAPPED (child))
-       continue;
-
-      temp_x = x_offset + child->x;
-      temp_y = y_offset + child->y;
-
-      /* Special-case the root window. We have to include the title
-       * bar in the checks, otherwise the window below the title bar
-       * will be found i.e. events punch through. (If we can find a
-       * better way to deal with the events in gdkevents-quartz, this
-       * might not be needed.)
-       */
-      if (window == _gdk_root)
-        {
-          NSRect frame = NSMakeRect (0, 0, 100, 100);
-          NSRect content;
-          NSUInteger mask;
-          int titlebar_height;
-
-          mask = [child_impl->toplevel styleMask];
-
-          /* Get the title bar height. */
-          content = [NSWindow contentRectForFrameRect:frame
-                                            styleMask:mask];
-          titlebar_height = frame.size.height - content.size.height;
-
-          if (titlebar_height > 0 &&
-              x >= temp_x && y >= temp_y - titlebar_height &&
-              x < temp_x + child->width && y < temp_y)
-            {
-              /* The root means "unknown" i.e. a window not managed by
-               * GDK.
-               */
-              return (GdkSurface *)_gdk_root;
-            }
-        }
-
-      if ((!get_toplevel || (get_toplevel && window == _gdk_root)) &&
-          x >= temp_x && y >= temp_y &&
-         x < temp_x + child->width && y < temp_y + child->height)
-       {
-         /* Look for child windows. */
-         return find_child_window_helper (l->data,
-                                          x, y,
-                                          temp_x, temp_y,
-                                           get_toplevel);
-       }
-    }
-  
-  return window;
-}
-
-/* Given a GdkSurface and coordinates relative to it, returns the
- * innermost subwindow that contains the point. If the coordinates are
- * outside the passed in window, NULL is returned.
- */
-GdkSurface *
-_gdk_quartz_surface_find_child (GdkSurface *window,
-                              gint       x,
-                              gint       y,
-                               gboolean   get_toplevel)
-{
-  if (x >= 0 && y >= 0 && x < window->width && y < window->height)
-    return find_child_window_helper (window, x, y, 0, 0, get_toplevel);
-
-  return NULL;
-}
-
-
-void
-_gdk_quartz_surface_did_become_main (GdkSurface *window)
-{
-  main_window_stack = g_slist_remove (main_window_stack, window);
-
-  if (window->window_type != GDK_SURFACE_TEMP)
-    main_window_stack = g_slist_prepend (main_window_stack, window);
-
-  clear_toplevel_order ();
-}
-
-void
-_gdk_quartz_surface_did_resign_main (GdkSurface *window)
-{
-  GdkSurface *new_window = NULL;
-
-  if (main_window_stack)
-    new_window = main_window_stack->data;
-  else
-    {
-      GList *toplevels;
-
-      toplevels = get_toplevels ();
-      if (toplevels)
-        new_window = toplevels->data;
-    }
-
-  if (new_window &&
-      new_window != window &&
-      GDK_SURFACE_IS_MAPPED (new_window) &&
-      WINDOW_IS_TOPLEVEL (new_window))
-    {
-      GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (new_window->impl);
-
-      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
-    }
-
-  clear_toplevel_order ();
-}
-
-static NSScreen *
-get_nsscreen_for_point (gint x, gint y)
-{
-  int i;
-  NSArray *screens;
-  NSScreen *screen = NULL;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  screens = [NSScreen screens];
-
-  for (i = 0; i < [screens count]; i++)
-    {
-      NSRect rect = [[screens objectAtIndex:i] frame];
-
-      if (x >= rect.origin.x && x <= rect.origin.x + rect.size.width &&
-          y >= rect.origin.y && y <= rect.origin.y + rect.size.height)
-        {
-          screen = [screens objectAtIndex:i];
-          break;
-        }
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-
-  return screen;
-}
-
-void
-_gdk_quartz_display_create_window_impl (GdkDisplay    *display,
-                                        GdkSurface     *window,
-                                        GdkSurface     *real_parent,
-                                        GdkEventMask   event_mask,
-                                        GdkSurfaceAttr *attributes)
-{
-  GdkSurfaceImplQuartz *impl;
-  GdkSurfaceImplQuartz *parent_impl;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  impl = g_object_new (GDK_TYPE_SURFACE_IMPL_QUARTZ, NULL);
-  window->impl = GDK_SURFACE_IMPL (impl);
-  impl->wrapper = window;
-
-  parent_impl = GDK_SURFACE_IMPL_QUARTZ (window->parent->impl);
-
-  switch (window->window_type)
-    {
-    case GDK_SURFACE_TOPLEVEL:
-    case GDK_SURFACE_TEMP:
-      if (GDK_SURFACE_TYPE (window->parent) != GDK_SURFACE_ROOT)
-       {
-         /* The common code warns for this case */
-          parent_impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
-       }
-    }
-
-  /* Maintain the z-ordered list of children. */
-  if (window->parent != _gdk_root)
-    parent_impl->sorted_children = g_list_prepend (parent_impl->sorted_children, window);
-  else
-    clear_toplevel_order ();
-
-  impl->view = NULL;
-
-  switch (window->window_type)
-    {
-    case GDK_SURFACE_TOPLEVEL:
-    case GDK_SURFACE_TEMP:
-      {
-        NSScreen *screen;
-        NSRect screen_rect;
-        NSRect content_rect;
-        NSUInteger style_mask;
-        int nx, ny;
-
-        /* initWithContentRect will place on the mainScreen by default.
-         * We want to select the screen to place on ourselves.  We need
-         * to find the screen the window will be on and correct the
-         * content_rect coordinates to be relative to that screen.
-         */
-        _gdk_quartz_surface_gdk_xy_to_xy (window->x, window->y, &nx, &ny);
-
-        screen = get_nsscreen_for_point (nx, ny);
-        screen_rect = [screen frame];
-        nx -= screen_rect.origin.x;
-        ny -= screen_rect.origin.y;
-
-        content_rect = NSMakeRect (nx, ny - window->height,
-                                   window->width,
-                                   window->height);
-
-        if (window->window_type == GDK_SURFACE_TEMP)
-          {
-            style_mask = NSBorderlessWindowMask;
-          }
-        else
-          {
-            style_mask = (NSTitledWindowMask |
-                          NSClosableWindowMask |
-                          NSMiniaturizableWindowMask |
-                          NSResizableWindowMask);
-          }
-
-       impl->toplevel = [[GdkQuartzNSWindow alloc] initWithContentRect:content_rect 
-                                                             styleMask:style_mask
-                                                               backing:NSBackingStoreBuffered
-                                                                 defer:NO
-                                                                  screen:screen];
-
-       gdk_surface_set_title (window, get_default_title ());
-  
-        [impl->toplevel setOpaque:NO];
-        [impl->toplevel setBackgroundColor:[NSColor clearColor]];
-
-        content_rect.origin.x = 0;
-        content_rect.origin.y = 0;
-
-       impl->view = [[GdkQuartzView alloc] initWithFrame:content_rect];
-       [impl->view setGdkSurface:window];
-       [impl->toplevel setContentView:impl->view];
-       [impl->view release];
-      }
-      break;
-
-    case GDK_SURFACE_CHILD:
-      {
-       GdkSurfaceImplQuartz *parent_impl = GDK_SURFACE_IMPL_QUARTZ (window->parent->impl);
-
-       if (!window->input_only)
-         {
-           NSRect frame_rect = NSMakeRect (window->x + window->parent->abs_x,
-                                            window->y + window->parent->abs_y,
-                                            window->width,
-                                            window->height);
-       
-           impl->view = [[GdkQuartzView alloc] initWithFrame:frame_rect];
-           
-           [impl->view setGdkSurface:window];
-
-           /* GdkSurfaces should be hidden by default */
-           [impl->view setHidden:YES];
-           [parent_impl->view addSubview:impl->view];
-           [impl->view release];
-         }
-      }
-      break;
-
-    default:
-      g_assert_not_reached ();
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-void
-_gdk_quartz_surface_update_position (GdkSurface *window)
-{
-  NSRect frame_rect;
-  NSRect content_rect;
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  frame_rect = [impl->toplevel frame];
-  content_rect = [impl->toplevel contentRectForFrameRect:frame_rect];
-
-  _gdk_quartz_surface_xy_to_gdk_xy (content_rect.origin.x,
-                                   content_rect.origin.y + content_rect.size.height,
-                                   &window->x, &window->y);
-
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-void
-_gdk_quartz_surface_init_windowing (GdkDisplay *display)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_assert (_gdk_root == NULL);
-
-  _gdk_root = _gdk_display_create_window (display);
-
-  _gdk_root->impl = g_object_new (_gdk_root_window_impl_quartz_get_type (), NULL);
-  _gdk_root->impl_window = _gdk_root;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
-
-  _gdk_quartz_screen_update_window_sizes (screen);
-
-  _gdk_root->state = 0; /* We don't want GDK_SURFACE_STATE_WITHDRAWN here */
-  _gdk_root->window_type = GDK_SURFACE_ROOT;
-  _gdk_root->viewable = TRUE;
-
-  impl->wrapper = _gdk_root;
-}
-
-static void
-gdk_quartz_surface_destroy (GdkSurface *window,
-                           gboolean   recursing,
-                           gboolean   foreign_destroy)
-{
-  GdkSurfaceImplQuartz *impl;
-  GdkSurface *parent;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  main_window_stack = g_slist_remove (main_window_stack, window);
-
-  g_list_free (impl->sorted_children);
-  impl->sorted_children = NULL;
-
-  parent = window->parent;
-  if (parent)
-    {
-      GdkSurfaceImplQuartz *parent_impl = GDK_SURFACE_IMPL_QUARTZ (parent->impl);
-
-      parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window);
-    }
-
-  if (impl->cairo_surface)
-    {
-      cairo_surface_finish (impl->cairo_surface);
-      cairo_surface_set_user_data (impl->cairo_surface, &gdk_quartz_cairo_key,
-                                  NULL, NULL);
-      impl->cairo_surface = NULL;
-    }
-
-  if (!recursing && !foreign_destroy)
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      if (impl->toplevel)
-       [impl->toplevel close];
-      else if (impl->view)
-       [impl->view removeFromSuperview];
-
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-}
-
-/* FIXME: This might be possible to simplify with client-side windows. Also
- * note that already_mapped is not used yet, see the x11 backend.
-*/
-static void
-gdk_surface_quartz_show (GdkSurface *window, gboolean already_mapped)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  gboolean focus_on_map;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  if (!GDK_SURFACE_IS_MAPPED (window))
-    focus_on_map = window->focus_on_map;
-  else
-    focus_on_map = TRUE;
-
-  if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel)
-    {
-      gboolean make_key;
-
-      make_key = (window->accept_focus && focus_on_map &&
-                  window->window_type != GDK_SURFACE_TEMP);
-
-      [(GdkQuartzNSWindow*)impl->toplevel showAndMakeKey:make_key];
-      clear_toplevel_order ();
-
-      _gdk_quartz_events_send_map_event (window);
-    }
-  else
-    {
-      [impl->view setHidden:NO];
-    }
-
-  [impl->view setNeedsDisplay:YES];
-
-  gdk_synthesize_window_state (window, GDK_SURFACE_STATE_WITHDRAWN, 0);
-
-  if (window->state & GDK_SURFACE_STATE_MAXIMIZED)
-    gdk_surface_maximize (window);
-
-  if (window->state & GDK_SURFACE_STATE_ICONIFIED)
-    gdk_surface_iconify (window);
-
-  if (impl->transient_for && !GDK_SURFACE_DESTROYED (impl->transient_for))
-    _gdk_quartz_surface_attach_to_parent (window);
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-/* Temporarily unsets the parent window, if the window is a
- * transient. 
- */
-void
-_gdk_quartz_surface_detach_from_parent (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  
-  g_return_if_fail (impl->toplevel != NULL);
-
-  if (impl->transient_for && !GDK_SURFACE_DESTROYED (impl->transient_for))
-    {
-      GdkSurfaceImplQuartz *parent_impl;
-
-      parent_impl = GDK_SURFACE_IMPL_QUARTZ (impl->transient_for->impl);
-      [parent_impl->toplevel removeChildWindow:impl->toplevel];
-      clear_toplevel_order ();
-    }
-}
-
-/* Re-sets the parent window, if the window is a transient. */
-void
-_gdk_quartz_surface_attach_to_parent (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  
-  g_return_if_fail (impl->toplevel != NULL);
-
-  if (impl->transient_for && !GDK_SURFACE_DESTROYED (impl->transient_for))
-    {
-      GdkSurfaceImplQuartz *parent_impl;
-
-      parent_impl = GDK_SURFACE_IMPL_QUARTZ (impl->transient_for->impl);
-      [parent_impl->toplevel addChildWindow:impl->toplevel ordered:NSWindowAbove];
-      clear_toplevel_order ();
-    }
-}
-
-void
-gdk_surface_quartz_hide (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  /* Make sure we're not stuck in fullscreen mode. */
-#ifndef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
-  if (get_fullscreen_geometry (window))
-    SetSystemUIMode (kUIModeNormal, 0);
-#endif
-
-  _gdk_surface_clear_update_area (window);
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (WINDOW_IS_TOPLEVEL (window)) 
-    {
-     /* Update main window. */
-      main_window_stack = g_slist_remove (main_window_stack, window);
-      if ([NSApp mainWindow] == impl->toplevel)
-        _gdk_quartz_surface_did_resign_main (window);
-
-      if (impl->transient_for)
-        _gdk_quartz_surface_detach_from_parent (window);
-
-      [(GdkQuartzNSWindow*)impl->toplevel hide];
-    }
-  else if (impl->view)
-    {
-      [impl->view setHidden:YES];
-    }
-}
-
-void
-gdk_surface_quartz_withdraw (GdkSurface *window)
-{
-  gdk_surface_hide (window);
-}
-
-static void
-move_resize_window_internal (GdkSurface *window,
-                            gint       x,
-                            gint       y,
-                            gint       width,
-                            gint       height)
-{
-  GdkSurfaceImplQuartz *impl;
-  GdkRectangle old_visible;
-  GdkRectangle new_visible;
-  GdkRectangle scroll_rect;
-  cairo_region_t *old_region;
-  cairo_region_t *expose_region;
-  NSSize delta;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if ((x == -1 || (x == window->x)) &&
-      (y == -1 || (y == window->y)) &&
-      (width == -1 || (width == window->width)) &&
-      (height == -1 || (height == window->height)))
-    {
-      return;
-    }
-
-  if (!impl->toplevel)
-    {
-      /* The previously visible area of this window in a coordinate
-       * system rooted at the origin of this window.
-       */
-      old_visible.x = -window->x;
-      old_visible.y = -window->y;
-
-      old_visible.width = window->width;
-      old_visible.height = window->height;
-    }
-
-  if (x != -1)
-    {
-      delta.width = x - window->x;
-      window->x = x;
-    }
-  else
-    {
-      delta.width = 0;
-    }
-
-  if (y != -1)
-    {
-      delta.height = y - window->y;
-      window->y = y;
-    }
-  else
-    {
-      delta.height = 0;
-    }
-
-  if (width != -1)
-    window->width = width;
-
-  if (height != -1)
-    window->height = height;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  if (impl->toplevel)
-    {
-      NSRect content_rect;
-      NSRect frame_rect;
-      gint gx, gy;
-
-      _gdk_quartz_surface_gdk_xy_to_xy (window->x, window->y + window->height,
-                                       &gx, &gy);
-
-      content_rect = NSMakeRect (gx, gy, window->width, window->height);
-
-      frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
-      [impl->toplevel setFrame:frame_rect display:YES];
-    }
-  else 
-    {
-      if (!window->input_only)
-        {
-          NSRect nsrect;
-
-          nsrect = NSMakeRect (window->x, window->y, window->width, window->height);
-
-          /* The newly visible area of this window in a coordinate
-           * system rooted at the origin of this window.
-           */
-          new_visible.x = -window->x;
-          new_visible.y = -window->y;
-          new_visible.width = old_visible.width;   /* parent has not changed size */
-          new_visible.height = old_visible.height; /* parent has not changed size */
-
-          expose_region = cairo_region_create_rectangle (&new_visible);
-          old_region = cairo_region_create_rectangle (&old_visible);
-          cairo_region_subtract (expose_region, old_region);
-
-          /* Determine what (if any) part of the previously visible
-           * part of the window can be copied without a redraw
-           */
-          scroll_rect = old_visible;
-          scroll_rect.x -= delta.width;
-          scroll_rect.y -= delta.height;
-          gdk_rectangle_intersect (&scroll_rect, &old_visible, &scroll_rect);
-
-          if (!cairo_region_is_empty (expose_region))
-            {
-              if (scroll_rect.width != 0 && scroll_rect.height != 0)
-                {
-                  [impl->view scrollRect:NSMakeRect (scroll_rect.x,
-                                                     scroll_rect.y,
-                                                     scroll_rect.width,
-                                                     scroll_rect.height)
-                                     by:delta];
-                }
-
-              [impl->view setFrame:nsrect];
-
-              gdk_quartz_surface_set_needs_display_in_region (window, expose_region);
-            }
-          else
-            {
-              [impl->view setFrame:nsrect];
-              [impl->view setNeedsDisplay:YES];
-            }
-
-          cairo_region_destroy (expose_region);
-          cairo_region_destroy (old_region);
-        }
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-static inline void
-window_quartz_move (GdkSurface *window,
-                    gint       x,
-                    gint       y)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
-    return;
-
-  move_resize_window_internal (window, x, y, -1, -1);
-}
-
-static inline void
-window_quartz_resize (GdkSurface *window,
-                      gint       width,
-                      gint       height)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
-    return;
-
-  if (width < 1)
-    width = 1;
-  if (height < 1)
-    height = 1;
-
-  move_resize_window_internal (window, -1, -1, width, height);
-}
-
-static inline void
-window_quartz_move_resize (GdkSurface *window,
-                           gint       x,
-                           gint       y,
-                           gint       width,
-                           gint       height)
-{
-  if (width < 1)
-    width = 1;
-  if (height < 1)
-    height = 1;
-
-  move_resize_window_internal (window, x, y, width, height);
-}
-
-static void
-gdk_surface_quartz_move_resize (GdkSurface *window,
-                               gboolean   with_move,
-                               gint       x,
-                               gint       y,
-                               gint       width,
-                               gint       height)
-{
-  if (with_move && (width < 0 && height < 0))
-    window_quartz_move (window, x, y);
-  else
-    {
-      if (with_move)
-        window_quartz_move_resize (window, x, y, width, height);
-      else
-        window_quartz_resize (window, width, height);
-    }
-}
-
-/* Get the toplevel ordering from NSApp and update our own list. We do
- * this on demand since the NSApp’s list is not up to date directly
- * after we get windowDidBecomeMain.
- */
-static void
-update_toplevel_order (void)
-{
-  GdkSurfaceImplQuartz *root_impl;
-  NSEnumerator *enumerator;
-  id nswindow;
-  GList *toplevels = NULL;
-
-  root_impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
-
-  if (root_impl->sorted_children)
-    return;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  enumerator = [[NSApp orderedWindows] objectEnumerator];
-  while ((nswindow = [enumerator nextObject]))
-    {
-      GdkSurface *window;
-
-      if (![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
-        continue;
-
-      window = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
-      toplevels = g_list_prepend (toplevels, window);
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-
-  root_impl->sorted_children = g_list_reverse (toplevels);
-}
-
-static void
-clear_toplevel_order (void)
-{
-  GdkSurfaceImplQuartz *root_impl;
-
-  root_impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
-
-  g_list_free (root_impl->sorted_children);
-  root_impl->sorted_children = NULL;
-}
-
-static void
-gdk_surface_quartz_raise (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (WINDOW_IS_TOPLEVEL (window))
-    {
-      GdkSurfaceImplQuartz *impl;
-
-      impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-      [impl->toplevel orderFront:impl->toplevel];
-
-      clear_toplevel_order ();
-    }
-  else
-    {
-      GdkSurface *parent = window->parent;
-
-      if (parent)
-        {
-          GdkSurfaceImplQuartz *impl;
-
-          impl = (GdkSurfaceImplQuartz *)parent->impl;
-
-          impl->sorted_children = g_list_remove (impl->sorted_children, window);
-          impl->sorted_children = g_list_prepend (impl->sorted_children, window);
-        }
-    }
-}
-
-static void
-gdk_surface_quartz_lower (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (WINDOW_IS_TOPLEVEL (window))
-    {
-      GdkSurfaceImplQuartz *impl;
-
-      impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-      [impl->toplevel orderBack:impl->toplevel];
-
-      clear_toplevel_order ();
-    }
-  else
-    {
-      GdkSurface *parent = window->parent;
-
-      if (parent)
-        {
-          GdkSurfaceImplQuartz *impl;
-
-          impl = (GdkSurfaceImplQuartz *)parent->impl;
-
-          impl->sorted_children = g_list_remove (impl->sorted_children, window);
-          impl->sorted_children = g_list_append (impl->sorted_children, window);
-        }
-    }
-}
-
-static void
-gdk_surface_quartz_restack_toplevel (GdkSurface *window,
-                                   GdkSurface *sibling,
-                                   gboolean   above)
-{
-  GdkSurfaceImplQuartz *impl;
-  gint sibling_num;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (sibling->impl);
-  sibling_num = [impl->toplevel windowNumber];
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (above)
-    [impl->toplevel orderWindow:NSWindowAbove relativeTo:sibling_num];
-  else
-    [impl->toplevel orderWindow:NSWindowBelow relativeTo:sibling_num];
-}
-
-static void
-gdk_surface_quartz_get_geometry (GdkSurface *window,
-                                gint      *x,
-                                gint      *y,
-                                gint      *width,
-                                gint      *height)
-{
-  GdkSurfaceImplQuartz *impl;
-  NSRect ns_rect;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  if (window == _gdk_root)
-    {
-      if (x) 
-        *x = 0;
-      if (y) 
-        *y = 0;
-
-      if (width) 
-        *width = window->width;
-      if (height)
-        *height = window->height;
-    }
-  else if (WINDOW_IS_TOPLEVEL (window))
-    {
-      ns_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
-
-      /* This doesn't work exactly as in X. There doesn't seem to be a
-       * way to get the coords relative to the parent window (usually
-       * the window frame), but that seems useless except for
-       * borderless windows where it's relative to the root window. So
-       * we return (0, 0) (should be something like (0, 22)) for
-       * windows with borders and the root relative coordinates
-       * otherwise.
-       */
-      if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
-        {
-          _gdk_quartz_surface_xy_to_gdk_xy (ns_rect.origin.x,
-                                           ns_rect.origin.y + ns_rect.size.height,
-                                           x, y);
-        }
-      else 
-        {
-          if (x)
-            *x = 0;
-          if (y)
-            *y = 0;
-        }
-
-      if (width)
-        *width = ns_rect.size.width;
-      if (height)
-        *height = ns_rect.size.height;
-    }
-  else
-    {
-      ns_rect = [impl->view frame];
-      
-      if (x)
-        *x = ns_rect.origin.x;
-      if (y)
-        *y = ns_rect.origin.y;
-      if (width)
-        *width  = ns_rect.size.width;
-      if (height)
-        *height = ns_rect.size.height;
-    }
-}
-
-static void
-gdk_surface_quartz_get_root_coords (GdkSurface *window,
-                                   gint       x,
-                                   gint       y,
-                                   gint      *root_x,
-                                   gint      *root_y)
-{
-  int tmp_x = 0, tmp_y = 0;
-  GdkSurface *toplevel;
-  NSRect content_rect;
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window)) 
-    {
-      if (root_x)
-       *root_x = 0;
-      if (root_y)
-       *root_y = 0;
-      
-      return;
-    }
-
-  if (window == _gdk_root)
-    {
-      if (root_x)
-        *root_x = x;
-      if (root_y)
-        *root_y = y;
-
-      return;
-    }
-  
-  toplevel = gdk_surface_get_toplevel (window);
-  impl = GDK_SURFACE_IMPL_QUARTZ (toplevel->impl);
-
-  content_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
-
-  _gdk_quartz_surface_xy_to_gdk_xy (content_rect.origin.x,
-                                   content_rect.origin.y + content_rect.size.height,
-                                   &tmp_x, &tmp_y);
-
-  tmp_x += x;
-  tmp_y += y;
-
-  while (window != toplevel)
-    {
-      if (_gdk_surface_has_impl ((GdkSurface *)window))
-        {
-          tmp_x += window->x;
-          tmp_y += window->y;
-        }
-
-      window = window->parent;
-    }
-
-  if (root_x)
-    *root_x = tmp_x;
-  if (root_y)
-    *root_y = tmp_y;
-}
-
-/* Returns coordinates relative to the passed in window. */
-static GdkSurface *
-gdk_surface_quartz_get_device_state_helper (GdkSurface       *window,
-                                           GdkDevice       *device,
-                                           gdouble         *x,
-                                           gdouble         *y,
-                                           GdkModifierType *mask)
-{
-  NSPoint point;
-  gint x_tmp, y_tmp;
-  GdkSurface *toplevel;
-  GdkSurface *found_window;
-
-  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), NULL);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    {
-      *x = 0;
-      *y = 0;
-      *mask = 0;
-      return NULL;
-    }
-  
-  toplevel = gdk_surface_get_toplevel (window);
-
-  *mask = _gdk_quartz_events_get_current_keyboard_modifiers () |
-      _gdk_quartz_events_get_current_mouse_modifiers ();
-
-  /* Get the y coordinate, needs to be flipped. */
-  if (window == _gdk_root)
-    {
-      point = [NSEvent mouseLocation];
-      _gdk_quartz_surface_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
-    }
-  else
-    {
-      GdkSurfaceImplQuartz *impl;
-      NSWindow *nswindow;
-
-      impl = GDK_SURFACE_IMPL_QUARTZ (toplevel->impl);
-      nswindow = impl->toplevel;
-
-      point = [nswindow mouseLocationOutsideOfEventStream];
-
-      x_tmp = point.x;
-      y_tmp = toplevel->height - point.y;
-
-      window = (GdkSurface *)toplevel;
-    }
-
-  found_window = _gdk_quartz_surface_find_child (window, x_tmp, y_tmp,
-                                                FALSE);
-
-  /* We never return the root window. */
-  if (found_window == _gdk_root)
-    found_window = NULL;
-
-  *x = x_tmp;
-  *y = y_tmp;
-
-  return found_window;
-}
-
-static gboolean
-gdk_surface_quartz_get_device_state (GdkSurface       *window,
-                                    GdkDevice       *device,
-                                    gdouble          *x,
-                                    gdouble          *y,
-                                    GdkModifierType *mask)
-{
-  return gdk_surface_quartz_get_device_state_helper (window,
-                                                    device,
-                                                    x, y, mask) != NULL;
-}
-
-static GdkEventMask
-gdk_surface_quartz_get_events (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return 0;
-  else
-    return window->event_mask;
-}
-
-static void
-gdk_surface_quartz_set_events (GdkSurface       *window,
-                              GdkEventMask     event_mask)
-{
-  /* The mask is set in the common code. */
-}
-
-static void
-gdk_quartz_surface_set_urgency_hint (GdkSurface *window,
-                                    gboolean   urgent)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_surface_set_geometry_hints (GdkSurface         *window,
-                                      const GdkGeometry *geometry,
-                                      GdkSurfaceHints     geom_mask)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_return_if_fail (geometry != NULL);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-  
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  if (!impl->toplevel)
-    return;
-
-  if (geom_mask & GDK_HINT_POS)
-    {
-      /* FIXME: Implement */
-    }
-
-  if (geom_mask & GDK_HINT_USER_POS)
-    {
-      /* FIXME: Implement */
-    }
-
-  if (geom_mask & GDK_HINT_USER_SIZE)
-    {
-      /* FIXME: Implement */
-    }
-  
-  if (geom_mask & GDK_HINT_MIN_SIZE)
-    {
-      NSSize size;
-
-      size.width = geometry->min_width;
-      size.height = geometry->min_height;
-
-      [impl->toplevel setContentMinSize:size];
-    }
-  
-  if (geom_mask & GDK_HINT_MAX_SIZE)
-    {
-      NSSize size;
-
-      size.width = geometry->max_width;
-      size.height = geometry->max_height;
-
-      [impl->toplevel setContentMaxSize:size];
-    }
-  
-  if (geom_mask & GDK_HINT_BASE_SIZE)
-    {
-      /* FIXME: Implement */
-    }
-  
-  if (geom_mask & GDK_HINT_RESIZE_INC)
-    {
-      NSSize size;
-
-      size.width = geometry->width_inc;
-      size.height = geometry->height_inc;
-
-      [impl->toplevel setContentResizeIncrements:size];
-    }
-  
-  if (geom_mask & GDK_HINT_ASPECT)
-    {
-      NSSize size;
-
-      if (geometry->min_aspect != geometry->max_aspect)
-        {
-          g_warning ("Only equal minimum and maximum aspect ratios are supported on Mac OS. Using minimum aspect ratio...");
-        }
-
-      size.width = geometry->min_aspect;
-      size.height = 1.0;
-
-      [impl->toplevel setContentAspectRatio:size];
-    }
-
-  if (geom_mask & GDK_HINT_WIN_GRAVITY)
-    {
-      /* FIXME: Implement */
-    }
-}
-
-static void
-gdk_quartz_surface_set_title (GdkSurface   *window,
-                             const gchar *title)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_return_if_fail (title != NULL);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (impl->toplevel)
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-      [impl->toplevel setTitle:[NSString stringWithUTF8String:title]];
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-}
-
-static void
-gdk_quartz_surface_set_role (GdkSurface   *window,
-                            const gchar *role)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_surface_set_startup_id (GdkSurface   *window,
-                                  const gchar *startup_id)
-{
-  /* FIXME: Implement? */
-}
-
-static void
-gdk_quartz_surface_set_transient_for (GdkSurface *window,
-                                     GdkSurface *parent)
-{
-  GdkSurfaceImplQuartz *window_impl;
-  GdkSurfaceImplQuartz *parent_impl;
-
-  if (GDK_SURFACE_DESTROYED (window)  || GDK_SURFACE_DESTROYED (parent) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  window_impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  if (!window_impl->toplevel)
-    return;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  if (window_impl->transient_for)
-    {
-      _gdk_quartz_surface_detach_from_parent (window);
-
-      g_object_unref (window_impl->transient_for);
-      window_impl->transient_for = NULL;
-    }
-
-  parent_impl = GDK_SURFACE_IMPL_QUARTZ (parent->impl);
-  if (parent_impl->toplevel)
-    {
-      /* We save the parent because it needs to be unset/reset when
-       * hiding and showing the window. 
-       */
-
-      /* We don't set transients for tooltips, they are already
-       * handled by the window level being the top one. If we do, then
-       * the parent window will be brought to the top just because the
-       * tooltip is, which is not what we want.
-       */
-      if (gdk_surface_get_type_hint (window) != GDK_SURFACE_TYPE_HINT_TOOLTIP)
-        {
-          window_impl->transient_for = g_object_ref (parent);
-
-          /* We only add the window if it is shown, otherwise it will
-           * be shown unconditionally here. If it is not shown, the
-           * window will be added in show() instead.
-           */
-          if (!(window->state & GDK_SURFACE_STATE_WITHDRAWN))
-            _gdk_quartz_surface_attach_to_parent (window);
-        }
-    }
-  
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-static void
-gdk_surface_quartz_shape_combine_region (GdkSurface       *window,
-                                        const cairo_region_t *shape,
-                                        gint             x,
-                                        gint             y)
-{
-  /* FIXME: Implement */
-}
-
-static void
-gdk_surface_quartz_input_shape_combine_region (GdkSurface       *window,
-                                              const cairo_region_t *shape_region,
-                                              gint             offset_x,
-                                              gint             offset_y)
-{
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_surface_set_accept_focus (GdkSurface *window,
-                                    gboolean accept_focus)
-{
-  window->accept_focus = accept_focus != FALSE;
-}
-
-static void
-gdk_quartz_surface_set_focus_on_map (GdkSurface *window,
-                                    gboolean focus_on_map)
-{
-  window->focus_on_map = focus_on_map != FALSE;
-}
-
-static void
-gdk_quartz_surface_set_icon_name (GdkSurface   *window,
-                                 const gchar *name)
-{
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_surface_focus (GdkSurface *window,
-                         guint32    timestamp)
-{
-  GdkSurfaceImplQuartz *impl;
-       
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  if (window->accept_focus && window->window_type != GDK_SURFACE_TEMP)
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
-      clear_toplevel_order ();
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-}
-
-static gint
-window_type_hint_to_level (GdkSurfaceTypeHint hint)
-{
-  /*  the order in this switch statement corresponds to the actual
-   *  stacking order: the first group is top, the last group is bottom
-   */
-  switch (hint)
-    {
-    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
-    case GDK_SURFACE_TYPE_HINT_COMBO:
-    case GDK_SURFACE_TYPE_HINT_DND:
-    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
-      return NSPopUpMenuWindowLevel;
-
-    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
-    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
-      return NSStatusWindowLevel;
-
-    case GDK_SURFACE_TYPE_HINT_MENU: /* Torn-off menu */
-    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
-      return NSTornOffMenuWindowLevel;
-
-    case GDK_SURFACE_TYPE_HINT_DOCK:
-      return NSFloatingWindowLevel; /* NSDockWindowLevel is deprecated, and not replaced */
-
-    case GDK_SURFACE_TYPE_HINT_UTILITY:
-    case GDK_SURFACE_TYPE_HINT_DIALOG:  /* Dialog window */
-    case GDK_SURFACE_TYPE_HINT_NORMAL:  /* Normal toplevel window */
-    case GDK_SURFACE_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
-      return NSNormalWindowLevel;
-
-    case GDK_SURFACE_TYPE_HINT_DESKTOP:
-      return kCGDesktopWindowLevelKey; /* doesn't map to any real Cocoa model */
-
-    default:
-      break;
-    }
-
-  return NSNormalWindowLevel;
-}
-
-static gboolean
-window_type_hint_to_shadow (GdkSurfaceTypeHint hint)
-{
-  switch (hint)
-    {
-    case GDK_SURFACE_TYPE_HINT_NORMAL:  /* Normal toplevel window */
-    case GDK_SURFACE_TYPE_HINT_DIALOG:  /* Dialog window */
-    case GDK_SURFACE_TYPE_HINT_DOCK:
-    case GDK_SURFACE_TYPE_HINT_UTILITY:
-    case GDK_SURFACE_TYPE_HINT_MENU: /* Torn-off menu */
-    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
-    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
-    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
-    case GDK_SURFACE_TYPE_HINT_COMBO:
-    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
-    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
-      return TRUE;
-
-    case GDK_SURFACE_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
-    case GDK_SURFACE_TYPE_HINT_DESKTOP: /* N/A */
-    case GDK_SURFACE_TYPE_HINT_DND:
-      break;
-
-    default:
-      break;
-    }
-
-  return FALSE;
-}
-
-static gboolean
-window_type_hint_to_hides_on_deactivate (GdkSurfaceTypeHint hint)
-{
-  switch (hint)
-    {
-    case GDK_SURFACE_TYPE_HINT_UTILITY:
-    case GDK_SURFACE_TYPE_HINT_MENU: /* Torn-off menu */
-    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
-    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
-    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
-      return TRUE;
-
-    default:
-      break;
-    }
-
-  return FALSE;
-}
-
-static void
-_gdk_quartz_surface_update_has_shadow (GdkSurfaceImplQuartz *impl)
-{
-    gboolean has_shadow;
-
-    /* In case there is any shadow set we have to turn off the
-     * NSWindow setHasShadow as the system drawn ones wont match our
-     * window boundary anymore */
-    has_shadow = (window_type_hint_to_shadow (impl->type_hint) && !impl->shadow_max);
-
-    [impl->toplevel setHasShadow: has_shadow];
-}
-
-static void
-gdk_quartz_surface_set_type_hint (GdkSurface        *window,
-                                 GdkSurfaceTypeHint hint)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  impl->type_hint = hint;
-
-  /* Match the documentation, only do something if we're not mapped yet. */
-  if (GDK_SURFACE_IS_MAPPED (window))
-    return;
-
-  _gdk_quartz_surface_update_has_shadow (impl);
-  [impl->toplevel setLevel: window_type_hint_to_level (hint)];
-  [impl->toplevel setHidesOnDeactivate: window_type_hint_to_hides_on_deactivate (hint)];
-}
-
-static GdkSurfaceTypeHint
-gdk_quartz_surface_get_type_hint (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return GDK_SURFACE_TYPE_HINT_NORMAL;
-  
-  return GDK_SURFACE_IMPL_QUARTZ (window->impl)->type_hint;
-}
-
-static void
-gdk_quartz_surface_set_modal_hint (GdkSurface *window,
-                                  gboolean   modal)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_surface_set_skip_taskbar_hint (GdkSurface *window,
-                                         gboolean   skips_taskbar)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_surface_set_skip_pager_hint (GdkSurface *window,
-                                       gboolean   skips_pager)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_surface_begin_resize_drag (GdkSurface     *window,
-                                     GdkSurfaceEdge  edge,
-                                     GdkDevice     *device,
-                                     gint           button,
-                                     gint           root_x,
-                                     gint           root_y,
-                                     guint32        timestamp)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (!impl->toplevel)
-    {
-      g_warning ("Can't call gdk_surface_begin_resize_drag on non-toplevel window");
-      return;
-    }
-
-  [(GdkQuartzNSWindow *)impl->toplevel beginManualResize:edge];
-}
-
-static void
-gdk_quartz_surface_begin_move_drag (GdkSurface *window,
-                                   GdkDevice *device,
-                                   gint       button,
-                                   gint       root_x,
-                                   gint       root_y,
-                                   guint32    timestamp)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (!impl->toplevel)
-    {
-      g_warning ("Can't call gdk_surface_begin_move_drag on non-toplevel window");
-      return;
-    }
-
-  [(GdkQuartzNSWindow *)impl->toplevel beginManualMove];
-}
-
-static void
-gdk_quartz_surface_set_icon_list (GdkSurface *window,
-                                 GList     *surfaces)
-{
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_surface_get_frame_extents (GdkSurface    *window,
-                                     GdkRectangle *rect)
-{
-  GdkSurface *toplevel;
-  GdkSurfaceImplQuartz *impl;
-  NSRect ns_rect;
-
-  g_return_if_fail (rect != NULL);
-
-
-  rect->x = 0;
-  rect->y = 0;
-  rect->width = 1;
-  rect->height = 1;
-  
-  toplevel = gdk_surface_get_toplevel (window);
-  impl = GDK_SURFACE_IMPL_QUARTZ (toplevel->impl);
-
-  ns_rect = [impl->toplevel frame];
-
-  _gdk_quartz_surface_xy_to_gdk_xy (ns_rect.origin.x,
-                                   ns_rect.origin.y + ns_rect.size.height,
-                                   &rect->x, &rect->y);
-
-  rect->width = ns_rect.size.width;
-  rect->height = ns_rect.size.height;
-}
-
-/* Fake protocol to make gcc think that it's OK to call setStyleMask
-   even if it isn't. We check to make sure before actually calling
-   it. */
-
-@protocol CanSetStyleMask
-- (void)setStyleMask:(int)mask;
-@end
-
-static void
-gdk_quartz_surface_set_decorations (GdkSurface       *window,
-                           GdkWMDecoration  decorations)
-{
-  GdkSurfaceImplQuartz *impl;
-  NSUInteger old_mask, new_mask;
-  NSView *old_view;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (decorations == 0 || GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP ||
-      impl->type_hint == GDK_SURFACE_TYPE_HINT_SPLASHSCREEN )
-    {
-      new_mask = NSBorderlessWindowMask;
-    }
-  else
-    {
-      /* FIXME: Honor other GDK_DECOR_* flags. */
-      new_mask = (NSTitledWindowMask | NSClosableWindowMask |
-                    NSMiniaturizableWindowMask | NSResizableWindowMask);
-    }
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  old_mask = [impl->toplevel styleMask];
-
-  if (old_mask != new_mask)
-    {
-      NSRect rect;
-
-      old_view = [[impl->toplevel contentView] retain];
-
-      rect = [impl->toplevel frame];
-
-      /* Properly update the size of the window when the titlebar is
-       * added or removed.
-       */
-      if (old_mask == NSBorderlessWindowMask &&
-          new_mask != NSBorderlessWindowMask)
-        {
-          rect = [NSWindow frameRectForContentRect:rect styleMask:new_mask];
-
-        }
-      else if (old_mask != NSBorderlessWindowMask &&
-               new_mask == NSBorderlessWindowMask)
-        {
-          rect = [NSWindow contentRectForFrameRect:rect styleMask:old_mask];
-        }
-
-      /* Note, before OS 10.6 there doesn't seem to be a way to change this
-       * without recreating the toplevel. From 10.6 onward, a simple call to
-       * setStyleMask takes care of most of this, except for ensuring that the
-       * title is set.
-       */
-      if ([impl->toplevel respondsToSelector:@selector(setStyleMask:)])
-        {
-          NSString *title = [impl->toplevel title];
-
-          [(id<CanSetStyleMask>)impl->toplevel setStyleMask:new_mask];
-
-          /* It appears that unsetting and then resetting NSTitledWindowMask
-           * does not reset the title in the title bar as might be expected.
-           *
-           * In theory we only need to set this if new_mask includes
-           * NSTitledWindowMask. This behaved extremely oddly when
-           * conditionalized upon that and since it has no side effects (i.e.
-           * if NSTitledWindowMask is not requested, the title will not be
-           * displayed) just do it unconditionally. We also must null check
-           * 'title' before setting it to avoid crashing.
-           */
-          if (title)
-            [impl->toplevel setTitle:title];
-        }
-      else
-        {
-          NSString *title = [impl->toplevel title];
-          NSColor *bg = [impl->toplevel backgroundColor];
-          NSScreen *screen = [impl->toplevel screen];
-
-          /* Make sure the old window is closed, recall that releasedWhenClosed
-           * is set on GdkQuartzSurfaces.
-           */
-          [impl->toplevel close];
-
-          impl->toplevel = [[GdkQuartzNSWindow alloc] initWithContentRect:rect
-                                                                styleMask:new_mask
-                                                                  backing:NSBackingStoreBuffered
-                                                                    defer:NO
-                                                                   screen:screen];
-          _gdk_quartz_surface_update_has_shadow (impl);
-
-          [impl->toplevel setLevel: window_type_hint_to_level (impl->type_hint)];
-          if (title)
-            [impl->toplevel setTitle:title];
-          [impl->toplevel setBackgroundColor:bg];
-          [impl->toplevel setHidesOnDeactivate: window_type_hint_to_hides_on_deactivate (impl->type_hint)];
-          [impl->toplevel setContentView:old_view];
-        }
-
-      if (new_mask == NSBorderlessWindowMask)
-        {
-          [impl->toplevel setContentSize:rect.size];
-          [impl->toplevel setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
-        }
-      else
-        [impl->toplevel setFrame:rect display:YES];
-
-      /* Invalidate the window shadow for non-opaque views that have shadow
-       * enabled, to get the shadow shape updated.
-       */
-      if (![old_view isOpaque] && [impl->toplevel hasShadow])
-        [(GdkQuartzView*)old_view setNeedsInvalidateShadow:YES];
-
-      [old_view release];
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-static gboolean
-gdk_quartz_surface_get_decorations (GdkSurface       *window,
-                                   GdkWMDecoration *decorations)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return FALSE;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (decorations)
-    {
-      /* Borderless is 0, so we can't check it as a bit being set. */
-      if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
-        {
-          *decorations = 0;
-        }
-      else
-        {
-          /* FIXME: Honor the other GDK_DECOR_* flags. */
-          *decorations = GDK_DECOR_ALL;
-        }
-    }
-
-  return TRUE;
-}
-
-static void
-gdk_quartz_surface_set_functions (GdkSurface    *window,
-                                 GdkWMFunction functions)
-{
-  GdkSurfaceImplQuartz *impl;
-  gboolean min, max, close;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (functions & GDK_FUNC_ALL)
-    {
-      min = !(functions & GDK_FUNC_MINIMIZE);
-      max = !(functions & GDK_FUNC_MAXIMIZE);
-      close = !(functions & GDK_FUNC_CLOSE);
-    }
-  else
-    {
-      min = (functions & GDK_FUNC_MINIMIZE);
-      max = (functions & GDK_FUNC_MAXIMIZE);
-      close = (functions & GDK_FUNC_CLOSE);
-    }
-
-  if (impl->toplevel)
-    {
-      NSUInteger mask = [impl->toplevel styleMask];
-
-      if (min)
-        mask = mask | NSMiniaturizableWindowMask;
-      else
-        mask = mask & ~NSMiniaturizableWindowMask;
-
-      if (max)
-        mask = mask | NSResizableWindowMask;
-      else
-        mask = mask & ~NSResizableWindowMask;
-
-      if (close)
-        mask = mask | NSClosableWindowMask;
-      else
-        mask = mask & ~NSClosableWindowMask;
-
-      [impl->toplevel setStyleMask:mask];
-    }
-}
-
-static void
-gdk_quartz_surface_stick (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-}
-
-static void
-gdk_quartz_surface_unstick (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-}
-
-static void
-gdk_quartz_surface_maximize (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-  gboolean maximized;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      if (impl->toplevel && !maximized)
-        [impl->toplevel zoom:nil];
-
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-}
-
-static void
-gdk_quartz_surface_unmaximize (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-  gboolean maximized;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      if (impl->toplevel && maximized)
-        [impl->toplevel zoom:nil];
-
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-}
-
-static void
-gdk_quartz_surface_iconify (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      if (impl->toplevel)
-       [impl->toplevel miniaturize:nil];
-
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-  else
-    {
-      gdk_synthesize_window_state (window,
-                                  0,
-                                  GDK_SURFACE_STATE_ICONIFIED);
-    }
-}
-
-static void
-gdk_quartz_surface_deiconify (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      if (impl->toplevel)
-       [impl->toplevel deminiaturize:nil];
-
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-  else
-    {
-      gdk_synthesize_window_state (window,
-                                  GDK_SURFACE_STATE_ICONIFIED,
-                                  0);
-    }
-}
-
-#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
-
-static gboolean
-window_is_fullscreen (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  return ([impl->toplevel styleMask] & NSFullScreenWindowMask) != 0;
-}
-
-static void
-gdk_quartz_surface_fullscreen (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (!window_is_fullscreen (window))
-    [impl->toplevel toggleFullScreen:nil];
-}
-
-static void
-gdk_quartz_surface_unfullscreen (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (window_is_fullscreen (window))
-    [impl->toplevel toggleFullScreen:nil];
-}
-
-void
-_gdk_quartz_surface_update_fullscreen_state (GdkSurface *window)
-{
-  gboolean is_fullscreen;
-  gboolean was_fullscreen;
-
-  is_fullscreen = window_is_fullscreen (window);
-  was_fullscreen = (gdk_surface_get_state (window) & GDK_SURFACE_STATE_FULLSCREEN) != 0;
-
-  if (is_fullscreen != was_fullscreen)
-    {
-      if (is_fullscreen)
-        gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
-      else
-        gdk_synthesize_window_state (window, GDK_SURFACE_STATE_FULLSCREEN, 0);
-    }
-}
-
-#else
-
-static FullscreenSavedGeometry *
-get_fullscreen_geometry (GdkSurface *window)
-{
-  return g_object_get_data (G_OBJECT (window), FULLSCREEN_DATA);
-}
-
-static void
-gdk_quartz_surface_fullscreen (GdkSurface *window)
-{
-  FullscreenSavedGeometry *geometry;
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  NSRect frame;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  geometry = get_fullscreen_geometry (window);
-  if (!geometry)
-    {
-      geometry = g_new (FullscreenSavedGeometry, 1);
-
-      geometry->x = window->x;
-      geometry->y = window->y;
-      geometry->width = window->width;
-      geometry->height = window->height;
-
-      if (!gdk_surface_get_decorations (window, &geometry->decor))
-        geometry->decor = GDK_DECOR_ALL;
-
-      g_object_set_data_full (G_OBJECT (window),
-                              FULLSCREEN_DATA, geometry, 
-                              g_free);
-
-      gdk_surface_set_decorations (window, 0);
-
-      frame = [[impl->toplevel screen] frame];
-      move_resize_window_internal (window,
-                                   0, 0, 
-                                   frame.size.width, frame.size.height);
-      [impl->toplevel setContentSize:frame.size];
-      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
-
-      clear_toplevel_order ();
-    }
-
-  SetSystemUIMode (kUIModeAllHidden, kUIOptionAutoShowMenuBar);
-
-  gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
-}
-
-static void
-gdk_quartz_surface_unfullscreen (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  FullscreenSavedGeometry *geometry;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  geometry = get_fullscreen_geometry (window);
-  if (geometry)
-    {
-      SetSystemUIMode (kUIModeNormal, 0);
-
-      move_resize_window_internal (window,
-                                   geometry->x,
-                                   geometry->y,
-                                   geometry->width,
-                                   geometry->height);
-      
-      gdk_surface_set_decorations (window, geometry->decor);
-
-      g_object_set_data (G_OBJECT (window), FULLSCREEN_DATA, NULL);
-
-      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
-      clear_toplevel_order ();
-
-      gdk_synthesize_window_state (window, GDK_SURFACE_STATE_FULLSCREEN, 0);
-    }
-}
-
-#endif
-
-static void
-gdk_quartz_surface_set_keep_above (GdkSurface *window,
-                                  gboolean   setting)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  gint level;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  level = window_type_hint_to_level (gdk_surface_get_type_hint (window));
-  
-  /* Adjust normal window level by one if necessary. */
-  [impl->toplevel setLevel: level + (setting ? 1 : 0)];
-}
-
-static void
-gdk_quartz_surface_set_keep_below (GdkSurface *window,
-                                  gboolean   setting)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  gint level;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-  
-  level = window_type_hint_to_level (gdk_surface_get_type_hint (window));
-  
-  /* Adjust normal window level by one if necessary. */
-  [impl->toplevel setLevel: level - (setting ? 1 : 0)];
-}
-
-static GdkSurface *
-gdk_quartz_surface_get_group (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD, NULL);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return NULL;
-
-  /* FIXME: Implement */
-
-  return NULL;
-}
-
-static void
-gdk_quartz_surface_set_group (GdkSurface *window,
-                             GdkSurface *leader)
-{
-  /* FIXME: Implement */       
-}
-
-static void
-gdk_quartz_surface_destroy_notify (GdkSurface *window)
-{
-  check_grab_destroy (window);
-}
-
-static void
-gdk_quartz_surface_set_opacity (GdkSurface *window,
-                               gdouble    opacity)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  if (opacity < 0)
-    opacity = 0;
-  else if (opacity > 1)
-    opacity = 1;
-
-  [impl->toplevel setAlphaValue: opacity];
-}
-
-static void
-gdk_quartz_surface_set_shadow_width (GdkSurface *window,
-                                    gint       left,
-                                    gint       right,
-                                    gint       top,
-                                    gint       bottom)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl->shadow_top = top;
-  impl->shadow_max = MAX (MAX (left, right), MAX (top, bottom));
-  _gdk_quartz_surface_update_has_shadow (impl);
-}
-
-/* Protocol to build cleanly for OSX < 10.7 */
-@protocol ScaleFactor
-- (CGFloat) backingScaleFactor;
-@end
-
-static gint
-gdk_quartz_surface_get_scale_factor (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return 1;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (impl->toplevel != NULL && gdk_quartz_osx_version() >= GDK_OSX_LION)
-    return [(id <ScaleFactor>) impl->toplevel backingScaleFactor];
-
-  return 1;
-}
-
-static void
-gdk_surface_impl_quartz_class_init (GdkSurfaceImplQuartzClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_CLASS (klass);
-  GdkSurfaceImplQuartzClass *impl_quartz_class = GDK_SURFACE_IMPL_QUARTZ_CLASS (klass);
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  object_class->finalize = gdk_surface_impl_quartz_finalize;
-
-  impl_class->ref_cairo_surface = gdk_quartz_ref_cairo_surface;
-  impl_class->show = gdk_surface_quartz_show;
-  impl_class->hide = gdk_surface_quartz_hide;
-  impl_class->withdraw = gdk_surface_quartz_withdraw;
-  impl_class->set_events = gdk_surface_quartz_set_events;
-  impl_class->get_events = gdk_surface_quartz_get_events;
-  impl_class->raise = gdk_surface_quartz_raise;
-  impl_class->lower = gdk_surface_quartz_lower;
-  impl_class->restack_toplevel = gdk_surface_quartz_restack_toplevel;
-  impl_class->move_resize = gdk_surface_quartz_move_resize;
-  impl_class->get_geometry = gdk_surface_quartz_get_geometry;
-  impl_class->get_root_coords = gdk_surface_quartz_get_root_coords;
-  impl_class->get_device_state = gdk_surface_quartz_get_device_state;
-  impl_class->shape_combine_region = gdk_surface_quartz_shape_combine_region;
-  impl_class->input_shape_combine_region = gdk_surface_quartz_input_shape_combine_region;
-  impl_class->destroy = gdk_quartz_surface_destroy;
-  impl_class->begin_paint = gdk_surface_impl_quartz_begin_paint;
-  impl_class->get_scale_factor = gdk_quartz_surface_get_scale_factor;
-
-  impl_class->focus = gdk_quartz_surface_focus;
-  impl_class->set_type_hint = gdk_quartz_surface_set_type_hint;
-  impl_class->get_type_hint = gdk_quartz_surface_get_type_hint;
-  impl_class->set_modal_hint = gdk_quartz_surface_set_modal_hint;
-  impl_class->set_skip_taskbar_hint = gdk_quartz_surface_set_skip_taskbar_hint;
-  impl_class->set_skip_pager_hint = gdk_quartz_surface_set_skip_pager_hint;
-  impl_class->set_urgency_hint = gdk_quartz_surface_set_urgency_hint;
-  impl_class->set_geometry_hints = gdk_quartz_surface_set_geometry_hints;
-  impl_class->set_title = gdk_quartz_surface_set_title;
-  impl_class->set_role = gdk_quartz_surface_set_role;
-  impl_class->set_startup_id = gdk_quartz_surface_set_startup_id;
-  impl_class->set_transient_for = gdk_quartz_surface_set_transient_for;
-  impl_class->get_frame_extents = gdk_quartz_surface_get_frame_extents;
-  impl_class->set_accept_focus = gdk_quartz_surface_set_accept_focus;
-  impl_class->set_focus_on_map = gdk_quartz_surface_set_focus_on_map;
-  impl_class->set_icon_list = gdk_quartz_surface_set_icon_list;
-  impl_class->set_icon_name = gdk_quartz_surface_set_icon_name;
-  impl_class->iconify = gdk_quartz_surface_iconify;
-  impl_class->deiconify = gdk_quartz_surface_deiconify;
-  impl_class->stick = gdk_quartz_surface_stick;
-  impl_class->unstick = gdk_quartz_surface_unstick;
-  impl_class->maximize = gdk_quartz_surface_maximize;
-  impl_class->unmaximize = gdk_quartz_surface_unmaximize;
-  impl_class->fullscreen = gdk_quartz_surface_fullscreen;
-  impl_class->unfullscreen = gdk_quartz_surface_unfullscreen;
-  impl_class->set_keep_above = gdk_quartz_surface_set_keep_above;
-  impl_class->set_keep_below = gdk_quartz_surface_set_keep_below;
-  impl_class->get_group = gdk_quartz_surface_get_group;
-  impl_class->set_group = gdk_quartz_surface_set_group;
-  impl_class->set_decorations = gdk_quartz_surface_set_decorations;
-  impl_class->get_decorations = gdk_quartz_surface_get_decorations;
-  impl_class->set_functions = gdk_quartz_surface_set_functions;
-  impl_class->set_functions = gdk_quartz_surface_set_functions;
-  impl_class->begin_resize_drag = gdk_quartz_surface_begin_resize_drag;
-  impl_class->begin_move_drag = gdk_quartz_surface_begin_move_drag;
-  impl_class->set_opacity = gdk_quartz_surface_set_opacity;
-  impl_class->set_shadow_width = gdk_quartz_surface_set_shadow_width;
-  impl_class->destroy_notify = gdk_quartz_surface_destroy_notify;
-  impl_class->register_dnd = _gdk_quartz_surface_register_dnd;
-  impl_class->drag_begin = _gdk_quartz_surface_drag_begin;
-  impl_class->process_updates_recurse = _gdk_quartz_surface_process_updates_recurse;
-
-  impl_class->create_gl_context = gdk_quartz_surface_create_gl_context;
-
-  impl_quartz_class->get_context = gdk_surface_impl_quartz_get_context;
-  impl_quartz_class->release_context = gdk_surface_impl_quartz_release_context;
-}
-
-GType
-_gdk_surface_impl_quartz_get_type (void)
-{
-  static GType object_type = 0;
-
-  if (!object_type)
-    {
-      const GTypeInfo object_info =
-       {
-         sizeof (GdkSurfaceImplQuartzClass),
-         (GBaseInitFunc) NULL,
-         (GBaseFinalizeFunc) NULL,
-         (GClassInitFunc) gdk_surface_impl_quartz_class_init,
-         NULL,           /* class_finalize */
-         NULL,           /* class_data */
-         sizeof (GdkSurfaceImplQuartz),
-         0,              /* n_preallocs */
-         (GInstanceInitFunc) gdk_surface_impl_quartz_init,
-       };
-
-      object_type = g_type_register_static (GDK_TYPE_SURFACE_IMPL,
-                                            "GdkSurfaceImplQuartz",
-                                            &object_info, 0);
-    }
-
-  return object_type;
-}
-
-CGContextRef
-gdk_quartz_surface_get_context (GdkSurfaceImplQuartz  *window,
-                               gboolean             antialias)
-{
-  if (!GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->get_context)
-    {
-      g_warning ("%s doesn't implement GdkSurfaceImplQuartzClass::get_context()",
-                 G_OBJECT_TYPE_NAME (window));
-      return NULL;
-    }
-
-  return GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->get_context (window, antialias);
-}
-
-void
-gdk_quartz_surface_release_context (GdkSurfaceImplQuartz  *window,
-                                   CGContextRef          cg_context)
-{
-  if (!GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->release_context)
-    {
-      g_warning ("%s doesn't implement GdkSurfaceImplQuartzClass::release_context()",
-                 G_OBJECT_TYPE_NAME (window));
-      return;
-    }
-
-  GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->release_context (window, cg_context);
-}
-
-
-
-static CGContextRef
-gdk_root_window_impl_quartz_get_context (GdkSurfaceImplQuartz *window,
-                                         gboolean             antialias)
-{
-  CGColorSpaceRef colorspace;
-  CGContextRef cg_context;
-  GdkSurfaceImplQuartz *window_impl = GDK_SURFACE_IMPL_QUARTZ (window);
-
-  if (GDK_SURFACE_DESTROYED (window_impl->wrapper))
-    return NULL;
-
-  /* We do not have the notion of a root window on OS X.  We fake this
-   * by creating a 1x1 bitmap and return a context to that.
-   */
-  colorspace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
-  cg_context = CGBitmapContextCreate (NULL,
-                                      1, 1, 8, 4, colorspace,
-                                      kCGImageAlphaPremultipliedLast);
-  CGColorSpaceRelease (colorspace);
-
-  return cg_context;
-}
-
-static void
-gdk_root_window_impl_quartz_release_context (GdkSurfaceImplQuartz *window,
-                                             CGContextRef         cg_context)
-{
-  CGContextRelease (cg_context);
-}
-
-static void
-gdk_root_window_impl_quartz_class_init (GdkRootWindowImplQuartzClass *klass)
-{
-  GdkSurfaceImplQuartzClass *window_quartz_class = GDK_SURFACE_IMPL_QUARTZ_CLASS (klass);
-
-  root_window_parent_class = g_type_class_peek_parent (klass);
-
-  window_quartz_class->get_context = gdk_root_window_impl_quartz_get_context;
-  window_quartz_class->release_context = gdk_root_window_impl_quartz_release_context;
-}
-
-static void
-gdk_root_window_impl_quartz_init (GdkRootWindowImplQuartz *impl)
-{
-}
-
-GType
-_gdk_root_window_impl_quartz_get_type (void)
-{
-  static GType object_type = 0;
-
-  if (!object_type)
-    {
-      const GTypeInfo object_info =
-        {
-          sizeof (GdkRootWindowImplQuartzClass),
-          (GBaseInitFunc) NULL,
-          (GBaseFinalizeFunc) NULL,
-          (GClassInitFunc) gdk_root_window_impl_quartz_class_init,
-          NULL,           /* class_finalize */
-          NULL,           /* class_data */
-          sizeof (GdkRootWindowImplQuartz),
-          0,              /* n_preallocs */
-          (GInstanceInitFunc) gdk_root_window_impl_quartz_init,
-        };
-
-      object_type = g_type_register_static (GDK_TYPE_SURFACE_IMPL_QUARTZ,
-                                            "GdkRootWindowQuartz",
-                                            &object_info, 0);
-    }
-
-  return object_type;
-}
-
-GList *
-get_toplevels (void)
-{
-  update_toplevel_order ();
-  return GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl)->sorted_children;
-}
diff --git a/gdk/quartz/gdkwindow-quartz.h b/gdk/quartz/gdkwindow-quartz.h
deleted file mode 100644 (file)
index cbadd75..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/* gdkdrawable-quartz.h
- *
- * Copyright (C) 2005 Imendio AB
- *
- * 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_SURFACE_QUARTZ_H__
-#define __GDK_SURFACE_QUARTZ_H__
-
-#import <gdk/quartz/GdkQuartzView.h>
-#import <gdk/quartz/GdkQuartzNSWindow.h>
-#include "gdk/gdkwindowimpl.h"
-
-G_BEGIN_DECLS
-
-/* Window implementation for Quartz
- */
-
-typedef struct _GdkSurfaceImplQuartz GdkSurfaceImplQuartz;
-typedef struct _GdkSurfaceImplQuartzClass GdkSurfaceImplQuartzClass;
-
-#define GDK_TYPE_SURFACE_IMPL_QUARTZ              (_gdk_surface_impl_quartz_get_type ())
-#define GDK_SURFACE_IMPL_QUARTZ(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartz))
-#define GDK_SURFACE_IMPL_QUARTZ_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartzClass))
-#define GDK_IS_SURFACE_IMPL_QUARTZ(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_QUARTZ))
-#define GDK_IS_SURFACE_IMPL_QUARTZ_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_QUARTZ))
-#define GDK_SURFACE_IMPL_QUARTZ_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartzClass))
-
-struct _GdkSurfaceImplQuartz
-{
-  GdkSurfaceImpl parent_instance;
-
-  GdkSurface *wrapper;
-
-  NSWindow *toplevel;
-  NSTrackingRectTag tracking_rect;
-  GdkQuartzView *view;
-
-  GdkSurfaceTypeHint type_hint;
-
-  gint in_paint_rect_count;
-
-  GdkSurface *transient_for;
-
-  /* Sorted by z-order */
-  GList *sorted_children;
-
-  cairo_region_t *needs_display_region;
-
-  cairo_surface_t *cairo_surface;
-
-  gint shadow_top;
-
-  gint shadow_max;
-};
-struct _GdkSurfaceImplQuartzClass 
-{
-  GdkSurfaceImplClass parent_class;
-
-  CGContextRef  (* get_context)     (GdkSurfaceImplQuartz *window,
-                                     gboolean             antialias);
-  void          (* release_context) (GdkSurfaceImplQuartz *window,
-                                     CGContextRef         cg_context);
-};
-
-GType _gdk_surface_impl_quartz_get_type (void);
-
-CGContextRef gdk_quartz_surface_get_context     (GdkSurfaceImplQuartz *window,
-                                                gboolean             antialias);
-void         gdk_quartz_surface_release_context (GdkSurfaceImplQuartz *window,
-                                                CGContextRef         context);
-
-/* Root window implementation for Quartz
- */
-
-typedef struct _GdkRootWindowImplQuartz GdkRootWindowImplQuartz;
-typedef struct _GdkRootWindowImplQuartzClass GdkRootWindowImplQuartzClass;
-
-#define GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ              (_gdk_root_window_impl_quartz_get_type ())
-#define GDK_ROOT_WINDOW_IMPL_QUARTZ(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartz))
-#define GDK_ROOT_WINDOW_IMPL_QUARTZ_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartzClass))
-#define GDK_IS_ROOT_WINDOW_IMPL_QUARTZ(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ))
-#define GDK_IS_ROOT_WINDOW_IMPL_QUARTZ_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ))
-#define GDK_ROOT_WINDOW_IMPL_QUARTZ_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartzClass))
-
-struct _GdkRootWindowImplQuartz
-{
-  GdkSurfaceImplQuartz parent_instance;
-};
-struct _GdkRootWindowImplQuartzClass 
-{
-  GdkSurfaceImplQuartzClass parent_class;
-};
-
-GType _gdk_root_window_impl_quartz_get_type (void);
-
-GList *get_toplevels (void);
-
-G_END_DECLS
-
-#endif /* __GDK_SURFACE_QUARTZ_H__ */
index acacd791a8999738d05055a64391a6d5de24d041..8d2e0fc2c309b2b335e6bc617a4dc04dfb6d71eb 100644 (file)
@@ -16,7 +16,7 @@ gdk_quartz_sources = files([
   'gdkscreen-quartz.c',
   'gdkselection-quartz.c',
   'gdkutils-quartz.c',
-  'gdkwindow-quartz.c',
+  'gdksurface-quartz.c',
 ])
 
 gdk_quartz_public_headers = files([
@@ -29,7 +29,7 @@ gdk_quartz_public_headers = files([
   'gdkquartzkeys.h',
   'gdkquartzscreen.h',
   'gdkquartzutils.h',
-  'gdkquartzwindow.h',
+  'gdkquartzsurface.h',
 ])
 
 install_headers(gdk_quartz_public_headers, subdir: 'gtk-4.0/gdk/quartz/')
index 7e9de9b08b41d67e1fdcaf55225226db498ec475..d4bbd2ef0d95d9eb55cbe6bd6c3551466a38d611 100644 (file)
@@ -22,7 +22,7 @@
 #include <errno.h>
 
 #include <string.h>
-#include <gdk/gdkwindow.h>
+#include <gdk/gdksurface.h>
 #include <gdk/gdktypes.h>
 #include "gdkclipboard-wayland.h"
 #include "gdkclipboardprivate.h"
index 5b0fa7918b340df44d086458d7078c8023c3ceda..625b5e2f4ad516a0af51de7631ae1cd9620f471b 100644 (file)
@@ -37,7 +37,7 @@
 
 #include <glib.h>
 #include <gdk/gdkkeys.h>
-#include <gdk/gdkwindow.h>
+#include <gdk/gdksurface.h>
 #include <gdk/gdkinternals.h>
 #include <gdk/gdk.h>           /* For gdk_get_program_class() */
 
index 6df899156a21e309444e0b3e34c552eb6da7795b..9fe7d8447e3d2079afefd4db9d0b8d10690b4367 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "gdkwaylanddisplay.h"
 #include "gdkwaylandglcontext.h"
-#include "gdkwaylandwindow.h"
+#include "gdkwaylandsurface.h"
 #include "gdkprivate-wayland.h"
 
 #include "gdkinternals.h"
index 3b98c3b7cf00290ba8762ceea1a7bc1009a1bdaa..e402994979b41cfb28e069c5f615b180ec229e7d 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "gdkglcontextprivate.h"
 #include "gdkdisplayprivate.h"
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkinternals.h"
 
 #include <epoxy/egl.h>
diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
new file mode 100644 (file)
index 0000000..99d02bf
--- /dev/null
@@ -0,0 +1,4206 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <netinet/in.h>
+#include <unistd.h>
+
+#include "gdk.h"
+#include "gdkwayland.h"
+
+#include "gdksurface.h"
+#include "gdksurfaceimpl.h"
+#include "gdkdisplay-wayland.h"
+#include "gdkglcontext-wayland.h"
+#include "gdkframeclockprivate.h"
+#include "gdkprivate-wayland.h"
+#include "gdkinternals.h"
+#include "gdkdeviceprivate.h"
+#include "gdkprivate-wayland.h"
+#include "gdkmonitor-wayland.h"
+#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+enum {
+  COMMITTED,
+
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+#define WINDOW_IS_TOPLEVEL(window) \
+  (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD)
+
+#define MAX_WL_BUFFER_SIZE (4083) /* 4096 minus header, string argument length and NUL byte */
+
+typedef struct _GdkWaylandSurface GdkWaylandSurface;
+typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
+
+struct _GdkWaylandSurface
+{
+  GdkSurface parent;
+};
+
+struct _GdkWaylandSurfaceClass
+{
+  GdkSurfaceClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkWaylandSurface, gdk_wayland_surface, GDK_TYPE_SURFACE)
+
+static void
+gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *wayland_surface_class)
+{
+}
+
+static void
+gdk_wayland_surface_init (GdkWaylandSurface *wayland_surface)
+{
+}
+
+#define GDK_TYPE_SURFACE_IMPL_WAYLAND              (_gdk_surface_impl_wayland_get_type ())
+#define GDK_SURFACE_IMPL_WAYLAND(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_WAYLAND, GdkSurfaceImplWayland))
+#define GDK_SURFACE_IMPL_WAYLAND_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_WAYLAND, GdkSurfaceImplWaylandClass))
+#define GDK_IS_SURFACE_IMPL_WAYLAND(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_WAYLAND))
+#define GDK_IS_SURFACE_IMPL_WAYLAND_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_WAYLAND))
+#define GDK_SURFACE_IMPL_WAYLAND_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_WAYLAND, GdkSurfaceImplWaylandClass))
+
+typedef struct _GdkSurfaceImplWayland GdkSurfaceImplWayland;
+typedef struct _GdkSurfaceImplWaylandClass GdkSurfaceImplWaylandClass;
+
+typedef enum _PositionMethod
+{
+  POSITION_METHOD_NONE,
+  POSITION_METHOD_MOVE_RESIZE,
+  POSITION_METHOD_MOVE_TO_RECT
+} PositionMethod;
+
+struct _GdkSurfaceImplWayland
+{
+  GdkSurfaceImpl parent_instance;
+
+  GdkSurface *wrapper;
+
+  struct {
+    /* The wl_outputs that this window currently touches */
+    GSList               *outputs;
+
+    struct wl_surface    *wl_surface;
+    struct zxdg_surface_v6 *xdg_surface;
+    struct zxdg_toplevel_v6 *xdg_toplevel;
+    struct zxdg_popup_v6 *xdg_popup;
+    struct gtk_surface1  *gtk_surface;
+    struct wl_subsurface *wl_subsurface;
+    struct wl_egl_window *egl_window;
+    struct wl_egl_window *dummy_egl_window;
+    struct zxdg_exported_v1 *xdg_exported;
+    struct org_kde_kwin_server_decoration *server_decoration;
+  } display_server;
+
+  EGLSurface egl_surface;
+  EGLSurface dummy_egl_surface;
+
+  unsigned int initial_configure_received : 1;
+  unsigned int mapped : 1;
+  unsigned int use_custom_surface : 1;
+  unsigned int pending_buffer_attached : 1;
+  unsigned int pending_commit : 1;
+  unsigned int awaiting_frame : 1;
+  GdkSurfaceTypeHint hint;
+  GdkSurface *transient_for;
+  GdkSurface *popup_parent;
+  PositionMethod position_method;
+
+  cairo_surface_t *staging_cairo_surface;
+  cairo_surface_t *committed_cairo_surface;
+  cairo_surface_t *backfill_cairo_surface;
+
+  int pending_buffer_offset_x;
+  int pending_buffer_offset_y;
+
+  gchar *title;
+
+  struct {
+    gboolean was_set;
+
+    gchar *application_id;
+    gchar *app_menu_path;
+    gchar *menubar_path;
+    gchar *window_object_path;
+    gchar *application_object_path;
+    gchar *unique_bus_name;
+  } application;
+
+  GdkGeometry geometry_hints;
+  GdkSurfaceHints geometry_mask;
+
+  GdkSeat *grab_input_seat;
+
+  gint64 pending_frame_counter;
+  guint32 scale;
+
+  int margin_left;
+  int margin_right;
+  int margin_top;
+  int margin_bottom;
+  gboolean margin_dirty;
+
+  struct wl_output *initial_fullscreen_output;
+
+  cairo_region_t *opaque_region;
+  gboolean opaque_region_dirty;
+
+  cairo_region_t *input_region;
+  gboolean input_region_dirty;
+
+  cairo_region_t *staged_updates_region;
+
+  int saved_width;
+  int saved_height;
+
+  gulong parent_surface_committed_handler;
+
+  struct {
+    GdkRectangle rect;
+    GdkGravity rect_anchor;
+    GdkGravity window_anchor;
+    GdkAnchorHints anchor_hints;
+    gint rect_anchor_dx;
+    gint rect_anchor_dy;
+  } pending_move_to_rect;
+
+  struct {
+    int width;
+    int height;
+    GdkSurfaceState state;
+  } pending;
+
+  struct {
+    GdkWaylandSurfaceExported callback;
+    gpointer user_data;
+    GDestroyNotify destroy_func;
+  } exported;
+
+  struct zxdg_imported_v1 *imported_transient_for;
+  GHashTable *shortcuts_inhibitors;
+};
+
+struct _GdkSurfaceImplWaylandClass
+{
+  GdkSurfaceImplClass parent_class;
+};
+
+static void gdk_wayland_surface_maybe_configure (GdkSurface *window,
+                                                int        width,
+                                                int        height,
+                                                int        scale);
+
+static void maybe_set_gtk_surface_dbus_properties (GdkSurface *window);
+static void maybe_set_gtk_surface_modal (GdkSurface *window);
+
+static void gdk_surface_request_transient_parent_commit (GdkSurface *window);
+
+static void gdk_wayland_surface_sync_margin (GdkSurface *window);
+static void gdk_wayland_surface_sync_input_region (GdkSurface *window);
+static void gdk_wayland_surface_sync_opaque_region (GdkSurface *window);
+
+static void unset_transient_for_exported (GdkSurface *window);
+
+static void calculate_moved_to_rect_result (GdkSurface    *window,
+                                            int           x,
+                                            int           y,
+                                            int           width,
+                                            int           height,
+                                            GdkRectangle *flipped_rect,
+                                            GdkRectangle *final_rect,
+                                            gboolean     *flipped_x,
+                                            gboolean     *flipped_y);
+
+static gboolean gdk_wayland_surface_is_exported (GdkSurface *window);
+
+GType _gdk_surface_impl_wayland_get_type (void);
+
+G_DEFINE_TYPE (GdkSurfaceImplWayland, _gdk_surface_impl_wayland, GDK_TYPE_SURFACE_IMPL)
+
+static void
+_gdk_surface_impl_wayland_init (GdkSurfaceImplWayland *impl)
+{
+  impl->scale = 1;
+  impl->initial_fullscreen_output = NULL;
+  impl->saved_width = -1;
+  impl->saved_height = -1;
+}
+
+static void
+_gdk_wayland_screen_add_orphan_dialog (GdkSurface *window)
+{
+  GdkWaylandDisplay *display_wayland =
+    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+
+  if (!g_list_find (display_wayland->orphan_dialogs, window))
+    display_wayland->orphan_dialogs =
+      g_list_prepend (display_wayland->orphan_dialogs, window);
+}
+
+static void
+drop_cairo_surfaces (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
+  g_clear_pointer (&impl->backfill_cairo_surface, cairo_surface_destroy);
+
+  /* We nullify this so if a buffer release comes in later, we won't
+   * try to reuse that buffer since it's no longer suitable
+   */
+  impl->committed_cairo_surface = NULL;
+}
+
+static void
+_gdk_wayland_surface_save_size (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (window->state & (GDK_SURFACE_STATE_FULLSCREEN | GDK_SURFACE_STATE_MAXIMIZED))
+    return;
+
+  impl->saved_width = window->width - impl->margin_left - impl->margin_right;
+  impl->saved_height = window->height - impl->margin_top - impl->margin_bottom;
+}
+
+static void
+_gdk_wayland_surface_clear_saved_size (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (window->state & (GDK_SURFACE_STATE_FULLSCREEN | GDK_SURFACE_STATE_MAXIMIZED))
+    return;
+
+  impl->saved_width = -1;
+  impl->saved_height = -1;
+}
+
+/*
+ * gdk_wayland_surface_update_size:
+ * @drawable: a #GdkDrawableImplWayland.
+ *
+ * Updates the state of the drawable (in particular the drawable's
+ * cairo surface) when its size has changed.
+ */
+static void
+gdk_wayland_surface_update_size (GdkSurface *window,
+                                int32_t    width,
+                                int32_t    height,
+                                int        scale)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkRectangle area;
+  cairo_region_t *region;
+
+  if ((window->width == width) &&
+      (window->height == height) &&
+      (impl->scale == scale))
+    return;
+
+  drop_cairo_surfaces (window);
+
+  window->width = width;
+  window->height = height;
+  impl->scale = scale;
+
+  if (impl->display_server.egl_window)
+    wl_egl_window_resize (impl->display_server.egl_window, width * scale, height * scale, 0, 0);
+  if (impl->display_server.wl_surface)
+    wl_surface_set_buffer_scale (impl->display_server.wl_surface, scale);
+
+  area.x = 0;
+  area.y = 0;
+  area.width = window->width;
+  area.height = window->height;
+
+  region = cairo_region_create_rectangle (&area);
+  _gdk_surface_invalidate_for_expose (window, region);
+  cairo_region_destroy (region);
+}
+
+static const gchar *
+get_default_title (void)
+{
+  const char *title;
+
+  title = g_get_application_name ();
+  if (!title)
+    title = g_get_prgname ();
+  if (!title)
+    title = "";
+
+  return title;
+}
+
+static void
+fill_presentation_time_from_frame_time (GdkFrameTimings *timings,
+                                        guint32          frame_time)
+{
+  /* The timestamp in a wayland frame is a msec time value that in some
+   * way reflects the time at which the server started drawing the frame.
+   * This is not useful from our perspective.
+   *
+   * However, for the DRM backend of Weston, on reasonably recent
+   * Linux, we know that the time is the
+   * clock_gettime (CLOCK_MONOTONIC) value at the vblank, and that
+   * backend starts drawing immediately after receiving the vblank
+   * notification. If we detect this, and make the assumption that the
+   * compositor will finish drawing before the next vblank, we can
+   * then determine the presentation time as the frame time we
+   * received plus one refresh interval.
+   *
+   * If a backend is using clock_gettime(CLOCK_MONOTONIC), but not
+   * picking values right at the vblank, then the presentation times
+   * we compute won't be accurate, but not really worse than then
+   * the alternative of not providing presentation times at all.
+   *
+   * The complexity here is dealing with the fact that we receive
+   * only the low 32 bits of the CLOCK_MONOTONIC value in milliseconds.
+   */
+  gint64 now_monotonic = g_get_monotonic_time ();
+  gint64 now_monotonic_msec = now_monotonic / 1000;
+  uint32_t now_monotonic_low = (uint32_t)now_monotonic_msec;
+
+  if (frame_time - now_monotonic_low < 1000 ||
+      frame_time - now_monotonic_low > (uint32_t)-1000)
+    {
+      /* Timestamp we received is within one second of the current time.
+       */
+      gint64 last_frame_time = now_monotonic + (gint64)1000 * (gint32)(frame_time - now_monotonic_low);
+      if ((gint32)now_monotonic_low < 0 && (gint32)frame_time > 0)
+        last_frame_time += (gint64)1000 * G_GINT64_CONSTANT(0x100000000);
+      else if ((gint32)now_monotonic_low > 0 && (gint32)frame_time < 0)
+        last_frame_time -= (gint64)1000 * G_GINT64_CONSTANT(0x100000000);
+
+      timings->presentation_time = last_frame_time + timings->refresh_interval;
+    }
+}
+
+static void
+read_back_cairo_surface (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  cairo_t *cr;
+  cairo_region_t *paint_region = NULL;
+
+  if (!impl->backfill_cairo_surface)
+    goto out;
+
+  paint_region = cairo_region_copy (window->clip_region);
+  cairo_region_subtract (paint_region, impl->staged_updates_region);
+
+  if (cairo_region_is_empty (paint_region))
+    goto out;
+
+  cr = cairo_create (impl->staging_cairo_surface);
+  cairo_set_source_surface (cr, impl->backfill_cairo_surface, 0, 0);
+  gdk_cairo_region (cr, paint_region);
+  cairo_clip (cr);
+  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+  cairo_paint (cr);
+  cairo_destroy (cr);
+  cairo_surface_flush (impl->staging_cairo_surface);
+
+out:
+  g_clear_pointer (&paint_region, cairo_region_destroy);
+  g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
+  g_clear_pointer (&impl->backfill_cairo_surface, cairo_surface_destroy);
+}
+
+static void
+frame_callback (void               *data,
+                struct wl_callback *callback,
+                uint32_t            time)
+{
+  GdkSurface *window = data;
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkWaylandDisplay *display_wayland =
+    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  GdkFrameClock *clock = gdk_surface_get_frame_clock (window);
+  GdkFrameTimings *timings;
+
+  GDK_DISPLAY_NOTE (GDK_DISPLAY (display_wayland), EVENTS, g_message ("frame %p", window));
+
+  wl_callback_destroy (callback);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (!impl->awaiting_frame)
+    return;
+
+  impl->awaiting_frame = FALSE;
+  _gdk_frame_clock_thaw (clock);
+
+  timings = gdk_frame_clock_get_timings (clock, impl->pending_frame_counter);
+  impl->pending_frame_counter = 0;
+
+  if (timings == NULL)
+    return;
+
+  timings->refresh_interval = 16667; /* default to 1/60th of a second */
+  if (impl->display_server.outputs)
+    {
+      /* We pick a random output out of the outputs that the window touches
+       * The rate here is in milli-hertz */
+      int refresh_rate =
+        gdk_wayland_display_get_output_refresh_rate (display_wayland,
+                                                     impl->display_server.outputs->data);
+      if (refresh_rate != 0)
+        timings->refresh_interval = G_GINT64_CONSTANT(1000000000) / refresh_rate;
+    }
+
+  fill_presentation_time_from_frame_time (timings, time);
+
+  timings->complete = TRUE;
+
+#ifdef G_ENABLE_DEBUG
+  if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
+    _gdk_frame_clock_debug_print_timings (clock, timings);
+#endif
+}
+
+static const struct wl_callback_listener frame_listener = {
+  frame_callback
+};
+
+static void
+on_frame_clock_before_paint (GdkFrameClock *clock,
+                             GdkSurface     *window)
+{
+  GdkFrameTimings *timings = gdk_frame_clock_get_current_timings (clock);
+  gint64 presentation_time;
+  gint64 refresh_interval;
+
+  if (window->update_freeze_count > 0)
+    return;
+
+  gdk_frame_clock_get_refresh_info (clock,
+                                    timings->frame_time,
+                                    &refresh_interval, &presentation_time);
+
+  if (presentation_time != 0)
+    {
+      /* Assume the algorithm used by the DRM backend of Weston - it
+       * starts drawing at the next vblank after receiving the commit
+       * for this frame, and presentation occurs at the vblank
+       * after that.
+       */
+      timings->predicted_presentation_time = presentation_time + refresh_interval;
+    }
+  else
+    {
+      /* As above, but we don't actually know the phase of the vblank,
+       * so just assume that we're half way through a refresh cycle.
+       */
+      timings->predicted_presentation_time = timings->frame_time + refresh_interval / 2 + refresh_interval;
+    }
+}
+
+static void
+on_frame_clock_after_paint (GdkFrameClock *clock,
+                            GdkSurface     *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  struct wl_callback *callback;
+
+  if (!impl->pending_commit)
+    return;
+
+  if (window->update_freeze_count > 0)
+    return;
+
+  callback = wl_surface_frame (impl->display_server.wl_surface);
+  wl_callback_add_listener (callback, &frame_listener, window);
+  _gdk_frame_clock_freeze (clock);
+
+  /* Before we commit a new buffer, make sure we've backfilled
+   * undrawn parts from any old committed buffer
+   */
+  if (impl->pending_buffer_attached)
+    read_back_cairo_surface (window);
+
+  /* From this commit forward, we can't write to the buffer,
+   * it's "live".  In the future, if we need to stage more changes
+   * we have to allocate a new staging buffer and draw to it instead.
+   *
+   * Our one saving grace is if the compositor releases the buffer
+   * before we need to stage any changes, then we can take it back and
+   * use it again.
+   */
+  wl_surface_commit (impl->display_server.wl_surface);
+
+  if (impl->pending_buffer_attached)
+    impl->committed_cairo_surface = g_steal_pointer (&impl->staging_cairo_surface);
+
+  impl->pending_buffer_attached = FALSE;
+  impl->pending_commit = FALSE;
+  impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
+  impl->awaiting_frame = TRUE;
+
+  g_signal_emit (impl, signals[COMMITTED], 0);
+}
+
+void
+gdk_wayland_surface_update_scale (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  guint32 scale;
+  GSList *l;
+  GList *children, *c;
+
+  if (display_wayland->compositor_version < WL_SURFACE_HAS_BUFFER_SCALE)
+    {
+      /* We can't set the scale on this surface */
+      return;
+    }
+
+  scale = 1;
+  for (l = impl->display_server.outputs; l != NULL; l = l->next)
+    {
+      guint32 output_scale = gdk_wayland_display_get_output_scale (display_wayland, l->data);
+      scale = MAX (scale, output_scale);
+    }
+
+  /* Notify app that scale changed */
+  gdk_wayland_surface_maybe_configure (window, window->width, window->height, scale);
+
+  children = gdk_surface_get_children (window);
+  for (c = children; c; c = c->next)
+    {
+      GdkSurface *child = c->data;
+      gdk_wayland_surface_update_scale (child);
+    }
+  g_list_free (children);
+}
+
+static void gdk_wayland_surface_create_surface (GdkSurface *window);
+
+void
+_gdk_wayland_display_create_window_impl (GdkDisplay    *display,
+                                         GdkSurface     *window,
+                                         GdkSurface     *real_parent,
+                                         GdkEventMask   event_mask,
+                                         GdkSurfaceAttr *attributes)
+{
+  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+  GdkSurfaceImplWayland *impl;
+  GdkFrameClock *frame_clock;
+
+  impl = g_object_new (GDK_TYPE_SURFACE_IMPL_WAYLAND, NULL);
+  window->impl = GDK_SURFACE_IMPL (impl);
+  impl->wrapper = GDK_SURFACE (window);
+  impl->shortcuts_inhibitors = g_hash_table_new (NULL, NULL);
+
+  if (window->width > 65535)
+    {
+      g_warning ("Native Windows wider than 65535 pixels are not supported");
+      window->width = 65535;
+    }
+  if (window->height > 65535)
+    {
+      g_warning ("Native Windows taller than 65535 pixels are not supported");
+      window->height = 65535;
+    }
+
+  g_object_ref (window);
+
+  /* More likely to be right than just assuming 1 */
+  if (display_wayland->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE &&
+      gdk_display_get_n_monitors (display) > 0)
+    impl->scale = gdk_monitor_get_scale_factor (gdk_display_get_monitor (display, 0));
+
+  impl->title = NULL;
+
+  switch (GDK_SURFACE_TYPE (window))
+    {
+    case GDK_SURFACE_TOPLEVEL:
+    case GDK_SURFACE_TEMP:
+      gdk_surface_set_title (window, get_default_title ());
+      break;
+
+    case GDK_SURFACE_CHILD:
+    default:
+      break;
+    }
+
+  if (real_parent == NULL)
+    display_wayland->toplevels = g_list_prepend (display_wayland->toplevels, window);
+
+  gdk_wayland_surface_create_surface (window);
+
+  frame_clock = gdk_surface_get_frame_clock (window);
+  g_signal_connect (frame_clock, "before-paint", G_CALLBACK (on_frame_clock_before_paint), window);
+  g_signal_connect (frame_clock, "after-paint", G_CALLBACK (on_frame_clock_after_paint), window);
+}
+
+static void
+gdk_wayland_surface_attach_image (GdkSurface *window)
+{
+  GdkWaylandDisplay *display;
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  g_assert (_gdk_wayland_is_shm_surface (impl->staging_cairo_surface));
+
+  /* Attach this new buffer to the surface */
+  wl_surface_attach (impl->display_server.wl_surface,
+                     _gdk_wayland_shm_surface_get_wl_buffer (impl->staging_cairo_surface),
+                     impl->pending_buffer_offset_x,
+                     impl->pending_buffer_offset_y);
+  impl->pending_buffer_offset_x = 0;
+  impl->pending_buffer_offset_y = 0;
+
+  /* Only set the buffer scale if supported by the compositor */
+  display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  if (display->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE)
+    wl_surface_set_buffer_scale (impl->display_server.wl_surface, impl->scale);
+
+  impl->pending_buffer_attached = TRUE;
+  impl->pending_commit = TRUE;
+}
+
+static const cairo_user_data_key_t gdk_wayland_surface_cairo_key;
+
+static void
+buffer_release_callback (void             *_data,
+                         struct wl_buffer *wl_buffer)
+{
+  cairo_surface_t *cairo_surface = _data;
+  GdkSurfaceImplWayland *impl = cairo_surface_get_user_data (cairo_surface, &gdk_wayland_surface_cairo_key);
+
+  g_return_if_fail (GDK_IS_SURFACE_IMPL_WAYLAND (impl));
+
+  /* The released buffer isn't the latest committed one, we have no further
+   * use for it, so clean it up.
+   */
+  if (impl->committed_cairo_surface != cairo_surface)
+    {
+      /* If this fails, then the surface buffer got reused before it was
+       * released from the compositor
+       */
+      g_warn_if_fail (impl->staging_cairo_surface != cairo_surface);
+
+      cairo_surface_destroy (cairo_surface);
+      return;
+    }
+
+  if (impl->staged_updates_region != NULL)
+    {
+      /* If this fails, then we're tracking staged updates on a staging surface
+       * that doesn't exist.
+       */
+      g_warn_if_fail (impl->staging_cairo_surface != NULL);
+
+      /* If we've staged updates into a new buffer before the release for this
+       * buffer came in, then we can't reuse this buffer, so unref it. It may still
+       * be alive as a readback buffer though (via impl->backfill_cairo_surface).
+       *
+       * It's possible a staging surface was allocated but no updates were staged.
+       * If that happened, clean up that staging surface now, since the old commit
+       * buffer is available again, and reusing the old commit buffer for future
+       * updates will save having to do a read back later.
+       */
+      if (!cairo_region_is_empty (impl->staged_updates_region))
+        {
+          g_clear_pointer (&impl->committed_cairo_surface, cairo_surface_destroy);
+          return;
+        }
+      else
+        {
+          g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
+          g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
+        }
+    }
+
+  /* Release came in, we haven't done any interim updates, so we can just use
+   * the old committed buffer again.
+   */
+  impl->staging_cairo_surface = g_steal_pointer (&impl->committed_cairo_surface);
+}
+
+static const struct wl_buffer_listener buffer_listener = {
+  buffer_release_callback
+};
+
+static void
+gdk_wayland_surface_ensure_cairo_surface (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  /* If we are drawing using OpenGL then we only need a logical 1x1 surface. */
+  if (impl->display_server.egl_window)
+    {
+      if (impl->staging_cairo_surface &&
+          _gdk_wayland_is_shm_surface (impl->staging_cairo_surface))
+        g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
+
+      if (!impl->staging_cairo_surface)
+        {
+          impl->staging_cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                                                    impl->scale,
+                                                                    impl->scale);
+          cairo_surface_set_device_scale (impl->staging_cairo_surface,
+                                          impl->scale, impl->scale);
+        }
+    }
+  else if (!impl->staging_cairo_surface)
+    {
+      GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (impl->wrapper));
+      struct wl_buffer *buffer;
+
+      impl->staging_cairo_surface = _gdk_wayland_display_create_shm_surface (display_wayland,
+                                                                             impl->wrapper->width,
+                                                                             impl->wrapper->height,
+                                                                             impl->scale);
+      cairo_surface_set_user_data (impl->staging_cairo_surface,
+                                   &gdk_wayland_surface_cairo_key,
+                                   g_object_ref (impl),
+                                   (cairo_destroy_func_t)
+                                   g_object_unref);
+      buffer = _gdk_wayland_shm_surface_get_wl_buffer (impl->staging_cairo_surface);
+      wl_buffer_add_listener (buffer, &buffer_listener, impl->staging_cairo_surface);
+    }
+}
+
+/* The cairo surface returned here uses a memory segment that's shared
+ * with the display server.  This is not a temporary buffer that gets
+ * copied to the display server, but the actual buffer the display server
+ * will ultimately end up sending to the GPU. At the time this happens
+ * impl->committed_cairo_surface gets set to impl->staging_cairo_surface, and
+ * impl->staging_cairo_surface gets nullified.
+ */
+static cairo_surface_t *
+gdk_wayland_surface_ref_cairo_surface (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (impl->wrapper))
+    return NULL;
+
+  gdk_wayland_surface_ensure_cairo_surface (window);
+
+  cairo_surface_reference (impl->staging_cairo_surface);
+
+  return impl->staging_cairo_surface;
+}
+
+static cairo_surface_t *
+gdk_wayland_surface_create_similar_image_surface (GdkSurface *     window,
+                                                 cairo_format_t  format,
+                                                 int             width,
+                                                 int             height)
+{
+  return cairo_image_surface_create (format, width, height);
+}
+
+static gboolean
+gdk_surface_impl_wayland_begin_paint (GdkSurface *window)
+{
+  gdk_wayland_surface_ensure_cairo_surface (window);
+
+  return FALSE;
+}
+
+static void
+gdk_surface_impl_wayland_end_paint (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  cairo_rectangle_int_t rect;
+  int i, n;
+
+  if (impl->staging_cairo_surface &&
+      _gdk_wayland_is_shm_surface (impl->staging_cairo_surface) &&
+      !cairo_region_is_empty (window->current_paint.region))
+    {
+      gdk_wayland_surface_attach_image (window);
+
+      /* If there's a committed buffer pending, then track which
+       * updates are staged until the next frame, so we can back
+       * fill the unstaged parts of the staging buffer with the
+       * last frame.
+       */
+      if (impl->committed_cairo_surface != NULL)
+        {
+          if (impl->staged_updates_region == NULL)
+            {
+              impl->staged_updates_region = cairo_region_copy (window->current_paint.region);
+              impl->backfill_cairo_surface = cairo_surface_reference (impl->committed_cairo_surface);
+            }
+          else
+            {
+              cairo_region_union (impl->staged_updates_region, window->current_paint.region);
+            }
+        }
+
+      n = cairo_region_num_rectangles (window->current_paint.region);
+      for (i = 0; i < n; i++)
+        {
+          cairo_region_get_rectangle (window->current_paint.region, i, &rect);
+          wl_surface_damage (impl->display_server.wl_surface, rect.x, rect.y, rect.width, rect.height);
+        }
+
+      impl->pending_commit = TRUE;
+    }
+
+  gdk_wayland_surface_sync (window);
+}
+
+void
+gdk_wayland_surface_sync (GdkSurface *window)
+{
+  gdk_wayland_surface_sync_margin (window);
+  gdk_wayland_surface_sync_opaque_region (window);
+  gdk_wayland_surface_sync_input_region (window);
+}
+
+static gboolean
+gdk_surface_impl_wayland_beep (GdkSurface *window)
+{
+  gdk_wayland_display_system_bell (gdk_surface_get_display (window),
+                                   window);
+
+  return TRUE;
+}
+
+static void
+gdk_surface_impl_wayland_finalize (GObject *object)
+{
+  GdkSurface *window = GDK_SURFACE (object);
+  GdkSurfaceImplWayland *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE_IMPL_WAYLAND (object));
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (object);
+
+  if (gdk_wayland_surface_is_exported (window))
+    gdk_wayland_surface_unexport_handle (window);
+
+  g_free (impl->title);
+
+  g_free (impl->application.application_id);
+  g_free (impl->application.app_menu_path);
+  g_free (impl->application.menubar_path);
+  g_free (impl->application.window_object_path);
+  g_free (impl->application.application_object_path);
+  g_free (impl->application.unique_bus_name);
+
+  g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
+  g_clear_pointer (&impl->input_region, cairo_region_destroy);
+  g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
+
+  g_hash_table_destroy (impl->shortcuts_inhibitors);
+
+  G_OBJECT_CLASS (_gdk_surface_impl_wayland_parent_class)->finalize (object);
+}
+
+static void
+gdk_wayland_surface_configure (GdkSurface *window,
+                              int        width,
+                              int        height,
+                              int        scale)
+{
+  GdkDisplay *display;
+  GdkEvent *event;
+
+  event = gdk_event_new (GDK_CONFIGURE);
+  event->any.window = g_object_ref (window);
+  event->any.send_event = FALSE;
+  event->configure.width = width;
+  event->configure.height = height;
+
+  gdk_wayland_surface_update_size (window, width, height, scale);
+  _gdk_surface_update_size (window);
+
+  display = gdk_surface_get_display (window);
+  _gdk_wayland_display_deliver_event (display, event);
+}
+
+static void
+gdk_wayland_surface_maybe_configure (GdkSurface *window,
+                                    int        width,
+                                    int        height,
+                                    int        scale)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  gboolean is_xdg_popup;
+  gboolean is_visible;
+
+  if (window->width == width &&
+      window->height == height &&
+      impl->scale == scale)
+    return;
+
+  /* For xdg_popup using an xdg_positioner, there is a race condition if
+   * the application tries to change the size after it's mapped, but before
+   * the initial configure is received, so hide and show the surface again
+   * force the new size onto the compositor. See bug #772505.
+   */
+
+  is_xdg_popup = (impl->display_server.xdg_popup != NULL);
+  is_visible = gdk_surface_is_visible (window);
+
+  if (is_xdg_popup && is_visible && !impl->initial_configure_received)
+    gdk_surface_hide (window);
+
+  gdk_wayland_surface_configure (window, width, height, scale);
+
+  if (is_xdg_popup && is_visible && !impl->initial_configure_received)
+    gdk_surface_show (window);
+}
+
+static void
+gdk_wayland_surface_sync_parent (GdkSurface *window,
+                                GdkSurface *parent)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkSurfaceImplWayland *impl_parent = NULL;
+  struct zxdg_toplevel_v6 *parent_toplevel;
+
+  g_assert (parent == NULL ||
+            gdk_surface_get_display (window) == gdk_surface_get_display (parent));
+
+  if (!impl->display_server.xdg_toplevel)
+    return;
+
+  if (impl->transient_for)
+    impl_parent = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
+  else if (parent)
+    impl_parent = GDK_SURFACE_IMPL_WAYLAND (parent->impl);
+
+  if (impl_parent)
+    {
+      /* XXX: Is this correct? */
+      if (!impl_parent->display_server.wl_surface)
+        return;
+
+      parent_toplevel = impl_parent->display_server.xdg_toplevel;
+    }
+  else
+    parent_toplevel = NULL;
+
+  zxdg_toplevel_v6_set_parent (impl->display_server.xdg_toplevel,
+                               parent_toplevel);
+}
+
+static void
+gdk_wayland_surface_sync_parent_of_imported (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (!impl->display_server.wl_surface)
+    return;
+
+  if (!impl->imported_transient_for)
+    return;
+
+  if (!impl->display_server.xdg_toplevel)
+    return;
+
+  zxdg_imported_v1_set_parent_of (impl->imported_transient_for,
+                                  impl->display_server.wl_surface);
+}
+
+static void
+gdk_wayland_surface_update_dialogs (GdkSurface *window)
+{
+  GdkWaylandDisplay *display_wayland =
+    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  GList *l;
+
+  if (!display_wayland->orphan_dialogs)
+    return;
+
+  for (l = display_wayland->orphan_dialogs; l; l = l->next)
+    {
+      GdkSurface *w = l->data;
+      GdkSurfaceImplWayland *impl;
+
+      if (!GDK_IS_SURFACE_IMPL_WAYLAND(w->impl))
+        continue;
+
+      impl = GDK_SURFACE_IMPL_WAYLAND (w->impl);
+      if (w == window)
+       continue;
+      if (impl->hint != GDK_SURFACE_TYPE_HINT_DIALOG)
+        continue;
+      if (impl->transient_for)
+        continue;
+
+      /* Update the parent relationship only for dialogs without transients */
+      gdk_wayland_surface_sync_parent (w, window);
+    }
+}
+
+static void
+gdk_wayland_surface_sync_title (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (!impl->display_server.xdg_toplevel)
+    return;
+
+  if (!impl->title)
+    return;
+
+  zxdg_toplevel_v6_set_title (impl->display_server.xdg_toplevel, impl->title);
+}
+
+static void
+gdk_wayland_surface_get_window_geometry (GdkSurface    *window,
+                                        GdkRectangle *geometry)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  *geometry = (GdkRectangle) {
+    .x = impl->margin_left,
+    .y = impl->margin_top,
+    .width = window->width - (impl->margin_left + impl->margin_right),
+    .height = window->height - (impl->margin_top + impl->margin_bottom)
+  };
+}
+
+static void
+gdk_wayland_surface_sync_margin (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkRectangle geometry;
+
+  if (!impl->display_server.xdg_surface)
+    return;
+
+  gdk_wayland_surface_get_window_geometry (window, &geometry);
+  gdk_surface_set_geometry_hints (window,
+                                 &impl->geometry_hints,
+                                 impl->geometry_mask);
+  zxdg_surface_v6_set_window_geometry (impl->display_server.xdg_surface,
+                                       geometry.x,
+                                       geometry.y,
+                                       geometry.width,
+                                       geometry.height);
+}
+
+static struct wl_region *
+wl_region_from_cairo_region (GdkWaylandDisplay *display,
+                             cairo_region_t    *region)
+{
+  struct wl_region *wl_region;
+  int i, n_rects;
+
+  wl_region = wl_compositor_create_region (display->compositor);
+  if (wl_region == NULL)
+    return NULL;
+
+  n_rects = cairo_region_num_rectangles (region);
+  for (i = 0; i < n_rects; i++)
+    {
+      cairo_rectangle_int_t rect;
+      cairo_region_get_rectangle (region, i, &rect);
+      wl_region_add (wl_region, rect.x, rect.y, rect.width, rect.height);
+    }
+
+  return wl_region;
+}
+
+static void
+gdk_wayland_surface_sync_opaque_region (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  struct wl_region *wl_region = NULL;
+
+  if (!impl->display_server.wl_surface)
+    return;
+
+  if (!impl->opaque_region_dirty)
+    return;
+
+  if (impl->opaque_region != NULL)
+    wl_region = wl_region_from_cairo_region (GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window)),
+                                             impl->opaque_region);
+
+  wl_surface_set_opaque_region (impl->display_server.wl_surface, wl_region);
+
+  if (wl_region != NULL)
+    wl_region_destroy (wl_region);
+
+  impl->opaque_region_dirty = FALSE;
+}
+
+static void
+gdk_wayland_surface_sync_input_region (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  struct wl_region *wl_region = NULL;
+
+  if (!impl->display_server.wl_surface)
+    return;
+
+  if (!impl->input_region_dirty)
+    return;
+
+  if (impl->input_region != NULL)
+    wl_region = wl_region_from_cairo_region (GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window)),
+                                             impl->input_region);
+
+  wl_surface_set_input_region (impl->display_server.wl_surface, wl_region);
+
+  if (wl_region != NULL)
+    wl_region_destroy (wl_region);
+
+  impl->input_region_dirty = FALSE;
+}
+
+static void
+gdk_wayland_set_input_region_if_empty (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkWaylandDisplay *display;
+  struct wl_region *empty;
+
+  if (!impl->input_region_dirty)
+    return;
+
+  if (impl->input_region == NULL)
+    return;
+
+  if (!cairo_region_is_empty (impl->input_region))
+    return;
+
+  display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  empty = wl_compositor_create_region (display->compositor);
+
+  wl_surface_set_input_region (impl->display_server.wl_surface, empty);
+  wl_region_destroy (empty);
+
+  impl->input_region_dirty = FALSE;
+}
+
+static void
+surface_enter (void              *data,
+               struct wl_surface *wl_surface,
+               struct wl_output  *output)
+{
+  GdkSurface *window = GDK_SURFACE (data);
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  GDK_DISPLAY_NOTE (gdk_surface_get_display (window), EVENTS,
+            g_message ("surface enter, window %p output %p", window, output));
+
+  impl->display_server.outputs = g_slist_prepend (impl->display_server.outputs, output);
+
+  gdk_wayland_surface_update_scale (window);
+}
+
+static void
+surface_leave (void              *data,
+               struct wl_surface *wl_surface,
+               struct wl_output  *output)
+{
+  GdkSurface *window = GDK_SURFACE (data);
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  GDK_DISPLAY_NOTE (gdk_surface_get_display (window), EVENTS,
+            g_message ("surface leave, window %p output %p", window, output));
+
+  impl->display_server.outputs = g_slist_remove (impl->display_server.outputs, output);
+
+  if (impl->display_server.outputs)
+    gdk_wayland_surface_update_scale (window);
+}
+
+static const struct wl_surface_listener surface_listener = {
+  surface_enter,
+  surface_leave
+};
+
+static void
+on_parent_surface_committed (GdkSurfaceImplWayland *parent_impl,
+                             GdkSurface            *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  g_signal_handler_disconnect (parent_impl,
+                               impl->parent_surface_committed_handler);
+  impl->parent_surface_committed_handler = 0;
+
+  wl_subsurface_set_desync (impl->display_server.wl_subsurface);
+
+  /* Special case if the input region is empty, it won't change on resize */
+  gdk_wayland_set_input_region_if_empty (window);
+}
+
+static void
+gdk_wayland_surface_create_subsurface (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl, *parent_impl = NULL;
+  GdkWaylandDisplay *display_wayland;
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (!impl->display_server.wl_surface)
+    return; /* Bail out, surface and subsurface will be created later when shown */
+
+  if (impl->display_server.wl_subsurface)
+    return;
+
+  if (impl->transient_for)
+    parent_impl = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
+
+  if (parent_impl && parent_impl->display_server.wl_surface)
+    {
+      display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+      impl->display_server.wl_subsurface =
+        wl_subcompositor_get_subsurface (display_wayland->subcompositor,
+                                         impl->display_server.wl_surface, parent_impl->display_server.wl_surface);
+      wl_subsurface_set_position (impl->display_server.wl_subsurface,
+                                  window->x + window->abs_x,
+                                  window->y + window->abs_y);
+
+      /* In order to synchronize the initial position with the initial frame
+       * content, wait with making the subsurface desynchronized until after
+       * the parent was committed.
+       */
+      impl->parent_surface_committed_handler =
+        g_signal_connect_object (parent_impl, "committed",
+                                 G_CALLBACK (on_parent_surface_committed),
+                                 window, 0);
+      gdk_surface_request_transient_parent_commit (window);
+    }
+}
+
+static void
+gdk_wayland_surface_create_surface (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+
+  impl->display_server.wl_surface = wl_compositor_create_surface (display_wayland->compositor);
+  wl_surface_add_listener (impl->display_server.wl_surface, &surface_listener, window);
+}
+
+static void
+xdg_surface_configure (void                   *data,
+                       struct zxdg_surface_v6 *xdg_surface,
+                       uint32_t                serial)
+{
+  GdkSurface *window = GDK_SURFACE (data);
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkSurfaceState new_state;
+  int width = impl->pending.width;
+  int height = impl->pending.height;
+  gboolean fixed_size;
+  gboolean saved_size;
+
+  if (!impl->initial_configure_received)
+    {
+      gdk_surface_thaw_updates (window);
+      impl->initial_configure_received = TRUE;
+    }
+
+  if (impl->display_server.xdg_popup)
+    {
+      zxdg_surface_v6_ack_configure (xdg_surface, serial);
+      return;
+    }
+
+  new_state = impl->pending.state;
+  impl->pending.state = 0;
+
+  fixed_size =
+    new_state & (GDK_SURFACE_STATE_MAXIMIZED | GDK_SURFACE_STATE_FULLSCREEN | GDK_SURFACE_STATE_TILED);
+
+  saved_size = (width == 0 && height == 0);
+  /* According to xdg_shell, an xdg_surface.configure with size 0x0
+   * should be interpreted as that it is up to the client to set a
+   * size.
+   *
+   * When transitioning from maximize or fullscreen state, this means
+   * the client should configure its size back to what it was before
+   * being maximize or fullscreen.
+   */
+  if (saved_size && !fixed_size)
+    {
+      width = impl->saved_width;
+      height = impl->saved_height;
+    }
+
+  if (width > 0 && height > 0)
+    {
+      GdkSurfaceHints geometry_mask = impl->geometry_mask;
+
+      /* Ignore size increments for maximized/fullscreen windows */
+      if (fixed_size)
+        geometry_mask &= ~GDK_HINT_RESIZE_INC;
+      if (!saved_size)
+        {
+          /* Do not reapply contrains if we are restoring original size */
+          gdk_surface_constrain_size (&impl->geometry_hints,
+                                     geometry_mask,
+                                     width + impl->margin_left + impl->margin_right,
+                                     height + impl->margin_top + impl->margin_bottom,
+                                     &width,
+                                     &height);
+
+          /* Save size for next time we get 0x0 */
+          _gdk_wayland_surface_save_size (window);
+        }
+
+      gdk_wayland_surface_configure (window, width, height, impl->scale);
+    }
+
+  GDK_DISPLAY_NOTE (gdk_surface_get_display (window), EVENTS,
+            g_message ("configure, window %p %dx%d,%s%s%s%s",
+                       window, width, height,
+                       (new_state & GDK_SURFACE_STATE_FULLSCREEN) ? " fullscreen" : "",
+                       (new_state & GDK_SURFACE_STATE_MAXIMIZED) ? " maximized" : "",
+                       (new_state & GDK_SURFACE_STATE_FOCUSED) ? " focused" : "",
+                       (new_state & GDK_SURFACE_STATE_TILED) ? " tiled" : ""));
+
+  gdk_surface_set_state (window, new_state);
+  zxdg_surface_v6_ack_configure (xdg_surface, serial);
+  if (impl->hint != GDK_SURFACE_TYPE_HINT_DIALOG &&
+      new_state & GDK_SURFACE_STATE_FOCUSED)
+    gdk_wayland_surface_update_dialogs (window);
+}
+
+static const struct zxdg_surface_v6_listener xdg_surface_listener = {
+  xdg_surface_configure,
+};
+
+static void
+xdg_toplevel_configure (void                    *data,
+                        struct zxdg_toplevel_v6 *xdg_toplevel,
+                        int32_t                  width,
+                        int32_t                  height,
+                        struct wl_array         *states)
+{
+  GdkSurface *window = GDK_SURFACE (data);
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  uint32_t *p;
+
+  wl_array_for_each (p, states)
+    {
+      uint32_t state = *p;
+      switch (state)
+        {
+        case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
+          impl->pending.state |= GDK_SURFACE_STATE_FULLSCREEN;
+          break;
+        case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED:
+          impl->pending.state |= GDK_SURFACE_STATE_MAXIMIZED;
+          break;
+        case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED:
+          impl->pending.state |= GDK_SURFACE_STATE_FOCUSED;
+          break;
+        case ZXDG_TOPLEVEL_V6_STATE_RESIZING:
+          break;
+        default:
+          /* Unknown state */
+          break;
+        }
+    }
+
+  impl->pending.width = width;
+  impl->pending.height = height;
+}
+
+static void
+xdg_toplevel_close (void                    *data,
+                    struct zxdg_toplevel_v6 *xdg_toplevel)
+{
+  GdkSurface *window = GDK_SURFACE (data);
+  GdkDisplay *display;
+  GdkEvent *event;
+
+  display = gdk_surface_get_display (window);
+
+  GDK_DISPLAY_NOTE (display, EVENTS, g_message ("close %p", window));
+
+  event = gdk_event_new (GDK_DELETE);
+  event->any.window = g_object_ref (window);
+  event->any.send_event = TRUE;
+
+  _gdk_wayland_display_deliver_event (display, event);
+}
+
+static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
+  xdg_toplevel_configure,
+  xdg_toplevel_close,
+};
+
+static void
+gdk_wayland_surface_create_xdg_toplevel (GdkSurface *window)
+{
+  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  const gchar *app_id;
+
+  impl->display_server.xdg_surface =
+    zxdg_shell_v6_get_xdg_surface (display_wayland->xdg_shell,
+                                   impl->display_server.wl_surface);
+  zxdg_surface_v6_add_listener (impl->display_server.xdg_surface,
+                                &xdg_surface_listener,
+                                window);
+  gdk_surface_freeze_updates (window);
+
+  impl->display_server.xdg_toplevel =
+    zxdg_surface_v6_get_toplevel (impl->display_server.xdg_surface);
+  zxdg_toplevel_v6_add_listener (impl->display_server.xdg_toplevel,
+                                 &xdg_toplevel_listener,
+                                 window);
+
+  gdk_wayland_surface_sync_parent (window, NULL);
+  gdk_wayland_surface_sync_parent_of_imported (window);
+  gdk_wayland_surface_sync_title (window);
+
+  if (window->state & GDK_SURFACE_STATE_MAXIMIZED)
+    zxdg_toplevel_v6_set_maximized (impl->display_server.xdg_toplevel);
+  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
+    zxdg_toplevel_v6_set_fullscreen (impl->display_server.xdg_toplevel,
+                                     impl->initial_fullscreen_output);
+
+  impl->initial_fullscreen_output = NULL;
+
+  app_id = g_get_prgname ();
+
+  if (app_id == NULL)
+    app_id = "GTK+ Application";
+
+  zxdg_toplevel_v6_set_app_id (impl->display_server.xdg_toplevel, app_id);
+
+  maybe_set_gtk_surface_dbus_properties (window);
+  maybe_set_gtk_surface_modal (window);
+
+  if (impl->hint == GDK_SURFACE_TYPE_HINT_DIALOG)
+    _gdk_wayland_screen_add_orphan_dialog (window);
+
+  wl_surface_commit (impl->display_server.wl_surface);
+}
+
+static void
+xdg_popup_configure (void                 *data,
+                     struct zxdg_popup_v6 *xdg_popup,
+                     int32_t               x,
+                     int32_t               y,
+                     int32_t               width,
+                     int32_t               height)
+{
+  GdkSurface *window = GDK_SURFACE (data);
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkRectangle flipped_rect;
+  GdkRectangle final_rect;
+  gboolean flipped_x;
+  gboolean flipped_y;
+
+  g_return_if_fail (impl->transient_for);
+
+  if (impl->position_method != POSITION_METHOD_MOVE_TO_RECT)
+    return;
+
+  calculate_moved_to_rect_result (window, x, y, width, height,
+                                  &flipped_rect,
+                                  &final_rect,
+                                  &flipped_x,
+                                  &flipped_y);
+
+  g_signal_emit_by_name (window,
+                         "moved-to-rect",
+                         &flipped_rect,
+                         &final_rect,
+                         flipped_x,
+                         flipped_y);
+}
+
+static void
+xdg_popup_done (void                 *data,
+                struct zxdg_popup_v6 *xdg_popup)
+{
+  GdkSurface *window = GDK_SURFACE (data);
+
+  GDK_DISPLAY_NOTE (gdk_surface_get_display (window), EVENTS, g_message ("done %p", window));
+
+  gdk_surface_hide (window);
+}
+
+static const struct zxdg_popup_v6_listener xdg_popup_listener = {
+  xdg_popup_configure,
+  xdg_popup_done,
+};
+
+static enum zxdg_positioner_v6_anchor
+rect_anchor_to_anchor (GdkGravity rect_anchor)
+{
+  switch (rect_anchor)
+    {
+    case GDK_GRAVITY_NORTH_WEST:
+    case GDK_GRAVITY_STATIC:
+      return (ZXDG_POSITIONER_V6_ANCHOR_TOP |
+              ZXDG_POSITIONER_V6_ANCHOR_LEFT);
+    case GDK_GRAVITY_NORTH:
+      return ZXDG_POSITIONER_V6_ANCHOR_TOP;
+    case GDK_GRAVITY_NORTH_EAST:
+      return (ZXDG_POSITIONER_V6_ANCHOR_TOP |
+              ZXDG_POSITIONER_V6_ANCHOR_RIGHT);
+    case GDK_GRAVITY_WEST:
+      return ZXDG_POSITIONER_V6_ANCHOR_LEFT;
+    case GDK_GRAVITY_CENTER:
+      return ZXDG_POSITIONER_V6_ANCHOR_NONE;
+    case GDK_GRAVITY_EAST:
+      return ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
+    case GDK_GRAVITY_SOUTH_WEST:
+      return (ZXDG_POSITIONER_V6_ANCHOR_BOTTOM |
+              ZXDG_POSITIONER_V6_ANCHOR_LEFT);
+    case GDK_GRAVITY_SOUTH:
+      return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM;
+    case GDK_GRAVITY_SOUTH_EAST:
+      return (ZXDG_POSITIONER_V6_ANCHOR_BOTTOM |
+              ZXDG_POSITIONER_V6_ANCHOR_RIGHT);
+    default:
+      g_assert_not_reached ();
+    }
+
+  return (ZXDG_POSITIONER_V6_ANCHOR_TOP |
+          ZXDG_POSITIONER_V6_ANCHOR_LEFT);
+}
+
+static enum zxdg_positioner_v6_gravity
+window_anchor_to_gravity (GdkGravity rect_anchor)
+{
+  switch (rect_anchor)
+    {
+    case GDK_GRAVITY_NORTH_WEST:
+    case GDK_GRAVITY_STATIC:
+      return (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
+              ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
+    case GDK_GRAVITY_NORTH:
+      return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM;
+    case GDK_GRAVITY_NORTH_EAST:
+      return (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
+              ZXDG_POSITIONER_V6_GRAVITY_LEFT);
+    case GDK_GRAVITY_WEST:
+      return ZXDG_POSITIONER_V6_GRAVITY_RIGHT;
+    case GDK_GRAVITY_CENTER:
+      return ZXDG_POSITIONER_V6_GRAVITY_NONE;
+    case GDK_GRAVITY_EAST:
+      return ZXDG_POSITIONER_V6_GRAVITY_LEFT;
+    case GDK_GRAVITY_SOUTH_WEST:
+      return (ZXDG_POSITIONER_V6_GRAVITY_TOP |
+              ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
+    case GDK_GRAVITY_SOUTH:
+      return ZXDG_POSITIONER_V6_GRAVITY_TOP;
+    case GDK_GRAVITY_SOUTH_EAST:
+      return (ZXDG_POSITIONER_V6_GRAVITY_TOP |
+              ZXDG_POSITIONER_V6_GRAVITY_LEFT);
+    default:
+      g_assert_not_reached ();
+    }
+
+  return (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
+          ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
+}
+
+void
+gdk_wayland_surface_announce_csd (GdkSurface *window)
+{
+  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  if (!display_wayland->server_decoration_manager)
+    return;
+  impl->display_server.server_decoration =
+    org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
+                                                  impl->display_server.wl_surface);
+  if (impl->display_server.server_decoration)
+    org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration,
+                                                ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT);
+}
+
+static GdkSurface *
+get_real_parent_and_translate (GdkSurface *window,
+                               gint      *x,
+                               gint      *y)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkSurface *parent = impl->transient_for;
+
+  while (parent)
+    {
+      GdkSurfaceImplWayland *parent_impl =
+        GDK_SURFACE_IMPL_WAYLAND (parent->impl);
+      GdkSurface *effective_parent = gdk_surface_get_parent (parent);
+
+      if ((gdk_surface_has_native (parent) &&
+           !parent_impl->display_server.wl_subsurface) ||
+          !effective_parent)
+        break;
+
+      *x += parent->x;
+      *y += parent->y;
+
+      if (gdk_surface_has_native (parent) &&
+          parent_impl->display_server.wl_subsurface)
+        parent = parent->transient_for;
+      else
+        parent = effective_parent;
+    }
+
+  return parent;
+}
+
+static void
+translate_to_real_parent_window_geometry (GdkSurface  *window,
+                                          gint       *x,
+                                          gint       *y)
+{
+  GdkSurface *parent;
+
+  parent = get_real_parent_and_translate (window, x, y);
+
+  *x -= parent->shadow_left;
+  *y -= parent->shadow_top;
+}
+
+static GdkSurface *
+translate_from_real_parent_window_geometry (GdkSurface *window,
+                                            gint      *x,
+                                            gint      *y)
+{
+  GdkSurface *parent;
+  gint dx = 0;
+  gint dy = 0;
+
+  parent = get_real_parent_and_translate (window, &dx, &dy);
+
+  *x -= dx - parent->shadow_left;
+  *y -= dy - parent->shadow_top;
+
+  return parent;
+}
+
+static void
+calculate_popup_rect (GdkSurface    *window,
+                      GdkGravity    rect_anchor,
+                      GdkGravity    window_anchor,
+                      GdkRectangle *out_rect)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkRectangle geometry;
+  GdkRectangle anchor_rect;
+  int x = 0, y = 0;
+
+  gdk_wayland_surface_get_window_geometry (window, &geometry);
+
+  anchor_rect = (GdkRectangle) {
+    .x = (impl->pending_move_to_rect.rect.x +
+          impl->pending_move_to_rect.rect_anchor_dx),
+    .y = (impl->pending_move_to_rect.rect.y +
+          impl->pending_move_to_rect.rect_anchor_dy),
+    .width = impl->pending_move_to_rect.rect.width,
+    .height = impl->pending_move_to_rect.rect.height
+  };
+
+  switch (rect_anchor)
+    {
+    default:
+    case GDK_GRAVITY_STATIC:
+    case GDK_GRAVITY_NORTH_WEST:
+      x = anchor_rect.x;
+      y = anchor_rect.y;
+      break;
+    case GDK_GRAVITY_NORTH:
+      x = anchor_rect.x + (anchor_rect.width / 2);
+      y = anchor_rect.y;
+      break;
+    case GDK_GRAVITY_NORTH_EAST:
+      x = anchor_rect.x + anchor_rect.width;
+      y = anchor_rect.y;
+      break;
+    case GDK_GRAVITY_WEST:
+      x = anchor_rect.x;
+      y = anchor_rect.y + (anchor_rect.height / 2);
+      break;
+    case GDK_GRAVITY_CENTER:
+      x = anchor_rect.x + (anchor_rect.width / 2);
+      y = anchor_rect.y + (anchor_rect.height / 2);
+      break;
+    case GDK_GRAVITY_EAST:
+      x = anchor_rect.x + anchor_rect.width;
+      y = anchor_rect.y + (anchor_rect.height / 2);
+      break;
+    case GDK_GRAVITY_SOUTH_WEST:
+      x = anchor_rect.x;
+      y = anchor_rect.y + anchor_rect.height;
+      break;
+    case GDK_GRAVITY_SOUTH:
+      x = anchor_rect.x + (anchor_rect.width / 2);
+      y = anchor_rect.y + anchor_rect.height;
+      break;
+    case GDK_GRAVITY_SOUTH_EAST:
+      x = anchor_rect.x + anchor_rect.width;
+      y = anchor_rect.y + anchor_rect.height;
+      break;
+    }
+
+  switch (window_anchor)
+    {
+    default:
+    case GDK_GRAVITY_STATIC:
+    case GDK_GRAVITY_NORTH_WEST:
+      break;
+    case GDK_GRAVITY_NORTH:
+      x -= geometry.width / 2;
+      break;
+    case GDK_GRAVITY_NORTH_EAST:
+      x -= geometry.width;
+      break;
+    case GDK_GRAVITY_WEST:
+      y -= geometry.height / 2;
+      break;
+    case GDK_GRAVITY_CENTER:
+      x -= geometry.width / 2;
+      y -= geometry.height / 2;
+      break;
+    case GDK_GRAVITY_EAST:
+      x -= geometry.width;
+      y -= geometry.height / 2;
+      break;
+    case GDK_GRAVITY_SOUTH_WEST:
+      y -= geometry.height;
+      break;
+    case GDK_GRAVITY_SOUTH:
+      x -= geometry.width / 2;
+      y -= geometry.height;
+      break;
+    case GDK_GRAVITY_SOUTH_EAST:
+      x -= geometry.width;
+      y -= geometry.height;
+      break;
+    }
+
+  *out_rect = (GdkRectangle) {
+    .x = x,
+    .y = y,
+    .width = geometry.width,
+    .height = geometry.height
+  };
+}
+
+static GdkGravity
+flip_anchor_horizontally (GdkGravity anchor)
+{
+  switch (anchor)
+    {
+    default:
+    case GDK_GRAVITY_STATIC:
+    case GDK_GRAVITY_NORTH_WEST:
+      return GDK_GRAVITY_NORTH_EAST;
+    case GDK_GRAVITY_NORTH:
+      return GDK_GRAVITY_NORTH;
+    case GDK_GRAVITY_NORTH_EAST:
+      return GDK_GRAVITY_NORTH_WEST;
+    case GDK_GRAVITY_WEST:
+      return GDK_GRAVITY_EAST;
+    case GDK_GRAVITY_CENTER:
+      return GDK_GRAVITY_CENTER;
+    case GDK_GRAVITY_EAST:
+      return GDK_GRAVITY_WEST;
+    case GDK_GRAVITY_SOUTH_WEST:
+      return GDK_GRAVITY_SOUTH_EAST;
+    case GDK_GRAVITY_SOUTH:
+      return GDK_GRAVITY_SOUTH;
+    case GDK_GRAVITY_SOUTH_EAST:
+      return GDK_GRAVITY_SOUTH_WEST;
+    }
+
+  g_assert_not_reached ();
+}
+
+static GdkGravity
+flip_anchor_vertically (GdkGravity anchor)
+{
+  switch (anchor)
+    {
+    default:
+    case GDK_GRAVITY_STATIC:
+    case GDK_GRAVITY_NORTH_WEST:
+      return GDK_GRAVITY_SOUTH_WEST;
+    case GDK_GRAVITY_NORTH:
+      return GDK_GRAVITY_SOUTH;
+    case GDK_GRAVITY_NORTH_EAST:
+      return GDK_GRAVITY_SOUTH_EAST;
+    case GDK_GRAVITY_WEST:
+      return GDK_GRAVITY_WEST;
+    case GDK_GRAVITY_CENTER:
+      return GDK_GRAVITY_CENTER;
+    case GDK_GRAVITY_EAST:
+      return GDK_GRAVITY_EAST;
+    case GDK_GRAVITY_SOUTH_WEST:
+      return GDK_GRAVITY_NORTH_WEST;
+    case GDK_GRAVITY_SOUTH:
+      return GDK_GRAVITY_NORTH;
+    case GDK_GRAVITY_SOUTH_EAST:
+      return GDK_GRAVITY_NORTH_EAST;
+    }
+
+  g_assert_not_reached ();
+}
+
+static void
+calculate_moved_to_rect_result (GdkSurface    *window,
+                                int           x,
+                                int           y,
+                                int           width,
+                                int           height,
+                                GdkRectangle *flipped_rect,
+                                GdkRectangle *final_rect,
+                                gboolean     *flipped_x,
+                                gboolean     *flipped_y)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkSurface *parent;
+  gint window_x, window_y;
+  gint window_width, window_height;
+  GdkRectangle best_rect;
+
+  parent = translate_from_real_parent_window_geometry (window, &x, &y);
+  *final_rect = (GdkRectangle) {
+    .x = x,
+    .y = y,
+    .width = width,
+    .height = height,
+  };
+
+  window_x = parent->x + x;
+  window_y = parent->y + y;
+  window_width = width + window->shadow_left + window->shadow_right;
+  window_height = height + window->shadow_top + window->shadow_bottom;
+
+  gdk_surface_move_resize (window,
+                          window_x, window_y,
+                          window_width, window_height);
+
+  calculate_popup_rect (window,
+                        impl->pending_move_to_rect.rect_anchor,
+                        impl->pending_move_to_rect.window_anchor,
+                        &best_rect);
+
+  *flipped_rect = best_rect;
+
+  if (x != best_rect.x &&
+      impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_X)
+    {
+      GdkRectangle flipped_x_rect;
+      GdkGravity flipped_rect_anchor;
+      GdkGravity flipped_window_anchor;
+
+      flipped_rect_anchor =
+        flip_anchor_horizontally (impl->pending_move_to_rect.rect_anchor);
+      flipped_window_anchor =
+        flip_anchor_horizontally (impl->pending_move_to_rect.window_anchor),
+      calculate_popup_rect (window,
+                            flipped_rect_anchor,
+                            flipped_window_anchor,
+                            &flipped_x_rect);
+
+      if (flipped_x_rect.x == x)
+        flipped_rect->x = x;
+    }
+  if (y != best_rect.y &&
+      impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_Y)
+    {
+      GdkRectangle flipped_y_rect;
+      GdkGravity flipped_rect_anchor;
+      GdkGravity flipped_window_anchor;
+
+      flipped_rect_anchor =
+        flip_anchor_vertically (impl->pending_move_to_rect.rect_anchor);
+      flipped_window_anchor =
+        flip_anchor_vertically (impl->pending_move_to_rect.window_anchor),
+      calculate_popup_rect (window,
+                            flipped_rect_anchor,
+                            flipped_window_anchor,
+                            &flipped_y_rect);
+
+      if (flipped_y_rect.y == y)
+        flipped_rect->y = y;
+    }
+
+  *flipped_x = flipped_rect->x != best_rect.x;
+  *flipped_y = flipped_rect->y != best_rect.y;
+}
+
+static struct zxdg_positioner_v6 *
+create_dynamic_positioner (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkWaylandDisplay *display =
+    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  struct zxdg_positioner_v6 *positioner;
+  GdkRectangle geometry;
+  enum zxdg_positioner_v6_anchor anchor;
+  enum zxdg_positioner_v6_gravity gravity;
+  uint32_t constraint_adjustment = ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE;
+  gint real_anchor_rect_x, real_anchor_rect_y;
+  gint anchor_rect_width, anchor_rect_height;
+
+  positioner = zxdg_shell_v6_create_positioner (display->xdg_shell);
+
+  gdk_wayland_surface_get_window_geometry (window, &geometry);
+  zxdg_positioner_v6_set_size (positioner, geometry.width, geometry.height);
+
+  real_anchor_rect_x = impl->pending_move_to_rect.rect.x;
+  real_anchor_rect_y = impl->pending_move_to_rect.rect.y;
+  translate_to_real_parent_window_geometry (window,
+                                            &real_anchor_rect_x,
+                                            &real_anchor_rect_y);
+
+  anchor_rect_width = impl->pending_move_to_rect.rect.width;
+  anchor_rect_height = impl->pending_move_to_rect.rect.height;
+  zxdg_positioner_v6_set_anchor_rect (positioner,
+                                      real_anchor_rect_x,
+                                      real_anchor_rect_y,
+                                      anchor_rect_width,
+                                      anchor_rect_height);
+
+  zxdg_positioner_v6_set_offset (positioner,
+                                 impl->pending_move_to_rect.rect_anchor_dx,
+                                 impl->pending_move_to_rect.rect_anchor_dy);
+
+  anchor = rect_anchor_to_anchor (impl->pending_move_to_rect.rect_anchor);
+  zxdg_positioner_v6_set_anchor (positioner, anchor);
+
+  gravity = window_anchor_to_gravity (impl->pending_move_to_rect.window_anchor);
+  zxdg_positioner_v6_set_gravity (positioner, gravity);
+
+  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_X)
+    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X;
+  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_Y)
+    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y;
+  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_SLIDE_X)
+    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X;
+  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_SLIDE_Y)
+    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y;
+  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_RESIZE_X)
+    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X;
+  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_RESIZE_Y)
+    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y;
+
+  zxdg_positioner_v6_set_constraint_adjustment (positioner,
+                                                constraint_adjustment);
+
+  return positioner;
+}
+
+static struct zxdg_positioner_v6 *
+create_simple_positioner (GdkSurface *window,
+                          GdkSurface *parent)
+{
+  GdkWaylandDisplay *display =
+    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  struct zxdg_positioner_v6 *positioner;
+  GdkRectangle geometry;
+  GdkRectangle parent_geometry;
+  int parent_x, parent_y;
+
+  positioner = zxdg_shell_v6_create_positioner (display->xdg_shell);
+
+  gdk_wayland_surface_get_window_geometry (window, &geometry);
+  zxdg_positioner_v6_set_size (positioner, geometry.width, geometry.height);
+
+  parent_x = parent->x;
+  parent_y = parent->y;
+
+  gdk_wayland_surface_get_window_geometry (parent, &parent_geometry);
+  parent_x += parent_geometry.x;
+  parent_y += parent_geometry.y;
+
+  zxdg_positioner_v6_set_anchor_rect (positioner,
+                                      (window->x + geometry.x) - parent_x,
+                                      (window->y + geometry.y) - parent_y,
+                                      1, 1);
+  zxdg_positioner_v6_set_anchor (positioner,
+                                 (ZXDG_POSITIONER_V6_ANCHOR_TOP |
+                                  ZXDG_POSITIONER_V6_ANCHOR_LEFT));
+  zxdg_positioner_v6_set_gravity (positioner,
+                                  (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
+                                   ZXDG_POSITIONER_V6_GRAVITY_RIGHT));
+
+  return positioner;
+}
+
+static void
+gdk_wayland_surface_create_xdg_popup (GdkSurface      *window,
+                                     GdkSurface      *parent,
+                                     struct wl_seat *seat)
+{
+  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkSurfaceImplWayland *parent_impl = GDK_SURFACE_IMPL_WAYLAND (parent->impl);
+  struct zxdg_positioner_v6 *positioner;
+  GdkSeat *gdk_seat;
+  guint32 serial;
+
+  if (!impl->display_server.wl_surface)
+    return;
+
+  if (!parent_impl->display_server.xdg_surface)
+    return;
+
+  if (impl->display_server.xdg_toplevel)
+    {
+      g_warning ("Can't map popup, already mapped as toplevel");
+      return;
+    }
+  if (impl->display_server.xdg_popup)
+    {
+      g_warning ("Can't map popup, already mapped");
+      return;
+    }
+  if ((display->current_popups &&
+       g_list_last (display->current_popups)->data != parent) ||
+      (!display->current_popups &&
+       !parent_impl->display_server.xdg_toplevel))
+    {
+      g_warning ("Tried to map a popup with a non-top most parent");
+      return;
+    }
+
+  impl->display_server.xdg_surface =
+    zxdg_shell_v6_get_xdg_surface (display->xdg_shell,
+                                   impl->display_server.wl_surface);
+  zxdg_surface_v6_add_listener (impl->display_server.xdg_surface,
+                                &xdg_surface_listener,
+                                window);
+  gdk_surface_freeze_updates (window);
+
+  if (impl->position_method == POSITION_METHOD_MOVE_TO_RECT)
+    positioner = create_dynamic_positioner (window);
+  else
+    positioner = create_simple_positioner (window, parent);
+
+  impl->display_server.xdg_popup =
+    zxdg_surface_v6_get_popup (impl->display_server.xdg_surface,
+                               parent_impl->display_server.xdg_surface,
+                               positioner);
+  zxdg_popup_v6_add_listener (impl->display_server.xdg_popup,
+                              &xdg_popup_listener,
+                              window);
+
+  zxdg_positioner_v6_destroy (positioner);
+
+  if (seat)
+    {
+      gdk_seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
+      serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_seat, NULL);
+      zxdg_popup_v6_grab (impl->display_server.xdg_popup, seat, serial);
+    }
+
+  wl_surface_commit (impl->display_server.wl_surface);
+
+  impl->popup_parent = parent;
+  display->current_popups = g_list_append (display->current_popups, window);
+}
+
+static struct wl_seat *
+find_grab_input_seat (GdkSurface *window, GdkSurface *transient_for)
+{
+  GdkSurface *attached_grab_window;
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkSurfaceImplWayland *tmp_impl;
+
+  /* Use the device that was used for the grab as the device for
+   * the popup window setup - so this relies on GTK+ taking the
+   * grab before showing the popup window.
+   */
+  if (impl->grab_input_seat)
+    return gdk_wayland_seat_get_wl_seat (impl->grab_input_seat);
+
+  /* HACK: GtkMenu grabs a special window known as the "grab transfer window"
+   * and then transfers the grab over to the correct window later. Look for
+   * this window when taking the grab to know it's correct.
+   *
+   * See: associate_menu_grab_transfer_window in gtkmenu.c
+   */
+  attached_grab_window = g_object_get_data (G_OBJECT (window), "gdk-attached-grab-window");
+  if (attached_grab_window)
+    {
+      tmp_impl = GDK_SURFACE_IMPL_WAYLAND (attached_grab_window->impl);
+      if (tmp_impl->grab_input_seat)
+        return gdk_wayland_seat_get_wl_seat (tmp_impl->grab_input_seat);
+    }
+
+  while (transient_for)
+    {
+      tmp_impl = GDK_SURFACE_IMPL_WAYLAND (transient_for->impl);
+
+      if (tmp_impl->grab_input_seat)
+        return gdk_wayland_seat_get_wl_seat (tmp_impl->grab_input_seat);
+
+      transient_for = tmp_impl->transient_for;
+    }
+
+  return NULL;
+}
+
+static gboolean
+should_be_mapped (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  /* Don't map crazy temp that GTK+ uses for internal X11 shenanigans. */
+  if (window->window_type == GDK_SURFACE_TEMP && window->x < 0 && window->y < 0)
+    return FALSE;
+
+  if (impl->hint == GDK_SURFACE_TYPE_HINT_DND)
+    return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+should_map_as_popup (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  /* Ideally, popup would be temp windows with a parent and grab */
+  if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP)
+    {
+      /* If a temp window has a parent and a grab, we can use a popup */
+      if (impl->transient_for)
+        {
+          if (impl->grab_input_seat)
+            return TRUE;
+        }
+      else
+        g_message ("Window %p is a temporary window without parent, "
+                   "application will not be able to position it on screen.",
+                   window);
+    }
+
+  /* Yet we need to keep the window type hint tests for compatibility */
+  switch ((guint) impl->hint)
+    {
+    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
+    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU:
+    case GDK_SURFACE_TYPE_HINT_COMBO:
+      return TRUE;
+
+    default:
+      break;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+should_map_as_subsurface (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_SUBSURFACE)
+    return TRUE;
+
+  if (GDK_SURFACE_TYPE (window) != GDK_SURFACE_TEMP)
+    return FALSE;
+
+  /* if we want a popup, we do not want a subsurface */
+  if (should_map_as_popup (window))
+    return FALSE;
+
+  if (impl->transient_for)
+    {
+      GdkSurfaceImplWayland *impl_parent;
+
+      impl_parent = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
+      /* subsurface require that the parent is mapped */
+      if (impl_parent->mapped)
+        return TRUE;
+      else
+        g_warning ("Couldn't map window %p as subsurface because its parent is not mapped.",
+                   window);
+
+    }
+
+  return FALSE;
+}
+
+/* Get the window that can be used as a parent for a popup, i.e. a xdg_toplevel
+ * or xdg_popup. If the window is not, traverse up the transiency parents until
+ * we find one.
+ */
+static GdkSurface *
+get_popup_parent (GdkSurface *window)
+{
+  while (window)
+    {
+      GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+      if (impl->display_server.xdg_popup || impl->display_server.xdg_toplevel)
+        return window;
+
+      window = impl->transient_for;
+    }
+
+  return NULL;
+}
+
+static void
+gdk_wayland_surface_map (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkSurface *transient_for = NULL;
+
+  if (!should_be_mapped (window))
+    return;
+
+  if (impl->mapped || impl->use_custom_surface)
+    return;
+
+  if (should_map_as_subsurface (window))
+    {
+      if (impl->transient_for)
+        gdk_wayland_surface_create_subsurface (window);
+      else
+        g_warning ("Couldn't map window %p as susburface yet because it doesn't have a parent",
+                   window);
+    }
+  else if (should_map_as_popup (window))
+    {
+      gboolean create_fallback = FALSE;
+      struct wl_seat *grab_input_seat;
+
+      /* Popup menus can appear without a transient parent, which means they
+       * cannot be positioned properly on Wayland. This attempts to guess the
+       * surface they should be positioned with by finding the surface beneath
+       * the device that created the grab for the popup window.
+       */
+      if (!impl->transient_for && impl->hint == GDK_SURFACE_TYPE_HINT_POPUP_MENU)
+        {
+          GdkDevice *grab_device = NULL;
+
+          /* The popup menu window is not the grabbed window. This may mean
+           * that a "transfer window" (see gtkmenu.c) is used, and we need
+           * to find that window to get the grab device. If so is the case
+           * the "transfer window" can be retrieved via the
+           * "gdk-attached-grab-window" associated data field.
+           */
+          if (!impl->grab_input_seat)
+            {
+              GdkSurface *attached_grab_window =
+                g_object_get_data (G_OBJECT (window),
+                                   "gdk-attached-grab-window");
+              if (attached_grab_window)
+                {
+                  GdkSurfaceImplWayland *attached_impl =
+                    GDK_SURFACE_IMPL_WAYLAND (attached_grab_window->impl);
+                  grab_device = gdk_seat_get_pointer (attached_impl->grab_input_seat);
+                  transient_for =
+                    gdk_device_get_window_at_position (grab_device,
+                                                       NULL, NULL);
+                }
+            }
+          else
+            {
+              grab_device = gdk_seat_get_pointer (impl->grab_input_seat);
+              transient_for =
+                gdk_device_get_window_at_position (grab_device, NULL, NULL);
+            }
+
+          if (transient_for)
+            transient_for = get_popup_parent (gdk_surface_get_toplevel (transient_for));
+
+          /* If the position was not explicitly set, start the popup at the
+           * position of the device that holds the grab.
+           */
+          if (impl->position_method == POSITION_METHOD_NONE && grab_device)
+            gdk_surface_get_device_position (transient_for, grab_device,
+                                            &window->x, &window->y, NULL);
+        }
+      else
+        {
+          transient_for = gdk_surface_get_toplevel (impl->transient_for);
+          transient_for = get_popup_parent (transient_for);
+        }
+
+      if (!transient_for)
+        {
+          g_warning ("Couldn't map as window %p as popup because it doesn't have a parent",
+                     window);
+
+          create_fallback = TRUE;
+        }
+      else
+        {
+          grab_input_seat = find_grab_input_seat (window, transient_for);
+        }
+
+      if (!create_fallback)
+        {
+          gdk_wayland_surface_create_xdg_popup (window,
+                                               transient_for,
+                                               grab_input_seat);
+        }
+      else
+        {
+          gdk_wayland_surface_create_xdg_toplevel (window);
+        }
+    }
+  else
+    {
+      gdk_wayland_surface_create_xdg_toplevel (window);
+    }
+
+  impl->mapped = TRUE;
+}
+
+static void
+gdk_wayland_surface_show (GdkSurface *window,
+                         gboolean   already_mapped)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (!impl->display_server.wl_surface)
+    gdk_wayland_surface_create_surface (window);
+
+  gdk_wayland_surface_map (window);
+
+  _gdk_make_event (window, GDK_MAP, NULL, FALSE);
+
+  if (impl->staging_cairo_surface &&
+      _gdk_wayland_is_shm_surface (impl->staging_cairo_surface))
+    gdk_wayland_surface_attach_image (window);
+}
+
+static void
+unmap_subsurface (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkSurfaceImplWayland *parent_impl;
+
+  g_return_if_fail (impl->display_server.wl_subsurface);
+  g_return_if_fail (impl->transient_for);
+
+  parent_impl = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
+  wl_subsurface_destroy (impl->display_server.wl_subsurface);
+  if (impl->parent_surface_committed_handler)
+    {
+      g_signal_handler_disconnect (parent_impl,
+                                   impl->parent_surface_committed_handler);
+      impl->parent_surface_committed_handler = 0;
+    }
+  impl->display_server.wl_subsurface = NULL;
+}
+
+static void
+unmap_popups_for_window (GdkSurface *window)
+{
+  GdkWaylandDisplay *display_wayland;
+  GList *l;
+
+  display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  for (l = display_wayland->current_popups; l; l = l->next)
+    {
+       GdkSurface *popup = l->data;
+       GdkSurfaceImplWayland *popup_impl = GDK_SURFACE_IMPL_WAYLAND (popup->impl);
+
+       if (popup_impl->popup_parent == window)
+         {
+           g_warning ("Tried to unmap the parent of a popup");
+           gdk_surface_hide (popup);
+
+           return;
+         }
+    }
+}
+
+static void
+gdk_wayland_surface_hide_surface (GdkSurface *window)
+{
+  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  unmap_popups_for_window (window);
+
+  if (impl->display_server.wl_surface)
+    {
+      if (impl->dummy_egl_surface)
+        {
+          eglDestroySurface (display_wayland->egl_display, impl->dummy_egl_surface);
+          impl->dummy_egl_surface = NULL;
+        }
+
+      if (impl->display_server.dummy_egl_window)
+        {
+          wl_egl_window_destroy (impl->display_server.dummy_egl_window);
+          impl->display_server.dummy_egl_window = NULL;
+        }
+
+      if (impl->egl_surface)
+        {
+          eglDestroySurface (display_wayland->egl_display, impl->egl_surface);
+          impl->egl_surface = NULL;
+        }
+
+      if (impl->display_server.egl_window)
+        {
+          wl_egl_window_destroy (impl->display_server.egl_window);
+          impl->display_server.egl_window = NULL;
+        }
+
+      if (impl->display_server.xdg_toplevel)
+        {
+          zxdg_toplevel_v6_destroy (impl->display_server.xdg_toplevel);
+          impl->display_server.xdg_toplevel = NULL;
+        }
+      else if (impl->display_server.xdg_popup)
+        {
+          zxdg_popup_v6_destroy (impl->display_server.xdg_popup);
+          impl->display_server.xdg_popup = NULL;
+          display_wayland->current_popups =
+            g_list_remove (display_wayland->current_popups, window);
+        }
+      if (impl->display_server.xdg_surface)
+        {
+          zxdg_surface_v6_destroy (impl->display_server.xdg_surface);
+          impl->display_server.xdg_surface = NULL;
+          if (!impl->initial_configure_received)
+            gdk_surface_thaw_updates (window);
+          else
+            impl->initial_configure_received = FALSE;
+        }
+
+      if (impl->display_server.wl_subsurface)
+        unmap_subsurface (window);
+
+      if (impl->awaiting_frame)
+        {
+          GdkFrameClock *frame_clock;
+
+          impl->awaiting_frame = FALSE;
+          frame_clock = gdk_surface_get_frame_clock (window);
+          if (frame_clock)
+            _gdk_frame_clock_thaw (frame_clock);
+        }
+
+      if (impl->display_server.gtk_surface)
+        {
+          gtk_surface1_destroy (impl->display_server.gtk_surface);
+          impl->display_server.gtk_surface = NULL;
+          impl->application.was_set = FALSE;
+        }
+
+      wl_surface_destroy (impl->display_server.wl_surface);
+      impl->display_server.wl_surface = NULL;
+
+      g_slist_free (impl->display_server.outputs);
+      impl->display_server.outputs = NULL;
+
+      if (impl->hint == GDK_SURFACE_TYPE_HINT_DIALOG && !impl->transient_for)
+        display_wayland->orphan_dialogs =
+          g_list_remove (display_wayland->orphan_dialogs, window);
+    }
+
+  unset_transient_for_exported (window);
+
+  _gdk_wayland_surface_clear_saved_size (window);
+  impl->pending_commit = FALSE;
+  impl->mapped = FALSE;
+}
+
+static void
+gdk_wayland_surface_hide (GdkSurface *window)
+{
+  gdk_wayland_surface_hide_surface (window);
+  _gdk_surface_clear_update_area (window);
+}
+
+static void
+gdk_surface_wayland_withdraw (GdkSurface *window)
+{
+  if (!window->destroyed)
+    {
+      if (GDK_SURFACE_IS_MAPPED (window))
+        gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_WITHDRAWN);
+
+      g_assert (!GDK_SURFACE_IS_MAPPED (window));
+
+      gdk_wayland_surface_hide_surface (window);
+    }
+}
+
+static void
+gdk_surface_wayland_set_events (GdkSurface    *window,
+                               GdkEventMask  event_mask)
+{
+  GDK_SURFACE (window)->event_mask = event_mask;
+}
+
+static GdkEventMask
+gdk_surface_wayland_get_events (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window))
+    return 0;
+  else
+    return GDK_SURFACE (window)->event_mask;
+}
+
+static void
+gdk_surface_wayland_raise (GdkSurface *window)
+{
+}
+
+static void
+gdk_surface_wayland_lower (GdkSurface *window)
+{
+}
+
+static void
+gdk_surface_wayland_restack_toplevel (GdkSurface *window,
+                                     GdkSurface *sibling,
+                                     gboolean   above)
+{
+}
+
+static void
+gdk_surface_request_transient_parent_commit (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *window_impl, *impl;
+  GdkFrameClock *frame_clock;
+
+  window_impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (!window_impl->transient_for)
+    return;
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window_impl->transient_for->impl);
+
+  if (!impl->display_server.wl_surface || impl->pending_commit)
+    return;
+
+  frame_clock = gdk_surface_get_frame_clock (window_impl->transient_for);
+
+  if (!frame_clock)
+    return;
+
+  impl->pending_commit = TRUE;
+  gdk_frame_clock_request_phase (frame_clock,
+                                 GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
+}
+
+static void
+gdk_surface_wayland_move_resize (GdkSurface *window,
+                                gboolean   with_move,
+                                gint       x,
+                                gint       y,
+                                gint       width,
+                                gint       height)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (with_move)
+    {
+      /* Each toplevel has in its own "root" coordinate system */
+      if (GDK_SURFACE_TYPE (window) != GDK_SURFACE_TOPLEVEL)
+        {
+          window->x = x;
+          window->y = y;
+          impl->position_method = POSITION_METHOD_MOVE_RESIZE;
+
+          if (impl->display_server.wl_subsurface)
+            {
+              wl_subsurface_set_position (impl->display_server.wl_subsurface,
+                                          window->x + window->abs_x,
+                                          window->y + window->abs_y);
+              gdk_surface_request_transient_parent_commit (window);
+            }
+        }
+    }
+
+  /* If this function is called with width and height = -1 then that means
+   * just move the window - don't update its size
+   */
+  if (width > 0 && height > 0)
+    gdk_wayland_surface_maybe_configure (window, width, height, impl->scale);
+}
+
+/* Avoid zero width/height as this is a protocol error */
+static void
+sanitize_anchor_rect (GdkSurface    *window,
+                      GdkRectangle *rect)
+{
+  gint original_width = rect->width;
+  gint original_height = rect->height;
+
+  rect->width  = MAX (1, rect->width);
+  rect->height = MAX (1, rect->height);
+  rect->x = MAX (rect->x + original_width - rect->width, 0);
+  rect->y = MAX (rect->y + original_height - rect->height, 0);
+}
+
+static void
+gdk_surface_wayland_move_to_rect (GdkSurface          *window,
+                                 const GdkRectangle *rect,
+                                 GdkGravity          rect_anchor,
+                                 GdkGravity          window_anchor,
+                                 GdkAnchorHints      anchor_hints,
+                                 gint                rect_anchor_dx,
+                                 gint                rect_anchor_dy)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  impl->pending_move_to_rect.rect = *rect;
+  sanitize_anchor_rect (window, &impl->pending_move_to_rect.rect);
+
+  impl->pending_move_to_rect.rect_anchor = rect_anchor;
+  impl->pending_move_to_rect.window_anchor = window_anchor;
+  impl->pending_move_to_rect.anchor_hints = anchor_hints;
+  impl->pending_move_to_rect.rect_anchor_dx = rect_anchor_dx;
+  impl->pending_move_to_rect.rect_anchor_dy = rect_anchor_dy;
+
+  impl->position_method = POSITION_METHOD_MOVE_TO_RECT;
+}
+
+static void
+gdk_surface_wayland_get_geometry (GdkSurface *window,
+                                 gint      *x,
+                                 gint      *y,
+                                 gint      *width,
+                                 gint      *height)
+{
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      if (x)
+        *x = window->x;
+      if (y)
+        *y = window->y;
+      if (width)
+        *width = window->width;
+      if (height)
+        *height = window->height;
+    }
+}
+
+static void
+gdk_surface_wayland_get_root_coords (GdkSurface *window,
+                                    gint       x,
+                                    gint       y,
+                                    gint      *root_x,
+                                    gint      *root_y)
+{
+  /*
+   * Wayland does not have a global coordinate space shared between surfaces. In
+   * fact, for regular toplevels, we have no idea where our surfaces are
+   * positioned, relatively.
+   *
+   * However, there are some cases like popups and subsurfaces where we do have
+   * some amount of control over the placement of our window, and we can
+   * semi-accurately control the x/y position of these windows, if they are
+   * relative to another surface.
+   *
+   * To pretend we have something called a root coordinate space, assume all
+   * parent-less windows are positioned in (0, 0), and all relative positioned
+   * popups and subsurfaces are placed within this fake root coordinate space.
+   *
+   * For example a 200x200 large toplevel window will have the position (0, 0).
+   * If a popup positioned in the middle of the toplevel will have the fake
+   * position (100,100). Furthermore, if a positioned is placed in the middle
+   * that popup, will have the fake position (150,150), even though it has the
+   * relative position (50,50). These three windows would make up one single
+   * fake root coordinate space.
+   */
+
+  if (root_x)
+    *root_x = window->x + x;
+
+  if (root_y)
+    *root_y = window->y + y;
+}
+
+static gboolean
+gdk_surface_wayland_get_device_state (GdkSurface       *window,
+                                     GdkDevice       *device,
+                                     gdouble         *x,
+                                     gdouble         *y,
+                                     GdkModifierType *mask)
+{
+  gboolean return_val;
+
+  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), FALSE);
+
+  return_val = TRUE;
+
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      GdkSurface *child;
+
+      GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
+                                                  &child,
+                                                  NULL, NULL,
+                                                  x, y, mask);
+      return_val = (child != NULL);
+    }
+
+  return return_val;
+}
+
+static void
+gdk_surface_wayland_shape_combine_region (GdkSurface            *window,
+                                         const cairo_region_t *shape_region,
+                                         gint                  offset_x,
+                                         gint                  offset_y)
+{
+}
+
+static void
+gdk_surface_wayland_input_shape_combine_region (GdkSurface            *window,
+                                               const cairo_region_t *shape_region,
+                                               gint                  offset_x,
+                                               gint                  offset_y)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  g_clear_pointer (&impl->input_region, cairo_region_destroy);
+
+  if (shape_region)
+    {
+      impl->input_region = cairo_region_copy (shape_region);
+      cairo_region_translate (impl->input_region, offset_x, offset_y);
+    }
+
+  impl->input_region_dirty = TRUE;
+}
+
+static void
+gdk_wayland_surface_destroy (GdkSurface *window,
+                            gboolean   recursing,
+                            gboolean   foreign_destroy)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  /* Wayland windows can't be externally destroyed; we may possibly
+   * eventually want to use this path at display close-down
+   */
+  g_return_if_fail (!foreign_destroy);
+
+  gdk_wayland_surface_hide_surface (window);
+  drop_cairo_surfaces (window);
+
+  if (window->parent == NULL)
+    {
+      GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+      display->toplevels = g_list_remove (display->toplevels, window);
+    }
+}
+
+static void
+gdk_wayland_surface_focus (GdkSurface *window,
+                          guint32    timestamp)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (!impl->display_server.gtk_surface)
+    return;
+
+  /* We didn't have an event to fetch a time from, meaning we have nothing valid
+   * to send. This should rather be translated to a 'needs-attention' request or
+   * something.
+   */
+  if (timestamp == GDK_CURRENT_TIME)
+    return;
+
+  gtk_surface1_present (impl->display_server.gtk_surface, timestamp);
+}
+
+static void
+gdk_wayland_surface_set_type_hint (GdkSurface         *window,
+                                  GdkSurfaceTypeHint  hint)
+{
+  GdkSurfaceImplWayland *impl;
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  impl->hint = hint;
+}
+
+static GdkSurfaceTypeHint
+gdk_wayland_surface_get_type_hint (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return GDK_SURFACE_TYPE_HINT_NORMAL;
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  return impl->hint;
+}
+
+static void
+gtk_surface_configure (void                *data,
+                       struct gtk_surface1 *gtk_surface,
+                       struct wl_array     *states)
+{
+  GdkSurface *window = GDK_SURFACE (data);
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkSurfaceState new_state = 0;
+  uint32_t *p;
+
+  wl_array_for_each (p, states)
+    {
+      uint32_t state = *p;
+
+      switch (state)
+        {
+        case GTK_SURFACE1_STATE_TILED:
+          new_state |= GDK_SURFACE_STATE_TILED;
+          break;
+
+        /* Since v2 */
+        case GTK_SURFACE1_STATE_TILED_TOP:
+          new_state |= (GDK_SURFACE_STATE_TILED | GDK_SURFACE_STATE_TOP_TILED);
+          break;
+        case GTK_SURFACE1_STATE_TILED_RIGHT:
+          new_state |= (GDK_SURFACE_STATE_TILED | GDK_SURFACE_STATE_RIGHT_TILED);
+          break;
+        case GTK_SURFACE1_STATE_TILED_BOTTOM:
+          new_state |= (GDK_SURFACE_STATE_TILED | GDK_SURFACE_STATE_BOTTOM_TILED);
+          break;
+        case GTK_SURFACE1_STATE_TILED_LEFT:
+          new_state |= (GDK_SURFACE_STATE_TILED | GDK_SURFACE_STATE_LEFT_TILED);
+          break;
+        default:
+          /* Unknown state */
+          break;
+        }
+    }
+
+  impl->pending.state |= new_state;
+}
+
+static void
+gtk_surface_configure_edges (void                *data,
+                             struct gtk_surface1 *gtk_surface,
+                             struct wl_array     *edge_constraints)
+{
+  GdkSurface *window = GDK_SURFACE (data);
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkSurfaceState new_state = 0;
+  uint32_t *p;
+
+  wl_array_for_each (p, edge_constraints)
+    {
+      uint32_t constraint = *p;
+
+      switch (constraint)
+        {
+        case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_TOP:
+          new_state |= GDK_SURFACE_STATE_TOP_RESIZABLE;
+          break;
+        case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_RIGHT:
+          new_state |= GDK_SURFACE_STATE_RIGHT_RESIZABLE;
+          break;
+        case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_BOTTOM:
+          new_state |= GDK_SURFACE_STATE_BOTTOM_RESIZABLE;
+          break;
+        case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_LEFT:
+          new_state |= GDK_SURFACE_STATE_LEFT_RESIZABLE;
+          break;
+        default:
+          /* Unknown state */
+          break;
+        }
+    }
+
+  impl->pending.state |= new_state;
+}
+
+static const struct gtk_surface1_listener gtk_surface_listener = {
+  gtk_surface_configure,
+  gtk_surface_configure_edges
+};
+
+static void
+gdk_wayland_surface_init_gtk_surface (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkWaylandDisplay *display =
+    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+
+  if (impl->display_server.gtk_surface != NULL)
+    return;
+  if (impl->display_server.xdg_surface == NULL)
+    return;
+  if (display->gtk_shell == NULL)
+    return;
+
+  impl->display_server.gtk_surface =
+    gtk_shell1_get_gtk_surface (display->gtk_shell,
+                                impl->display_server.wl_surface);
+  gdk_surface_set_geometry_hints (window,
+                                 &impl->geometry_hints,
+                                 impl->geometry_mask);
+  gtk_surface1_add_listener (impl->display_server.gtk_surface,
+                             &gtk_surface_listener,
+                             window);
+}
+
+static void
+maybe_set_gtk_surface_modal (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  gdk_wayland_surface_init_gtk_surface (window);
+  if (impl->display_server.gtk_surface == NULL)
+    return;
+
+  if (window->modal_hint)
+    gtk_surface1_set_modal (impl->display_server.gtk_surface);
+  else
+    gtk_surface1_unset_modal (impl->display_server.gtk_surface);
+
+}
+
+static void
+gdk_wayland_surface_set_modal_hint (GdkSurface *window,
+                                   gboolean   modal)
+{
+  window->modal_hint = modal;
+  maybe_set_gtk_surface_modal (window);
+}
+
+static void
+gdk_wayland_surface_set_skip_taskbar_hint (GdkSurface *window,
+                                          gboolean   skips_taskbar)
+{
+}
+
+static void
+gdk_wayland_surface_set_skip_pager_hint (GdkSurface *window,
+                                        gboolean   skips_pager)
+{
+}
+
+static void
+gdk_wayland_surface_set_urgency_hint (GdkSurface *window,
+                                     gboolean   urgent)
+{
+}
+
+static void
+gdk_wayland_surface_set_geometry_hints (GdkSurface         *window,
+                                       const GdkGeometry *geometry,
+                                       GdkSurfaceHints     geom_mask)
+{
+  GdkSurfaceImplWayland *impl;
+  int width, height;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  impl->geometry_hints = *geometry;
+  impl->geometry_mask = geom_mask;
+
+  if (!impl->display_server.xdg_toplevel)
+    return;
+
+  if (geom_mask & GDK_HINT_MIN_SIZE)
+    {
+      width = MAX (0, geometry->min_width - (impl->margin_left + impl->margin_right));
+      height = MAX (0, geometry->min_height - (impl->margin_top + impl->margin_bottom));
+    }
+  else
+    {
+      width = 0;
+      height = 0;
+    }
+
+  zxdg_toplevel_v6_set_min_size (impl->display_server.xdg_toplevel, width, height);
+
+  if (geom_mask & GDK_HINT_MAX_SIZE)
+    {
+      width = MAX (0, geometry->max_width - (impl->margin_left + impl->margin_right));
+      height = MAX (0, geometry->max_height - (impl->margin_top + impl->margin_bottom));
+    }
+  else
+    {
+      width = 0;
+      height = 0;
+    }
+
+  zxdg_toplevel_v6_set_max_size (impl->display_server.xdg_toplevel, width, height);
+}
+
+static void
+gdk_wayland_surface_set_title (GdkSurface   *window,
+                              const gchar *title)
+{
+  GdkSurfaceImplWayland *impl;
+  const char *end;
+  gsize title_length;
+
+  g_return_if_fail (title != NULL);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (g_strcmp0 (impl->title, title) == 0)
+    return;
+
+  g_free (impl->title);
+
+  title_length = MIN (strlen (title), MAX_WL_BUFFER_SIZE);
+  if (g_utf8_validate (title, title_length, &end))
+    {
+      impl->title = g_malloc (end - title + 1);
+      memcpy (impl->title, title, end - title);
+      impl->title[end - title] = '\0';
+    }
+  else
+    {
+      impl->title = g_utf8_make_valid (title, title_length);
+      g_warning ("Invalid utf8 passed to gdk_surface_set_title: '%s'", title);
+    }
+
+  gdk_wayland_surface_sync_title (window);
+}
+
+static void
+gdk_wayland_surface_set_role (GdkSurface   *window,
+                             const gchar *role)
+{
+}
+
+static void
+gdk_wayland_surface_set_startup_id (GdkSurface   *window,
+                                   const gchar *startup_id)
+{
+}
+
+static gboolean
+check_transient_for_loop (GdkSurface *window,
+                          GdkSurface *parent)
+{
+  while (parent)
+    {
+      GdkSurfaceImplWayland *impl;
+
+      if (!GDK_IS_SURFACE_IMPL_WAYLAND(parent->impl))
+        return FALSE;
+
+      impl = GDK_SURFACE_IMPL_WAYLAND (parent->impl);
+      if (impl->transient_for == window)
+        return TRUE;
+      parent = impl->transient_for;
+    }
+  return FALSE;
+}
+
+static void
+gdk_wayland_surface_set_transient_for (GdkSurface *window,
+                                      GdkSurface *parent)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkWaylandDisplay *display_wayland =
+    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  GdkSurface *previous_parent;
+
+  g_assert (parent == NULL ||
+            gdk_surface_get_display (window) == gdk_surface_get_display (parent));
+
+  if (check_transient_for_loop (window, parent))
+    {
+      g_warning ("Setting %p transient for %p would create a loop", window, parent);
+      return;
+    }
+
+  unset_transient_for_exported (window);
+
+  if (impl->display_server.wl_subsurface)
+    unmap_subsurface (window);
+
+  previous_parent = impl->transient_for;
+  impl->transient_for = parent;
+
+  if (impl->hint == GDK_SURFACE_TYPE_HINT_DIALOG)
+    {
+      if (!parent)
+        _gdk_wayland_screen_add_orphan_dialog (window);
+      else if (!previous_parent)
+        display_wayland->orphan_dialogs =
+          g_list_remove (display_wayland->orphan_dialogs, window);
+    }
+  gdk_wayland_surface_sync_parent (window, NULL);
+  if (should_map_as_subsurface (window) &&
+      parent && gdk_surface_is_visible (window))
+    gdk_wayland_surface_create_subsurface (window);
+}
+
+static void
+gdk_wayland_surface_get_frame_extents (GdkSurface    *window,
+                                      GdkRectangle *rect)
+{
+  *rect = (GdkRectangle) {
+    .x = window->x,
+    .y = window->y,
+    .width = window->width,
+    .height = window->height
+  };
+}
+
+static void
+gdk_wayland_surface_set_accept_focus (GdkSurface *window,
+                                     gboolean   accept_focus)
+{
+}
+
+static void
+gdk_wayland_surface_set_focus_on_map (GdkSurface *window,
+                                     gboolean focus_on_map)
+{
+}
+
+static void
+gdk_wayland_surface_set_icon_list (GdkSurface *window,
+                                  GList     *surfaces)
+{
+}
+
+static void
+gdk_wayland_surface_set_icon_name (GdkSurface   *window,
+                                  const gchar *name)
+{
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+}
+
+static void
+gdk_wayland_surface_iconify (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  if (!impl->display_server.xdg_toplevel)
+    return;
+
+  zxdg_toplevel_v6_set_minimized (impl->display_server.xdg_toplevel);
+}
+
+static void
+gdk_wayland_surface_deiconify (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    gdk_surface_show (window);
+  else
+    /* Flip our client side flag, the real work happens on map. */
+    gdk_synthesize_window_state (window, GDK_SURFACE_STATE_ICONIFIED, 0);
+}
+
+static void
+gdk_wayland_surface_stick (GdkSurface *window)
+{
+}
+
+static void
+gdk_wayland_surface_unstick (GdkSurface *window)
+{
+}
+
+static void
+gdk_wayland_surface_maximize (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  _gdk_wayland_surface_save_size (window);
+  if (impl->display_server.xdg_toplevel)
+    zxdg_toplevel_v6_set_maximized (impl->display_server.xdg_toplevel);
+  else
+    gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_MAXIMIZED);
+}
+
+static void
+gdk_wayland_surface_unmaximize (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (impl->display_server.xdg_toplevel)
+    zxdg_toplevel_v6_unset_maximized (impl->display_server.xdg_toplevel);
+  else
+    gdk_synthesize_window_state (window, GDK_SURFACE_STATE_MAXIMIZED, 0);
+}
+
+static void
+gdk_wayland_surface_fullscreen_on_monitor (GdkSurface  *window,
+                                          GdkMonitor *monitor)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  struct wl_output *output = ((GdkWaylandMonitor *)monitor)->output;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  _gdk_wayland_surface_save_size (window);
+  if (impl->display_server.xdg_toplevel)
+    {
+      zxdg_toplevel_v6_set_fullscreen (impl->display_server.xdg_toplevel, output);
+    }
+  else
+    {
+      gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
+      impl->initial_fullscreen_output = output;
+    }
+}
+
+static void
+gdk_wayland_surface_fullscreen (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  impl->initial_fullscreen_output = NULL;
+
+  _gdk_wayland_surface_save_size (window);
+  if (impl->display_server.xdg_toplevel)
+    zxdg_toplevel_v6_set_fullscreen (impl->display_server.xdg_toplevel, NULL);
+  else
+    gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
+}
+
+static void
+gdk_wayland_surface_unfullscreen (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  impl->initial_fullscreen_output = NULL;
+
+  if (impl->display_server.xdg_toplevel)
+    zxdg_toplevel_v6_unset_fullscreen (impl->display_server.xdg_toplevel);
+  else
+    gdk_synthesize_window_state (window, GDK_SURFACE_STATE_FULLSCREEN, 0);
+}
+
+static void
+gdk_wayland_surface_set_keep_above (GdkSurface *window, gboolean setting)
+{
+}
+
+static void
+gdk_wayland_surface_set_keep_below (GdkSurface *window, gboolean setting)
+{
+}
+
+static GdkSurface *
+gdk_wayland_surface_get_group (GdkSurface *window)
+{
+  return NULL;
+}
+
+static void
+gdk_wayland_surface_set_group (GdkSurface *window,
+                              GdkSurface *leader)
+{
+}
+
+static void
+gdk_wayland_surface_set_decorations (GdkSurface       *window,
+                                    GdkWMDecoration  decorations)
+{
+}
+
+static gboolean
+gdk_wayland_surface_get_decorations (GdkSurface       *window,
+                                    GdkWMDecoration *decorations)
+{
+  return FALSE;
+}
+
+static void
+gdk_wayland_surface_set_functions (GdkSurface     *window,
+                                  GdkWMFunction  functions)
+{
+}
+
+static void
+gdk_wayland_surface_begin_resize_drag (GdkSurface     *window,
+                                      GdkSurfaceEdge  edge,
+                                      GdkDevice     *device,
+                                      gint           button,
+                                      gint           root_x,
+                                      gint           root_y,
+                                      guint32        timestamp)
+{
+  GdkSurfaceImplWayland *impl;
+  GdkEventSequence *sequence;
+  uint32_t resize_edges, serial;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  switch (edge)
+    {
+    case GDK_SURFACE_EDGE_NORTH_WEST:
+      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_LEFT;
+      break;
+
+    case GDK_SURFACE_EDGE_NORTH:
+      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP;
+      break;
+
+    case GDK_SURFACE_EDGE_NORTH_EAST:
+      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_RIGHT;
+      break;
+
+    case GDK_SURFACE_EDGE_WEST:
+      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT;
+      break;
+
+    case GDK_SURFACE_EDGE_EAST:
+      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT;
+      break;
+
+    case GDK_SURFACE_EDGE_SOUTH_WEST:
+      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_LEFT;
+      break;
+
+    case GDK_SURFACE_EDGE_SOUTH:
+      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM;
+      break;
+
+    case GDK_SURFACE_EDGE_SOUTH_EAST:
+      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_RIGHT;
+      break;
+
+    default:
+      g_warning ("gdk_surface_begin_resize_drag: bad resize edge %d!", edge);
+      return;
+    }
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (!impl->display_server.xdg_toplevel)
+    return;
+
+  serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_device_get_seat (device),
+                                                            &sequence);
+
+  zxdg_toplevel_v6_resize (impl->display_server.xdg_toplevel,
+                           gdk_wayland_device_get_wl_seat (device),
+                           serial, resize_edges);
+
+  if (sequence)
+    gdk_wayland_device_unset_touch_grab (device, sequence);
+
+  /* This is needed since Wayland will absorb all the pointer events after the
+   * above function - FIXME: Is this always safe..?
+   */
+  gdk_seat_ungrab (gdk_device_get_seat (device));
+}
+
+static void
+gdk_wayland_surface_begin_move_drag (GdkSurface *window,
+                                    GdkDevice *device,
+                                    gint       button,
+                                    gint       root_x,
+                                    gint       root_y,
+                                    guint32    timestamp)
+{
+  GdkSurfaceImplWayland *impl;
+  GdkEventSequence *sequence;
+  uint32_t serial;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (!impl->display_server.xdg_toplevel)
+    return;
+
+  serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_device_get_seat (device),
+                                                            &sequence);
+  zxdg_toplevel_v6_move (impl->display_server.xdg_toplevel,
+                         gdk_wayland_device_get_wl_seat (device),
+                         serial);
+  if (sequence)
+    gdk_wayland_device_unset_touch_grab (device, sequence);
+
+  /* This is needed since Wayland will absorb all the pointer events after the
+   * above function - FIXME: Is this always safe..?
+   */
+  gdk_seat_ungrab (gdk_device_get_seat (device));
+}
+
+static void
+gdk_wayland_surface_set_opacity (GdkSurface *window,
+                                gdouble    opacity)
+{
+}
+
+static void
+gdk_wayland_surface_destroy_notify (GdkSurface *window)
+{
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      g_warning ("GdkSurface %p unexpectedly destroyed", window);
+      _gdk_surface_destroy (window, TRUE);
+    }
+
+  g_object_unref (window);
+}
+
+static gint
+gdk_wayland_surface_get_scale_factor (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return 1;
+
+  return impl->scale;
+}
+
+static void
+gdk_wayland_surface_set_opaque_region (GdkSurface      *window,
+                                      cairo_region_t *region)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
+  impl->opaque_region = cairo_region_reference (region);
+  impl->opaque_region_dirty = TRUE;
+}
+
+static void
+gdk_wayland_surface_set_shadow_width (GdkSurface *window,
+                                     int        left,
+                                     int        right,
+                                     int        top,
+                                     int        bottom)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  gint new_width, new_height;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  /* Reconfigure window to keep the same window geometry */
+  new_width = window->width -
+    (impl->margin_left + impl->margin_right) + (left + right);
+  new_height = window->height -
+    (impl->margin_top + impl->margin_bottom) + (top + bottom);
+  gdk_wayland_surface_maybe_configure (window, new_width, new_height, impl->scale);
+
+  impl->margin_left = left;
+  impl->margin_right = right;
+  impl->margin_top = top;
+  impl->margin_bottom = bottom;
+}
+
+static gboolean
+gdk_wayland_surface_show_window_menu (GdkSurface *window,
+                                     GdkEvent  *event)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  struct wl_seat *seat;
+  GdkWaylandDevice *device;
+  double x, y;
+  uint32_t serial;
+
+  switch ((guint) event->any.type)
+    {
+    case GDK_BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+    case GDK_TOUCH_BEGIN:
+    case GDK_TOUCH_END:
+      break;
+    default:
+      return FALSE;
+    }
+
+  if (!impl->display_server.xdg_surface)
+    return FALSE;
+
+  device = GDK_WAYLAND_DEVICE (gdk_event_get_device (event));
+  seat = gdk_wayland_device_get_wl_seat (GDK_DEVICE (device));
+  gdk_event_get_coords (event, &x, &y);
+
+  serial = _gdk_wayland_device_get_implicit_grab_serial (device, event);
+  zxdg_toplevel_v6_show_window_menu (impl->display_server.xdg_toplevel,
+                                     seat, serial, x, y);
+  return TRUE;
+}
+
+static gboolean
+gdk_wayland_surface_supports_edge_constraints (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  struct gtk_surface1 *gtk_surface = impl->display_server.gtk_surface;
+
+  if (!gtk_surface)
+    return FALSE;
+
+  return gtk_surface1_get_version (gtk_surface) >= GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION;
+}
+
+static void
+_gdk_surface_impl_wayland_class_init (GdkSurfaceImplWaylandClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_CLASS (klass);
+
+  object_class->finalize = gdk_surface_impl_wayland_finalize;
+
+  impl_class->ref_cairo_surface = gdk_wayland_surface_ref_cairo_surface;
+  impl_class->create_similar_image_surface = gdk_wayland_surface_create_similar_image_surface;
+  impl_class->show = gdk_wayland_surface_show;
+  impl_class->hide = gdk_wayland_surface_hide;
+  impl_class->withdraw = gdk_surface_wayland_withdraw;
+  impl_class->set_events = gdk_surface_wayland_set_events;
+  impl_class->get_events = gdk_surface_wayland_get_events;
+  impl_class->raise = gdk_surface_wayland_raise;
+  impl_class->lower = gdk_surface_wayland_lower;
+  impl_class->restack_toplevel = gdk_surface_wayland_restack_toplevel;
+  impl_class->move_resize = gdk_surface_wayland_move_resize;
+  impl_class->move_to_rect = gdk_surface_wayland_move_to_rect;
+  impl_class->get_geometry = gdk_surface_wayland_get_geometry;
+  impl_class->get_root_coords = gdk_surface_wayland_get_root_coords;
+  impl_class->get_device_state = gdk_surface_wayland_get_device_state;
+  impl_class->shape_combine_region = gdk_surface_wayland_shape_combine_region;
+  impl_class->input_shape_combine_region = gdk_surface_wayland_input_shape_combine_region;
+  impl_class->destroy = gdk_wayland_surface_destroy;
+  impl_class->begin_paint = gdk_surface_impl_wayland_begin_paint;
+  impl_class->end_paint = gdk_surface_impl_wayland_end_paint;
+  impl_class->beep = gdk_surface_impl_wayland_beep;
+
+  impl_class->focus = gdk_wayland_surface_focus;
+  impl_class->set_type_hint = gdk_wayland_surface_set_type_hint;
+  impl_class->get_type_hint = gdk_wayland_surface_get_type_hint;
+  impl_class->set_modal_hint = gdk_wayland_surface_set_modal_hint;
+  impl_class->set_skip_taskbar_hint = gdk_wayland_surface_set_skip_taskbar_hint;
+  impl_class->set_skip_pager_hint = gdk_wayland_surface_set_skip_pager_hint;
+  impl_class->set_urgency_hint = gdk_wayland_surface_set_urgency_hint;
+  impl_class->set_geometry_hints = gdk_wayland_surface_set_geometry_hints;
+  impl_class->set_title = gdk_wayland_surface_set_title;
+  impl_class->set_role = gdk_wayland_surface_set_role;
+  impl_class->set_startup_id = gdk_wayland_surface_set_startup_id;
+  impl_class->set_transient_for = gdk_wayland_surface_set_transient_for;
+  impl_class->get_frame_extents = gdk_wayland_surface_get_frame_extents;
+  impl_class->set_accept_focus = gdk_wayland_surface_set_accept_focus;
+  impl_class->set_focus_on_map = gdk_wayland_surface_set_focus_on_map;
+  impl_class->set_icon_list = gdk_wayland_surface_set_icon_list;
+  impl_class->set_icon_name = gdk_wayland_surface_set_icon_name;
+  impl_class->iconify = gdk_wayland_surface_iconify;
+  impl_class->deiconify = gdk_wayland_surface_deiconify;
+  impl_class->stick = gdk_wayland_surface_stick;
+  impl_class->unstick = gdk_wayland_surface_unstick;
+  impl_class->maximize = gdk_wayland_surface_maximize;
+  impl_class->unmaximize = gdk_wayland_surface_unmaximize;
+  impl_class->fullscreen = gdk_wayland_surface_fullscreen;
+  impl_class->fullscreen_on_monitor = gdk_wayland_surface_fullscreen_on_monitor;
+  impl_class->unfullscreen = gdk_wayland_surface_unfullscreen;
+  impl_class->set_keep_above = gdk_wayland_surface_set_keep_above;
+  impl_class->set_keep_below = gdk_wayland_surface_set_keep_below;
+  impl_class->get_group = gdk_wayland_surface_get_group;
+  impl_class->set_group = gdk_wayland_surface_set_group;
+  impl_class->set_decorations = gdk_wayland_surface_set_decorations;
+  impl_class->get_decorations = gdk_wayland_surface_get_decorations;
+  impl_class->set_functions = gdk_wayland_surface_set_functions;
+  impl_class->begin_resize_drag = gdk_wayland_surface_begin_resize_drag;
+  impl_class->begin_move_drag = gdk_wayland_surface_begin_move_drag;
+  impl_class->set_opacity = gdk_wayland_surface_set_opacity;
+  impl_class->destroy_notify = gdk_wayland_surface_destroy_notify;
+  impl_class->register_dnd = _gdk_wayland_surface_register_dnd;
+  impl_class->drag_begin = _gdk_wayland_surface_drag_begin;
+  impl_class->get_scale_factor = gdk_wayland_surface_get_scale_factor;
+  impl_class->set_opaque_region = gdk_wayland_surface_set_opaque_region;
+  impl_class->set_shadow_width = gdk_wayland_surface_set_shadow_width;
+  impl_class->show_window_menu = gdk_wayland_surface_show_window_menu;
+  impl_class->create_gl_context = gdk_wayland_surface_create_gl_context;
+  impl_class->supports_edge_constraints = gdk_wayland_surface_supports_edge_constraints;
+
+  signals[COMMITTED] = g_signal_new (g_intern_static_string ("committed"),
+                                     G_TYPE_FROM_CLASS (object_class),
+                                     G_SIGNAL_RUN_LAST,
+                                     0,
+                                     NULL, NULL, NULL,
+                                     G_TYPE_NONE, 0);
+}
+
+void
+_gdk_wayland_surface_set_grab_seat (GdkSurface *window,
+                                   GdkSeat   *seat)
+{
+  GdkSurfaceImplWayland *impl;
+
+  g_return_if_fail (window != NULL);
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  impl->grab_input_seat = seat;
+}
+
+/**
+ * gdk_wayland_surface_new_subsurface: (constructor)
+ * @display: the display to create the window on
+ * @position: position relative to the transient window
+ *
+ * Creates a new subsurface window.
+ *
+ * Returns: (transfer full): the new #GdkSurface
+ **/
+GdkSurface *
+gdk_wayland_surface_new_subsurface (GdkDisplay         *display,
+                                   const GdkRectangle *position)
+{
+  GdkSurfaceAttr attr;
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+  g_return_val_if_fail (position != NULL, NULL);
+
+  attr.wclass = GDK_INPUT_OUTPUT;
+  attr.x = position->x;
+  attr.y = position->y;
+  attr.width = position->width;
+  attr.height = position->height;
+  attr.window_type = GDK_SURFACE_SUBSURFACE;
+
+  return gdk_surface_new (display, NULL, &attr);
+}
+
+/**
+ * gdk_wayland_surface_get_wl_surface:
+ * @window: (type GdkWaylandSurface): a #GdkSurface
+ *
+ * Returns the Wayland surface of a #GdkSurface.
+ *
+ * Returns: (transfer none): a Wayland wl_surface
+ */
+struct wl_surface *
+gdk_wayland_surface_get_wl_surface (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), NULL);
+
+  return GDK_SURFACE_IMPL_WAYLAND (window->impl)->display_server.wl_surface;
+}
+
+struct wl_output *
+gdk_wayland_surface_get_wl_output (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl;
+
+  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), NULL);
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  /* We pick the head of the list as this is the last entered output */
+  if (impl->display_server.outputs)
+    return (struct wl_output *) impl->display_server.outputs->data;
+
+  return NULL;
+}
+
+static struct wl_egl_window *
+gdk_wayland_surface_get_wl_egl_window (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (impl->display_server.egl_window == NULL)
+    {
+      impl->display_server.egl_window =
+        wl_egl_window_create (impl->display_server.wl_surface,
+                              impl->wrapper->width * impl->scale,
+                              impl->wrapper->height * impl->scale);
+      wl_surface_set_buffer_scale (impl->display_server.wl_surface, impl->scale);
+    }
+
+  return impl->display_server.egl_window;
+}
+
+EGLSurface
+gdk_wayland_surface_get_egl_surface (GdkSurface *window,
+                                    EGLConfig  config)
+{
+  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  GdkSurfaceImplWayland *impl;
+  struct wl_egl_window *egl_window;
+
+  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), NULL);
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (impl->egl_surface == NULL)
+    {
+      egl_window = gdk_wayland_surface_get_wl_egl_window (window);
+
+      impl->egl_surface =
+        eglCreateWindowSurface (display->egl_display, config, egl_window, NULL);
+    }
+
+  return impl->egl_surface;
+}
+
+EGLSurface
+gdk_wayland_surface_get_dummy_egl_surface (GdkSurface *window,
+                                          EGLConfig  config)
+{
+  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  GdkSurfaceImplWayland *impl;
+
+  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), NULL);
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (impl->dummy_egl_surface == NULL)
+    {
+      impl->display_server.dummy_egl_window =
+        wl_egl_window_create (impl->display_server.wl_surface, 1, 1);
+
+      impl->dummy_egl_surface =
+        eglCreateWindowSurface (display->egl_display, config, impl->display_server.dummy_egl_window, NULL);
+    }
+
+  return impl->dummy_egl_surface;
+}
+
+struct gtk_surface1 *
+gdk_wayland_surface_get_gtk_surface (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), NULL);
+
+  return GDK_SURFACE_IMPL_WAYLAND (window->impl)->display_server.gtk_surface;
+}
+
+/**
+ * gdk_wayland_surface_set_use_custom_surface:
+ * @window: (type GdkWaylandSurface): a #GdkSurface
+ *
+ * Marks a #GdkSurface as a custom Wayland surface. The application is
+ * expected to register the surface as some type of surface using
+ * some Wayland interface.
+ *
+ * A good example would be writing a panel or on-screen-keyboard as an
+ * out-of-process helper - as opposed to having those in the compositor
+ * process. In this case the underlying surface isn’t an xdg_shell
+ * surface and the panel or OSK client need to identify the wl_surface
+ * as a panel or OSK to the compositor. The assumption is that the
+ * compositor will expose a private interface to the special client
+ * that lets the client identify the wl_surface as a panel or such.
+ *
+ * This function should be called before a #GdkSurface is shown. This is
+ * best done by connecting to the #GtkWidget::realize signal:
+ *
+ * |[<!-- language="C" -->
+ *   static void
+ *   widget_realize_cb (GtkWidget *widget)
+ *   {
+ *     GdkSurface *window;
+ *     struct wl_surface *surface;
+ *     struct input_panel_surface *ip_surface;
+ *
+ *     window = gtk_widget_get_window (widget);
+ *     gdk_wayland_surface_set_custom_surface (window);
+ *
+ *     surface = gdk_wayland_surface_get_wl_surface (window);
+ *     ip_surface = input_panel_get_input_panel_surface (input_panel, surface);
+ *     input_panel_surface_set_panel (ip_surface);
+ *   }
+ *
+ *   static void
+ *   setup_window (GtkWindow *window)
+ *   {
+ *     g_signal_connect (window, "realize", G_CALLBACK (widget_realize_cb), NULL);
+ *   }
+ * ]|
+ */
+void
+gdk_wayland_surface_set_use_custom_surface (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl;
+
+  g_return_if_fail (GDK_IS_WAYLAND_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (!impl->display_server.wl_surface)
+    gdk_wayland_surface_create_surface (window);
+
+  impl->use_custom_surface = TRUE;
+}
+
+static void
+maybe_set_gtk_surface_dbus_properties (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  if (impl->application.was_set)
+    return;
+
+  if (impl->application.application_id == NULL &&
+      impl->application.app_menu_path == NULL &&
+      impl->application.menubar_path == NULL &&
+      impl->application.window_object_path == NULL &&
+      impl->application.application_object_path == NULL &&
+      impl->application.unique_bus_name == NULL)
+    return;
+
+  gdk_wayland_surface_init_gtk_surface (window);
+  if (impl->display_server.gtk_surface == NULL)
+    return;
+
+  gtk_surface1_set_dbus_properties (impl->display_server.gtk_surface,
+                                    impl->application.application_id,
+                                    impl->application.app_menu_path,
+                                    impl->application.menubar_path,
+                                    impl->application.window_object_path,
+                                    impl->application.application_object_path,
+                                    impl->application.unique_bus_name);
+  impl->application.was_set = TRUE;
+}
+
+void
+gdk_wayland_surface_set_dbus_properties_libgtk_only (GdkSurface  *window,
+                                                    const char *application_id,
+                                                    const char *app_menu_path,
+                                                    const char *menubar_path,
+                                                    const char *window_object_path,
+                                                    const char *application_object_path,
+                                                    const char *unique_bus_name)
+{
+  GdkSurfaceImplWayland *impl;
+
+  g_return_if_fail (GDK_IS_WAYLAND_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  impl->application.application_id = g_strdup (application_id);
+  impl->application.app_menu_path = g_strdup (app_menu_path);
+  impl->application.menubar_path = g_strdup (menubar_path);
+  impl->application.window_object_path = g_strdup (window_object_path);
+  impl->application.application_object_path =
+    g_strdup (application_object_path);
+  impl->application.unique_bus_name = g_strdup (unique_bus_name);
+
+  maybe_set_gtk_surface_dbus_properties (window);
+}
+
+void
+_gdk_wayland_surface_offset_next_wl_buffer (GdkSurface *window,
+                                           int        x,
+                                           int        y)
+{
+  GdkSurfaceImplWayland *impl;
+
+  g_return_if_fail (GDK_IS_WAYLAND_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  impl->pending_buffer_offset_x = x;
+  impl->pending_buffer_offset_y = y;
+}
+
+static void
+xdg_exported_handle (void                    *data,
+                     struct zxdg_exported_v1 *zxdg_exported_v1,
+                     const char              *handle)
+{
+  GdkSurface *window = data;
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  impl->exported.callback (window, handle, impl->exported.user_data);
+  g_clear_pointer (&impl->exported.user_data,
+                   impl->exported.destroy_func);
+}
+
+static const struct zxdg_exported_v1_listener xdg_exported_listener = {
+  xdg_exported_handle
+};
+
+/**
+ * GdkWaylandSurfaceExported:
+ * @window: the #GdkSurface that is exported
+ * @handle: the handle
+ * @user_data: user data that was passed to gdk_wayland_surface_export_handle()
+ *
+ * Callback that gets called when the handle for a window has been
+ * obtained from the Wayland compositor. The handle can be passed
+ * to other processes, for the purpose of marking windows as transient
+ * for out-of-process surfaces.
+ */
+
+static gboolean
+gdk_wayland_surface_is_exported (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  return !!impl->display_server.xdg_exported;
+}
+
+/**
+ * gdk_wayland_surface_export_handle:
+ * @window: the #GdkSurface to obtain a handle for
+ * @callback: callback to call with the handle
+ * @user_data: user data for @callback
+ * @destroy_func: destroy notify for @user_data
+ *
+ * Asynchronously obtains a handle for a surface that can be passed
+ * to other processes. When the handle has been obtained, @callback
+ * will be called.
+ *
+ * It is an error to call this function on a window that is already
+ * exported.
+ *
+ * When the handle is no longer needed, gdk_wayland_surface_unexport_handle()
+ * should be called to clean up resources.
+ *
+ * The main purpose for obtaining a handle is to mark a surface
+ * from another window as transient for this one, see
+ * gdk_wayland_surface_set_transient_for_exported().
+ *
+ * Note that this API depends on an unstable Wayland protocol,
+ * and thus may require changes in the future.
+ *
+ * Return value: %TRUE if the handle has been requested, %FALSE if
+ *     an error occurred.
+ */
+gboolean
+gdk_wayland_surface_export_handle (GdkSurface                *window,
+                                  GdkWaylandSurfaceExported  callback,
+                                  gpointer                  user_data,
+                                  GDestroyNotify            destroy_func)
+{
+  GdkSurfaceImplWayland *impl;
+  GdkWaylandDisplay *display_wayland;
+  GdkDisplay *display = gdk_surface_get_display (window);
+  struct zxdg_exported_v1 *xdg_exported;
+
+  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), FALSE);
+  g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  display_wayland = GDK_WAYLAND_DISPLAY (display);
+
+  g_return_val_if_fail (!impl->display_server.xdg_exported, FALSE);
+
+  if (!display_wayland->xdg_exporter)
+    {
+      g_warning ("Server is missing xdg_foreign support");
+      return FALSE;
+    }
+
+  xdg_exported = zxdg_exporter_v1_export (display_wayland->xdg_exporter,
+                                          impl->display_server.wl_surface);
+  zxdg_exported_v1_add_listener (xdg_exported,  &xdg_exported_listener, window);
+
+  impl->display_server.xdg_exported = xdg_exported;
+  impl->exported.callback = callback;
+  impl->exported.user_data = user_data;
+  impl->exported.destroy_func = destroy_func;
+
+  return TRUE;
+}
+
+/**
+ * gdk_wayland_surface_unexport_handle:
+ * @window: the #GdkSurface to unexport
+ *
+ * Destroys the handle that was obtained with
+ * gdk_wayland_surface_export_handle().
+ *
+ * It is an error to call this function on a window that
+ * does not have a handle.
+ *
+ * Note that this API depends on an unstable Wayland protocol,
+ * and thus may require changes in the future.
+ */
+void
+gdk_wayland_surface_unexport_handle (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl;
+
+  g_return_if_fail (GDK_IS_WAYLAND_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  g_return_if_fail (impl->display_server.xdg_exported);
+
+  g_clear_pointer (&impl->display_server.xdg_exported,
+                   zxdg_exported_v1_destroy);
+  g_clear_pointer (&impl->exported.user_data,
+                   impl->exported.destroy_func);
+}
+
+static void
+unset_transient_for_exported (GdkSurface *window)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+
+  g_clear_pointer (&impl->imported_transient_for, zxdg_imported_v1_destroy);
+}
+
+static void
+xdg_imported_destroyed (void                    *data,
+                        struct zxdg_imported_v1 *zxdg_imported_v1)
+{
+  GdkSurface *window = data;
+
+  unset_transient_for_exported (window);
+}
+
+static const struct zxdg_imported_v1_listener xdg_imported_listener = {
+  xdg_imported_destroyed,
+};
+
+/**
+ * gdk_wayland_surface_set_transient_for_exported:
+ * @window: the #GdkSurface to make as transient
+ * @parent_handle_str: an exported handle for a surface
+ *
+ * Marks @window as transient for the surface to which the given
+ * @parent_handle_str refers. Typically, the handle will originate
+ * from a gdk_wayland_surface_export_handle() call in another process.
+ *
+ * Note that this API depends on an unstable Wayland protocol,
+ * and thus may require changes in the future.
+ *
+ * Return value: %TRUE if the window has been marked as transient,
+ *     %FALSE if an error occurred.
+ */
+gboolean
+gdk_wayland_surface_set_transient_for_exported (GdkSurface *window,
+                                               char      *parent_handle_str)
+{
+  GdkSurfaceImplWayland *impl;
+  GdkWaylandDisplay *display_wayland;
+  GdkDisplay *display = gdk_surface_get_display (window);
+
+  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), FALSE);
+  g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
+  g_return_val_if_fail (!should_map_as_subsurface (window) &&
+                        !should_map_as_popup (window), FALSE);
+
+  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  display_wayland = GDK_WAYLAND_DISPLAY (display);
+
+  if (!display_wayland->xdg_importer)
+    {
+      g_warning ("Server is missing xdg_foreign support");
+      return FALSE;
+    }
+
+  gdk_surface_set_transient_for (window, NULL);
+
+  impl->imported_transient_for =
+    zxdg_importer_v1_import (display_wayland->xdg_importer, parent_handle_str);
+  zxdg_imported_v1_add_listener (impl->imported_transient_for,
+                                 &xdg_imported_listener,
+                                 window);
+
+  gdk_wayland_surface_sync_parent_of_imported (window);
+
+  return TRUE;
+}
+
+static struct zwp_keyboard_shortcuts_inhibitor_v1 *
+gdk_wayland_surface_get_inhibitor (GdkSurfaceImplWayland *impl,
+                                  struct wl_seat *seat)
+{
+  return g_hash_table_lookup (impl->shortcuts_inhibitors, seat);
+}
+
+void
+gdk_wayland_surface_inhibit_shortcuts (GdkSurface *window,
+                                      GdkSeat   *gdk_seat)
+{
+  GdkSurfaceImplWayland *impl= GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
+  struct wl_surface *surface = impl->display_server.wl_surface;
+  struct wl_seat *seat = gdk_wayland_seat_get_wl_seat (gdk_seat);
+  struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
+
+  if (display->keyboard_shortcuts_inhibit == NULL)
+    return;
+
+  if (gdk_wayland_surface_get_inhibitor (impl, seat))
+    return; /* Already inhibitted */
+
+  inhibitor =
+      zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts (
+          display->keyboard_shortcuts_inhibit, surface, seat);
+
+  g_hash_table_insert (impl->shortcuts_inhibitors, seat, inhibitor);
+}
+
+void
+gdk_wayland_surface_restore_shortcuts (GdkSurface *window,
+                                      GdkSeat   *gdk_seat)
+{
+  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
+  struct wl_seat *seat = gdk_wayland_seat_get_wl_seat (gdk_seat);
+  struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
+
+  inhibitor = gdk_wayland_surface_get_inhibitor (impl, seat);
+  if (inhibitor == NULL)
+    return; /* Not inhibitted */
+
+  zwp_keyboard_shortcuts_inhibitor_v1_destroy (inhibitor);
+  g_hash_table_remove (impl->shortcuts_inhibitors, seat);
+}
+
index cdac2076352a1cb807ab1d4f583fc5b639e7938c..a5f721ec64dd792dbe98ae6ed4bd7211db3f0672 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "gdkinternals.h"
 #include "gdkwaylanddisplay.h"
-#include "gdkwaylandwindow.h"
+#include "gdkwaylandsurface.h"
 #include "gdkprivate-wayland.h"
 
 G_DEFINE_TYPE (GdkWaylandVulkanContext, gdk_wayland_vulkan_context, GDK_TYPE_VULKAN_CONTEXT)
index 14f25d1d1d433b45bd4372e14b7f33e1137f6edd..9179d58e779a074d5a05c832233d58af39c668f8 100644 (file)
@@ -32,7 +32,7 @@
 #include <gdk/wayland/gdkwaylanddevice.h>
 #include <gdk/wayland/gdkwaylanddisplay.h>
 #include <gdk/wayland/gdkwaylandmonitor.h>
-#include <gdk/wayland/gdkwaylandwindow.h>
+#include <gdk/wayland/gdkwaylandsurface.h>
 #include <gdk/wayland/gdkwaylandglcontext.h>
 
 #undef __GDKWAYLAND_H_INSIDE__
diff --git a/gdk/wayland/gdkwaylandsurface.h b/gdk/wayland/gdkwaylandsurface.h
new file mode 100644 (file)
index 0000000..b9747b6
--- /dev/null
@@ -0,0 +1,87 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2013 Jan Arne Petersen
+ *
+ * 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_WAYLAND_SURFACE_H__
+#define __GDK_WAYLAND_SURFACE_H__
+
+#if !defined (__GDKWAYLAND_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdkwayland.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+#include <wayland-client.h>
+
+G_BEGIN_DECLS
+
+#ifdef GDK_COMPILATION
+typedef struct _GdkWaylandSurface GdkWaylandSurface;
+#else
+typedef GdkSurface GdkWaylandSurface;
+#endif
+typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
+
+#define GDK_TYPE_WAYLAND_SURFACE              (gdk_wayland_surface_get_type())
+#define GDK_WAYLAND_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_SURFACE, GdkWaylandSurface))
+#define GDK_WAYLAND_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_SURFACE, GdkWaylandSurfaceClass))
+#define GDK_IS_WAYLAND_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_SURFACE))
+#define GDK_IS_WAYLAND_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_SURFACE))
+#define GDK_WAYLAND_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_SURFACE, GdkWaylandSurfaceClass))
+
+GDK_AVAILABLE_IN_ALL
+GType                    gdk_wayland_surface_get_type             (void);
+
+GDK_AVAILABLE_IN_ALL
+GdkSurface *              gdk_wayland_surface_new_subsurface       (GdkDisplay            *display,
+                                                                  const GdkRectangle    *position);
+GDK_AVAILABLE_IN_ALL
+struct wl_surface       *gdk_wayland_surface_get_wl_surface       (GdkSurface *window);
+
+GDK_AVAILABLE_IN_ALL
+void                     gdk_wayland_surface_set_use_custom_surface (GdkSurface *window);
+
+GDK_AVAILABLE_IN_ALL
+void                     gdk_wayland_surface_set_dbus_properties_libgtk_only (GdkSurface  *window,
+                                                                            const char *application_id,
+                                                                            const char *app_menu_path,
+                                                                            const char *menubar_path,
+                                                                            const char *window_object_path,
+                                                                            const char *application_object_path,
+                                                                            const char *unique_bus_name);
+
+typedef void (*GdkWaylandSurfaceExported) (GdkSurface  *window,
+                                          const char *handle,
+                                          gpointer    user_data);
+
+GDK_AVAILABLE_IN_ALL
+gboolean                 gdk_wayland_surface_export_handle (GdkSurface               *window,
+                                                           GdkWaylandSurfaceExported callback,
+                                                           gpointer                 user_data,
+                                                           GDestroyNotify           destroy_func);
+
+GDK_AVAILABLE_IN_ALL
+void                     gdk_wayland_surface_unexport_handle (GdkSurface *window);
+
+GDK_AVAILABLE_IN_ALL
+gboolean                 gdk_wayland_surface_set_transient_for_exported (GdkSurface *window,
+                                                                        char      *parent_handle_str);
+
+void gdk_wayland_surface_announce_csd                        (GdkSurface *window);
+
+G_END_DECLS
+
+#endif /* __GDK_WAYLAND_SURFACE_H__ */
diff --git a/gdk/wayland/gdkwaylandwindow.h b/gdk/wayland/gdkwaylandwindow.h
deleted file mode 100644 (file)
index b9747b6..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- * Copyright (C) 2013 Jan Arne Petersen
- *
- * 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_WAYLAND_SURFACE_H__
-#define __GDK_WAYLAND_SURFACE_H__
-
-#if !defined (__GDKWAYLAND_H_INSIDE__) && !defined (GDK_COMPILATION)
-#error "Only <gdk/gdkwayland.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-#include <wayland-client.h>
-
-G_BEGIN_DECLS
-
-#ifdef GDK_COMPILATION
-typedef struct _GdkWaylandSurface GdkWaylandSurface;
-#else
-typedef GdkSurface GdkWaylandSurface;
-#endif
-typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
-
-#define GDK_TYPE_WAYLAND_SURFACE              (gdk_wayland_surface_get_type())
-#define GDK_WAYLAND_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_SURFACE, GdkWaylandSurface))
-#define GDK_WAYLAND_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_SURFACE, GdkWaylandSurfaceClass))
-#define GDK_IS_WAYLAND_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_SURFACE))
-#define GDK_IS_WAYLAND_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_SURFACE))
-#define GDK_WAYLAND_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_SURFACE, GdkWaylandSurfaceClass))
-
-GDK_AVAILABLE_IN_ALL
-GType                    gdk_wayland_surface_get_type             (void);
-
-GDK_AVAILABLE_IN_ALL
-GdkSurface *              gdk_wayland_surface_new_subsurface       (GdkDisplay            *display,
-                                                                  const GdkRectangle    *position);
-GDK_AVAILABLE_IN_ALL
-struct wl_surface       *gdk_wayland_surface_get_wl_surface       (GdkSurface *window);
-
-GDK_AVAILABLE_IN_ALL
-void                     gdk_wayland_surface_set_use_custom_surface (GdkSurface *window);
-
-GDK_AVAILABLE_IN_ALL
-void                     gdk_wayland_surface_set_dbus_properties_libgtk_only (GdkSurface  *window,
-                                                                            const char *application_id,
-                                                                            const char *app_menu_path,
-                                                                            const char *menubar_path,
-                                                                            const char *window_object_path,
-                                                                            const char *application_object_path,
-                                                                            const char *unique_bus_name);
-
-typedef void (*GdkWaylandSurfaceExported) (GdkSurface  *window,
-                                          const char *handle,
-                                          gpointer    user_data);
-
-GDK_AVAILABLE_IN_ALL
-gboolean                 gdk_wayland_surface_export_handle (GdkSurface               *window,
-                                                           GdkWaylandSurfaceExported callback,
-                                                           gpointer                 user_data,
-                                                           GDestroyNotify           destroy_func);
-
-GDK_AVAILABLE_IN_ALL
-void                     gdk_wayland_surface_unexport_handle (GdkSurface *window);
-
-GDK_AVAILABLE_IN_ALL
-gboolean                 gdk_wayland_surface_set_transient_for_exported (GdkSurface *window,
-                                                                        char      *parent_handle_str);
-
-void gdk_wayland_surface_announce_csd                        (GdkSurface *window);
-
-G_END_DECLS
-
-#endif /* __GDK_WAYLAND_SURFACE_H__ */
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
deleted file mode 100644 (file)
index ead400f..0000000
+++ /dev/null
@@ -1,4206 +0,0 @@
-/*
- * Copyright Â© 2010 Intel Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <netinet/in.h>
-#include <unistd.h>
-
-#include "gdk.h"
-#include "gdkwayland.h"
-
-#include "gdkwindow.h"
-#include "gdkwindowimpl.h"
-#include "gdkdisplay-wayland.h"
-#include "gdkglcontext-wayland.h"
-#include "gdkframeclockprivate.h"
-#include "gdkprivate-wayland.h"
-#include "gdkinternals.h"
-#include "gdkdeviceprivate.h"
-#include "gdkprivate-wayland.h"
-#include "gdkmonitor-wayland.h"
-#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-enum {
-  COMMITTED,
-
-  LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL];
-
-#define WINDOW_IS_TOPLEVEL(window) \
-  (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD)
-
-#define MAX_WL_BUFFER_SIZE (4083) /* 4096 minus header, string argument length and NUL byte */
-
-typedef struct _GdkWaylandSurface GdkWaylandSurface;
-typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
-
-struct _GdkWaylandSurface
-{
-  GdkSurface parent;
-};
-
-struct _GdkWaylandSurfaceClass
-{
-  GdkSurfaceClass parent_class;
-};
-
-G_DEFINE_TYPE (GdkWaylandSurface, gdk_wayland_surface, GDK_TYPE_SURFACE)
-
-static void
-gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *wayland_surface_class)
-{
-}
-
-static void
-gdk_wayland_surface_init (GdkWaylandSurface *wayland_surface)
-{
-}
-
-#define GDK_TYPE_SURFACE_IMPL_WAYLAND              (_gdk_surface_impl_wayland_get_type ())
-#define GDK_SURFACE_IMPL_WAYLAND(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_WAYLAND, GdkSurfaceImplWayland))
-#define GDK_SURFACE_IMPL_WAYLAND_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_WAYLAND, GdkSurfaceImplWaylandClass))
-#define GDK_IS_SURFACE_IMPL_WAYLAND(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_WAYLAND))
-#define GDK_IS_SURFACE_IMPL_WAYLAND_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_WAYLAND))
-#define GDK_SURFACE_IMPL_WAYLAND_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_WAYLAND, GdkSurfaceImplWaylandClass))
-
-typedef struct _GdkSurfaceImplWayland GdkSurfaceImplWayland;
-typedef struct _GdkSurfaceImplWaylandClass GdkSurfaceImplWaylandClass;
-
-typedef enum _PositionMethod
-{
-  POSITION_METHOD_NONE,
-  POSITION_METHOD_MOVE_RESIZE,
-  POSITION_METHOD_MOVE_TO_RECT
-} PositionMethod;
-
-struct _GdkSurfaceImplWayland
-{
-  GdkSurfaceImpl parent_instance;
-
-  GdkSurface *wrapper;
-
-  struct {
-    /* The wl_outputs that this window currently touches */
-    GSList               *outputs;
-
-    struct wl_surface    *wl_surface;
-    struct zxdg_surface_v6 *xdg_surface;
-    struct zxdg_toplevel_v6 *xdg_toplevel;
-    struct zxdg_popup_v6 *xdg_popup;
-    struct gtk_surface1  *gtk_surface;
-    struct wl_subsurface *wl_subsurface;
-    struct wl_egl_window *egl_window;
-    struct wl_egl_window *dummy_egl_window;
-    struct zxdg_exported_v1 *xdg_exported;
-    struct org_kde_kwin_server_decoration *server_decoration;
-  } display_server;
-
-  EGLSurface egl_surface;
-  EGLSurface dummy_egl_surface;
-
-  unsigned int initial_configure_received : 1;
-  unsigned int mapped : 1;
-  unsigned int use_custom_surface : 1;
-  unsigned int pending_buffer_attached : 1;
-  unsigned int pending_commit : 1;
-  unsigned int awaiting_frame : 1;
-  GdkSurfaceTypeHint hint;
-  GdkSurface *transient_for;
-  GdkSurface *popup_parent;
-  PositionMethod position_method;
-
-  cairo_surface_t *staging_cairo_surface;
-  cairo_surface_t *committed_cairo_surface;
-  cairo_surface_t *backfill_cairo_surface;
-
-  int pending_buffer_offset_x;
-  int pending_buffer_offset_y;
-
-  gchar *title;
-
-  struct {
-    gboolean was_set;
-
-    gchar *application_id;
-    gchar *app_menu_path;
-    gchar *menubar_path;
-    gchar *window_object_path;
-    gchar *application_object_path;
-    gchar *unique_bus_name;
-  } application;
-
-  GdkGeometry geometry_hints;
-  GdkSurfaceHints geometry_mask;
-
-  GdkSeat *grab_input_seat;
-
-  gint64 pending_frame_counter;
-  guint32 scale;
-
-  int margin_left;
-  int margin_right;
-  int margin_top;
-  int margin_bottom;
-  gboolean margin_dirty;
-
-  struct wl_output *initial_fullscreen_output;
-
-  cairo_region_t *opaque_region;
-  gboolean opaque_region_dirty;
-
-  cairo_region_t *input_region;
-  gboolean input_region_dirty;
-
-  cairo_region_t *staged_updates_region;
-
-  int saved_width;
-  int saved_height;
-
-  gulong parent_surface_committed_handler;
-
-  struct {
-    GdkRectangle rect;
-    GdkGravity rect_anchor;
-    GdkGravity window_anchor;
-    GdkAnchorHints anchor_hints;
-    gint rect_anchor_dx;
-    gint rect_anchor_dy;
-  } pending_move_to_rect;
-
-  struct {
-    int width;
-    int height;
-    GdkSurfaceState state;
-  } pending;
-
-  struct {
-    GdkWaylandSurfaceExported callback;
-    gpointer user_data;
-    GDestroyNotify destroy_func;
-  } exported;
-
-  struct zxdg_imported_v1 *imported_transient_for;
-  GHashTable *shortcuts_inhibitors;
-};
-
-struct _GdkSurfaceImplWaylandClass
-{
-  GdkSurfaceImplClass parent_class;
-};
-
-static void gdk_wayland_surface_maybe_configure (GdkSurface *window,
-                                                int        width,
-                                                int        height,
-                                                int        scale);
-
-static void maybe_set_gtk_surface_dbus_properties (GdkSurface *window);
-static void maybe_set_gtk_surface_modal (GdkSurface *window);
-
-static void gdk_surface_request_transient_parent_commit (GdkSurface *window);
-
-static void gdk_wayland_surface_sync_margin (GdkSurface *window);
-static void gdk_wayland_surface_sync_input_region (GdkSurface *window);
-static void gdk_wayland_surface_sync_opaque_region (GdkSurface *window);
-
-static void unset_transient_for_exported (GdkSurface *window);
-
-static void calculate_moved_to_rect_result (GdkSurface    *window,
-                                            int           x,
-                                            int           y,
-                                            int           width,
-                                            int           height,
-                                            GdkRectangle *flipped_rect,
-                                            GdkRectangle *final_rect,
-                                            gboolean     *flipped_x,
-                                            gboolean     *flipped_y);
-
-static gboolean gdk_wayland_surface_is_exported (GdkSurface *window);
-
-GType _gdk_surface_impl_wayland_get_type (void);
-
-G_DEFINE_TYPE (GdkSurfaceImplWayland, _gdk_surface_impl_wayland, GDK_TYPE_SURFACE_IMPL)
-
-static void
-_gdk_surface_impl_wayland_init (GdkSurfaceImplWayland *impl)
-{
-  impl->scale = 1;
-  impl->initial_fullscreen_output = NULL;
-  impl->saved_width = -1;
-  impl->saved_height = -1;
-}
-
-static void
-_gdk_wayland_screen_add_orphan_dialog (GdkSurface *window)
-{
-  GdkWaylandDisplay *display_wayland =
-    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-
-  if (!g_list_find (display_wayland->orphan_dialogs, window))
-    display_wayland->orphan_dialogs =
-      g_list_prepend (display_wayland->orphan_dialogs, window);
-}
-
-static void
-drop_cairo_surfaces (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
-  g_clear_pointer (&impl->backfill_cairo_surface, cairo_surface_destroy);
-
-  /* We nullify this so if a buffer release comes in later, we won't
-   * try to reuse that buffer since it's no longer suitable
-   */
-  impl->committed_cairo_surface = NULL;
-}
-
-static void
-_gdk_wayland_surface_save_size (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (window->state & (GDK_SURFACE_STATE_FULLSCREEN | GDK_SURFACE_STATE_MAXIMIZED))
-    return;
-
-  impl->saved_width = window->width - impl->margin_left - impl->margin_right;
-  impl->saved_height = window->height - impl->margin_top - impl->margin_bottom;
-}
-
-static void
-_gdk_wayland_surface_clear_saved_size (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (window->state & (GDK_SURFACE_STATE_FULLSCREEN | GDK_SURFACE_STATE_MAXIMIZED))
-    return;
-
-  impl->saved_width = -1;
-  impl->saved_height = -1;
-}
-
-/*
- * gdk_wayland_surface_update_size:
- * @drawable: a #GdkDrawableImplWayland.
- *
- * Updates the state of the drawable (in particular the drawable's
- * cairo surface) when its size has changed.
- */
-static void
-gdk_wayland_surface_update_size (GdkSurface *window,
-                                int32_t    width,
-                                int32_t    height,
-                                int        scale)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkRectangle area;
-  cairo_region_t *region;
-
-  if ((window->width == width) &&
-      (window->height == height) &&
-      (impl->scale == scale))
-    return;
-
-  drop_cairo_surfaces (window);
-
-  window->width = width;
-  window->height = height;
-  impl->scale = scale;
-
-  if (impl->display_server.egl_window)
-    wl_egl_window_resize (impl->display_server.egl_window, width * scale, height * scale, 0, 0);
-  if (impl->display_server.wl_surface)
-    wl_surface_set_buffer_scale (impl->display_server.wl_surface, scale);
-
-  area.x = 0;
-  area.y = 0;
-  area.width = window->width;
-  area.height = window->height;
-
-  region = cairo_region_create_rectangle (&area);
-  _gdk_surface_invalidate_for_expose (window, region);
-  cairo_region_destroy (region);
-}
-
-static const gchar *
-get_default_title (void)
-{
-  const char *title;
-
-  title = g_get_application_name ();
-  if (!title)
-    title = g_get_prgname ();
-  if (!title)
-    title = "";
-
-  return title;
-}
-
-static void
-fill_presentation_time_from_frame_time (GdkFrameTimings *timings,
-                                        guint32          frame_time)
-{
-  /* The timestamp in a wayland frame is a msec time value that in some
-   * way reflects the time at which the server started drawing the frame.
-   * This is not useful from our perspective.
-   *
-   * However, for the DRM backend of Weston, on reasonably recent
-   * Linux, we know that the time is the
-   * clock_gettime (CLOCK_MONOTONIC) value at the vblank, and that
-   * backend starts drawing immediately after receiving the vblank
-   * notification. If we detect this, and make the assumption that the
-   * compositor will finish drawing before the next vblank, we can
-   * then determine the presentation time as the frame time we
-   * received plus one refresh interval.
-   *
-   * If a backend is using clock_gettime(CLOCK_MONOTONIC), but not
-   * picking values right at the vblank, then the presentation times
-   * we compute won't be accurate, but not really worse than then
-   * the alternative of not providing presentation times at all.
-   *
-   * The complexity here is dealing with the fact that we receive
-   * only the low 32 bits of the CLOCK_MONOTONIC value in milliseconds.
-   */
-  gint64 now_monotonic = g_get_monotonic_time ();
-  gint64 now_monotonic_msec = now_monotonic / 1000;
-  uint32_t now_monotonic_low = (uint32_t)now_monotonic_msec;
-
-  if (frame_time - now_monotonic_low < 1000 ||
-      frame_time - now_monotonic_low > (uint32_t)-1000)
-    {
-      /* Timestamp we received is within one second of the current time.
-       */
-      gint64 last_frame_time = now_monotonic + (gint64)1000 * (gint32)(frame_time - now_monotonic_low);
-      if ((gint32)now_monotonic_low < 0 && (gint32)frame_time > 0)
-        last_frame_time += (gint64)1000 * G_GINT64_CONSTANT(0x100000000);
-      else if ((gint32)now_monotonic_low > 0 && (gint32)frame_time < 0)
-        last_frame_time -= (gint64)1000 * G_GINT64_CONSTANT(0x100000000);
-
-      timings->presentation_time = last_frame_time + timings->refresh_interval;
-    }
-}
-
-static void
-read_back_cairo_surface (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  cairo_t *cr;
-  cairo_region_t *paint_region = NULL;
-
-  if (!impl->backfill_cairo_surface)
-    goto out;
-
-  paint_region = cairo_region_copy (window->clip_region);
-  cairo_region_subtract (paint_region, impl->staged_updates_region);
-
-  if (cairo_region_is_empty (paint_region))
-    goto out;
-
-  cr = cairo_create (impl->staging_cairo_surface);
-  cairo_set_source_surface (cr, impl->backfill_cairo_surface, 0, 0);
-  gdk_cairo_region (cr, paint_region);
-  cairo_clip (cr);
-  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-  cairo_paint (cr);
-  cairo_destroy (cr);
-  cairo_surface_flush (impl->staging_cairo_surface);
-
-out:
-  g_clear_pointer (&paint_region, cairo_region_destroy);
-  g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
-  g_clear_pointer (&impl->backfill_cairo_surface, cairo_surface_destroy);
-}
-
-static void
-frame_callback (void               *data,
-                struct wl_callback *callback,
-                uint32_t            time)
-{
-  GdkSurface *window = data;
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkWaylandDisplay *display_wayland =
-    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  GdkFrameClock *clock = gdk_surface_get_frame_clock (window);
-  GdkFrameTimings *timings;
-
-  GDK_DISPLAY_NOTE (GDK_DISPLAY (display_wayland), EVENTS, g_message ("frame %p", window));
-
-  wl_callback_destroy (callback);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (!impl->awaiting_frame)
-    return;
-
-  impl->awaiting_frame = FALSE;
-  _gdk_frame_clock_thaw (clock);
-
-  timings = gdk_frame_clock_get_timings (clock, impl->pending_frame_counter);
-  impl->pending_frame_counter = 0;
-
-  if (timings == NULL)
-    return;
-
-  timings->refresh_interval = 16667; /* default to 1/60th of a second */
-  if (impl->display_server.outputs)
-    {
-      /* We pick a random output out of the outputs that the window touches
-       * The rate here is in milli-hertz */
-      int refresh_rate =
-        gdk_wayland_display_get_output_refresh_rate (display_wayland,
-                                                     impl->display_server.outputs->data);
-      if (refresh_rate != 0)
-        timings->refresh_interval = G_GINT64_CONSTANT(1000000000) / refresh_rate;
-    }
-
-  fill_presentation_time_from_frame_time (timings, time);
-
-  timings->complete = TRUE;
-
-#ifdef G_ENABLE_DEBUG
-  if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
-    _gdk_frame_clock_debug_print_timings (clock, timings);
-#endif
-}
-
-static const struct wl_callback_listener frame_listener = {
-  frame_callback
-};
-
-static void
-on_frame_clock_before_paint (GdkFrameClock *clock,
-                             GdkSurface     *window)
-{
-  GdkFrameTimings *timings = gdk_frame_clock_get_current_timings (clock);
-  gint64 presentation_time;
-  gint64 refresh_interval;
-
-  if (window->update_freeze_count > 0)
-    return;
-
-  gdk_frame_clock_get_refresh_info (clock,
-                                    timings->frame_time,
-                                    &refresh_interval, &presentation_time);
-
-  if (presentation_time != 0)
-    {
-      /* Assume the algorithm used by the DRM backend of Weston - it
-       * starts drawing at the next vblank after receiving the commit
-       * for this frame, and presentation occurs at the vblank
-       * after that.
-       */
-      timings->predicted_presentation_time = presentation_time + refresh_interval;
-    }
-  else
-    {
-      /* As above, but we don't actually know the phase of the vblank,
-       * so just assume that we're half way through a refresh cycle.
-       */
-      timings->predicted_presentation_time = timings->frame_time + refresh_interval / 2 + refresh_interval;
-    }
-}
-
-static void
-on_frame_clock_after_paint (GdkFrameClock *clock,
-                            GdkSurface     *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  struct wl_callback *callback;
-
-  if (!impl->pending_commit)
-    return;
-
-  if (window->update_freeze_count > 0)
-    return;
-
-  callback = wl_surface_frame (impl->display_server.wl_surface);
-  wl_callback_add_listener (callback, &frame_listener, window);
-  _gdk_frame_clock_freeze (clock);
-
-  /* Before we commit a new buffer, make sure we've backfilled
-   * undrawn parts from any old committed buffer
-   */
-  if (impl->pending_buffer_attached)
-    read_back_cairo_surface (window);
-
-  /* From this commit forward, we can't write to the buffer,
-   * it's "live".  In the future, if we need to stage more changes
-   * we have to allocate a new staging buffer and draw to it instead.
-   *
-   * Our one saving grace is if the compositor releases the buffer
-   * before we need to stage any changes, then we can take it back and
-   * use it again.
-   */
-  wl_surface_commit (impl->display_server.wl_surface);
-
-  if (impl->pending_buffer_attached)
-    impl->committed_cairo_surface = g_steal_pointer (&impl->staging_cairo_surface);
-
-  impl->pending_buffer_attached = FALSE;
-  impl->pending_commit = FALSE;
-  impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
-  impl->awaiting_frame = TRUE;
-
-  g_signal_emit (impl, signals[COMMITTED], 0);
-}
-
-void
-gdk_wayland_surface_update_scale (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  guint32 scale;
-  GSList *l;
-  GList *children, *c;
-
-  if (display_wayland->compositor_version < WL_SURFACE_HAS_BUFFER_SCALE)
-    {
-      /* We can't set the scale on this surface */
-      return;
-    }
-
-  scale = 1;
-  for (l = impl->display_server.outputs; l != NULL; l = l->next)
-    {
-      guint32 output_scale = gdk_wayland_display_get_output_scale (display_wayland, l->data);
-      scale = MAX (scale, output_scale);
-    }
-
-  /* Notify app that scale changed */
-  gdk_wayland_surface_maybe_configure (window, window->width, window->height, scale);
-
-  children = gdk_surface_get_children (window);
-  for (c = children; c; c = c->next)
-    {
-      GdkSurface *child = c->data;
-      gdk_wayland_surface_update_scale (child);
-    }
-  g_list_free (children);
-}
-
-static void gdk_wayland_surface_create_surface (GdkSurface *window);
-
-void
-_gdk_wayland_display_create_window_impl (GdkDisplay    *display,
-                                         GdkSurface     *window,
-                                         GdkSurface     *real_parent,
-                                         GdkEventMask   event_mask,
-                                         GdkSurfaceAttr *attributes)
-{
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
-  GdkSurfaceImplWayland *impl;
-  GdkFrameClock *frame_clock;
-
-  impl = g_object_new (GDK_TYPE_SURFACE_IMPL_WAYLAND, NULL);
-  window->impl = GDK_SURFACE_IMPL (impl);
-  impl->wrapper = GDK_SURFACE (window);
-  impl->shortcuts_inhibitors = g_hash_table_new (NULL, NULL);
-
-  if (window->width > 65535)
-    {
-      g_warning ("Native Windows wider than 65535 pixels are not supported");
-      window->width = 65535;
-    }
-  if (window->height > 65535)
-    {
-      g_warning ("Native Windows taller than 65535 pixels are not supported");
-      window->height = 65535;
-    }
-
-  g_object_ref (window);
-
-  /* More likely to be right than just assuming 1 */
-  if (display_wayland->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE &&
-      gdk_display_get_n_monitors (display) > 0)
-    impl->scale = gdk_monitor_get_scale_factor (gdk_display_get_monitor (display, 0));
-
-  impl->title = NULL;
-
-  switch (GDK_SURFACE_TYPE (window))
-    {
-    case GDK_SURFACE_TOPLEVEL:
-    case GDK_SURFACE_TEMP:
-      gdk_surface_set_title (window, get_default_title ());
-      break;
-
-    case GDK_SURFACE_CHILD:
-    default:
-      break;
-    }
-
-  if (real_parent == NULL)
-    display_wayland->toplevels = g_list_prepend (display_wayland->toplevels, window);
-
-  gdk_wayland_surface_create_surface (window);
-
-  frame_clock = gdk_surface_get_frame_clock (window);
-  g_signal_connect (frame_clock, "before-paint", G_CALLBACK (on_frame_clock_before_paint), window);
-  g_signal_connect (frame_clock, "after-paint", G_CALLBACK (on_frame_clock_after_paint), window);
-}
-
-static void
-gdk_wayland_surface_attach_image (GdkSurface *window)
-{
-  GdkWaylandDisplay *display;
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  g_assert (_gdk_wayland_is_shm_surface (impl->staging_cairo_surface));
-
-  /* Attach this new buffer to the surface */
-  wl_surface_attach (impl->display_server.wl_surface,
-                     _gdk_wayland_shm_surface_get_wl_buffer (impl->staging_cairo_surface),
-                     impl->pending_buffer_offset_x,
-                     impl->pending_buffer_offset_y);
-  impl->pending_buffer_offset_x = 0;
-  impl->pending_buffer_offset_y = 0;
-
-  /* Only set the buffer scale if supported by the compositor */
-  display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  if (display->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE)
-    wl_surface_set_buffer_scale (impl->display_server.wl_surface, impl->scale);
-
-  impl->pending_buffer_attached = TRUE;
-  impl->pending_commit = TRUE;
-}
-
-static const cairo_user_data_key_t gdk_wayland_surface_cairo_key;
-
-static void
-buffer_release_callback (void             *_data,
-                         struct wl_buffer *wl_buffer)
-{
-  cairo_surface_t *cairo_surface = _data;
-  GdkSurfaceImplWayland *impl = cairo_surface_get_user_data (cairo_surface, &gdk_wayland_surface_cairo_key);
-
-  g_return_if_fail (GDK_IS_SURFACE_IMPL_WAYLAND (impl));
-
-  /* The released buffer isn't the latest committed one, we have no further
-   * use for it, so clean it up.
-   */
-  if (impl->committed_cairo_surface != cairo_surface)
-    {
-      /* If this fails, then the surface buffer got reused before it was
-       * released from the compositor
-       */
-      g_warn_if_fail (impl->staging_cairo_surface != cairo_surface);
-
-      cairo_surface_destroy (cairo_surface);
-      return;
-    }
-
-  if (impl->staged_updates_region != NULL)
-    {
-      /* If this fails, then we're tracking staged updates on a staging surface
-       * that doesn't exist.
-       */
-      g_warn_if_fail (impl->staging_cairo_surface != NULL);
-
-      /* If we've staged updates into a new buffer before the release for this
-       * buffer came in, then we can't reuse this buffer, so unref it. It may still
-       * be alive as a readback buffer though (via impl->backfill_cairo_surface).
-       *
-       * It's possible a staging surface was allocated but no updates were staged.
-       * If that happened, clean up that staging surface now, since the old commit
-       * buffer is available again, and reusing the old commit buffer for future
-       * updates will save having to do a read back later.
-       */
-      if (!cairo_region_is_empty (impl->staged_updates_region))
-        {
-          g_clear_pointer (&impl->committed_cairo_surface, cairo_surface_destroy);
-          return;
-        }
-      else
-        {
-          g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
-          g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
-        }
-    }
-
-  /* Release came in, we haven't done any interim updates, so we can just use
-   * the old committed buffer again.
-   */
-  impl->staging_cairo_surface = g_steal_pointer (&impl->committed_cairo_surface);
-}
-
-static const struct wl_buffer_listener buffer_listener = {
-  buffer_release_callback
-};
-
-static void
-gdk_wayland_surface_ensure_cairo_surface (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  /* If we are drawing using OpenGL then we only need a logical 1x1 surface. */
-  if (impl->display_server.egl_window)
-    {
-      if (impl->staging_cairo_surface &&
-          _gdk_wayland_is_shm_surface (impl->staging_cairo_surface))
-        g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy);
-
-      if (!impl->staging_cairo_surface)
-        {
-          impl->staging_cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-                                                                    impl->scale,
-                                                                    impl->scale);
-          cairo_surface_set_device_scale (impl->staging_cairo_surface,
-                                          impl->scale, impl->scale);
-        }
-    }
-  else if (!impl->staging_cairo_surface)
-    {
-      GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (impl->wrapper));
-      struct wl_buffer *buffer;
-
-      impl->staging_cairo_surface = _gdk_wayland_display_create_shm_surface (display_wayland,
-                                                                             impl->wrapper->width,
-                                                                             impl->wrapper->height,
-                                                                             impl->scale);
-      cairo_surface_set_user_data (impl->staging_cairo_surface,
-                                   &gdk_wayland_surface_cairo_key,
-                                   g_object_ref (impl),
-                                   (cairo_destroy_func_t)
-                                   g_object_unref);
-      buffer = _gdk_wayland_shm_surface_get_wl_buffer (impl->staging_cairo_surface);
-      wl_buffer_add_listener (buffer, &buffer_listener, impl->staging_cairo_surface);
-    }
-}
-
-/* The cairo surface returned here uses a memory segment that's shared
- * with the display server.  This is not a temporary buffer that gets
- * copied to the display server, but the actual buffer the display server
- * will ultimately end up sending to the GPU. At the time this happens
- * impl->committed_cairo_surface gets set to impl->staging_cairo_surface, and
- * impl->staging_cairo_surface gets nullified.
- */
-static cairo_surface_t *
-gdk_wayland_surface_ref_cairo_surface (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (impl->wrapper))
-    return NULL;
-
-  gdk_wayland_surface_ensure_cairo_surface (window);
-
-  cairo_surface_reference (impl->staging_cairo_surface);
-
-  return impl->staging_cairo_surface;
-}
-
-static cairo_surface_t *
-gdk_wayland_surface_create_similar_image_surface (GdkSurface *     window,
-                                                 cairo_format_t  format,
-                                                 int             width,
-                                                 int             height)
-{
-  return cairo_image_surface_create (format, width, height);
-}
-
-static gboolean
-gdk_surface_impl_wayland_begin_paint (GdkSurface *window)
-{
-  gdk_wayland_surface_ensure_cairo_surface (window);
-
-  return FALSE;
-}
-
-static void
-gdk_surface_impl_wayland_end_paint (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  cairo_rectangle_int_t rect;
-  int i, n;
-
-  if (impl->staging_cairo_surface &&
-      _gdk_wayland_is_shm_surface (impl->staging_cairo_surface) &&
-      !cairo_region_is_empty (window->current_paint.region))
-    {
-      gdk_wayland_surface_attach_image (window);
-
-      /* If there's a committed buffer pending, then track which
-       * updates are staged until the next frame, so we can back
-       * fill the unstaged parts of the staging buffer with the
-       * last frame.
-       */
-      if (impl->committed_cairo_surface != NULL)
-        {
-          if (impl->staged_updates_region == NULL)
-            {
-              impl->staged_updates_region = cairo_region_copy (window->current_paint.region);
-              impl->backfill_cairo_surface = cairo_surface_reference (impl->committed_cairo_surface);
-            }
-          else
-            {
-              cairo_region_union (impl->staged_updates_region, window->current_paint.region);
-            }
-        }
-
-      n = cairo_region_num_rectangles (window->current_paint.region);
-      for (i = 0; i < n; i++)
-        {
-          cairo_region_get_rectangle (window->current_paint.region, i, &rect);
-          wl_surface_damage (impl->display_server.wl_surface, rect.x, rect.y, rect.width, rect.height);
-        }
-
-      impl->pending_commit = TRUE;
-    }
-
-  gdk_wayland_surface_sync (window);
-}
-
-void
-gdk_wayland_surface_sync (GdkSurface *window)
-{
-  gdk_wayland_surface_sync_margin (window);
-  gdk_wayland_surface_sync_opaque_region (window);
-  gdk_wayland_surface_sync_input_region (window);
-}
-
-static gboolean
-gdk_surface_impl_wayland_beep (GdkSurface *window)
-{
-  gdk_wayland_display_system_bell (gdk_surface_get_display (window),
-                                   window);
-
-  return TRUE;
-}
-
-static void
-gdk_surface_impl_wayland_finalize (GObject *object)
-{
-  GdkSurface *window = GDK_SURFACE (object);
-  GdkSurfaceImplWayland *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE_IMPL_WAYLAND (object));
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (object);
-
-  if (gdk_wayland_surface_is_exported (window))
-    gdk_wayland_surface_unexport_handle (window);
-
-  g_free (impl->title);
-
-  g_free (impl->application.application_id);
-  g_free (impl->application.app_menu_path);
-  g_free (impl->application.menubar_path);
-  g_free (impl->application.window_object_path);
-  g_free (impl->application.application_object_path);
-  g_free (impl->application.unique_bus_name);
-
-  g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
-  g_clear_pointer (&impl->input_region, cairo_region_destroy);
-  g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
-
-  g_hash_table_destroy (impl->shortcuts_inhibitors);
-
-  G_OBJECT_CLASS (_gdk_surface_impl_wayland_parent_class)->finalize (object);
-}
-
-static void
-gdk_wayland_surface_configure (GdkSurface *window,
-                              int        width,
-                              int        height,
-                              int        scale)
-{
-  GdkDisplay *display;
-  GdkEvent *event;
-
-  event = gdk_event_new (GDK_CONFIGURE);
-  event->any.window = g_object_ref (window);
-  event->any.send_event = FALSE;
-  event->configure.width = width;
-  event->configure.height = height;
-
-  gdk_wayland_surface_update_size (window, width, height, scale);
-  _gdk_surface_update_size (window);
-
-  display = gdk_surface_get_display (window);
-  _gdk_wayland_display_deliver_event (display, event);
-}
-
-static void
-gdk_wayland_surface_maybe_configure (GdkSurface *window,
-                                    int        width,
-                                    int        height,
-                                    int        scale)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  gboolean is_xdg_popup;
-  gboolean is_visible;
-
-  if (window->width == width &&
-      window->height == height &&
-      impl->scale == scale)
-    return;
-
-  /* For xdg_popup using an xdg_positioner, there is a race condition if
-   * the application tries to change the size after it's mapped, but before
-   * the initial configure is received, so hide and show the surface again
-   * force the new size onto the compositor. See bug #772505.
-   */
-
-  is_xdg_popup = (impl->display_server.xdg_popup != NULL);
-  is_visible = gdk_surface_is_visible (window);
-
-  if (is_xdg_popup && is_visible && !impl->initial_configure_received)
-    gdk_surface_hide (window);
-
-  gdk_wayland_surface_configure (window, width, height, scale);
-
-  if (is_xdg_popup && is_visible && !impl->initial_configure_received)
-    gdk_surface_show (window);
-}
-
-static void
-gdk_wayland_surface_sync_parent (GdkSurface *window,
-                                GdkSurface *parent)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkSurfaceImplWayland *impl_parent = NULL;
-  struct zxdg_toplevel_v6 *parent_toplevel;
-
-  g_assert (parent == NULL ||
-            gdk_surface_get_display (window) == gdk_surface_get_display (parent));
-
-  if (!impl->display_server.xdg_toplevel)
-    return;
-
-  if (impl->transient_for)
-    impl_parent = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
-  else if (parent)
-    impl_parent = GDK_SURFACE_IMPL_WAYLAND (parent->impl);
-
-  if (impl_parent)
-    {
-      /* XXX: Is this correct? */
-      if (!impl_parent->display_server.wl_surface)
-        return;
-
-      parent_toplevel = impl_parent->display_server.xdg_toplevel;
-    }
-  else
-    parent_toplevel = NULL;
-
-  zxdg_toplevel_v6_set_parent (impl->display_server.xdg_toplevel,
-                               parent_toplevel);
-}
-
-static void
-gdk_wayland_surface_sync_parent_of_imported (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (!impl->display_server.wl_surface)
-    return;
-
-  if (!impl->imported_transient_for)
-    return;
-
-  if (!impl->display_server.xdg_toplevel)
-    return;
-
-  zxdg_imported_v1_set_parent_of (impl->imported_transient_for,
-                                  impl->display_server.wl_surface);
-}
-
-static void
-gdk_wayland_surface_update_dialogs (GdkSurface *window)
-{
-  GdkWaylandDisplay *display_wayland =
-    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  GList *l;
-
-  if (!display_wayland->orphan_dialogs)
-    return;
-
-  for (l = display_wayland->orphan_dialogs; l; l = l->next)
-    {
-      GdkSurface *w = l->data;
-      GdkSurfaceImplWayland *impl;
-
-      if (!GDK_IS_SURFACE_IMPL_WAYLAND(w->impl))
-        continue;
-
-      impl = GDK_SURFACE_IMPL_WAYLAND (w->impl);
-      if (w == window)
-       continue;
-      if (impl->hint != GDK_SURFACE_TYPE_HINT_DIALOG)
-        continue;
-      if (impl->transient_for)
-        continue;
-
-      /* Update the parent relationship only for dialogs without transients */
-      gdk_wayland_surface_sync_parent (w, window);
-    }
-}
-
-static void
-gdk_wayland_surface_sync_title (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (!impl->display_server.xdg_toplevel)
-    return;
-
-  if (!impl->title)
-    return;
-
-  zxdg_toplevel_v6_set_title (impl->display_server.xdg_toplevel, impl->title);
-}
-
-static void
-gdk_wayland_surface_get_window_geometry (GdkSurface    *window,
-                                        GdkRectangle *geometry)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  *geometry = (GdkRectangle) {
-    .x = impl->margin_left,
-    .y = impl->margin_top,
-    .width = window->width - (impl->margin_left + impl->margin_right),
-    .height = window->height - (impl->margin_top + impl->margin_bottom)
-  };
-}
-
-static void
-gdk_wayland_surface_sync_margin (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkRectangle geometry;
-
-  if (!impl->display_server.xdg_surface)
-    return;
-
-  gdk_wayland_surface_get_window_geometry (window, &geometry);
-  gdk_surface_set_geometry_hints (window,
-                                 &impl->geometry_hints,
-                                 impl->geometry_mask);
-  zxdg_surface_v6_set_window_geometry (impl->display_server.xdg_surface,
-                                       geometry.x,
-                                       geometry.y,
-                                       geometry.width,
-                                       geometry.height);
-}
-
-static struct wl_region *
-wl_region_from_cairo_region (GdkWaylandDisplay *display,
-                             cairo_region_t    *region)
-{
-  struct wl_region *wl_region;
-  int i, n_rects;
-
-  wl_region = wl_compositor_create_region (display->compositor);
-  if (wl_region == NULL)
-    return NULL;
-
-  n_rects = cairo_region_num_rectangles (region);
-  for (i = 0; i < n_rects; i++)
-    {
-      cairo_rectangle_int_t rect;
-      cairo_region_get_rectangle (region, i, &rect);
-      wl_region_add (wl_region, rect.x, rect.y, rect.width, rect.height);
-    }
-
-  return wl_region;
-}
-
-static void
-gdk_wayland_surface_sync_opaque_region (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  struct wl_region *wl_region = NULL;
-
-  if (!impl->display_server.wl_surface)
-    return;
-
-  if (!impl->opaque_region_dirty)
-    return;
-
-  if (impl->opaque_region != NULL)
-    wl_region = wl_region_from_cairo_region (GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window)),
-                                             impl->opaque_region);
-
-  wl_surface_set_opaque_region (impl->display_server.wl_surface, wl_region);
-
-  if (wl_region != NULL)
-    wl_region_destroy (wl_region);
-
-  impl->opaque_region_dirty = FALSE;
-}
-
-static void
-gdk_wayland_surface_sync_input_region (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  struct wl_region *wl_region = NULL;
-
-  if (!impl->display_server.wl_surface)
-    return;
-
-  if (!impl->input_region_dirty)
-    return;
-
-  if (impl->input_region != NULL)
-    wl_region = wl_region_from_cairo_region (GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window)),
-                                             impl->input_region);
-
-  wl_surface_set_input_region (impl->display_server.wl_surface, wl_region);
-
-  if (wl_region != NULL)
-    wl_region_destroy (wl_region);
-
-  impl->input_region_dirty = FALSE;
-}
-
-static void
-gdk_wayland_set_input_region_if_empty (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkWaylandDisplay *display;
-  struct wl_region *empty;
-
-  if (!impl->input_region_dirty)
-    return;
-
-  if (impl->input_region == NULL)
-    return;
-
-  if (!cairo_region_is_empty (impl->input_region))
-    return;
-
-  display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  empty = wl_compositor_create_region (display->compositor);
-
-  wl_surface_set_input_region (impl->display_server.wl_surface, empty);
-  wl_region_destroy (empty);
-
-  impl->input_region_dirty = FALSE;
-}
-
-static void
-surface_enter (void              *data,
-               struct wl_surface *wl_surface,
-               struct wl_output  *output)
-{
-  GdkSurface *window = GDK_SURFACE (data);
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  GDK_DISPLAY_NOTE (gdk_surface_get_display (window), EVENTS,
-            g_message ("surface enter, window %p output %p", window, output));
-
-  impl->display_server.outputs = g_slist_prepend (impl->display_server.outputs, output);
-
-  gdk_wayland_surface_update_scale (window);
-}
-
-static void
-surface_leave (void              *data,
-               struct wl_surface *wl_surface,
-               struct wl_output  *output)
-{
-  GdkSurface *window = GDK_SURFACE (data);
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  GDK_DISPLAY_NOTE (gdk_surface_get_display (window), EVENTS,
-            g_message ("surface leave, window %p output %p", window, output));
-
-  impl->display_server.outputs = g_slist_remove (impl->display_server.outputs, output);
-
-  if (impl->display_server.outputs)
-    gdk_wayland_surface_update_scale (window);
-}
-
-static const struct wl_surface_listener surface_listener = {
-  surface_enter,
-  surface_leave
-};
-
-static void
-on_parent_surface_committed (GdkSurfaceImplWayland *parent_impl,
-                             GdkSurface            *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  g_signal_handler_disconnect (parent_impl,
-                               impl->parent_surface_committed_handler);
-  impl->parent_surface_committed_handler = 0;
-
-  wl_subsurface_set_desync (impl->display_server.wl_subsurface);
-
-  /* Special case if the input region is empty, it won't change on resize */
-  gdk_wayland_set_input_region_if_empty (window);
-}
-
-static void
-gdk_wayland_surface_create_subsurface (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl, *parent_impl = NULL;
-  GdkWaylandDisplay *display_wayland;
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (!impl->display_server.wl_surface)
-    return; /* Bail out, surface and subsurface will be created later when shown */
-
-  if (impl->display_server.wl_subsurface)
-    return;
-
-  if (impl->transient_for)
-    parent_impl = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
-
-  if (parent_impl && parent_impl->display_server.wl_surface)
-    {
-      display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-      impl->display_server.wl_subsurface =
-        wl_subcompositor_get_subsurface (display_wayland->subcompositor,
-                                         impl->display_server.wl_surface, parent_impl->display_server.wl_surface);
-      wl_subsurface_set_position (impl->display_server.wl_subsurface,
-                                  window->x + window->abs_x,
-                                  window->y + window->abs_y);
-
-      /* In order to synchronize the initial position with the initial frame
-       * content, wait with making the subsurface desynchronized until after
-       * the parent was committed.
-       */
-      impl->parent_surface_committed_handler =
-        g_signal_connect_object (parent_impl, "committed",
-                                 G_CALLBACK (on_parent_surface_committed),
-                                 window, 0);
-      gdk_surface_request_transient_parent_commit (window);
-    }
-}
-
-static void
-gdk_wayland_surface_create_surface (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-
-  impl->display_server.wl_surface = wl_compositor_create_surface (display_wayland->compositor);
-  wl_surface_add_listener (impl->display_server.wl_surface, &surface_listener, window);
-}
-
-static void
-xdg_surface_configure (void                   *data,
-                       struct zxdg_surface_v6 *xdg_surface,
-                       uint32_t                serial)
-{
-  GdkSurface *window = GDK_SURFACE (data);
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkSurfaceState new_state;
-  int width = impl->pending.width;
-  int height = impl->pending.height;
-  gboolean fixed_size;
-  gboolean saved_size;
-
-  if (!impl->initial_configure_received)
-    {
-      gdk_surface_thaw_updates (window);
-      impl->initial_configure_received = TRUE;
-    }
-
-  if (impl->display_server.xdg_popup)
-    {
-      zxdg_surface_v6_ack_configure (xdg_surface, serial);
-      return;
-    }
-
-  new_state = impl->pending.state;
-  impl->pending.state = 0;
-
-  fixed_size =
-    new_state & (GDK_SURFACE_STATE_MAXIMIZED | GDK_SURFACE_STATE_FULLSCREEN | GDK_SURFACE_STATE_TILED);
-
-  saved_size = (width == 0 && height == 0);
-  /* According to xdg_shell, an xdg_surface.configure with size 0x0
-   * should be interpreted as that it is up to the client to set a
-   * size.
-   *
-   * When transitioning from maximize or fullscreen state, this means
-   * the client should configure its size back to what it was before
-   * being maximize or fullscreen.
-   */
-  if (saved_size && !fixed_size)
-    {
-      width = impl->saved_width;
-      height = impl->saved_height;
-    }
-
-  if (width > 0 && height > 0)
-    {
-      GdkSurfaceHints geometry_mask = impl->geometry_mask;
-
-      /* Ignore size increments for maximized/fullscreen windows */
-      if (fixed_size)
-        geometry_mask &= ~GDK_HINT_RESIZE_INC;
-      if (!saved_size)
-        {
-          /* Do not reapply contrains if we are restoring original size */
-          gdk_surface_constrain_size (&impl->geometry_hints,
-                                     geometry_mask,
-                                     width + impl->margin_left + impl->margin_right,
-                                     height + impl->margin_top + impl->margin_bottom,
-                                     &width,
-                                     &height);
-
-          /* Save size for next time we get 0x0 */
-          _gdk_wayland_surface_save_size (window);
-        }
-
-      gdk_wayland_surface_configure (window, width, height, impl->scale);
-    }
-
-  GDK_DISPLAY_NOTE (gdk_surface_get_display (window), EVENTS,
-            g_message ("configure, window %p %dx%d,%s%s%s%s",
-                       window, width, height,
-                       (new_state & GDK_SURFACE_STATE_FULLSCREEN) ? " fullscreen" : "",
-                       (new_state & GDK_SURFACE_STATE_MAXIMIZED) ? " maximized" : "",
-                       (new_state & GDK_SURFACE_STATE_FOCUSED) ? " focused" : "",
-                       (new_state & GDK_SURFACE_STATE_TILED) ? " tiled" : ""));
-
-  gdk_surface_set_state (window, new_state);
-  zxdg_surface_v6_ack_configure (xdg_surface, serial);
-  if (impl->hint != GDK_SURFACE_TYPE_HINT_DIALOG &&
-      new_state & GDK_SURFACE_STATE_FOCUSED)
-    gdk_wayland_surface_update_dialogs (window);
-}
-
-static const struct zxdg_surface_v6_listener xdg_surface_listener = {
-  xdg_surface_configure,
-};
-
-static void
-xdg_toplevel_configure (void                    *data,
-                        struct zxdg_toplevel_v6 *xdg_toplevel,
-                        int32_t                  width,
-                        int32_t                  height,
-                        struct wl_array         *states)
-{
-  GdkSurface *window = GDK_SURFACE (data);
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  uint32_t *p;
-
-  wl_array_for_each (p, states)
-    {
-      uint32_t state = *p;
-      switch (state)
-        {
-        case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
-          impl->pending.state |= GDK_SURFACE_STATE_FULLSCREEN;
-          break;
-        case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED:
-          impl->pending.state |= GDK_SURFACE_STATE_MAXIMIZED;
-          break;
-        case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED:
-          impl->pending.state |= GDK_SURFACE_STATE_FOCUSED;
-          break;
-        case ZXDG_TOPLEVEL_V6_STATE_RESIZING:
-          break;
-        default:
-          /* Unknown state */
-          break;
-        }
-    }
-
-  impl->pending.width = width;
-  impl->pending.height = height;
-}
-
-static void
-xdg_toplevel_close (void                    *data,
-                    struct zxdg_toplevel_v6 *xdg_toplevel)
-{
-  GdkSurface *window = GDK_SURFACE (data);
-  GdkDisplay *display;
-  GdkEvent *event;
-
-  display = gdk_surface_get_display (window);
-
-  GDK_DISPLAY_NOTE (display, EVENTS, g_message ("close %p", window));
-
-  event = gdk_event_new (GDK_DELETE);
-  event->any.window = g_object_ref (window);
-  event->any.send_event = TRUE;
-
-  _gdk_wayland_display_deliver_event (display, event);
-}
-
-static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
-  xdg_toplevel_configure,
-  xdg_toplevel_close,
-};
-
-static void
-gdk_wayland_surface_create_xdg_toplevel (GdkSurface *window)
-{
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  const gchar *app_id;
-
-  impl->display_server.xdg_surface =
-    zxdg_shell_v6_get_xdg_surface (display_wayland->xdg_shell,
-                                   impl->display_server.wl_surface);
-  zxdg_surface_v6_add_listener (impl->display_server.xdg_surface,
-                                &xdg_surface_listener,
-                                window);
-  gdk_surface_freeze_updates (window);
-
-  impl->display_server.xdg_toplevel =
-    zxdg_surface_v6_get_toplevel (impl->display_server.xdg_surface);
-  zxdg_toplevel_v6_add_listener (impl->display_server.xdg_toplevel,
-                                 &xdg_toplevel_listener,
-                                 window);
-
-  gdk_wayland_surface_sync_parent (window, NULL);
-  gdk_wayland_surface_sync_parent_of_imported (window);
-  gdk_wayland_surface_sync_title (window);
-
-  if (window->state & GDK_SURFACE_STATE_MAXIMIZED)
-    zxdg_toplevel_v6_set_maximized (impl->display_server.xdg_toplevel);
-  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
-    zxdg_toplevel_v6_set_fullscreen (impl->display_server.xdg_toplevel,
-                                     impl->initial_fullscreen_output);
-
-  impl->initial_fullscreen_output = NULL;
-
-  app_id = g_get_prgname ();
-
-  if (app_id == NULL)
-    app_id = "GTK+ Application";
-
-  zxdg_toplevel_v6_set_app_id (impl->display_server.xdg_toplevel, app_id);
-
-  maybe_set_gtk_surface_dbus_properties (window);
-  maybe_set_gtk_surface_modal (window);
-
-  if (impl->hint == GDK_SURFACE_TYPE_HINT_DIALOG)
-    _gdk_wayland_screen_add_orphan_dialog (window);
-
-  wl_surface_commit (impl->display_server.wl_surface);
-}
-
-static void
-xdg_popup_configure (void                 *data,
-                     struct zxdg_popup_v6 *xdg_popup,
-                     int32_t               x,
-                     int32_t               y,
-                     int32_t               width,
-                     int32_t               height)
-{
-  GdkSurface *window = GDK_SURFACE (data);
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkRectangle flipped_rect;
-  GdkRectangle final_rect;
-  gboolean flipped_x;
-  gboolean flipped_y;
-
-  g_return_if_fail (impl->transient_for);
-
-  if (impl->position_method != POSITION_METHOD_MOVE_TO_RECT)
-    return;
-
-  calculate_moved_to_rect_result (window, x, y, width, height,
-                                  &flipped_rect,
-                                  &final_rect,
-                                  &flipped_x,
-                                  &flipped_y);
-
-  g_signal_emit_by_name (window,
-                         "moved-to-rect",
-                         &flipped_rect,
-                         &final_rect,
-                         flipped_x,
-                         flipped_y);
-}
-
-static void
-xdg_popup_done (void                 *data,
-                struct zxdg_popup_v6 *xdg_popup)
-{
-  GdkSurface *window = GDK_SURFACE (data);
-
-  GDK_DISPLAY_NOTE (gdk_surface_get_display (window), EVENTS, g_message ("done %p", window));
-
-  gdk_surface_hide (window);
-}
-
-static const struct zxdg_popup_v6_listener xdg_popup_listener = {
-  xdg_popup_configure,
-  xdg_popup_done,
-};
-
-static enum zxdg_positioner_v6_anchor
-rect_anchor_to_anchor (GdkGravity rect_anchor)
-{
-  switch (rect_anchor)
-    {
-    case GDK_GRAVITY_NORTH_WEST:
-    case GDK_GRAVITY_STATIC:
-      return (ZXDG_POSITIONER_V6_ANCHOR_TOP |
-              ZXDG_POSITIONER_V6_ANCHOR_LEFT);
-    case GDK_GRAVITY_NORTH:
-      return ZXDG_POSITIONER_V6_ANCHOR_TOP;
-    case GDK_GRAVITY_NORTH_EAST:
-      return (ZXDG_POSITIONER_V6_ANCHOR_TOP |
-              ZXDG_POSITIONER_V6_ANCHOR_RIGHT);
-    case GDK_GRAVITY_WEST:
-      return ZXDG_POSITIONER_V6_ANCHOR_LEFT;
-    case GDK_GRAVITY_CENTER:
-      return ZXDG_POSITIONER_V6_ANCHOR_NONE;
-    case GDK_GRAVITY_EAST:
-      return ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
-    case GDK_GRAVITY_SOUTH_WEST:
-      return (ZXDG_POSITIONER_V6_ANCHOR_BOTTOM |
-              ZXDG_POSITIONER_V6_ANCHOR_LEFT);
-    case GDK_GRAVITY_SOUTH:
-      return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM;
-    case GDK_GRAVITY_SOUTH_EAST:
-      return (ZXDG_POSITIONER_V6_ANCHOR_BOTTOM |
-              ZXDG_POSITIONER_V6_ANCHOR_RIGHT);
-    default:
-      g_assert_not_reached ();
-    }
-
-  return (ZXDG_POSITIONER_V6_ANCHOR_TOP |
-          ZXDG_POSITIONER_V6_ANCHOR_LEFT);
-}
-
-static enum zxdg_positioner_v6_gravity
-window_anchor_to_gravity (GdkGravity rect_anchor)
-{
-  switch (rect_anchor)
-    {
-    case GDK_GRAVITY_NORTH_WEST:
-    case GDK_GRAVITY_STATIC:
-      return (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
-              ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
-    case GDK_GRAVITY_NORTH:
-      return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM;
-    case GDK_GRAVITY_NORTH_EAST:
-      return (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
-              ZXDG_POSITIONER_V6_GRAVITY_LEFT);
-    case GDK_GRAVITY_WEST:
-      return ZXDG_POSITIONER_V6_GRAVITY_RIGHT;
-    case GDK_GRAVITY_CENTER:
-      return ZXDG_POSITIONER_V6_GRAVITY_NONE;
-    case GDK_GRAVITY_EAST:
-      return ZXDG_POSITIONER_V6_GRAVITY_LEFT;
-    case GDK_GRAVITY_SOUTH_WEST:
-      return (ZXDG_POSITIONER_V6_GRAVITY_TOP |
-              ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
-    case GDK_GRAVITY_SOUTH:
-      return ZXDG_POSITIONER_V6_GRAVITY_TOP;
-    case GDK_GRAVITY_SOUTH_EAST:
-      return (ZXDG_POSITIONER_V6_GRAVITY_TOP |
-              ZXDG_POSITIONER_V6_GRAVITY_LEFT);
-    default:
-      g_assert_not_reached ();
-    }
-
-  return (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
-          ZXDG_POSITIONER_V6_GRAVITY_RIGHT);
-}
-
-void
-gdk_wayland_surface_announce_csd (GdkSurface *window)
-{
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  if (!display_wayland->server_decoration_manager)
-    return;
-  impl->display_server.server_decoration =
-    org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
-                                                  impl->display_server.wl_surface);
-  if (impl->display_server.server_decoration)
-    org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration,
-                                                ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT);
-}
-
-static GdkSurface *
-get_real_parent_and_translate (GdkSurface *window,
-                               gint      *x,
-                               gint      *y)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkSurface *parent = impl->transient_for;
-
-  while (parent)
-    {
-      GdkSurfaceImplWayland *parent_impl =
-        GDK_SURFACE_IMPL_WAYLAND (parent->impl);
-      GdkSurface *effective_parent = gdk_surface_get_parent (parent);
-
-      if ((gdk_surface_has_native (parent) &&
-           !parent_impl->display_server.wl_subsurface) ||
-          !effective_parent)
-        break;
-
-      *x += parent->x;
-      *y += parent->y;
-
-      if (gdk_surface_has_native (parent) &&
-          parent_impl->display_server.wl_subsurface)
-        parent = parent->transient_for;
-      else
-        parent = effective_parent;
-    }
-
-  return parent;
-}
-
-static void
-translate_to_real_parent_window_geometry (GdkSurface  *window,
-                                          gint       *x,
-                                          gint       *y)
-{
-  GdkSurface *parent;
-
-  parent = get_real_parent_and_translate (window, x, y);
-
-  *x -= parent->shadow_left;
-  *y -= parent->shadow_top;
-}
-
-static GdkSurface *
-translate_from_real_parent_window_geometry (GdkSurface *window,
-                                            gint      *x,
-                                            gint      *y)
-{
-  GdkSurface *parent;
-  gint dx = 0;
-  gint dy = 0;
-
-  parent = get_real_parent_and_translate (window, &dx, &dy);
-
-  *x -= dx - parent->shadow_left;
-  *y -= dy - parent->shadow_top;
-
-  return parent;
-}
-
-static void
-calculate_popup_rect (GdkSurface    *window,
-                      GdkGravity    rect_anchor,
-                      GdkGravity    window_anchor,
-                      GdkRectangle *out_rect)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkRectangle geometry;
-  GdkRectangle anchor_rect;
-  int x = 0, y = 0;
-
-  gdk_wayland_surface_get_window_geometry (window, &geometry);
-
-  anchor_rect = (GdkRectangle) {
-    .x = (impl->pending_move_to_rect.rect.x +
-          impl->pending_move_to_rect.rect_anchor_dx),
-    .y = (impl->pending_move_to_rect.rect.y +
-          impl->pending_move_to_rect.rect_anchor_dy),
-    .width = impl->pending_move_to_rect.rect.width,
-    .height = impl->pending_move_to_rect.rect.height
-  };
-
-  switch (rect_anchor)
-    {
-    default:
-    case GDK_GRAVITY_STATIC:
-    case GDK_GRAVITY_NORTH_WEST:
-      x = anchor_rect.x;
-      y = anchor_rect.y;
-      break;
-    case GDK_GRAVITY_NORTH:
-      x = anchor_rect.x + (anchor_rect.width / 2);
-      y = anchor_rect.y;
-      break;
-    case GDK_GRAVITY_NORTH_EAST:
-      x = anchor_rect.x + anchor_rect.width;
-      y = anchor_rect.y;
-      break;
-    case GDK_GRAVITY_WEST:
-      x = anchor_rect.x;
-      y = anchor_rect.y + (anchor_rect.height / 2);
-      break;
-    case GDK_GRAVITY_CENTER:
-      x = anchor_rect.x + (anchor_rect.width / 2);
-      y = anchor_rect.y + (anchor_rect.height / 2);
-      break;
-    case GDK_GRAVITY_EAST:
-      x = anchor_rect.x + anchor_rect.width;
-      y = anchor_rect.y + (anchor_rect.height / 2);
-      break;
-    case GDK_GRAVITY_SOUTH_WEST:
-      x = anchor_rect.x;
-      y = anchor_rect.y + anchor_rect.height;
-      break;
-    case GDK_GRAVITY_SOUTH:
-      x = anchor_rect.x + (anchor_rect.width / 2);
-      y = anchor_rect.y + anchor_rect.height;
-      break;
-    case GDK_GRAVITY_SOUTH_EAST:
-      x = anchor_rect.x + anchor_rect.width;
-      y = anchor_rect.y + anchor_rect.height;
-      break;
-    }
-
-  switch (window_anchor)
-    {
-    default:
-    case GDK_GRAVITY_STATIC:
-    case GDK_GRAVITY_NORTH_WEST:
-      break;
-    case GDK_GRAVITY_NORTH:
-      x -= geometry.width / 2;
-      break;
-    case GDK_GRAVITY_NORTH_EAST:
-      x -= geometry.width;
-      break;
-    case GDK_GRAVITY_WEST:
-      y -= geometry.height / 2;
-      break;
-    case GDK_GRAVITY_CENTER:
-      x -= geometry.width / 2;
-      y -= geometry.height / 2;
-      break;
-    case GDK_GRAVITY_EAST:
-      x -= geometry.width;
-      y -= geometry.height / 2;
-      break;
-    case GDK_GRAVITY_SOUTH_WEST:
-      y -= geometry.height;
-      break;
-    case GDK_GRAVITY_SOUTH:
-      x -= geometry.width / 2;
-      y -= geometry.height;
-      break;
-    case GDK_GRAVITY_SOUTH_EAST:
-      x -= geometry.width;
-      y -= geometry.height;
-      break;
-    }
-
-  *out_rect = (GdkRectangle) {
-    .x = x,
-    .y = y,
-    .width = geometry.width,
-    .height = geometry.height
-  };
-}
-
-static GdkGravity
-flip_anchor_horizontally (GdkGravity anchor)
-{
-  switch (anchor)
-    {
-    default:
-    case GDK_GRAVITY_STATIC:
-    case GDK_GRAVITY_NORTH_WEST:
-      return GDK_GRAVITY_NORTH_EAST;
-    case GDK_GRAVITY_NORTH:
-      return GDK_GRAVITY_NORTH;
-    case GDK_GRAVITY_NORTH_EAST:
-      return GDK_GRAVITY_NORTH_WEST;
-    case GDK_GRAVITY_WEST:
-      return GDK_GRAVITY_EAST;
-    case GDK_GRAVITY_CENTER:
-      return GDK_GRAVITY_CENTER;
-    case GDK_GRAVITY_EAST:
-      return GDK_GRAVITY_WEST;
-    case GDK_GRAVITY_SOUTH_WEST:
-      return GDK_GRAVITY_SOUTH_EAST;
-    case GDK_GRAVITY_SOUTH:
-      return GDK_GRAVITY_SOUTH;
-    case GDK_GRAVITY_SOUTH_EAST:
-      return GDK_GRAVITY_SOUTH_WEST;
-    }
-
-  g_assert_not_reached ();
-}
-
-static GdkGravity
-flip_anchor_vertically (GdkGravity anchor)
-{
-  switch (anchor)
-    {
-    default:
-    case GDK_GRAVITY_STATIC:
-    case GDK_GRAVITY_NORTH_WEST:
-      return GDK_GRAVITY_SOUTH_WEST;
-    case GDK_GRAVITY_NORTH:
-      return GDK_GRAVITY_SOUTH;
-    case GDK_GRAVITY_NORTH_EAST:
-      return GDK_GRAVITY_SOUTH_EAST;
-    case GDK_GRAVITY_WEST:
-      return GDK_GRAVITY_WEST;
-    case GDK_GRAVITY_CENTER:
-      return GDK_GRAVITY_CENTER;
-    case GDK_GRAVITY_EAST:
-      return GDK_GRAVITY_EAST;
-    case GDK_GRAVITY_SOUTH_WEST:
-      return GDK_GRAVITY_NORTH_WEST;
-    case GDK_GRAVITY_SOUTH:
-      return GDK_GRAVITY_NORTH;
-    case GDK_GRAVITY_SOUTH_EAST:
-      return GDK_GRAVITY_NORTH_EAST;
-    }
-
-  g_assert_not_reached ();
-}
-
-static void
-calculate_moved_to_rect_result (GdkSurface    *window,
-                                int           x,
-                                int           y,
-                                int           width,
-                                int           height,
-                                GdkRectangle *flipped_rect,
-                                GdkRectangle *final_rect,
-                                gboolean     *flipped_x,
-                                gboolean     *flipped_y)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkSurface *parent;
-  gint window_x, window_y;
-  gint window_width, window_height;
-  GdkRectangle best_rect;
-
-  parent = translate_from_real_parent_window_geometry (window, &x, &y);
-  *final_rect = (GdkRectangle) {
-    .x = x,
-    .y = y,
-    .width = width,
-    .height = height,
-  };
-
-  window_x = parent->x + x;
-  window_y = parent->y + y;
-  window_width = width + window->shadow_left + window->shadow_right;
-  window_height = height + window->shadow_top + window->shadow_bottom;
-
-  gdk_surface_move_resize (window,
-                          window_x, window_y,
-                          window_width, window_height);
-
-  calculate_popup_rect (window,
-                        impl->pending_move_to_rect.rect_anchor,
-                        impl->pending_move_to_rect.window_anchor,
-                        &best_rect);
-
-  *flipped_rect = best_rect;
-
-  if (x != best_rect.x &&
-      impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_X)
-    {
-      GdkRectangle flipped_x_rect;
-      GdkGravity flipped_rect_anchor;
-      GdkGravity flipped_window_anchor;
-
-      flipped_rect_anchor =
-        flip_anchor_horizontally (impl->pending_move_to_rect.rect_anchor);
-      flipped_window_anchor =
-        flip_anchor_horizontally (impl->pending_move_to_rect.window_anchor),
-      calculate_popup_rect (window,
-                            flipped_rect_anchor,
-                            flipped_window_anchor,
-                            &flipped_x_rect);
-
-      if (flipped_x_rect.x == x)
-        flipped_rect->x = x;
-    }
-  if (y != best_rect.y &&
-      impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_Y)
-    {
-      GdkRectangle flipped_y_rect;
-      GdkGravity flipped_rect_anchor;
-      GdkGravity flipped_window_anchor;
-
-      flipped_rect_anchor =
-        flip_anchor_vertically (impl->pending_move_to_rect.rect_anchor);
-      flipped_window_anchor =
-        flip_anchor_vertically (impl->pending_move_to_rect.window_anchor),
-      calculate_popup_rect (window,
-                            flipped_rect_anchor,
-                            flipped_window_anchor,
-                            &flipped_y_rect);
-
-      if (flipped_y_rect.y == y)
-        flipped_rect->y = y;
-    }
-
-  *flipped_x = flipped_rect->x != best_rect.x;
-  *flipped_y = flipped_rect->y != best_rect.y;
-}
-
-static struct zxdg_positioner_v6 *
-create_dynamic_positioner (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkWaylandDisplay *display =
-    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  struct zxdg_positioner_v6 *positioner;
-  GdkRectangle geometry;
-  enum zxdg_positioner_v6_anchor anchor;
-  enum zxdg_positioner_v6_gravity gravity;
-  uint32_t constraint_adjustment = ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE;
-  gint real_anchor_rect_x, real_anchor_rect_y;
-  gint anchor_rect_width, anchor_rect_height;
-
-  positioner = zxdg_shell_v6_create_positioner (display->xdg_shell);
-
-  gdk_wayland_surface_get_window_geometry (window, &geometry);
-  zxdg_positioner_v6_set_size (positioner, geometry.width, geometry.height);
-
-  real_anchor_rect_x = impl->pending_move_to_rect.rect.x;
-  real_anchor_rect_y = impl->pending_move_to_rect.rect.y;
-  translate_to_real_parent_window_geometry (window,
-                                            &real_anchor_rect_x,
-                                            &real_anchor_rect_y);
-
-  anchor_rect_width = impl->pending_move_to_rect.rect.width;
-  anchor_rect_height = impl->pending_move_to_rect.rect.height;
-  zxdg_positioner_v6_set_anchor_rect (positioner,
-                                      real_anchor_rect_x,
-                                      real_anchor_rect_y,
-                                      anchor_rect_width,
-                                      anchor_rect_height);
-
-  zxdg_positioner_v6_set_offset (positioner,
-                                 impl->pending_move_to_rect.rect_anchor_dx,
-                                 impl->pending_move_to_rect.rect_anchor_dy);
-
-  anchor = rect_anchor_to_anchor (impl->pending_move_to_rect.rect_anchor);
-  zxdg_positioner_v6_set_anchor (positioner, anchor);
-
-  gravity = window_anchor_to_gravity (impl->pending_move_to_rect.window_anchor);
-  zxdg_positioner_v6_set_gravity (positioner, gravity);
-
-  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_X)
-    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X;
-  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_FLIP_Y)
-    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y;
-  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_SLIDE_X)
-    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X;
-  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_SLIDE_Y)
-    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y;
-  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_RESIZE_X)
-    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X;
-  if (impl->pending_move_to_rect.anchor_hints & GDK_ANCHOR_RESIZE_Y)
-    constraint_adjustment |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y;
-
-  zxdg_positioner_v6_set_constraint_adjustment (positioner,
-                                                constraint_adjustment);
-
-  return positioner;
-}
-
-static struct zxdg_positioner_v6 *
-create_simple_positioner (GdkSurface *window,
-                          GdkSurface *parent)
-{
-  GdkWaylandDisplay *display =
-    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  struct zxdg_positioner_v6 *positioner;
-  GdkRectangle geometry;
-  GdkRectangle parent_geometry;
-  int parent_x, parent_y;
-
-  positioner = zxdg_shell_v6_create_positioner (display->xdg_shell);
-
-  gdk_wayland_surface_get_window_geometry (window, &geometry);
-  zxdg_positioner_v6_set_size (positioner, geometry.width, geometry.height);
-
-  parent_x = parent->x;
-  parent_y = parent->y;
-
-  gdk_wayland_surface_get_window_geometry (parent, &parent_geometry);
-  parent_x += parent_geometry.x;
-  parent_y += parent_geometry.y;
-
-  zxdg_positioner_v6_set_anchor_rect (positioner,
-                                      (window->x + geometry.x) - parent_x,
-                                      (window->y + geometry.y) - parent_y,
-                                      1, 1);
-  zxdg_positioner_v6_set_anchor (positioner,
-                                 (ZXDG_POSITIONER_V6_ANCHOR_TOP |
-                                  ZXDG_POSITIONER_V6_ANCHOR_LEFT));
-  zxdg_positioner_v6_set_gravity (positioner,
-                                  (ZXDG_POSITIONER_V6_GRAVITY_BOTTOM |
-                                   ZXDG_POSITIONER_V6_GRAVITY_RIGHT));
-
-  return positioner;
-}
-
-static void
-gdk_wayland_surface_create_xdg_popup (GdkSurface      *window,
-                                     GdkSurface      *parent,
-                                     struct wl_seat *seat)
-{
-  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkSurfaceImplWayland *parent_impl = GDK_SURFACE_IMPL_WAYLAND (parent->impl);
-  struct zxdg_positioner_v6 *positioner;
-  GdkSeat *gdk_seat;
-  guint32 serial;
-
-  if (!impl->display_server.wl_surface)
-    return;
-
-  if (!parent_impl->display_server.xdg_surface)
-    return;
-
-  if (impl->display_server.xdg_toplevel)
-    {
-      g_warning ("Can't map popup, already mapped as toplevel");
-      return;
-    }
-  if (impl->display_server.xdg_popup)
-    {
-      g_warning ("Can't map popup, already mapped");
-      return;
-    }
-  if ((display->current_popups &&
-       g_list_last (display->current_popups)->data != parent) ||
-      (!display->current_popups &&
-       !parent_impl->display_server.xdg_toplevel))
-    {
-      g_warning ("Tried to map a popup with a non-top most parent");
-      return;
-    }
-
-  impl->display_server.xdg_surface =
-    zxdg_shell_v6_get_xdg_surface (display->xdg_shell,
-                                   impl->display_server.wl_surface);
-  zxdg_surface_v6_add_listener (impl->display_server.xdg_surface,
-                                &xdg_surface_listener,
-                                window);
-  gdk_surface_freeze_updates (window);
-
-  if (impl->position_method == POSITION_METHOD_MOVE_TO_RECT)
-    positioner = create_dynamic_positioner (window);
-  else
-    positioner = create_simple_positioner (window, parent);
-
-  impl->display_server.xdg_popup =
-    zxdg_surface_v6_get_popup (impl->display_server.xdg_surface,
-                               parent_impl->display_server.xdg_surface,
-                               positioner);
-  zxdg_popup_v6_add_listener (impl->display_server.xdg_popup,
-                              &xdg_popup_listener,
-                              window);
-
-  zxdg_positioner_v6_destroy (positioner);
-
-  if (seat)
-    {
-      gdk_seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
-      serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_seat, NULL);
-      zxdg_popup_v6_grab (impl->display_server.xdg_popup, seat, serial);
-    }
-
-  wl_surface_commit (impl->display_server.wl_surface);
-
-  impl->popup_parent = parent;
-  display->current_popups = g_list_append (display->current_popups, window);
-}
-
-static struct wl_seat *
-find_grab_input_seat (GdkSurface *window, GdkSurface *transient_for)
-{
-  GdkSurface *attached_grab_window;
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkSurfaceImplWayland *tmp_impl;
-
-  /* Use the device that was used for the grab as the device for
-   * the popup window setup - so this relies on GTK+ taking the
-   * grab before showing the popup window.
-   */
-  if (impl->grab_input_seat)
-    return gdk_wayland_seat_get_wl_seat (impl->grab_input_seat);
-
-  /* HACK: GtkMenu grabs a special window known as the "grab transfer window"
-   * and then transfers the grab over to the correct window later. Look for
-   * this window when taking the grab to know it's correct.
-   *
-   * See: associate_menu_grab_transfer_window in gtkmenu.c
-   */
-  attached_grab_window = g_object_get_data (G_OBJECT (window), "gdk-attached-grab-window");
-  if (attached_grab_window)
-    {
-      tmp_impl = GDK_SURFACE_IMPL_WAYLAND (attached_grab_window->impl);
-      if (tmp_impl->grab_input_seat)
-        return gdk_wayland_seat_get_wl_seat (tmp_impl->grab_input_seat);
-    }
-
-  while (transient_for)
-    {
-      tmp_impl = GDK_SURFACE_IMPL_WAYLAND (transient_for->impl);
-
-      if (tmp_impl->grab_input_seat)
-        return gdk_wayland_seat_get_wl_seat (tmp_impl->grab_input_seat);
-
-      transient_for = tmp_impl->transient_for;
-    }
-
-  return NULL;
-}
-
-static gboolean
-should_be_mapped (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  /* Don't map crazy temp that GTK+ uses for internal X11 shenanigans. */
-  if (window->window_type == GDK_SURFACE_TEMP && window->x < 0 && window->y < 0)
-    return FALSE;
-
-  if (impl->hint == GDK_SURFACE_TYPE_HINT_DND)
-    return FALSE;
-
-  return TRUE;
-}
-
-static gboolean
-should_map_as_popup (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  /* Ideally, popup would be temp windows with a parent and grab */
-  if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP)
-    {
-      /* If a temp window has a parent and a grab, we can use a popup */
-      if (impl->transient_for)
-        {
-          if (impl->grab_input_seat)
-            return TRUE;
-        }
-      else
-        g_message ("Window %p is a temporary window without parent, "
-                   "application will not be able to position it on screen.",
-                   window);
-    }
-
-  /* Yet we need to keep the window type hint tests for compatibility */
-  switch ((guint) impl->hint)
-    {
-    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
-    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU:
-    case GDK_SURFACE_TYPE_HINT_COMBO:
-      return TRUE;
-
-    default:
-      break;
-    }
-
-  return FALSE;
-}
-
-static gboolean
-should_map_as_subsurface (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_SUBSURFACE)
-    return TRUE;
-
-  if (GDK_SURFACE_TYPE (window) != GDK_SURFACE_TEMP)
-    return FALSE;
-
-  /* if we want a popup, we do not want a subsurface */
-  if (should_map_as_popup (window))
-    return FALSE;
-
-  if (impl->transient_for)
-    {
-      GdkSurfaceImplWayland *impl_parent;
-
-      impl_parent = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
-      /* subsurface require that the parent is mapped */
-      if (impl_parent->mapped)
-        return TRUE;
-      else
-        g_warning ("Couldn't map window %p as subsurface because its parent is not mapped.",
-                   window);
-
-    }
-
-  return FALSE;
-}
-
-/* Get the window that can be used as a parent for a popup, i.e. a xdg_toplevel
- * or xdg_popup. If the window is not, traverse up the transiency parents until
- * we find one.
- */
-static GdkSurface *
-get_popup_parent (GdkSurface *window)
-{
-  while (window)
-    {
-      GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-      if (impl->display_server.xdg_popup || impl->display_server.xdg_toplevel)
-        return window;
-
-      window = impl->transient_for;
-    }
-
-  return NULL;
-}
-
-static void
-gdk_wayland_surface_map (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkSurface *transient_for = NULL;
-
-  if (!should_be_mapped (window))
-    return;
-
-  if (impl->mapped || impl->use_custom_surface)
-    return;
-
-  if (should_map_as_subsurface (window))
-    {
-      if (impl->transient_for)
-        gdk_wayland_surface_create_subsurface (window);
-      else
-        g_warning ("Couldn't map window %p as susburface yet because it doesn't have a parent",
-                   window);
-    }
-  else if (should_map_as_popup (window))
-    {
-      gboolean create_fallback = FALSE;
-      struct wl_seat *grab_input_seat;
-
-      /* Popup menus can appear without a transient parent, which means they
-       * cannot be positioned properly on Wayland. This attempts to guess the
-       * surface they should be positioned with by finding the surface beneath
-       * the device that created the grab for the popup window.
-       */
-      if (!impl->transient_for && impl->hint == GDK_SURFACE_TYPE_HINT_POPUP_MENU)
-        {
-          GdkDevice *grab_device = NULL;
-
-          /* The popup menu window is not the grabbed window. This may mean
-           * that a "transfer window" (see gtkmenu.c) is used, and we need
-           * to find that window to get the grab device. If so is the case
-           * the "transfer window" can be retrieved via the
-           * "gdk-attached-grab-window" associated data field.
-           */
-          if (!impl->grab_input_seat)
-            {
-              GdkSurface *attached_grab_window =
-                g_object_get_data (G_OBJECT (window),
-                                   "gdk-attached-grab-window");
-              if (attached_grab_window)
-                {
-                  GdkSurfaceImplWayland *attached_impl =
-                    GDK_SURFACE_IMPL_WAYLAND (attached_grab_window->impl);
-                  grab_device = gdk_seat_get_pointer (attached_impl->grab_input_seat);
-                  transient_for =
-                    gdk_device_get_window_at_position (grab_device,
-                                                       NULL, NULL);
-                }
-            }
-          else
-            {
-              grab_device = gdk_seat_get_pointer (impl->grab_input_seat);
-              transient_for =
-                gdk_device_get_window_at_position (grab_device, NULL, NULL);
-            }
-
-          if (transient_for)
-            transient_for = get_popup_parent (gdk_surface_get_toplevel (transient_for));
-
-          /* If the position was not explicitly set, start the popup at the
-           * position of the device that holds the grab.
-           */
-          if (impl->position_method == POSITION_METHOD_NONE && grab_device)
-            gdk_surface_get_device_position (transient_for, grab_device,
-                                            &window->x, &window->y, NULL);
-        }
-      else
-        {
-          transient_for = gdk_surface_get_toplevel (impl->transient_for);
-          transient_for = get_popup_parent (transient_for);
-        }
-
-      if (!transient_for)
-        {
-          g_warning ("Couldn't map as window %p as popup because it doesn't have a parent",
-                     window);
-
-          create_fallback = TRUE;
-        }
-      else
-        {
-          grab_input_seat = find_grab_input_seat (window, transient_for);
-        }
-
-      if (!create_fallback)
-        {
-          gdk_wayland_surface_create_xdg_popup (window,
-                                               transient_for,
-                                               grab_input_seat);
-        }
-      else
-        {
-          gdk_wayland_surface_create_xdg_toplevel (window);
-        }
-    }
-  else
-    {
-      gdk_wayland_surface_create_xdg_toplevel (window);
-    }
-
-  impl->mapped = TRUE;
-}
-
-static void
-gdk_wayland_surface_show (GdkSurface *window,
-                         gboolean   already_mapped)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (!impl->display_server.wl_surface)
-    gdk_wayland_surface_create_surface (window);
-
-  gdk_wayland_surface_map (window);
-
-  _gdk_make_event (window, GDK_MAP, NULL, FALSE);
-
-  if (impl->staging_cairo_surface &&
-      _gdk_wayland_is_shm_surface (impl->staging_cairo_surface))
-    gdk_wayland_surface_attach_image (window);
-}
-
-static void
-unmap_subsurface (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkSurfaceImplWayland *parent_impl;
-
-  g_return_if_fail (impl->display_server.wl_subsurface);
-  g_return_if_fail (impl->transient_for);
-
-  parent_impl = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
-  wl_subsurface_destroy (impl->display_server.wl_subsurface);
-  if (impl->parent_surface_committed_handler)
-    {
-      g_signal_handler_disconnect (parent_impl,
-                                   impl->parent_surface_committed_handler);
-      impl->parent_surface_committed_handler = 0;
-    }
-  impl->display_server.wl_subsurface = NULL;
-}
-
-static void
-unmap_popups_for_window (GdkSurface *window)
-{
-  GdkWaylandDisplay *display_wayland;
-  GList *l;
-
-  display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  for (l = display_wayland->current_popups; l; l = l->next)
-    {
-       GdkSurface *popup = l->data;
-       GdkSurfaceImplWayland *popup_impl = GDK_SURFACE_IMPL_WAYLAND (popup->impl);
-
-       if (popup_impl->popup_parent == window)
-         {
-           g_warning ("Tried to unmap the parent of a popup");
-           gdk_surface_hide (popup);
-
-           return;
-         }
-    }
-}
-
-static void
-gdk_wayland_surface_hide_surface (GdkSurface *window)
-{
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  unmap_popups_for_window (window);
-
-  if (impl->display_server.wl_surface)
-    {
-      if (impl->dummy_egl_surface)
-        {
-          eglDestroySurface (display_wayland->egl_display, impl->dummy_egl_surface);
-          impl->dummy_egl_surface = NULL;
-        }
-
-      if (impl->display_server.dummy_egl_window)
-        {
-          wl_egl_window_destroy (impl->display_server.dummy_egl_window);
-          impl->display_server.dummy_egl_window = NULL;
-        }
-
-      if (impl->egl_surface)
-        {
-          eglDestroySurface (display_wayland->egl_display, impl->egl_surface);
-          impl->egl_surface = NULL;
-        }
-
-      if (impl->display_server.egl_window)
-        {
-          wl_egl_window_destroy (impl->display_server.egl_window);
-          impl->display_server.egl_window = NULL;
-        }
-
-      if (impl->display_server.xdg_toplevel)
-        {
-          zxdg_toplevel_v6_destroy (impl->display_server.xdg_toplevel);
-          impl->display_server.xdg_toplevel = NULL;
-        }
-      else if (impl->display_server.xdg_popup)
-        {
-          zxdg_popup_v6_destroy (impl->display_server.xdg_popup);
-          impl->display_server.xdg_popup = NULL;
-          display_wayland->current_popups =
-            g_list_remove (display_wayland->current_popups, window);
-        }
-      if (impl->display_server.xdg_surface)
-        {
-          zxdg_surface_v6_destroy (impl->display_server.xdg_surface);
-          impl->display_server.xdg_surface = NULL;
-          if (!impl->initial_configure_received)
-            gdk_surface_thaw_updates (window);
-          else
-            impl->initial_configure_received = FALSE;
-        }
-
-      if (impl->display_server.wl_subsurface)
-        unmap_subsurface (window);
-
-      if (impl->awaiting_frame)
-        {
-          GdkFrameClock *frame_clock;
-
-          impl->awaiting_frame = FALSE;
-          frame_clock = gdk_surface_get_frame_clock (window);
-          if (frame_clock)
-            _gdk_frame_clock_thaw (frame_clock);
-        }
-
-      if (impl->display_server.gtk_surface)
-        {
-          gtk_surface1_destroy (impl->display_server.gtk_surface);
-          impl->display_server.gtk_surface = NULL;
-          impl->application.was_set = FALSE;
-        }
-
-      wl_surface_destroy (impl->display_server.wl_surface);
-      impl->display_server.wl_surface = NULL;
-
-      g_slist_free (impl->display_server.outputs);
-      impl->display_server.outputs = NULL;
-
-      if (impl->hint == GDK_SURFACE_TYPE_HINT_DIALOG && !impl->transient_for)
-        display_wayland->orphan_dialogs =
-          g_list_remove (display_wayland->orphan_dialogs, window);
-    }
-
-  unset_transient_for_exported (window);
-
-  _gdk_wayland_surface_clear_saved_size (window);
-  impl->pending_commit = FALSE;
-  impl->mapped = FALSE;
-}
-
-static void
-gdk_wayland_surface_hide (GdkSurface *window)
-{
-  gdk_wayland_surface_hide_surface (window);
-  _gdk_surface_clear_update_area (window);
-}
-
-static void
-gdk_surface_wayland_withdraw (GdkSurface *window)
-{
-  if (!window->destroyed)
-    {
-      if (GDK_SURFACE_IS_MAPPED (window))
-        gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_WITHDRAWN);
-
-      g_assert (!GDK_SURFACE_IS_MAPPED (window));
-
-      gdk_wayland_surface_hide_surface (window);
-    }
-}
-
-static void
-gdk_surface_wayland_set_events (GdkSurface    *window,
-                               GdkEventMask  event_mask)
-{
-  GDK_SURFACE (window)->event_mask = event_mask;
-}
-
-static GdkEventMask
-gdk_surface_wayland_get_events (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return 0;
-  else
-    return GDK_SURFACE (window)->event_mask;
-}
-
-static void
-gdk_surface_wayland_raise (GdkSurface *window)
-{
-}
-
-static void
-gdk_surface_wayland_lower (GdkSurface *window)
-{
-}
-
-static void
-gdk_surface_wayland_restack_toplevel (GdkSurface *window,
-                                     GdkSurface *sibling,
-                                     gboolean   above)
-{
-}
-
-static void
-gdk_surface_request_transient_parent_commit (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *window_impl, *impl;
-  GdkFrameClock *frame_clock;
-
-  window_impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (!window_impl->transient_for)
-    return;
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window_impl->transient_for->impl);
-
-  if (!impl->display_server.wl_surface || impl->pending_commit)
-    return;
-
-  frame_clock = gdk_surface_get_frame_clock (window_impl->transient_for);
-
-  if (!frame_clock)
-    return;
-
-  impl->pending_commit = TRUE;
-  gdk_frame_clock_request_phase (frame_clock,
-                                 GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
-}
-
-static void
-gdk_surface_wayland_move_resize (GdkSurface *window,
-                                gboolean   with_move,
-                                gint       x,
-                                gint       y,
-                                gint       width,
-                                gint       height)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (with_move)
-    {
-      /* Each toplevel has in its own "root" coordinate system */
-      if (GDK_SURFACE_TYPE (window) != GDK_SURFACE_TOPLEVEL)
-        {
-          window->x = x;
-          window->y = y;
-          impl->position_method = POSITION_METHOD_MOVE_RESIZE;
-
-          if (impl->display_server.wl_subsurface)
-            {
-              wl_subsurface_set_position (impl->display_server.wl_subsurface,
-                                          window->x + window->abs_x,
-                                          window->y + window->abs_y);
-              gdk_surface_request_transient_parent_commit (window);
-            }
-        }
-    }
-
-  /* If this function is called with width and height = -1 then that means
-   * just move the window - don't update its size
-   */
-  if (width > 0 && height > 0)
-    gdk_wayland_surface_maybe_configure (window, width, height, impl->scale);
-}
-
-/* Avoid zero width/height as this is a protocol error */
-static void
-sanitize_anchor_rect (GdkSurface    *window,
-                      GdkRectangle *rect)
-{
-  gint original_width = rect->width;
-  gint original_height = rect->height;
-
-  rect->width  = MAX (1, rect->width);
-  rect->height = MAX (1, rect->height);
-  rect->x = MAX (rect->x + original_width - rect->width, 0);
-  rect->y = MAX (rect->y + original_height - rect->height, 0);
-}
-
-static void
-gdk_surface_wayland_move_to_rect (GdkSurface          *window,
-                                 const GdkRectangle *rect,
-                                 GdkGravity          rect_anchor,
-                                 GdkGravity          window_anchor,
-                                 GdkAnchorHints      anchor_hints,
-                                 gint                rect_anchor_dx,
-                                 gint                rect_anchor_dy)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  impl->pending_move_to_rect.rect = *rect;
-  sanitize_anchor_rect (window, &impl->pending_move_to_rect.rect);
-
-  impl->pending_move_to_rect.rect_anchor = rect_anchor;
-  impl->pending_move_to_rect.window_anchor = window_anchor;
-  impl->pending_move_to_rect.anchor_hints = anchor_hints;
-  impl->pending_move_to_rect.rect_anchor_dx = rect_anchor_dx;
-  impl->pending_move_to_rect.rect_anchor_dy = rect_anchor_dy;
-
-  impl->position_method = POSITION_METHOD_MOVE_TO_RECT;
-}
-
-static void
-gdk_surface_wayland_get_geometry (GdkSurface *window,
-                                 gint      *x,
-                                 gint      *y,
-                                 gint      *width,
-                                 gint      *height)
-{
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      if (x)
-        *x = window->x;
-      if (y)
-        *y = window->y;
-      if (width)
-        *width = window->width;
-      if (height)
-        *height = window->height;
-    }
-}
-
-static void
-gdk_surface_wayland_get_root_coords (GdkSurface *window,
-                                    gint       x,
-                                    gint       y,
-                                    gint      *root_x,
-                                    gint      *root_y)
-{
-  /*
-   * Wayland does not have a global coordinate space shared between surfaces. In
-   * fact, for regular toplevels, we have no idea where our surfaces are
-   * positioned, relatively.
-   *
-   * However, there are some cases like popups and subsurfaces where we do have
-   * some amount of control over the placement of our window, and we can
-   * semi-accurately control the x/y position of these windows, if they are
-   * relative to another surface.
-   *
-   * To pretend we have something called a root coordinate space, assume all
-   * parent-less windows are positioned in (0, 0), and all relative positioned
-   * popups and subsurfaces are placed within this fake root coordinate space.
-   *
-   * For example a 200x200 large toplevel window will have the position (0, 0).
-   * If a popup positioned in the middle of the toplevel will have the fake
-   * position (100,100). Furthermore, if a positioned is placed in the middle
-   * that popup, will have the fake position (150,150), even though it has the
-   * relative position (50,50). These three windows would make up one single
-   * fake root coordinate space.
-   */
-
-  if (root_x)
-    *root_x = window->x + x;
-
-  if (root_y)
-    *root_y = window->y + y;
-}
-
-static gboolean
-gdk_surface_wayland_get_device_state (GdkSurface       *window,
-                                     GdkDevice       *device,
-                                     gdouble         *x,
-                                     gdouble         *y,
-                                     GdkModifierType *mask)
-{
-  gboolean return_val;
-
-  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), FALSE);
-
-  return_val = TRUE;
-
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      GdkSurface *child;
-
-      GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
-                                                  &child,
-                                                  NULL, NULL,
-                                                  x, y, mask);
-      return_val = (child != NULL);
-    }
-
-  return return_val;
-}
-
-static void
-gdk_surface_wayland_shape_combine_region (GdkSurface            *window,
-                                         const cairo_region_t *shape_region,
-                                         gint                  offset_x,
-                                         gint                  offset_y)
-{
-}
-
-static void
-gdk_surface_wayland_input_shape_combine_region (GdkSurface            *window,
-                                               const cairo_region_t *shape_region,
-                                               gint                  offset_x,
-                                               gint                  offset_y)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  g_clear_pointer (&impl->input_region, cairo_region_destroy);
-
-  if (shape_region)
-    {
-      impl->input_region = cairo_region_copy (shape_region);
-      cairo_region_translate (impl->input_region, offset_x, offset_y);
-    }
-
-  impl->input_region_dirty = TRUE;
-}
-
-static void
-gdk_wayland_surface_destroy (GdkSurface *window,
-                            gboolean   recursing,
-                            gboolean   foreign_destroy)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  /* Wayland windows can't be externally destroyed; we may possibly
-   * eventually want to use this path at display close-down
-   */
-  g_return_if_fail (!foreign_destroy);
-
-  gdk_wayland_surface_hide_surface (window);
-  drop_cairo_surfaces (window);
-
-  if (window->parent == NULL)
-    {
-      GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-      display->toplevels = g_list_remove (display->toplevels, window);
-    }
-}
-
-static void
-gdk_wayland_surface_focus (GdkSurface *window,
-                          guint32    timestamp)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (!impl->display_server.gtk_surface)
-    return;
-
-  /* We didn't have an event to fetch a time from, meaning we have nothing valid
-   * to send. This should rather be translated to a 'needs-attention' request or
-   * something.
-   */
-  if (timestamp == GDK_CURRENT_TIME)
-    return;
-
-  gtk_surface1_present (impl->display_server.gtk_surface, timestamp);
-}
-
-static void
-gdk_wayland_surface_set_type_hint (GdkSurface         *window,
-                                  GdkSurfaceTypeHint  hint)
-{
-  GdkSurfaceImplWayland *impl;
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  impl->hint = hint;
-}
-
-static GdkSurfaceTypeHint
-gdk_wayland_surface_get_type_hint (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return GDK_SURFACE_TYPE_HINT_NORMAL;
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  return impl->hint;
-}
-
-static void
-gtk_surface_configure (void                *data,
-                       struct gtk_surface1 *gtk_surface,
-                       struct wl_array     *states)
-{
-  GdkSurface *window = GDK_SURFACE (data);
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkSurfaceState new_state = 0;
-  uint32_t *p;
-
-  wl_array_for_each (p, states)
-    {
-      uint32_t state = *p;
-
-      switch (state)
-        {
-        case GTK_SURFACE1_STATE_TILED:
-          new_state |= GDK_SURFACE_STATE_TILED;
-          break;
-
-        /* Since v2 */
-        case GTK_SURFACE1_STATE_TILED_TOP:
-          new_state |= (GDK_SURFACE_STATE_TILED | GDK_SURFACE_STATE_TOP_TILED);
-          break;
-        case GTK_SURFACE1_STATE_TILED_RIGHT:
-          new_state |= (GDK_SURFACE_STATE_TILED | GDK_SURFACE_STATE_RIGHT_TILED);
-          break;
-        case GTK_SURFACE1_STATE_TILED_BOTTOM:
-          new_state |= (GDK_SURFACE_STATE_TILED | GDK_SURFACE_STATE_BOTTOM_TILED);
-          break;
-        case GTK_SURFACE1_STATE_TILED_LEFT:
-          new_state |= (GDK_SURFACE_STATE_TILED | GDK_SURFACE_STATE_LEFT_TILED);
-          break;
-        default:
-          /* Unknown state */
-          break;
-        }
-    }
-
-  impl->pending.state |= new_state;
-}
-
-static void
-gtk_surface_configure_edges (void                *data,
-                             struct gtk_surface1 *gtk_surface,
-                             struct wl_array     *edge_constraints)
-{
-  GdkSurface *window = GDK_SURFACE (data);
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkSurfaceState new_state = 0;
-  uint32_t *p;
-
-  wl_array_for_each (p, edge_constraints)
-    {
-      uint32_t constraint = *p;
-
-      switch (constraint)
-        {
-        case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_TOP:
-          new_state |= GDK_SURFACE_STATE_TOP_RESIZABLE;
-          break;
-        case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_RIGHT:
-          new_state |= GDK_SURFACE_STATE_RIGHT_RESIZABLE;
-          break;
-        case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_BOTTOM:
-          new_state |= GDK_SURFACE_STATE_BOTTOM_RESIZABLE;
-          break;
-        case GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_LEFT:
-          new_state |= GDK_SURFACE_STATE_LEFT_RESIZABLE;
-          break;
-        default:
-          /* Unknown state */
-          break;
-        }
-    }
-
-  impl->pending.state |= new_state;
-}
-
-static const struct gtk_surface1_listener gtk_surface_listener = {
-  gtk_surface_configure,
-  gtk_surface_configure_edges
-};
-
-static void
-gdk_wayland_surface_init_gtk_surface (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkWaylandDisplay *display =
-    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-
-  if (impl->display_server.gtk_surface != NULL)
-    return;
-  if (impl->display_server.xdg_surface == NULL)
-    return;
-  if (display->gtk_shell == NULL)
-    return;
-
-  impl->display_server.gtk_surface =
-    gtk_shell1_get_gtk_surface (display->gtk_shell,
-                                impl->display_server.wl_surface);
-  gdk_surface_set_geometry_hints (window,
-                                 &impl->geometry_hints,
-                                 impl->geometry_mask);
-  gtk_surface1_add_listener (impl->display_server.gtk_surface,
-                             &gtk_surface_listener,
-                             window);
-}
-
-static void
-maybe_set_gtk_surface_modal (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  gdk_wayland_surface_init_gtk_surface (window);
-  if (impl->display_server.gtk_surface == NULL)
-    return;
-
-  if (window->modal_hint)
-    gtk_surface1_set_modal (impl->display_server.gtk_surface);
-  else
-    gtk_surface1_unset_modal (impl->display_server.gtk_surface);
-
-}
-
-static void
-gdk_wayland_surface_set_modal_hint (GdkSurface *window,
-                                   gboolean   modal)
-{
-  window->modal_hint = modal;
-  maybe_set_gtk_surface_modal (window);
-}
-
-static void
-gdk_wayland_surface_set_skip_taskbar_hint (GdkSurface *window,
-                                          gboolean   skips_taskbar)
-{
-}
-
-static void
-gdk_wayland_surface_set_skip_pager_hint (GdkSurface *window,
-                                        gboolean   skips_pager)
-{
-}
-
-static void
-gdk_wayland_surface_set_urgency_hint (GdkSurface *window,
-                                     gboolean   urgent)
-{
-}
-
-static void
-gdk_wayland_surface_set_geometry_hints (GdkSurface         *window,
-                                       const GdkGeometry *geometry,
-                                       GdkSurfaceHints     geom_mask)
-{
-  GdkSurfaceImplWayland *impl;
-  int width, height;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  impl->geometry_hints = *geometry;
-  impl->geometry_mask = geom_mask;
-
-  if (!impl->display_server.xdg_toplevel)
-    return;
-
-  if (geom_mask & GDK_HINT_MIN_SIZE)
-    {
-      width = MAX (0, geometry->min_width - (impl->margin_left + impl->margin_right));
-      height = MAX (0, geometry->min_height - (impl->margin_top + impl->margin_bottom));
-    }
-  else
-    {
-      width = 0;
-      height = 0;
-    }
-
-  zxdg_toplevel_v6_set_min_size (impl->display_server.xdg_toplevel, width, height);
-
-  if (geom_mask & GDK_HINT_MAX_SIZE)
-    {
-      width = MAX (0, geometry->max_width - (impl->margin_left + impl->margin_right));
-      height = MAX (0, geometry->max_height - (impl->margin_top + impl->margin_bottom));
-    }
-  else
-    {
-      width = 0;
-      height = 0;
-    }
-
-  zxdg_toplevel_v6_set_max_size (impl->display_server.xdg_toplevel, width, height);
-}
-
-static void
-gdk_wayland_surface_set_title (GdkSurface   *window,
-                              const gchar *title)
-{
-  GdkSurfaceImplWayland *impl;
-  const char *end;
-  gsize title_length;
-
-  g_return_if_fail (title != NULL);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (g_strcmp0 (impl->title, title) == 0)
-    return;
-
-  g_free (impl->title);
-
-  title_length = MIN (strlen (title), MAX_WL_BUFFER_SIZE);
-  if (g_utf8_validate (title, title_length, &end))
-    {
-      impl->title = g_malloc (end - title + 1);
-      memcpy (impl->title, title, end - title);
-      impl->title[end - title] = '\0';
-    }
-  else
-    {
-      impl->title = g_utf8_make_valid (title, title_length);
-      g_warning ("Invalid utf8 passed to gdk_surface_set_title: '%s'", title);
-    }
-
-  gdk_wayland_surface_sync_title (window);
-}
-
-static void
-gdk_wayland_surface_set_role (GdkSurface   *window,
-                             const gchar *role)
-{
-}
-
-static void
-gdk_wayland_surface_set_startup_id (GdkSurface   *window,
-                                   const gchar *startup_id)
-{
-}
-
-static gboolean
-check_transient_for_loop (GdkSurface *window,
-                          GdkSurface *parent)
-{
-  while (parent)
-    {
-      GdkSurfaceImplWayland *impl;
-
-      if (!GDK_IS_SURFACE_IMPL_WAYLAND(parent->impl))
-        return FALSE;
-
-      impl = GDK_SURFACE_IMPL_WAYLAND (parent->impl);
-      if (impl->transient_for == window)
-        return TRUE;
-      parent = impl->transient_for;
-    }
-  return FALSE;
-}
-
-static void
-gdk_wayland_surface_set_transient_for (GdkSurface *window,
-                                      GdkSurface *parent)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkWaylandDisplay *display_wayland =
-    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  GdkSurface *previous_parent;
-
-  g_assert (parent == NULL ||
-            gdk_surface_get_display (window) == gdk_surface_get_display (parent));
-
-  if (check_transient_for_loop (window, parent))
-    {
-      g_warning ("Setting %p transient for %p would create a loop", window, parent);
-      return;
-    }
-
-  unset_transient_for_exported (window);
-
-  if (impl->display_server.wl_subsurface)
-    unmap_subsurface (window);
-
-  previous_parent = impl->transient_for;
-  impl->transient_for = parent;
-
-  if (impl->hint == GDK_SURFACE_TYPE_HINT_DIALOG)
-    {
-      if (!parent)
-        _gdk_wayland_screen_add_orphan_dialog (window);
-      else if (!previous_parent)
-        display_wayland->orphan_dialogs =
-          g_list_remove (display_wayland->orphan_dialogs, window);
-    }
-  gdk_wayland_surface_sync_parent (window, NULL);
-  if (should_map_as_subsurface (window) &&
-      parent && gdk_surface_is_visible (window))
-    gdk_wayland_surface_create_subsurface (window);
-}
-
-static void
-gdk_wayland_surface_get_frame_extents (GdkSurface    *window,
-                                      GdkRectangle *rect)
-{
-  *rect = (GdkRectangle) {
-    .x = window->x,
-    .y = window->y,
-    .width = window->width,
-    .height = window->height
-  };
-}
-
-static void
-gdk_wayland_surface_set_accept_focus (GdkSurface *window,
-                                     gboolean   accept_focus)
-{
-}
-
-static void
-gdk_wayland_surface_set_focus_on_map (GdkSurface *window,
-                                     gboolean focus_on_map)
-{
-}
-
-static void
-gdk_wayland_surface_set_icon_list (GdkSurface *window,
-                                  GList     *surfaces)
-{
-}
-
-static void
-gdk_wayland_surface_set_icon_name (GdkSurface   *window,
-                                  const gchar *name)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-}
-
-static void
-gdk_wayland_surface_iconify (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  if (!impl->display_server.xdg_toplevel)
-    return;
-
-  zxdg_toplevel_v6_set_minimized (impl->display_server.xdg_toplevel);
-}
-
-static void
-gdk_wayland_surface_deiconify (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    gdk_surface_show (window);
-  else
-    /* Flip our client side flag, the real work happens on map. */
-    gdk_synthesize_window_state (window, GDK_SURFACE_STATE_ICONIFIED, 0);
-}
-
-static void
-gdk_wayland_surface_stick (GdkSurface *window)
-{
-}
-
-static void
-gdk_wayland_surface_unstick (GdkSurface *window)
-{
-}
-
-static void
-gdk_wayland_surface_maximize (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  _gdk_wayland_surface_save_size (window);
-  if (impl->display_server.xdg_toplevel)
-    zxdg_toplevel_v6_set_maximized (impl->display_server.xdg_toplevel);
-  else
-    gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_MAXIMIZED);
-}
-
-static void
-gdk_wayland_surface_unmaximize (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (impl->display_server.xdg_toplevel)
-    zxdg_toplevel_v6_unset_maximized (impl->display_server.xdg_toplevel);
-  else
-    gdk_synthesize_window_state (window, GDK_SURFACE_STATE_MAXIMIZED, 0);
-}
-
-static void
-gdk_wayland_surface_fullscreen_on_monitor (GdkSurface  *window,
-                                          GdkMonitor *monitor)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  struct wl_output *output = ((GdkWaylandMonitor *)monitor)->output;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  _gdk_wayland_surface_save_size (window);
-  if (impl->display_server.xdg_toplevel)
-    {
-      zxdg_toplevel_v6_set_fullscreen (impl->display_server.xdg_toplevel, output);
-    }
-  else
-    {
-      gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
-      impl->initial_fullscreen_output = output;
-    }
-}
-
-static void
-gdk_wayland_surface_fullscreen (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  impl->initial_fullscreen_output = NULL;
-
-  _gdk_wayland_surface_save_size (window);
-  if (impl->display_server.xdg_toplevel)
-    zxdg_toplevel_v6_set_fullscreen (impl->display_server.xdg_toplevel, NULL);
-  else
-    gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
-}
-
-static void
-gdk_wayland_surface_unfullscreen (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  impl->initial_fullscreen_output = NULL;
-
-  if (impl->display_server.xdg_toplevel)
-    zxdg_toplevel_v6_unset_fullscreen (impl->display_server.xdg_toplevel);
-  else
-    gdk_synthesize_window_state (window, GDK_SURFACE_STATE_FULLSCREEN, 0);
-}
-
-static void
-gdk_wayland_surface_set_keep_above (GdkSurface *window, gboolean setting)
-{
-}
-
-static void
-gdk_wayland_surface_set_keep_below (GdkSurface *window, gboolean setting)
-{
-}
-
-static GdkSurface *
-gdk_wayland_surface_get_group (GdkSurface *window)
-{
-  return NULL;
-}
-
-static void
-gdk_wayland_surface_set_group (GdkSurface *window,
-                              GdkSurface *leader)
-{
-}
-
-static void
-gdk_wayland_surface_set_decorations (GdkSurface       *window,
-                                    GdkWMDecoration  decorations)
-{
-}
-
-static gboolean
-gdk_wayland_surface_get_decorations (GdkSurface       *window,
-                                    GdkWMDecoration *decorations)
-{
-  return FALSE;
-}
-
-static void
-gdk_wayland_surface_set_functions (GdkSurface     *window,
-                                  GdkWMFunction  functions)
-{
-}
-
-static void
-gdk_wayland_surface_begin_resize_drag (GdkSurface     *window,
-                                      GdkSurfaceEdge  edge,
-                                      GdkDevice     *device,
-                                      gint           button,
-                                      gint           root_x,
-                                      gint           root_y,
-                                      guint32        timestamp)
-{
-  GdkSurfaceImplWayland *impl;
-  GdkEventSequence *sequence;
-  uint32_t resize_edges, serial;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  switch (edge)
-    {
-    case GDK_SURFACE_EDGE_NORTH_WEST:
-      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_LEFT;
-      break;
-
-    case GDK_SURFACE_EDGE_NORTH:
-      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP;
-      break;
-
-    case GDK_SURFACE_EDGE_NORTH_EAST:
-      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_RIGHT;
-      break;
-
-    case GDK_SURFACE_EDGE_WEST:
-      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT;
-      break;
-
-    case GDK_SURFACE_EDGE_EAST:
-      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT;
-      break;
-
-    case GDK_SURFACE_EDGE_SOUTH_WEST:
-      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_LEFT;
-      break;
-
-    case GDK_SURFACE_EDGE_SOUTH:
-      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM;
-      break;
-
-    case GDK_SURFACE_EDGE_SOUTH_EAST:
-      resize_edges = ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_RIGHT;
-      break;
-
-    default:
-      g_warning ("gdk_surface_begin_resize_drag: bad resize edge %d!", edge);
-      return;
-    }
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (!impl->display_server.xdg_toplevel)
-    return;
-
-  serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_device_get_seat (device),
-                                                            &sequence);
-
-  zxdg_toplevel_v6_resize (impl->display_server.xdg_toplevel,
-                           gdk_wayland_device_get_wl_seat (device),
-                           serial, resize_edges);
-
-  if (sequence)
-    gdk_wayland_device_unset_touch_grab (device, sequence);
-
-  /* This is needed since Wayland will absorb all the pointer events after the
-   * above function - FIXME: Is this always safe..?
-   */
-  gdk_seat_ungrab (gdk_device_get_seat (device));
-}
-
-static void
-gdk_wayland_surface_begin_move_drag (GdkSurface *window,
-                                    GdkDevice *device,
-                                    gint       button,
-                                    gint       root_x,
-                                    gint       root_y,
-                                    guint32    timestamp)
-{
-  GdkSurfaceImplWayland *impl;
-  GdkEventSequence *sequence;
-  uint32_t serial;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (!impl->display_server.xdg_toplevel)
-    return;
-
-  serial = _gdk_wayland_seat_get_last_implicit_grab_serial (gdk_device_get_seat (device),
-                                                            &sequence);
-  zxdg_toplevel_v6_move (impl->display_server.xdg_toplevel,
-                         gdk_wayland_device_get_wl_seat (device),
-                         serial);
-  if (sequence)
-    gdk_wayland_device_unset_touch_grab (device, sequence);
-
-  /* This is needed since Wayland will absorb all the pointer events after the
-   * above function - FIXME: Is this always safe..?
-   */
-  gdk_seat_ungrab (gdk_device_get_seat (device));
-}
-
-static void
-gdk_wayland_surface_set_opacity (GdkSurface *window,
-                                gdouble    opacity)
-{
-}
-
-static void
-gdk_wayland_surface_destroy_notify (GdkSurface *window)
-{
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      g_warning ("GdkSurface %p unexpectedly destroyed", window);
-      _gdk_surface_destroy (window, TRUE);
-    }
-
-  g_object_unref (window);
-}
-
-static gint
-gdk_wayland_surface_get_scale_factor (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return 1;
-
-  return impl->scale;
-}
-
-static void
-gdk_wayland_surface_set_opaque_region (GdkSurface      *window,
-                                      cairo_region_t *region)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
-  impl->opaque_region = cairo_region_reference (region);
-  impl->opaque_region_dirty = TRUE;
-}
-
-static void
-gdk_wayland_surface_set_shadow_width (GdkSurface *window,
-                                     int        left,
-                                     int        right,
-                                     int        top,
-                                     int        bottom)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  gint new_width, new_height;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  /* Reconfigure window to keep the same window geometry */
-  new_width = window->width -
-    (impl->margin_left + impl->margin_right) + (left + right);
-  new_height = window->height -
-    (impl->margin_top + impl->margin_bottom) + (top + bottom);
-  gdk_wayland_surface_maybe_configure (window, new_width, new_height, impl->scale);
-
-  impl->margin_left = left;
-  impl->margin_right = right;
-  impl->margin_top = top;
-  impl->margin_bottom = bottom;
-}
-
-static gboolean
-gdk_wayland_surface_show_window_menu (GdkSurface *window,
-                                     GdkEvent  *event)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  struct wl_seat *seat;
-  GdkWaylandDevice *device;
-  double x, y;
-  uint32_t serial;
-
-  switch ((guint) event->any.type)
-    {
-    case GDK_BUTTON_PRESS:
-    case GDK_BUTTON_RELEASE:
-    case GDK_TOUCH_BEGIN:
-    case GDK_TOUCH_END:
-      break;
-    default:
-      return FALSE;
-    }
-
-  if (!impl->display_server.xdg_surface)
-    return FALSE;
-
-  device = GDK_WAYLAND_DEVICE (gdk_event_get_device (event));
-  seat = gdk_wayland_device_get_wl_seat (GDK_DEVICE (device));
-  gdk_event_get_coords (event, &x, &y);
-
-  serial = _gdk_wayland_device_get_implicit_grab_serial (device, event);
-  zxdg_toplevel_v6_show_window_menu (impl->display_server.xdg_toplevel,
-                                     seat, serial, x, y);
-  return TRUE;
-}
-
-static gboolean
-gdk_wayland_surface_supports_edge_constraints (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  struct gtk_surface1 *gtk_surface = impl->display_server.gtk_surface;
-
-  if (!gtk_surface)
-    return FALSE;
-
-  return gtk_surface1_get_version (gtk_surface) >= GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION;
-}
-
-static void
-_gdk_surface_impl_wayland_class_init (GdkSurfaceImplWaylandClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_CLASS (klass);
-
-  object_class->finalize = gdk_surface_impl_wayland_finalize;
-
-  impl_class->ref_cairo_surface = gdk_wayland_surface_ref_cairo_surface;
-  impl_class->create_similar_image_surface = gdk_wayland_surface_create_similar_image_surface;
-  impl_class->show = gdk_wayland_surface_show;
-  impl_class->hide = gdk_wayland_surface_hide;
-  impl_class->withdraw = gdk_surface_wayland_withdraw;
-  impl_class->set_events = gdk_surface_wayland_set_events;
-  impl_class->get_events = gdk_surface_wayland_get_events;
-  impl_class->raise = gdk_surface_wayland_raise;
-  impl_class->lower = gdk_surface_wayland_lower;
-  impl_class->restack_toplevel = gdk_surface_wayland_restack_toplevel;
-  impl_class->move_resize = gdk_surface_wayland_move_resize;
-  impl_class->move_to_rect = gdk_surface_wayland_move_to_rect;
-  impl_class->get_geometry = gdk_surface_wayland_get_geometry;
-  impl_class->get_root_coords = gdk_surface_wayland_get_root_coords;
-  impl_class->get_device_state = gdk_surface_wayland_get_device_state;
-  impl_class->shape_combine_region = gdk_surface_wayland_shape_combine_region;
-  impl_class->input_shape_combine_region = gdk_surface_wayland_input_shape_combine_region;
-  impl_class->destroy = gdk_wayland_surface_destroy;
-  impl_class->begin_paint = gdk_surface_impl_wayland_begin_paint;
-  impl_class->end_paint = gdk_surface_impl_wayland_end_paint;
-  impl_class->beep = gdk_surface_impl_wayland_beep;
-
-  impl_class->focus = gdk_wayland_surface_focus;
-  impl_class->set_type_hint = gdk_wayland_surface_set_type_hint;
-  impl_class->get_type_hint = gdk_wayland_surface_get_type_hint;
-  impl_class->set_modal_hint = gdk_wayland_surface_set_modal_hint;
-  impl_class->set_skip_taskbar_hint = gdk_wayland_surface_set_skip_taskbar_hint;
-  impl_class->set_skip_pager_hint = gdk_wayland_surface_set_skip_pager_hint;
-  impl_class->set_urgency_hint = gdk_wayland_surface_set_urgency_hint;
-  impl_class->set_geometry_hints = gdk_wayland_surface_set_geometry_hints;
-  impl_class->set_title = gdk_wayland_surface_set_title;
-  impl_class->set_role = gdk_wayland_surface_set_role;
-  impl_class->set_startup_id = gdk_wayland_surface_set_startup_id;
-  impl_class->set_transient_for = gdk_wayland_surface_set_transient_for;
-  impl_class->get_frame_extents = gdk_wayland_surface_get_frame_extents;
-  impl_class->set_accept_focus = gdk_wayland_surface_set_accept_focus;
-  impl_class->set_focus_on_map = gdk_wayland_surface_set_focus_on_map;
-  impl_class->set_icon_list = gdk_wayland_surface_set_icon_list;
-  impl_class->set_icon_name = gdk_wayland_surface_set_icon_name;
-  impl_class->iconify = gdk_wayland_surface_iconify;
-  impl_class->deiconify = gdk_wayland_surface_deiconify;
-  impl_class->stick = gdk_wayland_surface_stick;
-  impl_class->unstick = gdk_wayland_surface_unstick;
-  impl_class->maximize = gdk_wayland_surface_maximize;
-  impl_class->unmaximize = gdk_wayland_surface_unmaximize;
-  impl_class->fullscreen = gdk_wayland_surface_fullscreen;
-  impl_class->fullscreen_on_monitor = gdk_wayland_surface_fullscreen_on_monitor;
-  impl_class->unfullscreen = gdk_wayland_surface_unfullscreen;
-  impl_class->set_keep_above = gdk_wayland_surface_set_keep_above;
-  impl_class->set_keep_below = gdk_wayland_surface_set_keep_below;
-  impl_class->get_group = gdk_wayland_surface_get_group;
-  impl_class->set_group = gdk_wayland_surface_set_group;
-  impl_class->set_decorations = gdk_wayland_surface_set_decorations;
-  impl_class->get_decorations = gdk_wayland_surface_get_decorations;
-  impl_class->set_functions = gdk_wayland_surface_set_functions;
-  impl_class->begin_resize_drag = gdk_wayland_surface_begin_resize_drag;
-  impl_class->begin_move_drag = gdk_wayland_surface_begin_move_drag;
-  impl_class->set_opacity = gdk_wayland_surface_set_opacity;
-  impl_class->destroy_notify = gdk_wayland_surface_destroy_notify;
-  impl_class->register_dnd = _gdk_wayland_surface_register_dnd;
-  impl_class->drag_begin = _gdk_wayland_surface_drag_begin;
-  impl_class->get_scale_factor = gdk_wayland_surface_get_scale_factor;
-  impl_class->set_opaque_region = gdk_wayland_surface_set_opaque_region;
-  impl_class->set_shadow_width = gdk_wayland_surface_set_shadow_width;
-  impl_class->show_window_menu = gdk_wayland_surface_show_window_menu;
-  impl_class->create_gl_context = gdk_wayland_surface_create_gl_context;
-  impl_class->supports_edge_constraints = gdk_wayland_surface_supports_edge_constraints;
-
-  signals[COMMITTED] = g_signal_new (g_intern_static_string ("committed"),
-                                     G_TYPE_FROM_CLASS (object_class),
-                                     G_SIGNAL_RUN_LAST,
-                                     0,
-                                     NULL, NULL, NULL,
-                                     G_TYPE_NONE, 0);
-}
-
-void
-_gdk_wayland_surface_set_grab_seat (GdkSurface *window,
-                                   GdkSeat   *seat)
-{
-  GdkSurfaceImplWayland *impl;
-
-  g_return_if_fail (window != NULL);
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  impl->grab_input_seat = seat;
-}
-
-/**
- * gdk_wayland_surface_new_subsurface: (constructor)
- * @display: the display to create the window on
- * @position: position relative to the transient window
- *
- * Creates a new subsurface window.
- *
- * Returns: (transfer full): the new #GdkSurface
- **/
-GdkSurface *
-gdk_wayland_surface_new_subsurface (GdkDisplay         *display,
-                                   const GdkRectangle *position)
-{
-  GdkSurfaceAttr attr;
-
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-  g_return_val_if_fail (position != NULL, NULL);
-
-  attr.wclass = GDK_INPUT_OUTPUT;
-  attr.x = position->x;
-  attr.y = position->y;
-  attr.width = position->width;
-  attr.height = position->height;
-  attr.window_type = GDK_SURFACE_SUBSURFACE;
-
-  return gdk_surface_new (display, NULL, &attr);
-}
-
-/**
- * gdk_wayland_surface_get_wl_surface:
- * @window: (type GdkWaylandSurface): a #GdkSurface
- *
- * Returns the Wayland surface of a #GdkSurface.
- *
- * Returns: (transfer none): a Wayland wl_surface
- */
-struct wl_surface *
-gdk_wayland_surface_get_wl_surface (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), NULL);
-
-  return GDK_SURFACE_IMPL_WAYLAND (window->impl)->display_server.wl_surface;
-}
-
-struct wl_output *
-gdk_wayland_surface_get_wl_output (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), NULL);
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  /* We pick the head of the list as this is the last entered output */
-  if (impl->display_server.outputs)
-    return (struct wl_output *) impl->display_server.outputs->data;
-
-  return NULL;
-}
-
-static struct wl_egl_window *
-gdk_wayland_surface_get_wl_egl_window (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (impl->display_server.egl_window == NULL)
-    {
-      impl->display_server.egl_window =
-        wl_egl_window_create (impl->display_server.wl_surface,
-                              impl->wrapper->width * impl->scale,
-                              impl->wrapper->height * impl->scale);
-      wl_surface_set_buffer_scale (impl->display_server.wl_surface, impl->scale);
-    }
-
-  return impl->display_server.egl_window;
-}
-
-EGLSurface
-gdk_wayland_surface_get_egl_surface (GdkSurface *window,
-                                    EGLConfig  config)
-{
-  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  GdkSurfaceImplWayland *impl;
-  struct wl_egl_window *egl_window;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), NULL);
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (impl->egl_surface == NULL)
-    {
-      egl_window = gdk_wayland_surface_get_wl_egl_window (window);
-
-      impl->egl_surface =
-        eglCreateWindowSurface (display->egl_display, config, egl_window, NULL);
-    }
-
-  return impl->egl_surface;
-}
-
-EGLSurface
-gdk_wayland_surface_get_dummy_egl_surface (GdkSurface *window,
-                                          EGLConfig  config)
-{
-  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  GdkSurfaceImplWayland *impl;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), NULL);
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (impl->dummy_egl_surface == NULL)
-    {
-      impl->display_server.dummy_egl_window =
-        wl_egl_window_create (impl->display_server.wl_surface, 1, 1);
-
-      impl->dummy_egl_surface =
-        eglCreateWindowSurface (display->egl_display, config, impl->display_server.dummy_egl_window, NULL);
-    }
-
-  return impl->dummy_egl_surface;
-}
-
-struct gtk_surface1 *
-gdk_wayland_surface_get_gtk_surface (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), NULL);
-
-  return GDK_SURFACE_IMPL_WAYLAND (window->impl)->display_server.gtk_surface;
-}
-
-/**
- * gdk_wayland_surface_set_use_custom_surface:
- * @window: (type GdkWaylandSurface): a #GdkSurface
- *
- * Marks a #GdkSurface as a custom Wayland surface. The application is
- * expected to register the surface as some type of surface using
- * some Wayland interface.
- *
- * A good example would be writing a panel or on-screen-keyboard as an
- * out-of-process helper - as opposed to having those in the compositor
- * process. In this case the underlying surface isn’t an xdg_shell
- * surface and the panel or OSK client need to identify the wl_surface
- * as a panel or OSK to the compositor. The assumption is that the
- * compositor will expose a private interface to the special client
- * that lets the client identify the wl_surface as a panel or such.
- *
- * This function should be called before a #GdkSurface is shown. This is
- * best done by connecting to the #GtkWidget::realize signal:
- *
- * |[<!-- language="C" -->
- *   static void
- *   widget_realize_cb (GtkWidget *widget)
- *   {
- *     GdkSurface *window;
- *     struct wl_surface *surface;
- *     struct input_panel_surface *ip_surface;
- *
- *     window = gtk_widget_get_window (widget);
- *     gdk_wayland_surface_set_custom_surface (window);
- *
- *     surface = gdk_wayland_surface_get_wl_surface (window);
- *     ip_surface = input_panel_get_input_panel_surface (input_panel, surface);
- *     input_panel_surface_set_panel (ip_surface);
- *   }
- *
- *   static void
- *   setup_window (GtkWindow *window)
- *   {
- *     g_signal_connect (window, "realize", G_CALLBACK (widget_realize_cb), NULL);
- *   }
- * ]|
- */
-void
-gdk_wayland_surface_set_use_custom_surface (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl;
-
-  g_return_if_fail (GDK_IS_WAYLAND_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (!impl->display_server.wl_surface)
-    gdk_wayland_surface_create_surface (window);
-
-  impl->use_custom_surface = TRUE;
-}
-
-static void
-maybe_set_gtk_surface_dbus_properties (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  if (impl->application.was_set)
-    return;
-
-  if (impl->application.application_id == NULL &&
-      impl->application.app_menu_path == NULL &&
-      impl->application.menubar_path == NULL &&
-      impl->application.window_object_path == NULL &&
-      impl->application.application_object_path == NULL &&
-      impl->application.unique_bus_name == NULL)
-    return;
-
-  gdk_wayland_surface_init_gtk_surface (window);
-  if (impl->display_server.gtk_surface == NULL)
-    return;
-
-  gtk_surface1_set_dbus_properties (impl->display_server.gtk_surface,
-                                    impl->application.application_id,
-                                    impl->application.app_menu_path,
-                                    impl->application.menubar_path,
-                                    impl->application.window_object_path,
-                                    impl->application.application_object_path,
-                                    impl->application.unique_bus_name);
-  impl->application.was_set = TRUE;
-}
-
-void
-gdk_wayland_surface_set_dbus_properties_libgtk_only (GdkSurface  *window,
-                                                    const char *application_id,
-                                                    const char *app_menu_path,
-                                                    const char *menubar_path,
-                                                    const char *window_object_path,
-                                                    const char *application_object_path,
-                                                    const char *unique_bus_name)
-{
-  GdkSurfaceImplWayland *impl;
-
-  g_return_if_fail (GDK_IS_WAYLAND_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  impl->application.application_id = g_strdup (application_id);
-  impl->application.app_menu_path = g_strdup (app_menu_path);
-  impl->application.menubar_path = g_strdup (menubar_path);
-  impl->application.window_object_path = g_strdup (window_object_path);
-  impl->application.application_object_path =
-    g_strdup (application_object_path);
-  impl->application.unique_bus_name = g_strdup (unique_bus_name);
-
-  maybe_set_gtk_surface_dbus_properties (window);
-}
-
-void
-_gdk_wayland_surface_offset_next_wl_buffer (GdkSurface *window,
-                                           int        x,
-                                           int        y)
-{
-  GdkSurfaceImplWayland *impl;
-
-  g_return_if_fail (GDK_IS_WAYLAND_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  impl->pending_buffer_offset_x = x;
-  impl->pending_buffer_offset_y = y;
-}
-
-static void
-xdg_exported_handle (void                    *data,
-                     struct zxdg_exported_v1 *zxdg_exported_v1,
-                     const char              *handle)
-{
-  GdkSurface *window = data;
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  impl->exported.callback (window, handle, impl->exported.user_data);
-  g_clear_pointer (&impl->exported.user_data,
-                   impl->exported.destroy_func);
-}
-
-static const struct zxdg_exported_v1_listener xdg_exported_listener = {
-  xdg_exported_handle
-};
-
-/**
- * GdkWaylandSurfaceExported:
- * @window: the #GdkSurface that is exported
- * @handle: the handle
- * @user_data: user data that was passed to gdk_wayland_surface_export_handle()
- *
- * Callback that gets called when the handle for a window has been
- * obtained from the Wayland compositor. The handle can be passed
- * to other processes, for the purpose of marking windows as transient
- * for out-of-process surfaces.
- */
-
-static gboolean
-gdk_wayland_surface_is_exported (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  return !!impl->display_server.xdg_exported;
-}
-
-/**
- * gdk_wayland_surface_export_handle:
- * @window: the #GdkSurface to obtain a handle for
- * @callback: callback to call with the handle
- * @user_data: user data for @callback
- * @destroy_func: destroy notify for @user_data
- *
- * Asynchronously obtains a handle for a surface that can be passed
- * to other processes. When the handle has been obtained, @callback
- * will be called.
- *
- * It is an error to call this function on a window that is already
- * exported.
- *
- * When the handle is no longer needed, gdk_wayland_surface_unexport_handle()
- * should be called to clean up resources.
- *
- * The main purpose for obtaining a handle is to mark a surface
- * from another window as transient for this one, see
- * gdk_wayland_surface_set_transient_for_exported().
- *
- * Note that this API depends on an unstable Wayland protocol,
- * and thus may require changes in the future.
- *
- * Return value: %TRUE if the handle has been requested, %FALSE if
- *     an error occurred.
- */
-gboolean
-gdk_wayland_surface_export_handle (GdkSurface                *window,
-                                  GdkWaylandSurfaceExported  callback,
-                                  gpointer                  user_data,
-                                  GDestroyNotify            destroy_func)
-{
-  GdkSurfaceImplWayland *impl;
-  GdkWaylandDisplay *display_wayland;
-  GdkDisplay *display = gdk_surface_get_display (window);
-  struct zxdg_exported_v1 *xdg_exported;
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), FALSE);
-  g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  display_wayland = GDK_WAYLAND_DISPLAY (display);
-
-  g_return_val_if_fail (!impl->display_server.xdg_exported, FALSE);
-
-  if (!display_wayland->xdg_exporter)
-    {
-      g_warning ("Server is missing xdg_foreign support");
-      return FALSE;
-    }
-
-  xdg_exported = zxdg_exporter_v1_export (display_wayland->xdg_exporter,
-                                          impl->display_server.wl_surface);
-  zxdg_exported_v1_add_listener (xdg_exported,  &xdg_exported_listener, window);
-
-  impl->display_server.xdg_exported = xdg_exported;
-  impl->exported.callback = callback;
-  impl->exported.user_data = user_data;
-  impl->exported.destroy_func = destroy_func;
-
-  return TRUE;
-}
-
-/**
- * gdk_wayland_surface_unexport_handle:
- * @window: the #GdkSurface to unexport
- *
- * Destroys the handle that was obtained with
- * gdk_wayland_surface_export_handle().
- *
- * It is an error to call this function on a window that
- * does not have a handle.
- *
- * Note that this API depends on an unstable Wayland protocol,
- * and thus may require changes in the future.
- */
-void
-gdk_wayland_surface_unexport_handle (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl;
-
-  g_return_if_fail (GDK_IS_WAYLAND_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  g_return_if_fail (impl->display_server.xdg_exported);
-
-  g_clear_pointer (&impl->display_server.xdg_exported,
-                   zxdg_exported_v1_destroy);
-  g_clear_pointer (&impl->exported.user_data,
-                   impl->exported.destroy_func);
-}
-
-static void
-unset_transient_for_exported (GdkSurface *window)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-
-  g_clear_pointer (&impl->imported_transient_for, zxdg_imported_v1_destroy);
-}
-
-static void
-xdg_imported_destroyed (void                    *data,
-                        struct zxdg_imported_v1 *zxdg_imported_v1)
-{
-  GdkSurface *window = data;
-
-  unset_transient_for_exported (window);
-}
-
-static const struct zxdg_imported_v1_listener xdg_imported_listener = {
-  xdg_imported_destroyed,
-};
-
-/**
- * gdk_wayland_surface_set_transient_for_exported:
- * @window: the #GdkSurface to make as transient
- * @parent_handle_str: an exported handle for a surface
- *
- * Marks @window as transient for the surface to which the given
- * @parent_handle_str refers. Typically, the handle will originate
- * from a gdk_wayland_surface_export_handle() call in another process.
- *
- * Note that this API depends on an unstable Wayland protocol,
- * and thus may require changes in the future.
- *
- * Return value: %TRUE if the window has been marked as transient,
- *     %FALSE if an error occurred.
- */
-gboolean
-gdk_wayland_surface_set_transient_for_exported (GdkSurface *window,
-                                               char      *parent_handle_str)
-{
-  GdkSurfaceImplWayland *impl;
-  GdkWaylandDisplay *display_wayland;
-  GdkDisplay *display = gdk_surface_get_display (window);
-
-  g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (window), FALSE);
-  g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
-  g_return_val_if_fail (!should_map_as_subsurface (window) &&
-                        !should_map_as_popup (window), FALSE);
-
-  impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  display_wayland = GDK_WAYLAND_DISPLAY (display);
-
-  if (!display_wayland->xdg_importer)
-    {
-      g_warning ("Server is missing xdg_foreign support");
-      return FALSE;
-    }
-
-  gdk_surface_set_transient_for (window, NULL);
-
-  impl->imported_transient_for =
-    zxdg_importer_v1_import (display_wayland->xdg_importer, parent_handle_str);
-  zxdg_imported_v1_add_listener (impl->imported_transient_for,
-                                 &xdg_imported_listener,
-                                 window);
-
-  gdk_wayland_surface_sync_parent_of_imported (window);
-
-  return TRUE;
-}
-
-static struct zwp_keyboard_shortcuts_inhibitor_v1 *
-gdk_wayland_surface_get_inhibitor (GdkSurfaceImplWayland *impl,
-                                  struct wl_seat *seat)
-{
-  return g_hash_table_lookup (impl->shortcuts_inhibitors, seat);
-}
-
-void
-gdk_wayland_surface_inhibit_shortcuts (GdkSurface *window,
-                                      GdkSeat   *gdk_seat)
-{
-  GdkSurfaceImplWayland *impl= GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (window));
-  struct wl_surface *surface = impl->display_server.wl_surface;
-  struct wl_seat *seat = gdk_wayland_seat_get_wl_seat (gdk_seat);
-  struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
-
-  if (display->keyboard_shortcuts_inhibit == NULL)
-    return;
-
-  if (gdk_wayland_surface_get_inhibitor (impl, seat))
-    return; /* Already inhibitted */
-
-  inhibitor =
-      zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts (
-          display->keyboard_shortcuts_inhibit, surface, seat);
-
-  g_hash_table_insert (impl->shortcuts_inhibitors, seat, inhibitor);
-}
-
-void
-gdk_wayland_surface_restore_shortcuts (GdkSurface *window,
-                                      GdkSeat   *gdk_seat)
-{
-  GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (window->impl);
-  struct wl_seat *seat = gdk_wayland_seat_get_wl_seat (gdk_seat);
-  struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
-
-  inhibitor = gdk_wayland_surface_get_inhibitor (impl, seat);
-  if (inhibitor == NULL)
-    return; /* Not inhibitted */
-
-  zwp_keyboard_shortcuts_inhibitor_v1_destroy (inhibitor);
-  g_hash_table_remove (impl->shortcuts_inhibitors, seat);
-}
-
index fec3d2c74e6e0256bf6f10f6478681ce3815b5a7..6390e57c19e0ca9a1d3b6196f792f978161fcb6b 100644 (file)
@@ -12,7 +12,7 @@ gdk_wayland_sources = files([
   'gdkprimary-wayland.c',
   'gdkselection-wayland.c',
   'gdkvulkancontext-wayland.c',
-  'gdkwindow-wayland.c',
+  'gdksurface-wayland.c',
   'wm-button-layout-translation.c',
 ])
 
@@ -21,7 +21,7 @@ gdk_wayland_public_headers = files([
   'gdkwaylanddisplay.h',
   'gdkwaylandglcontext.h',
   'gdkwaylandmonitor.h',
-  'gdkwaylandwindow.h'
+  'gdkwaylandsurface.h'
 ])
 
 install_headers(gdk_wayland_public_headers, subdir: 'gtk-4.0/gdk/wayland/')
index adeec0d8b09a17e07f7a2b50c29623538eda7bc6..8e83cfae303a562fca85da4d1c8f63fcbaaed426 100644 (file)
@@ -934,7 +934,7 @@ _gdk_win32_display_get_maximal_cursor_size (GdkDisplay *display,
 
 /* Convert a pixbuf to an HICON (or HCURSOR).  Supports alpha under
  * Windows XP, thresholds alpha otherwise.  Also used from
- * gdkwindow-win32.c for creating application icons.
+ * gdksurface-win32.c for creating application icons.
  */
 
 static HBITMAP
index f5658e137bf34005d9daa729d7582acf9c8e8ac6..95f6fdd871160bcbca788475714f06dd303af974 100644 (file)
@@ -17,7 +17,7 @@
 
 #include "config.h"
 
-#include <gdk/gdkwindow.h>
+#include <gdk/gdksurface.h>
 
 #include <windowsx.h>
 #include <objbase.h>
index 580506a971c36390933bf2b8bcb038c0df0d8d6a..86218dc02c2631f6dc24684855733a6d920b7ab6 100644 (file)
@@ -17,7 +17,7 @@
 
 #include "config.h"
 
-#include <gdk/gdkwindow.h>
+#include <gdk/gdksurface.h>
 
 #include <windowsx.h>
 #include <objbase.h>
index a8a41785c793d76a033749df7fcb68ae7b687158..73bf2b1773b31bf6ca3af9a14b4fcd56aa573883 100644 (file)
@@ -17,7 +17,7 @@
 
 #include "config.h"
 
-#include <gdk/gdkwindow.h>
+#include <gdk/gdksurface.h>
 
 #include <windowsx.h>
 #include <objbase.h>
index 47891e6a0fef2af0f4ad8dde5d1cb17b98b5f667..e546e4b1be3ab89ed792d7e2910446193187f917 100644 (file)
@@ -28,7 +28,7 @@
 #include "gdkglcontext-win32.h"
 #include "gdkwin32display.h"
 #include "gdkwin32screen.h"
-#include "gdkwin32window.h"
+#include "gdkwin32surface.h"
 #include "gdkmonitor-win32.h"
 #include "gdkwin32.h"
 #include "gdkvulkancontext-win32.h"
index d40608096821aaaeea2616e0da9cc9fce9cd4b68..ed3db37eac8c12344b5cb51ac6574e301d9bb540 100644 (file)
@@ -23,7 +23,7 @@
 #include "config.h"
 
 #include "gdkprivate-win32.h"
-#include "gdkwindow-win32.h"
+#include "gdksurface-win32.h"
 #include "gdkglcontext-win32.h"
 #include "gdkdisplay-win32.h"
 
 #include "gdkwin32glcontext.h"
 #include "gdkwin32misc.h"
 #include "gdkwin32screen.h"
-#include "gdkwin32window.h"
+#include "gdkwin32surface.h"
 
 #include "gdkglcontext.h"
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkinternals.h"
 #include "gdkintl.h"
 
index 77b656592ac1cd1a068c5431ae56ad44b1da86b8..85496795596be429301b092c1071d38a988ce61b 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "gdkglcontextprivate.h"
 #include "gdkdisplayprivate.h"
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkinternals.h"
 
 G_BEGIN_DECLS
index 8249a60b65ecdc41da7af4ccac778fcd8163594b..f22fa696345e5093c59a7b2381d07463f76d7751 100644 (file)
@@ -35,7 +35,7 @@
 #endif
 
 #include <gdk/gdkcursorprivate.h>
-#include <gdk/win32/gdkwindow-win32.h>
+#include <gdk/win32/gdksurface-win32.h>
 #include <gdk/win32/gdkwin32display.h>
 #include <gdk/win32/gdkwin32screen.h>
 #include <gdk/win32/gdkwin32keys.h>
diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c
new file mode 100644 (file)
index 0000000..f41534f
--- /dev/null
@@ -0,0 +1,5959 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 1998-2004 Tor Lillqvist
+ * Copyright (C) 2001-2011 Hans Breuer
+ * Copyright (C) 2007-2009 Cody Russell
+ *
+ * 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+
+#include "gdk.h"
+#include "gdksurfaceimpl.h"
+#include "gdkprivate-win32.h"
+#include "gdkdeviceprivate.h"
+#include "gdkdevicemanager-win32.h"
+#include "gdkenumtypes.h"
+#include "gdkwin32.h"
+#include "gdkdisplayprivate.h"
+#include "gdkmonitorprivate.h"
+#include "gdkwin32surface.h"
+#include "gdkglcontext-win32.h"
+#include "gdkdisplay-win32.h"
+
+#include <cairo-win32.h>
+#include <dwmapi.h>
+#include <math.h>
+#include "fallback-c89.c"
+
+static void gdk_surface_impl_win32_init       (GdkSurfaceImplWin32      *window);
+static void gdk_surface_impl_win32_class_init (GdkSurfaceImplWin32Class *klass);
+static void gdk_surface_impl_win32_finalize   (GObject                 *object);
+
+static gpointer parent_class = NULL;
+static GSList *modal_window_stack = NULL;
+
+static const cairo_user_data_key_t gdk_win32_cairo_key;
+typedef struct _FullscreenInfo FullscreenInfo;
+
+struct _FullscreenInfo
+{
+  RECT  r;
+  guint hint_flags;
+  LONG  style;
+};
+
+struct _AeroSnapEdgeRegion
+{
+  /* The rectangle along the edge of the desktop
+   * that allows application of the snap transformation.
+   */
+  GdkRectangle edge;
+
+  /* A subregion of the "edge". When the pointer hits
+   * this region, the transformation is revealed.
+   * Usually it is 1-pixel thick and is located at the
+   * very edge of the screen. When there's a toolbar
+   * at that edge, the "trigger" and the "edge" regions
+   * are extended to cover that toolbar.
+   */
+  GdkRectangle trigger;
+};
+
+typedef struct _AeroSnapEdgeRegion AeroSnapEdgeRegion;
+
+/* Use this for hWndInsertAfter (2nd argument to SetWindowPos()) if
+ * SWP_NOZORDER flag is used. Otherwise it's unobvious why a particular
+ * argument is used. Using NULL is misleading, because
+ * NULL is equivalent to HWND_TOP.
+ */
+#define SWP_NOZORDER_SPECIFIED HWND_TOP
+
+/* Size of the regions at the edges of the desktop where
+ * snapping can take place (in pixels)
+ */
+#define AEROSNAP_REGION_THICKNESS (20)
+/* Size of the subregions that actually trigger the snapping prompt
+ * (in pixels).
+ */
+#define AEROSNAP_REGION_TRIGGER_THICKNESS (1)
+
+/* The gap between the snap indicator and the edge of the work area
+ * (in pixels).
+ */
+#define AEROSNAP_INDICATOR_EDGE_GAP (10)
+
+/* Width of the outline of the snap indicator
+ * (in pixels).
+ */
+#define AEROSNAP_INDICATOR_LINE_WIDTH (3.0)
+
+/* Corner radius of the snap indicator.
+ */
+#define AEROSNAP_INDICATOR_CORNER_RADIUS (3.0)
+
+/* The time it takes for snap indicator to expand/shrink
+ * from current window size to future position of the
+ * snapped window (in microseconds).
+ */
+#define AEROSNAP_INDICATOR_ANIMATION_DURATION (200 * 1000)
+
+/* Opacity if the snap indicator. */
+#define AEROSNAP_INDICATOR_OPACITY (0.5)
+
+/* The interval between snap indicator redraws (in milliseconds).
+ * 16 is ~ 1/60 of a second, for ~60 FPS.
+ */
+#define AEROSNAP_INDICATOR_ANIMATION_TICK (16)
+
+static gboolean _gdk_surface_get_functions (GdkSurface         *window,
+                                           GdkWMFunction     *functions);
+static HDC     _gdk_win32_impl_acquire_dc (GdkSurfaceImplWin32 *impl);
+static void    _gdk_win32_impl_release_dc (GdkSurfaceImplWin32 *impl);
+
+#define WINDOW_IS_TOPLEVEL(window)                \
+  (GDK_SURFACE_TYPE (window) != GDK_SURFACE_FOREIGN)
+
+struct _GdkWin32Surface {
+  GdkSurface parent;
+};
+
+struct _GdkWin32SurfaceClass {
+  GdkSurfaceClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkWin32Surface, gdk_win32_surface, GDK_TYPE_SURFACE)
+
+static void
+gdk_win32_surface_class_init (GdkWin32SurfaceClass *window_class)
+{
+}
+
+static void
+gdk_win32_surface_init (GdkWin32Surface *window)
+{
+}
+
+
+G_DEFINE_TYPE (GdkSurfaceImplWin32, gdk_surface_impl_win32, GDK_TYPE_SURFACE_IMPL)
+
+GType
+_gdk_surface_impl_win32_get_type (void)
+{
+  static GType object_type = 0;
+
+  if (!object_type)
+    {
+      const GTypeInfo object_info =
+      {
+        sizeof (GdkSurfaceImplWin32Class),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) gdk_surface_impl_win32_class_init,
+        NULL,           /* class_finalize */
+        NULL,           /* class_data */
+        sizeof (GdkSurfaceImplWin32),
+        0,              /* n_preallocs */
+        (GInstanceInitFunc) gdk_surface_impl_win32_init,
+      };
+
+      object_type = g_type_register_static (GDK_TYPE_SURFACE_IMPL,
+                                            "GdkSurfaceImplWin32",
+                                            &object_info, 0);
+    }
+
+  return object_type;
+}
+
+static void
+gdk_surface_impl_win32_init (GdkSurfaceImplWin32 *impl)
+{
+  GdkDisplay *display = gdk_display_get_default ();
+
+  impl->toplevel_window_type = -1;
+  impl->hicon_big = NULL;
+  impl->hicon_small = NULL;
+  impl->hint_flags = 0;
+  impl->type_hint = GDK_SURFACE_TYPE_HINT_NORMAL;
+  impl->transient_owner = NULL;
+  impl->transient_children = NULL;
+  impl->num_transients = 0;
+  impl->changing_state = FALSE;
+  impl->window_scale = 1;
+}
+
+static void
+gdk_surface_impl_win32_finalize (GObject *object)
+{
+  GdkSurface *wrapper;
+  GdkSurfaceImplWin32 *window_impl;
+
+  g_return_if_fail (GDK_IS_SURFACE_IMPL_WIN32 (object));
+
+  window_impl = GDK_SURFACE_IMPL_WIN32 (object);
+
+  wrapper = window_impl->wrapper;
+
+  if (!GDK_SURFACE_DESTROYED (wrapper))
+    {
+      gdk_win32_handle_table_remove (window_impl->handle);
+    }
+
+  g_clear_pointer (&window_impl->snap_stash, g_free);
+  g_clear_pointer (&window_impl->snap_stash_int, g_free);
+
+  if (window_impl->hicon_big != NULL)
+    {
+      GDI_CALL (DestroyIcon, (window_impl->hicon_big));
+      window_impl->hicon_big = NULL;
+    }
+
+  if (window_impl->hicon_small != NULL)
+    {
+      GDI_CALL (DestroyIcon, (window_impl->hicon_small));
+      window_impl->hicon_small = NULL;
+    }
+
+  g_free (window_impl->decorations);
+
+  if (window_impl->cache_surface)
+    {
+      cairo_surface_destroy (window_impl->cache_surface);
+      window_impl->cache_surface = NULL;
+    }
+
+  if (window_impl->cairo_surface)
+    {
+      cairo_surface_destroy (window_impl->cairo_surface);
+      window_impl->cairo_surface = NULL;
+    }
+
+  g_assert (window_impl->transient_owner == NULL);
+  g_assert (window_impl->transient_children == NULL);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gdk_win32_get_window_client_area_rect (GdkSurface *window,
+                                       gint       scale,
+                                       RECT      *rect)
+{
+  gint x, y, width, height;
+
+  gdk_surface_get_position (window, &x, &y);
+  width = gdk_surface_get_width (window);
+  height = gdk_surface_get_height (window);
+  rect->left = x * scale;
+  rect->top = y * scale;
+  rect->right = rect->left + width * scale;
+  rect->bottom = rect->top + height * scale;
+}
+
+static void
+gdk_win32_surface_get_queued_window_rect (GdkSurface *window,
+                                         RECT      *return_window_rect)
+{
+  RECT window_rect;
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  gdk_win32_get_window_client_area_rect (window, impl->window_scale, &window_rect);
+
+  /* Turn client area into window area */
+  _gdk_win32_adjust_client_rect (window, &window_rect);
+
+  /* Convert GDK screen coordinates to W32 desktop coordinates */
+  window_rect.left -= _gdk_offset_x * impl->window_scale;
+  window_rect.right -= _gdk_offset_x * impl->window_scale;
+  window_rect.top -= _gdk_offset_y * impl->window_scale;
+  window_rect.bottom -= _gdk_offset_y * impl->window_scale;
+
+  *return_window_rect = window_rect;
+}
+
+static void
+gdk_win32_surface_apply_queued_move_resize (GdkSurface *window,
+                                           RECT       window_rect)
+{
+  if (!IsIconic (GDK_SURFACE_HWND (window)))
+    {
+      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+      GDK_NOTE (EVENTS, g_print ("Setting window position ... "));
+
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                               SWP_NOZORDER_SPECIFIED,
+                               window_rect.left, window_rect.top,
+                               window_rect.right - window_rect.left,
+                               window_rect.bottom - window_rect.top,
+                               SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW));
+
+      GDK_NOTE (EVENTS, g_print (" ... set window position\n"));
+
+      return;
+    }
+
+  /* Don't move iconic windows */
+  /* TODO: use SetWindowPlacement() to change non-minimized window position */
+}
+
+static gboolean
+gdk_win32_surface_begin_paint (GdkSurface *window)
+{
+  GdkSurfaceImplWin32 *impl;
+  RECT window_rect;
+
+  if (window == NULL || GDK_SURFACE_DESTROYED (window))
+    return TRUE;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  /* Layered windows are moved *after* repaint.
+   * We supply our own surface, return FALSE to make GDK use it.
+   */
+  if (impl->layered)
+    return FALSE;
+
+  /* FIXME: Possibly remove the following lines when we transition to GL
+   *        drawing fully.  This will probably mean that we won't
+   *        be able to use layered windows, as layered windows seem
+   *        to support only up to OpenGL 1.1, which is not enough for our
+   *        needs here.
+   */
+
+  /* Non-GL windows are moved *after* repaint.
+   * We don't supply our own surface, return TRUE to make GDK create
+   * one by itself.
+   *//*
+  if (!window->current_paint.use_gl)
+    return TRUE;*/
+
+  /* GL windows are moved *before* repaint (otherwise
+   * repainting doesn't work), but if there's no move queued up,
+   * return immediately. Doesn't matter what we return, GDK
+   * will create a surface anyway, as if we returned TRUE.
+   */
+  if (!impl->drag_move_resize_context.native_move_resize_pending)
+    return TRUE;
+
+  impl->drag_move_resize_context.native_move_resize_pending = FALSE;
+
+  /* Get the position/size of the window that GDK wants,
+   * apply it.
+   */
+  gdk_win32_surface_get_queued_window_rect (window, &window_rect);
+  gdk_win32_surface_apply_queued_move_resize (window, window_rect);
+
+  return TRUE;
+}
+
+static void
+gdk_win32_surface_end_paint (GdkSurface *window)
+{
+  /* FIXME: Possibly make gdk_win32_surface_end_paint() a
+   *        no-op stub, like what is done in Wayland, as
+   *        the items here rely on layered window usage,
+   *        when we transition to full GL drawing, as
+   *        layered windows do not support enough GL
+   *        for our needs here
+   */
+  GdkSurfaceImplWin32 *impl;
+  RECT window_rect;
+  HDC hdc;
+  POINT window_position;
+  SIZE window_size;
+  POINT source_point;
+  BLENDFUNCTION blender;
+  cairo_t *cr;
+
+  if (window == NULL || GDK_SURFACE_DESTROYED (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  /* GL windows are moved *before* repaint */
+  /*if (window->current_paint.use_gl)
+    return;*/
+
+  /* No move/resize is queued up, and we don't need to update
+   * the contents of a layered window, so return immediately.
+   */
+  if (!impl->layered &&
+      !impl->drag_move_resize_context.native_move_resize_pending)
+    return;
+
+  impl->drag_move_resize_context.native_move_resize_pending = FALSE;
+
+  /* Get the position/size of the window that GDK wants. */
+  gdk_win32_surface_get_queued_window_rect (window, &window_rect);
+
+  if (!impl->layered)
+    {
+      gdk_win32_surface_apply_queued_move_resize (window, window_rect);
+
+      return;
+    }
+
+  window_position.x = window_rect.left;
+  window_position.y = window_rect.top;
+
+  window_size.cx = window_rect.right - window_rect.left;
+  window_size.cy = window_rect.bottom - window_rect.top;
+
+  cairo_surface_flush (impl->cairo_surface);
+
+  /* we always draw in the top-left corner of the surface */
+  source_point.x = source_point.y = 0;
+
+  blender.BlendOp = AC_SRC_OVER;
+  blender.BlendFlags = 0;
+  blender.AlphaFormat = AC_SRC_ALPHA;
+  blender.SourceConstantAlpha = impl->layered_opacity * 255;
+
+  /* Update cache surface contents */
+  cr = cairo_create (impl->cache_surface);
+
+  cairo_set_source_surface (cr, window->current_paint.surface, 0, 0);
+  gdk_cairo_region (cr, window->current_paint.region);
+  cairo_clip (cr);
+
+  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+  cairo_paint (cr);
+
+  cairo_destroy (cr);
+
+  cairo_surface_flush (impl->cache_surface);
+  hdc = cairo_win32_surface_get_dc (impl->cache_surface);
+
+  /* Don't use UpdateLayeredWindow on minimized windows */
+  if (IsIconic (GDK_SURFACE_HWND (window)))
+    {
+      gdk_win32_surface_apply_queued_move_resize (window, window_rect);
+
+      return;
+    }
+
+  /* Move, resize and redraw layered window in one call */
+  API_CALL (UpdateLayeredWindow, (GDK_SURFACE_HWND (window), NULL,
+                                  &window_position, &window_size,
+                                  hdc, &source_point,
+                                  0, &blender, ULW_ALPHA));
+}
+
+void
+_gdk_win32_adjust_client_rect (GdkSurface *window,
+                              RECT      *rect)
+{
+  LONG style, exstyle;
+
+  style = GetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE);
+  exstyle = GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE);
+  API_CALL (AdjustWindowRectEx, (rect, style, FALSE, exstyle));
+}
+
+gboolean
+_gdk_win32_surface_enable_transparency (GdkSurface *window)
+{
+  GdkSurfaceImplWin32 *impl;
+  DWM_BLURBEHIND blur_behind;
+  HRGN empty_region;
+  HRESULT call_result;
+  HWND parent, thiswindow;
+
+  if (window == NULL || GDK_SURFACE_HWND (window) == NULL)
+    return FALSE;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  /* layered windows don't need blurbehind for transparency */
+  if (impl->layered)
+    return TRUE;
+
+  if (!gdk_display_is_composited (gdk_surface_get_display (window)))
+    return FALSE;
+
+  thiswindow = GDK_SURFACE_HWND (window);
+
+  /* Blurbehind only works on toplevel windows */
+  parent = GetAncestor (thiswindow, GA_PARENT);
+  if (!(GetWindowLong (thiswindow, GWL_STYLE) & WS_POPUP) &&
+      (parent == NULL || parent != GetDesktopWindow ()))
+    return FALSE;
+
+  empty_region = CreateRectRgn (0, 0, -1, -1);
+
+  if (empty_region == NULL)
+    return FALSE;
+
+  memset (&blur_behind, 0, sizeof (blur_behind));
+  blur_behind.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
+  blur_behind.hRgnBlur = empty_region;
+  blur_behind.fEnable = TRUE;
+  call_result = DwmEnableBlurBehindWindow (thiswindow, &blur_behind);
+
+  if (!SUCCEEDED (call_result))
+    g_warning ("%s: %s (%p) failed: %" G_GINT32_MODIFIER "x",
+        G_STRLOC, "DwmEnableBlurBehindWindow", thiswindow, (guint32) call_result);
+
+  DeleteObject (empty_region);
+
+  return SUCCEEDED (call_result);
+}
+
+static const gchar *
+get_default_title (void)
+{
+  const char *title;
+  title = g_get_application_name ();
+  if (!title)
+    title = g_get_prgname ();
+
+  return title;
+}
+
+/* RegisterGdkClass
+ *   is a wrapper function for RegisterWindowClassEx.
+ *   It creates at least one unique class for every
+ *   GdkSurfaceType. If support for single window-specific icons
+ *   is ever needed (e.g Dialog specific), every such window should
+ *   get its own class
+ */
+static ATOM
+RegisterGdkClass (GdkSurfaceType wtype, GdkSurfaceTypeHint wtype_hint)
+{
+  static ATOM klassTOPLEVEL   = 0;
+  static ATOM klassCHILD      = 0;
+  static ATOM klassTEMP       = 0;
+  static ATOM klassTEMPSHADOW = 0;
+  static HICON hAppIcon = NULL;
+  static HICON hAppIconSm = NULL;
+  static WNDCLASSEXW wcl;
+  ATOM klass = 0;
+
+  wcl.cbSize = sizeof (WNDCLASSEX);
+  wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
+                  * on WM_SIZE and WM_MOVE. Flicker, Performance!
+                  */
+  wcl.lpfnWndProc = _gdk_win32_surface_procedure;
+  wcl.cbClsExtra = 0;
+  wcl.cbWndExtra = 0;
+  wcl.hInstance = _gdk_app_hmodule;
+  wcl.hIcon = 0;
+  wcl.hIconSm = 0;
+
+  /* initialize once! */
+  if (0 == hAppIcon && 0 == hAppIconSm)
+    {
+      gchar sLoc [MAX_PATH+1];
+
+      if (0 != GetModuleFileName (_gdk_app_hmodule, sLoc, MAX_PATH))
+        {
+          ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
+
+          if (0 == hAppIcon && 0 == hAppIconSm)
+            {
+              if (0 != GetModuleFileName (_gdk_dll_hinstance, sLoc, MAX_PATH))
+               {
+                 ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
+               }
+            }
+        }
+
+      if (0 == hAppIcon && 0 == hAppIconSm)
+        {
+          hAppIcon = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
+                                GetSystemMetrics (SM_CXICON),
+                                GetSystemMetrics (SM_CYICON), 0);
+          hAppIconSm = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
+                                  GetSystemMetrics (SM_CXSMICON),
+                                  GetSystemMetrics (SM_CYSMICON), 0);
+        }
+    }
+
+  if (0 == hAppIcon)
+    hAppIcon = hAppIconSm;
+  else if (0 == hAppIconSm)
+    hAppIconSm = hAppIcon;
+
+  wcl.lpszMenuName = NULL;
+
+  /* initialize once per class */
+  /*
+   * HB: Setting the background brush leads to flicker, because we
+   * don't get asked how to clear the background. This is not what
+   * we want, at least not for input_only windows ...
+   */
+#define ONCE_PER_CLASS() \
+  wcl.hIcon = CopyIcon (hAppIcon); \
+  wcl.hIconSm = CopyIcon (hAppIconSm); \
+  wcl.hbrBackground = NULL; \
+  wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
+
+  switch (wtype)
+    {
+    case GDK_SURFACE_TOPLEVEL:
+      /* MSDN: CS_OWNDC is needed for OpenGL contexts */
+      wcl.style |= CS_OWNDC;
+      if (0 == klassTOPLEVEL)
+        {
+          wcl.lpszClassName = L"gdkWindowToplevel";
+
+          ONCE_PER_CLASS ();
+          klassTOPLEVEL = RegisterClassExW (&wcl);
+        }
+      klass = klassTOPLEVEL;
+      break;
+
+    case GDK_SURFACE_TEMP:
+      if ((wtype_hint == GDK_SURFACE_TYPE_HINT_MENU) ||
+          (wtype_hint == GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU) ||
+          (wtype_hint == GDK_SURFACE_TYPE_HINT_POPUP_MENU))
+        {
+          if (klassTEMPSHADOW == 0)
+            {
+              wcl.lpszClassName = L"gdkWindowTempShadow";
+              wcl.style |= CS_SAVEBITS;
+              wcl.style |= 0x00020000; /* CS_DROPSHADOW */
+
+              ONCE_PER_CLASS ();
+              klassTEMPSHADOW = RegisterClassExW (&wcl);
+            }
+
+          klass = klassTEMPSHADOW;
+        }
+       else
+        {
+          if (klassTEMP == 0)
+            {
+              wcl.lpszClassName = L"gdkWindowTemp";
+              wcl.style |= CS_SAVEBITS;
+              ONCE_PER_CLASS ();
+              klassTEMP = RegisterClassExW (&wcl);
+            }
+
+          klass = klassTEMP;
+        }
+      break;
+
+    case GDK_SURFACE_CHILD:
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  if (klass == 0)
+    {
+      WIN32_API_FAILED ("RegisterClassExW");
+      g_error ("That is a fatal error");
+    }
+  return klass;
+}
+
+/*
+ * Create native windows.
+ *
+ * With the default Gdk the created windows are mostly toplevel windows.
+ *
+ * Placement of the window is derived from the passed in window,
+ * except for toplevel window where OS/Window Manager placement
+ * is used.
+ *
+ * From attributes the only things used is: colormap, title,
+ * wmclass and type_hint. [1]. We are checking redundant information
+ * and complain if that changes, which would break this implementation
+ * again.
+ *
+ * [1] http://mail.gnome.org/archives/gtk-devel-list/2010-August/msg00214.html
+ */
+void
+_gdk_win32_display_create_window_impl (GdkDisplay    *display,
+                                      GdkSurface     *window,
+                                      GdkSurface     *real_parent,
+                                      GdkEventMask   event_mask,
+                                      GdkSurfaceAttr *attributes)
+{
+  HWND hwndNew;
+  HANDLE hparent;
+  ATOM klass = 0;
+  DWORD dwStyle = 0, dwExStyle;
+  RECT rect;
+  GdkSurfaceImplWin32 *impl;
+  GdkWin32Display *display_win32;
+  const gchar *title;
+  wchar_t *wtitle;
+  gint window_width, window_height;
+  gint offset_x = 0, offset_y = 0;
+  gint x, y, real_x = 0, real_y = 0;
+
+  g_return_if_fail (display == _gdk_display);
+
+  GDK_NOTE (MISC,
+            g_print ("_gdk_surface_impl_new: %s %s\n", (window->window_type == GDK_SURFACE_TOPLEVEL ? "TOPLEVEL" :
+                                                       (window->window_type == GDK_SURFACE_TEMP ? "TEMP" : "???")),
+                                                       (attributes->wclass == GDK_INPUT_OUTPUT ? "" : "input-only")));
+
+  hparent = (real_parent != NULL) ? GDK_SURFACE_HWND (real_parent) : NULL;
+
+  impl = g_object_new (GDK_TYPE_SURFACE_IMPL_WIN32, NULL);
+  impl->wrapper = GDK_SURFACE (window);
+  window->impl = GDK_SURFACE_IMPL (impl);
+
+  impl->layered = FALSE;
+  impl->layered_opacity = 1.0;
+
+  display_win32 = GDK_WIN32_DISPLAY (display);
+  impl->window_scale = _gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL, NULL);
+  impl->unscaled_width = window->width * impl->window_scale;
+  impl->unscaled_height = window->height * impl->window_scale;
+
+  if (!window->input_only)
+    {
+      dwExStyle = 0;
+    }
+  else
+    {
+      /* I very much doubt using WS_EX_TRANSPARENT actually
+       * corresponds to how X11 InputOnly windows work, but it appears
+       * to work well enough for the actual use cases in gtk.
+       */
+      dwExStyle = WS_EX_TRANSPARENT;
+      GDK_NOTE (MISC, g_print ("... GDK_INPUT_ONLY\n"));
+    }
+
+  switch (window->window_type)
+    {
+    case GDK_SURFACE_TOPLEVEL:
+      if (window->parent)
+       {
+         /* The common code warns for this case. */
+         hparent = GetDesktopWindow ();
+       }
+      /* Children of foreign windows aren't toplevel windows */
+      if (real_parent != NULL && GDK_SURFACE_TYPE (real_parent) == GDK_SURFACE_FOREIGN)
+       {
+         dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN;
+       }
+      else
+       {
+         /* MSDN: We need WS_CLIPCHILDREN and WS_CLIPSIBLINGS for GL Context Creation */
+         if (window->window_type == GDK_SURFACE_TOPLEVEL)
+           dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+         else
+           dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
+
+         offset_x = _gdk_offset_x;
+         offset_y = _gdk_offset_y;
+       }
+      break;
+
+    case GDK_SURFACE_TEMP:
+      /* A temp window is not necessarily a top level window */
+      dwStyle = real_parent == NULL ? WS_POPUP : WS_CHILDWINDOW;
+      dwStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+      dwExStyle |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
+      offset_x = _gdk_offset_x;
+      offset_y = _gdk_offset_y;
+      break;
+
+
+    case GDK_SURFACE_CHILD:
+    default:
+      g_assert_not_reached ();
+    }
+
+  rect.left = window->x * impl->window_scale;
+  rect.top = window->y * impl->window_scale;
+  rect.right = rect.left + window->width * impl->window_scale;
+  rect.bottom = rect.top + window->height * impl->window_scale;
+
+  AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
+
+  real_x = (window->x - offset_x) * impl->window_scale;
+  real_y = (window->y - offset_y) * impl->window_scale;
+
+  if (window->window_type == GDK_SURFACE_TOPLEVEL)
+    {
+      /* We initially place it at default so that we can get the
+         default window positioning if we want */
+      x = y = CW_USEDEFAULT;
+    }
+  else
+         {
+      /* TEMP, FOREIGN: Put these where requested */
+      x = real_x;
+      y = real_y;
+    }
+
+  window_width = rect.right - rect.left;
+  window_height = rect.bottom - rect.top;
+
+  title = get_default_title ();
+  if (!title || !*title)
+    title = "";
+
+  impl->native_event_mask = GDK_STRUCTURE_MASK | event_mask;
+
+  if (impl->type_hint == GDK_SURFACE_TYPE_HINT_UTILITY)
+    dwExStyle |= WS_EX_TOOLWINDOW;
+
+  /* WS_EX_TRANSPARENT means "try draw this window last, and ignore input".
+   * It's the last part we're after. We don't want DND indicator to accept
+   * input, because that will make it a potential drop target, and if it's
+   * under the mouse cursor, this will kill any DND.
+   */
+  if (impl->type_hint == GDK_SURFACE_TYPE_HINT_DND)
+    dwExStyle |= WS_EX_TRANSPARENT;
+
+  klass = RegisterGdkClass (window->window_type, impl->type_hint);
+
+  wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
+
+  hwndNew = CreateWindowExW (dwExStyle,
+                            MAKEINTRESOURCEW (klass),
+                            wtitle,
+                            dwStyle,
+                            x,
+                            y,
+                            window_width, window_height,
+                            hparent,
+                            NULL,
+                            _gdk_app_hmodule,
+                            window);
+  if (GDK_SURFACE_HWND (window) != hwndNew)
+    {
+      g_warning ("gdk_surface_new: gdk_event_translate::WM_CREATE (%p, %p) HWND mismatch.",
+                GDK_SURFACE_HWND (window),
+                hwndNew);
+
+      /* HB: IHMO due to a race condition the handle was increased by
+       * one, which causes much trouble. Because I can't find the
+       * real bug, try to workaround it ...
+       * To reproduce: compile with MSVC 5, DEBUG=1
+       */
+# if 0
+      gdk_win32_handle_table_remove (GDK_SURFACE_HWND (window));
+      GDK_SURFACE_HWND (window) = hwndNew;
+      gdk_win32_handle_table_insert (&GDK_SURFACE_HWND (window), window);
+# else
+      /* the old behaviour, but with warning */
+      impl->handle = hwndNew;
+# endif
+
+    }
+
+  GetWindowRect (GDK_SURFACE_HWND (window), &rect);
+  impl->initial_x = rect.left;
+  impl->initial_y = rect.top;
+
+  /* Now we know the initial position, move to actually specified position */
+  if (real_x != x || real_y != y)
+    {
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                SWP_NOZORDER_SPECIFIED,
+                real_x, real_y, 0, 0,
+                SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
+    }
+
+  g_object_ref (window);
+  gdk_win32_handle_table_insert (&GDK_SURFACE_HWND (window), window);
+
+  GDK_NOTE (MISC, g_print ("... \"%s\" %dx%d@%+d%+d %p = %p\n",
+                          title,
+                          window_width, window_height,
+                          window->x - offset_x,
+                          window->y - offset_y,
+                          hparent,
+                          GDK_SURFACE_HWND (window)));
+
+  /* Add window handle to title */
+  GDK_NOTE (MISC_OR_EVENTS, gdk_surface_set_title (window, title));
+
+  g_free (wtitle);
+
+  if (impl->handle == NULL)
+    {
+      WIN32_API_FAILED ("CreateWindowExW");
+      g_object_unref (window);
+      return;
+    }
+
+//  if (!from_set_skip_taskbar_hint && window->window_type == GDK_SURFACE_TEMP)
+//    gdk_surface_set_skip_taskbar_hint (window, TRUE);
+
+  _gdk_win32_surface_enable_transparency (window);
+}
+
+GdkSurface *
+gdk_win32_surface_foreign_new_for_display (GdkDisplay *display,
+                                          HWND        anid)
+{
+  GdkSurface *window;
+  GdkSurfaceImplWin32 *impl;
+
+  HANDLE parent;
+  RECT rect;
+  POINT point;
+
+  if ((window = gdk_win32_surface_lookup_for_display (display, anid)) != NULL)
+    return g_object_ref (window);
+
+  window = _gdk_display_create_window (display);
+  window->impl = g_object_new (GDK_TYPE_SURFACE_IMPL_WIN32, NULL);
+  window->impl_window = window;
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+  impl->wrapper = window;
+  parent = GetParent (anid);
+
+  /* Always treat foreigns as toplevels */
+  window->parent = NULL;
+
+  GetClientRect ((HWND) anid, &rect);
+  point.x = rect.left;
+  point.y = rect.right;
+  ClientToScreen ((HWND) anid, &point);
+  if (parent != GetDesktopWindow ())
+    ScreenToClient (parent, &point);
+  window->x = point.x / impl->window_scale;
+  window->y = point.y / impl->window_scale;
+  impl->unscaled_width = rect.right - rect.left;
+  impl->unscaled_height = rect.bottom - rect.top;
+  window->width = (impl->unscaled_width + impl->window_scale - 1) / impl->window_scale;
+  window->height = (impl->unscaled_height + impl->window_scale - 1) / impl->window_scale;
+  window->window_type = GDK_SURFACE_FOREIGN;
+  window->destroyed = FALSE;
+  window->event_mask = GDK_ALL_EVENTS_MASK; /* XXX */
+  if (IsWindowVisible ((HWND) anid))
+    window->state &= (~GDK_SURFACE_STATE_WITHDRAWN);
+  else
+    window->state |= GDK_SURFACE_STATE_WITHDRAWN;
+  if (GetWindowLong ((HWND)anid, GWL_EXSTYLE) & WS_EX_TOPMOST)
+    window->state |= GDK_SURFACE_STATE_ABOVE;
+  else
+    window->state &= (~GDK_SURFACE_STATE_ABOVE);
+  window->state &= (~GDK_SURFACE_STATE_BELOW);
+  window->viewable = TRUE;
+
+  GDK_SURFACE_HWND (window) = anid;
+
+  g_object_ref (window);
+  gdk_win32_handle_table_insert (&GDK_SURFACE_HWND (window), window);
+
+  GDK_NOTE (MISC, g_print ("gdk_win32_surface_foreign_new_for_display: %p: %s@%+d%+d\n",
+                          (HWND) anid,
+                          _gdk_win32_surface_description (window),
+                          window->x, window->y));
+
+  return window;
+}
+
+static void
+gdk_win32_surface_destroy (GdkSurface *window,
+                         gboolean   recursing,
+                         gboolean   foreign_destroy)
+{
+  GdkSurfaceImplWin32 *window_impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+  GSList *tmp;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  GDK_NOTE (MISC, g_print ("gdk_win32_surface_destroy: %p\n",
+                          GDK_SURFACE_HWND (window)));
+
+  /* Remove ourself from the modal stack */
+  _gdk_remove_modal_window (window);
+
+  /* Remove all our transient children */
+  tmp = window_impl->transient_children;
+  while (tmp != NULL)
+    {
+      GdkSurface *child = tmp->data;
+      GdkSurfaceImplWin32 *child_impl = GDK_SURFACE_IMPL_WIN32 (GDK_SURFACE (child)->impl);
+
+      child_impl->transient_owner = NULL;
+      tmp = tmp->next;
+    }
+  g_slist_free (window_impl->transient_children);
+  window_impl->transient_children = NULL;
+
+  /* Remove ourself from our transient owner */
+  if (window_impl->transient_owner != NULL)
+    {
+      gdk_surface_set_transient_for (window, NULL);
+    }
+
+  if (!recursing && !foreign_destroy)
+    {
+      window->destroyed = TRUE;
+      DestroyWindow (GDK_SURFACE_HWND (window));
+    }
+}
+
+/* This function is called when the window really gone.
+ */
+static void
+gdk_win32_surface_destroy_notify (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  GDK_NOTE (EVENTS,
+           g_print ("gdk_surface_destroy_notify: %p%s\n",
+                    GDK_SURFACE_HWND (window),
+                    (GDK_SURFACE_DESTROYED (window) ? " (destroyed)" : "")));
+
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      if (GDK_SURFACE_TYPE (window) != GDK_SURFACE_FOREIGN)
+       g_warning ("window %p unexpectedly destroyed",
+                  GDK_SURFACE_HWND (window));
+
+      _gdk_surface_destroy (window, TRUE);
+    }
+
+  gdk_win32_handle_table_remove (GDK_SURFACE_HWND (window));
+  g_object_unref (window);
+}
+
+static void
+get_outer_rect (GdkSurface *window,
+               gint       width,
+               gint       height,
+               RECT      *rect)
+{
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  rect->left = rect->top = 0;
+  rect->right = width * impl->window_scale;
+  rect->bottom = height * impl->window_scale;
+
+  _gdk_win32_adjust_client_rect (window, rect);
+}
+
+static void
+adjust_for_gravity_hints (GdkSurface *window,
+                         RECT      *outer_rect,
+                         gint          *x,
+                         gint          *y)
+{
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  if (impl->hint_flags & GDK_HINT_WIN_GRAVITY)
+    {
+#ifdef G_ENABLE_DEBUG
+      gint orig_x = *x, orig_y = *y;
+#endif
+
+      switch (impl->hints.win_gravity)
+       {
+       case GDK_GRAVITY_NORTH:
+       case GDK_GRAVITY_CENTER:
+       case GDK_GRAVITY_SOUTH:
+         *x -= (outer_rect->right - outer_rect->left / 2) / impl->window_scale;
+         *x += window->width / 2;
+         break;
+
+       case GDK_GRAVITY_SOUTH_EAST:
+       case GDK_GRAVITY_EAST:
+       case GDK_GRAVITY_NORTH_EAST:
+         *x -= (outer_rect->right - outer_rect->left) / impl->window_scale;
+         *x += window->width;
+         break;
+
+       case GDK_GRAVITY_STATIC:
+         *x += outer_rect->left / impl->window_scale;
+         break;
+
+       default:
+         break;
+       }
+
+      switch (impl->hints.win_gravity)
+       {
+       case GDK_GRAVITY_WEST:
+       case GDK_GRAVITY_CENTER:
+       case GDK_GRAVITY_EAST:
+         *y -= ((outer_rect->bottom - outer_rect->top) / 2) / impl->window_scale;
+         *y += window->height / 2;
+         break;
+
+       case GDK_GRAVITY_SOUTH_WEST:
+       case GDK_GRAVITY_SOUTH:
+       case GDK_GRAVITY_SOUTH_EAST:
+         *y -= (outer_rect->bottom - outer_rect->top) / impl->window_scale;
+         *y += window->height;
+         break;
+
+       case GDK_GRAVITY_STATIC:
+         *y += outer_rect->top * impl->window_scale;
+         break;
+
+       default:
+         break;
+       }
+      GDK_NOTE (MISC,
+               (orig_x != *x || orig_y != *y) ?
+               g_print ("adjust_for_gravity_hints: x: %d->%d, y: %d->%d\n",
+                        orig_x, *x, orig_y, *y)
+                 : (void) 0);
+    }
+}
+
+static void
+show_window_internal (GdkSurface *window,
+                      gboolean   already_mapped,
+                     gboolean   deiconify)
+{
+  GdkSurfaceImplWin32 *window_impl;
+  gboolean focus_on_map = FALSE;
+  DWORD exstyle;
+
+  if (window->destroyed)
+    return;
+
+  GDK_NOTE (MISC, g_print ("show_window_internal: %p: %s%s\n",
+                          GDK_SURFACE_HWND (window),
+                          _gdk_win32_surface_state_to_string (window->state),
+                          (deiconify ? " deiconify" : "")));
+
+  /* If asked to show (not deiconify) an withdrawn and iconified
+   * window, do that.
+   */
+  if (!deiconify &&
+      !already_mapped &&
+      (window->state & GDK_SURFACE_STATE_ICONIFIED))
+    {
+      GtkShowWindow (window, SW_SHOWMINNOACTIVE);
+      return;
+    }
+
+  /* If asked to just show an iconified window, do nothing. */
+  if (!deiconify && (window->state & GDK_SURFACE_STATE_ICONIFIED))
+    return;
+
+  /* If asked to deiconify an already noniconified window, do
+   * nothing. (Especially, don't cause the window to rise and
+   * activate. There are different calls for that.)
+   */
+  if (deiconify && !(window->state & GDK_SURFACE_STATE_ICONIFIED))
+    return;
+
+  /* If asked to show (but not raise) a window that is already
+   * visible, do nothing.
+   */
+  if (!deiconify && !already_mapped && IsWindowVisible (GDK_SURFACE_HWND (window)))
+    return;
+
+  /* Other cases */
+
+  if (!already_mapped)
+    focus_on_map = window->focus_on_map;
+
+  exstyle = GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE);
+
+  /* Use SetWindowPos to show transparent windows so automatic redraws
+   * in other windows can be suppressed.
+   */
+  if (exstyle & WS_EX_TRANSPARENT)
+    {
+      UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
+
+      if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP || !focus_on_map)
+       flags |= SWP_NOACTIVATE;
+
+      SetWindowPos (GDK_SURFACE_HWND (window),
+                   SWP_NOZORDER_SPECIFIED, 0, 0, 0, 0, flags);
+
+      return;
+    }
+
+  /* For initial map of "normal" windows we want to emulate WM window
+   * positioning behaviour, which means:
+   * + Use user specified position if GDK_HINT_POS or GDK_HINT_USER_POS
+   * otherwise:
+   * + default to the initial CW_USEDEFAULT placement,
+   *   no matter if the user moved the window before showing it.
+   * + Certain window types and hints have more elaborate positioning
+   *   schemes.
+   */
+  window_impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+  if (!already_mapped &&
+      GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL &&
+      (window_impl->hint_flags & (GDK_HINT_POS | GDK_HINT_USER_POS)) == 0)
+    {
+      gboolean center = FALSE;
+      RECT window_rect, center_on_rect;
+      int x, y;
+
+      x = window_impl->initial_x;
+      y = window_impl->initial_y;
+
+      if (window_impl->type_hint == GDK_SURFACE_TYPE_HINT_SPLASHSCREEN)
+       {
+         HMONITOR monitor;
+         MONITORINFO mi;
+
+         monitor = MonitorFromWindow (GDK_SURFACE_HWND (window), MONITOR_DEFAULTTONEAREST);
+         mi.cbSize = sizeof (mi);
+         if (monitor && GetMonitorInfo (monitor, &mi))
+           center_on_rect = mi.rcMonitor;
+         else
+           {
+             center_on_rect.left = 0;
+             center_on_rect.top = 0;
+             center_on_rect.right = GetSystemMetrics (SM_CXSCREEN);
+             center_on_rect.bottom = GetSystemMetrics (SM_CYSCREEN);
+           }
+         center = TRUE;
+       }
+      else if (window_impl->transient_owner != NULL &&
+              GDK_SURFACE_IS_MAPPED (window_impl->transient_owner))
+       {
+         GdkSurface *owner = window_impl->transient_owner;
+         /* Center on transient parent */
+         center_on_rect.left = (owner->x - _gdk_offset_x) * window_impl->window_scale;
+         center_on_rect.top = (owner->y - _gdk_offset_y) * window_impl->window_scale;
+         center_on_rect.right = center_on_rect.left + owner->width * window_impl->window_scale;
+         center_on_rect.bottom = center_on_rect.top + owner->height * window_impl->window_scale;
+
+         _gdk_win32_adjust_client_rect (GDK_SURFACE (owner), &center_on_rect);
+         center = TRUE;
+       }
+
+      if (center)
+       {
+         window_rect.left = 0;
+         window_rect.top = 0;
+         window_rect.right = window->width * window_impl->window_scale;
+         window_rect.bottom = window->height * window_impl->window_scale;
+         _gdk_win32_adjust_client_rect (window, &window_rect);
+
+         x = center_on_rect.left + ((center_on_rect.right - center_on_rect.left) - (window_rect.right - window_rect.left)) / 2;
+         y = center_on_rect.top + ((center_on_rect.bottom - center_on_rect.top) - (window_rect.bottom - window_rect.top)) / 2;
+       }
+
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                              SWP_NOZORDER_SPECIFIED,
+                              x, y, 0, 0,
+                              SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
+    }
+
+  if (!already_mapped &&
+      GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL)
+    {
+      /* Ensure new windows are fully onscreen */
+      RECT window_rect;
+      HMONITOR monitor;
+      MONITORINFO mi;
+      int x, y;
+
+      GetWindowRect (GDK_SURFACE_HWND (window), &window_rect);
+
+      monitor = MonitorFromWindow (GDK_SURFACE_HWND (window), MONITOR_DEFAULTTONEAREST);
+      mi.cbSize = sizeof (mi);
+      if (monitor && GetMonitorInfo (monitor, &mi))
+       {
+         x = window_rect.left;
+         y = window_rect.top;
+
+         if (window_rect.right > mi.rcWork.right)
+           {
+             window_rect.left -= (window_rect.right - mi.rcWork.right);
+             window_rect.right -= (window_rect.right - mi.rcWork.right);
+           }
+
+         if (window_rect.bottom > mi.rcWork.bottom)
+           {
+             window_rect.top -= (window_rect.bottom - mi.rcWork.bottom);
+             window_rect.bottom -= (window_rect.bottom - mi.rcWork.bottom);
+           }
+
+         if (window_rect.left < mi.rcWork.left)
+           {
+             window_rect.right += (mi.rcWork.left - window_rect.left);
+             window_rect.left += (mi.rcWork.left - window_rect.left);
+           }
+
+         if (window_rect.top < mi.rcWork.top)
+           {
+             window_rect.bottom += (mi.rcWork.top - window_rect.top);
+             window_rect.top += (mi.rcWork.top - window_rect.top);
+           }
+
+         if (x != window_rect.left || y != window_rect.top)
+           API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                                    SWP_NOZORDER_SPECIFIED,
+                                    window_rect.left, window_rect.top, 0, 0,
+                                    SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
+       }
+    }
+
+
+  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
+    {
+      gdk_surface_fullscreen (window);
+    }
+  else if (window->state & GDK_SURFACE_STATE_MAXIMIZED)
+    {
+      GtkShowWindow (window, SW_MAXIMIZE);
+    }
+  else if (window->state & GDK_SURFACE_STATE_ICONIFIED)
+    {
+      if (focus_on_map)
+        GtkShowWindow (window, SW_RESTORE);
+      else
+        GtkShowWindow (window, SW_SHOWNOACTIVATE);
+    }
+  else if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP || !focus_on_map)
+    {
+      if (!IsWindowVisible (GDK_SURFACE_HWND (window)))
+        GtkShowWindow (window, SW_SHOWNOACTIVATE);
+      else
+        GtkShowWindow (window, SW_SHOWNA);
+    }
+  else if (!IsWindowVisible (GDK_SURFACE_HWND (window)))
+    {
+      GtkShowWindow (window, SW_SHOWNORMAL);
+    }
+  else
+    {
+      GtkShowWindow (window, SW_SHOW);
+    }
+
+  /* Sync STATE_ABOVE to TOPMOST */
+  if (GDK_SURFACE_TYPE (window) != GDK_SURFACE_TEMP &&
+      (((window->state & GDK_SURFACE_STATE_ABOVE) &&
+       !(exstyle & WS_EX_TOPMOST)) ||
+       (!(window->state & GDK_SURFACE_STATE_ABOVE) &&
+       (exstyle & WS_EX_TOPMOST))))
+    {
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                              (window->state & GDK_SURFACE_STATE_ABOVE)?HWND_TOPMOST:HWND_NOTOPMOST,
+                              0, 0, 0, 0,
+                              SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
+    }
+}
+
+static void
+gdk_win32_surface_show (GdkSurface *window,
+                      gboolean already_mapped)
+{
+  show_window_internal (window, FALSE, FALSE);
+}
+
+static void
+gdk_win32_surface_hide (GdkSurface *window)
+{
+  if (window->destroyed)
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_win32_surface_hide: %p: %s\n",
+                          GDK_SURFACE_HWND (window),
+                          _gdk_win32_surface_state_to_string (window->state)));
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    gdk_synthesize_window_state (window,
+                                0,
+                                GDK_SURFACE_STATE_WITHDRAWN);
+
+  _gdk_surface_clear_update_area (window);
+
+  if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL)
+    ShowOwnedPopups (GDK_SURFACE_HWND (window), FALSE);
+
+  /* Use SetWindowPos to hide transparent windows so automatic redraws
+   * in other windows can be suppressed.
+   */
+  if (GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
+    {
+      SetWindowPos (GDK_SURFACE_HWND (window), SWP_NOZORDER_SPECIFIED,
+                   0, 0, 0, 0,
+                   SWP_HIDEWINDOW | SWP_NOREDRAW | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
+    }
+  else
+    {
+      GtkShowWindow (window, SW_HIDE);
+    }
+}
+
+static void
+gdk_win32_surface_withdraw (GdkSurface *window)
+{
+  if (window->destroyed)
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_win32_surface_withdraw: %p: %s\n",
+                          GDK_SURFACE_HWND (window),
+                          _gdk_win32_surface_state_to_string (window->state)));
+
+  gdk_surface_hide (window);   /* ??? */
+}
+
+static void
+gdk_win32_surface_move (GdkSurface *window,
+                      gint x, gint y)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_win32_surface_move: %p: %+d%+d\n",
+                           GDK_SURFACE_HWND (window), x, y));
+
+  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
+    return;
+
+  /* Don't check GDK_SURFACE_TYPE (window) == GDK_SURFACE_CHILD.
+   * Foreign windows (another app's windows) might be children of our
+   * windows! Especially in the case of gtkplug/socket.
+   */
+  if (GetAncestor (GDK_SURFACE_HWND (window), GA_PARENT) != GetDesktopWindow ())
+    {
+      _gdk_surface_move_resize_child (window, x, y, window->width, window->height);
+    }
+  else
+    {
+      RECT outer_rect;
+      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+      get_outer_rect (window, window->width, window->height, &outer_rect);
+
+      adjust_for_gravity_hints (window, &outer_rect, &x, &y);
+
+      GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,0,0,"
+                               "NOACTIVATE|NOSIZE|NOZORDER)\n",
+                               GDK_SURFACE_HWND (window),
+                               (x - _gdk_offset_x) * impl->window_scale,
+                               (y - _gdk_offset_y) * impl->window_scale));
+
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                              SWP_NOZORDER_SPECIFIED,
+                               (x - _gdk_offset_x) * impl->window_scale,
+                               (y - _gdk_offset_y) * impl->window_scale,
+                               0, 0,
+                               SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
+    }
+}
+
+static void
+gdk_win32_surface_resize (GdkSurface *window,
+                        gint width, gint height)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (width < 1)
+    width = 1;
+  if (height < 1)
+    height = 1;
+
+  GDK_NOTE (MISC, g_print ("gdk_win32_surface_resize: %p: %dx%d\n",
+                           GDK_SURFACE_HWND (window), width, height));
+
+  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
+    return;
+
+  if (GetAncestor (GDK_SURFACE_HWND (window), GA_PARENT) != GetDesktopWindow ())
+    {
+      _gdk_surface_move_resize_child (window, window->x, window->y, width, height);
+    }
+  else
+    {
+      RECT outer_rect;
+      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+      get_outer_rect (window, width, height, &outer_rect);
+
+      GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,0,0,%ld,%ld,"
+                               "NOACTIVATE|NOMOVE|NOZORDER)\n",
+                               GDK_SURFACE_HWND (window),
+                               outer_rect.right - outer_rect.left,
+                               outer_rect.bottom - outer_rect.top));
+
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                              SWP_NOZORDER_SPECIFIED,
+                               0, 0,
+                               outer_rect.right - outer_rect.left,
+                               outer_rect.bottom - outer_rect.top,
+                               SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER));
+      window->resize_count += 1;
+    }
+}
+
+static void
+gdk_win32_surface_move_resize_internal (GdkSurface *window,
+                                      gint       x,
+                                      gint       y,
+                                      gint       width,
+                                      gint       height)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (width < 1)
+    width = 1;
+  if (height < 1)
+    height = 1;
+
+  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_win32_surface_move_resize: %p: %dx%d@%+d%+d\n",
+                           GDK_SURFACE_HWND (window),
+                           width, height, x, y));
+
+  if (GetAncestor (GDK_SURFACE_HWND (window), GA_PARENT) != GetDesktopWindow ())
+    {
+      _gdk_surface_move_resize_child (window, x, y, width, height);
+    }
+  else
+    {
+      RECT outer_rect;
+      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+      get_outer_rect (window, width, height, &outer_rect);
+
+      adjust_for_gravity_hints (window, &outer_rect, &x, &y);
+
+      GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%ld,%ld,"
+                               "NOACTIVATE|NOZORDER)\n",
+                               GDK_SURFACE_HWND (window),
+                               (x - _gdk_offset_x) * impl->window_scale,
+                               (y - _gdk_offset_y) * impl->window_scale,
+                               outer_rect.right - outer_rect.left,
+                               outer_rect.bottom - outer_rect.top));
+
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                              SWP_NOZORDER_SPECIFIED,
+                               (x - _gdk_offset_x) * impl->window_scale,
+                               (y - _gdk_offset_y) * impl->window_scale,
+                               outer_rect.right - outer_rect.left,
+                               outer_rect.bottom - outer_rect.top,
+                               SWP_NOACTIVATE | SWP_NOZORDER));
+    }
+}
+
+static void
+gdk_win32_surface_move_resize (GdkSurface *window,
+                             gboolean   with_move,
+                             gint       x,
+                             gint       y,
+                             gint       width,
+                             gint       height)
+{
+  GdkSurfaceImplWin32 *window_impl;
+
+  window_impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+  window_impl->inhibit_configure = TRUE;
+
+  /* We ignore changes to the window being moved or resized by the
+     user, as we don't want to fight the user */
+  if (GDK_SURFACE_HWND (window) == _modal_move_resize_window)
+    goto out;
+
+  if (with_move && (width < 0 && height < 0))
+    {
+      gdk_win32_surface_move (window, x, y);
+    }
+  else
+    {
+      if (with_move)
+       {
+         gdk_win32_surface_move_resize_internal (window, x, y, width, height);
+       }
+      else
+       {
+         gdk_win32_surface_resize (window, width, height);
+       }
+    }
+
+ out:
+  window_impl->inhibit_configure = FALSE;
+
+  if (WINDOW_IS_TOPLEVEL (window))
+    _gdk_win32_emit_configure_event (window);
+}
+
+static void
+gdk_win32_surface_raise (GdkSurface *window)
+{
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      GDK_NOTE (MISC, g_print ("gdk_win32_surface_raise: %p\n",
+                              GDK_SURFACE_HWND (window)));
+
+      if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP)
+        API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOPMOST,
+                                0, 0, 0, 0,
+                                SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
+      else if (window->accept_focus)
+        /* Do not wrap this in an API_CALL macro as SetForegroundWindow might
+         * fail when for example dragging a window belonging to a different
+         * application at the time of a gtk_window_present() call due to focus
+         * stealing prevention. */
+        SetForegroundWindow (GDK_SURFACE_HWND (window));
+      else
+        API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOP,
+                                0, 0, 0, 0,
+                                SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
+    }
+}
+
+static void
+gdk_win32_surface_lower (GdkSurface *window)
+{
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      GDK_NOTE (MISC, g_print ("gdk_win32_surface_lower: %p\n"
+                              "... SetWindowPos(%p,HWND_BOTTOM,0,0,0,0,"
+                              "NOACTIVATE|NOMOVE|NOSIZE)\n",
+                              GDK_SURFACE_HWND (window),
+                              GDK_SURFACE_HWND (window)));
+
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_BOTTOM,
+                              0, 0, 0, 0,
+                              SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
+    }
+}
+
+static void
+gdk_win32_surface_set_urgency_hint (GdkSurface *window,
+                            gboolean   urgent)
+{
+  FLASHWINFO flashwinfo;
+  typedef BOOL (WINAPI *PFN_FlashWindowEx) (FLASHWINFO*);
+  PFN_FlashWindowEx flashWindowEx = NULL;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  flashWindowEx = (PFN_FlashWindowEx) GetProcAddress (GetModuleHandle ("user32.dll"), "FlashWindowEx");
+
+  if (flashWindowEx)
+    {
+      flashwinfo.cbSize = sizeof (flashwinfo);
+      flashwinfo.hwnd = GDK_SURFACE_HWND (window);
+      if (urgent)
+       flashwinfo.dwFlags = FLASHW_ALL | FLASHW_TIMER;
+      else
+       flashwinfo.dwFlags = FLASHW_STOP;
+      flashwinfo.uCount = 0;
+      flashwinfo.dwTimeout = 0;
+
+      flashWindowEx (&flashwinfo);
+    }
+  else
+    {
+      FlashWindow (GDK_SURFACE_HWND (window), urgent);
+    }
+}
+
+static gboolean
+get_effective_window_decorations (GdkSurface       *window,
+                                  GdkWMDecoration *decoration)
+{
+  GdkSurfaceImplWin32 *impl;
+
+  impl = (GdkSurfaceImplWin32 *)window->impl;
+
+  if (gdk_surface_get_decorations (window, decoration))
+    return TRUE;
+
+  if (window->window_type != GDK_SURFACE_TOPLEVEL)
+    {
+      return FALSE;
+    }
+
+  if ((impl->hint_flags & GDK_HINT_MIN_SIZE) &&
+      (impl->hint_flags & GDK_HINT_MAX_SIZE) &&
+      impl->hints.min_width == impl->hints.max_width &&
+      impl->hints.min_height == impl->hints.max_height)
+    {
+      *decoration = GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MAXIMIZE;
+
+      if (impl->type_hint == GDK_SURFACE_TYPE_HINT_DIALOG ||
+         impl->type_hint == GDK_SURFACE_TYPE_HINT_MENU ||
+         impl->type_hint == GDK_SURFACE_TYPE_HINT_TOOLBAR)
+       {
+         *decoration |= GDK_DECOR_MINIMIZE;
+       }
+      else if (impl->type_hint == GDK_SURFACE_TYPE_HINT_SPLASHSCREEN)
+       {
+         *decoration |= GDK_DECOR_MENU | GDK_DECOR_MINIMIZE;
+       }
+
+      return TRUE;
+    }
+  else if (impl->hint_flags & GDK_HINT_MAX_SIZE)
+    {
+      *decoration = GDK_DECOR_ALL | GDK_DECOR_MAXIMIZE;
+      if (impl->type_hint == GDK_SURFACE_TYPE_HINT_DIALOG ||
+         impl->type_hint == GDK_SURFACE_TYPE_HINT_MENU ||
+         impl->type_hint == GDK_SURFACE_TYPE_HINT_TOOLBAR)
+       {
+         *decoration |= GDK_DECOR_MINIMIZE;
+       }
+
+      return TRUE;
+    }
+  else
+    {
+      switch (impl->type_hint)
+       {
+       case GDK_SURFACE_TYPE_HINT_DIALOG:
+         *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
+         return TRUE;
+
+       case GDK_SURFACE_TYPE_HINT_MENU:
+         *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
+         return TRUE;
+
+       case GDK_SURFACE_TYPE_HINT_TOOLBAR:
+       case GDK_SURFACE_TYPE_HINT_UTILITY:
+         gdk_surface_set_skip_taskbar_hint (window, TRUE);
+         gdk_surface_set_skip_pager_hint (window, TRUE);
+         *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
+         return TRUE;
+
+       case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
+         *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MENU |
+                        GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
+         return TRUE;
+
+       case GDK_SURFACE_TYPE_HINT_DOCK:
+         return FALSE;
+
+       case GDK_SURFACE_TYPE_HINT_DESKTOP:
+         return FALSE;
+
+       default:
+         /* Fall thru */
+       case GDK_SURFACE_TYPE_HINT_NORMAL:
+         *decoration = GDK_DECOR_ALL;
+         return TRUE;
+       }
+    }
+
+  return FALSE;
+}
+
+static void
+gdk_win32_surface_set_geometry_hints (GdkSurface         *window,
+                              const GdkGeometry *geometry,
+                              GdkSurfaceHints     geom_mask)
+{
+  GdkSurfaceImplWin32 *impl;
+  FullscreenInfo *fi;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_set_geometry_hints: %p\n",
+                          GDK_SURFACE_HWND (window)));
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
+  if (fi)
+    fi->hint_flags = geom_mask;
+  else
+    impl->hint_flags = geom_mask;
+  impl->hints = *geometry;
+
+  if (geom_mask & GDK_HINT_POS)
+    {
+      /* even the X11 mplementation doesn't care */
+    }
+
+  if (geom_mask & GDK_HINT_MIN_SIZE)
+    {
+      GDK_NOTE (MISC, g_print ("... MIN_SIZE: %dx%d\n",
+                              geometry->min_width, geometry->min_height));
+    }
+
+  if (geom_mask & GDK_HINT_MAX_SIZE)
+    {
+      GDK_NOTE (MISC, g_print ("... MAX_SIZE: %dx%d\n",
+                              geometry->max_width, geometry->max_height));
+    }
+
+  if (geom_mask & GDK_HINT_BASE_SIZE)
+    {
+      GDK_NOTE (MISC, g_print ("... BASE_SIZE: %dx%d\n",
+                              geometry->base_width, geometry->base_height));
+    }
+
+  if (geom_mask & GDK_HINT_RESIZE_INC)
+    {
+      GDK_NOTE (MISC, g_print ("... RESIZE_INC: (%d,%d)\n",
+                              geometry->width_inc, geometry->height_inc));
+    }
+
+  if (geom_mask & GDK_HINT_ASPECT)
+    {
+      GDK_NOTE (MISC, g_print ("... ASPECT: %g--%g\n",
+                              geometry->min_aspect, geometry->max_aspect));
+    }
+
+  if (geom_mask & GDK_HINT_WIN_GRAVITY)
+    {
+      GDK_NOTE (MISC, g_print ("... GRAVITY: %d\n", geometry->win_gravity));
+    }
+
+  _gdk_win32_surface_update_style_bits (window);
+}
+
+static void
+gdk_win32_surface_set_title (GdkSurface   *window,
+                     const gchar *title)
+{
+  wchar_t *wtitle;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (title != NULL);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  /* Empty window titles not allowed, so set it to just a period. */
+  if (!title[0])
+    title = ".";
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_set_title: %p: %s\n",
+                          GDK_SURFACE_HWND (window), title));
+
+  GDK_NOTE (MISC_OR_EVENTS, title = g_strdup_printf ("%p %s", GDK_SURFACE_HWND (window), title));
+
+  wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
+  API_CALL (SetWindowTextW, (GDK_SURFACE_HWND (window), wtitle));
+  g_free (wtitle);
+
+  GDK_NOTE (MISC_OR_EVENTS, g_free ((char *) title));
+}
+
+static void
+gdk_win32_surface_set_role (GdkSurface   *window,
+                    const gchar *role)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_set_role: %p: %s\n",
+                          GDK_SURFACE_HWND (window),
+                          (role ? role : "NULL")));
+  /* XXX */
+}
+
+static void
+gdk_win32_surface_set_transient_for (GdkSurface *window,
+                             GdkSurface *parent)
+{
+  HWND window_id, parent_id;
+  LONG_PTR old_ptr;
+  DWORD w32_error;
+  GdkSurfaceImplWin32 *window_impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+  GdkSurfaceImplWin32 *parent_impl = NULL;
+  GSList *item;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  window_id = GDK_SURFACE_HWND (window);
+  parent_id = parent != NULL ? GDK_SURFACE_HWND (parent) : NULL;
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_set_transient_for: %p: %p\n", window_id, parent_id));
+
+  if (GDK_SURFACE_DESTROYED (window) || (parent && GDK_SURFACE_DESTROYED (parent)))
+    {
+      if (GDK_SURFACE_DESTROYED (window))
+       GDK_NOTE (MISC, g_print ("... destroyed!\n"));
+      else
+       GDK_NOTE (MISC, g_print ("... owner destroyed!\n"));
+
+      return;
+    }
+
+  if (parent == NULL)
+    {
+      GdkSurfaceImplWin32 *trans_impl = GDK_SURFACE_IMPL_WIN32 (window_impl->transient_owner->impl);
+      if (trans_impl->transient_children != NULL)
+        {
+          item = g_slist_find (trans_impl->transient_children, window);
+          item->data = NULL;
+          trans_impl->transient_children = g_slist_delete_link (trans_impl->transient_children, item);
+          trans_impl->num_transients--;
+
+          if (!trans_impl->num_transients)
+            {
+              trans_impl->transient_children = NULL;
+            }
+        }
+      g_object_unref (G_OBJECT (window_impl->transient_owner));
+      g_object_unref (G_OBJECT (window));
+
+      window_impl->transient_owner = NULL;
+    }
+  else
+    {
+      parent_impl = GDK_SURFACE_IMPL_WIN32 (parent->impl);
+
+      parent_impl->transient_children = g_slist_append (parent_impl->transient_children, window);
+      g_object_ref (G_OBJECT (window));
+      parent_impl->num_transients++;
+      window_impl->transient_owner = parent;
+      g_object_ref (G_OBJECT (parent));
+    }
+
+  SetLastError (0);
+  old_ptr = GetWindowLongPtr (window_id, GWLP_HWNDPARENT);
+  w32_error = GetLastError ();
+
+  /* Don't re-set GWLP_HWNDPARENT to the same value */
+  if ((HWND) old_ptr == parent_id && w32_error == NO_ERROR)
+    return;
+
+  /* Don't return if it failed, try SetWindowLongPtr() anyway */
+  if (old_ptr == 0 && w32_error != NO_ERROR)
+    WIN32_API_FAILED ("GetWindowLongPtr");
+
+  /* This changes the *owner* of the window, despite the misleading
+   * name. (Owner and parent are unrelated concepts.) At least that's
+   * what people who seem to know what they talk about say on
+   * USENET. Search on Google.
+   */
+  SetLastError (0);
+  old_ptr = SetWindowLongPtr (window_id, GWLP_HWNDPARENT, (LONG_PTR) parent_id);
+  w32_error = GetLastError ();
+
+  if (old_ptr == 0 && w32_error != NO_ERROR)
+    WIN32_API_FAILED ("SetWindowLongPtr");
+}
+
+void
+_gdk_push_modal_window (GdkSurface *window)
+{
+  modal_window_stack = g_slist_prepend (modal_window_stack,
+                                        window);
+}
+
+void
+_gdk_remove_modal_window (GdkSurface *window)
+{
+  GSList *tmp;
+
+  g_return_if_fail (window != NULL);
+
+  /* It's possible to be NULL here if someone sets the modal hint of the window
+   * to FALSE before a modal window stack has ever been created. */
+  if (modal_window_stack == NULL)
+    return;
+
+  /* Find the requested window in the stack and remove it.  Yeah, I realize this
+   * means we're not a 'real stack', strictly speaking.  Sue me. :) */
+  tmp = g_slist_find (modal_window_stack, window);
+  if (tmp != NULL)
+    {
+      modal_window_stack = g_slist_delete_link (modal_window_stack, tmp);
+    }
+}
+
+gboolean
+_gdk_modal_blocked (GdkSurface *window)
+{
+  GSList *l;
+  gboolean found_any = FALSE;
+
+  for (l = modal_window_stack; l != NULL; l = l->next)
+    {
+      GdkSurface *modal = l->data;
+
+      if (modal == window)
+       return FALSE;
+
+      if (GDK_SURFACE_IS_MAPPED (modal))
+       found_any = TRUE;
+    }
+
+  return found_any;
+}
+
+GdkSurface *
+_gdk_modal_current (void)
+{
+  GSList *l;
+
+  for (l = modal_window_stack; l != NULL; l = l->next)
+    {
+      GdkSurface *modal = l->data;
+
+      if (GDK_SURFACE_IS_MAPPED (modal))
+       return modal;
+    }
+
+  return NULL;
+}
+
+static void
+gdk_win32_surface_get_geometry (GdkSurface *window,
+                              gint      *x,
+                              gint      *y,
+                              gint      *width,
+                              gint      *height)
+{
+  GdkDisplay *display;
+  gboolean window_is_root;
+
+  display = gdk_surface_get_display (window);
+
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      RECT rect;
+      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+      API_CALL (GetClientRect, (GDK_SURFACE_HWND (window), &rect));
+
+         POINT pt;
+         GdkSurface *parent = gdk_surface_get_parent (window);
+
+         pt.x = rect.left;
+         pt.y = rect.top;
+         ClientToScreen (GDK_SURFACE_HWND (window), &pt);
+          if (parent)
+           ScreenToClient (GDK_SURFACE_HWND (parent), &pt);
+         rect.left = pt.x;
+         rect.top = pt.y;
+
+         pt.x = rect.right;
+         pt.y = rect.bottom;
+         ClientToScreen (GDK_SURFACE_HWND (window), &pt);
+          if (parent)
+           ScreenToClient (GDK_SURFACE_HWND (parent), &pt);
+         rect.right = pt.x;
+         rect.bottom = pt.y;
+
+         if (parent == NULL)
+           {
+             rect.left += _gdk_offset_x * impl->window_scale;
+             rect.top += _gdk_offset_y * impl->window_scale;
+             rect.right += _gdk_offset_x * impl->window_scale;
+             rect.bottom += _gdk_offset_y * impl->window_scale;
+           }
+
+      if (x)
+       *x = rect.left / impl->window_scale;
+      if (y)
+       *y = rect.top / impl->window_scale;
+      if (width)
+       *width = (rect.right - rect.left) / impl->window_scale;
+      if (height)
+       *height = (rect.bottom - rect.top) / impl->window_scale;
+
+      GDK_NOTE (MISC, g_print ("gdk_win32_surface_get_geometry: %p: %ldx%ld@%+ld%\n",
+                              GDK_SURFACE_HWND (window),
+                              (rect.right - rect.left) / impl->window_scale,
+                              (rect.bottom - rect.top) / impl->window_scale,
+                              rect.left, rect.top));
+    }
+}
+
+static void
+gdk_win32_surface_get_root_coords (GdkSurface *window,
+                                 gint       x,
+                                 gint       y,
+                                 gint      *root_x,
+                                 gint      *root_y)
+{
+  gint tx;
+  gint ty;
+  POINT pt;
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  pt.x = x * impl->window_scale;
+  pt.y = y * impl->window_scale;
+  ClientToScreen (GDK_SURFACE_HWND (window), &pt);
+  tx = pt.x;
+  ty = pt.y;
+
+  if (root_x)
+    *root_x = (tx + _gdk_offset_x) / impl->window_scale;
+  if (root_y)
+    *root_y = (ty + _gdk_offset_y) / impl->window_scale;
+
+  GDK_NOTE (MISC, g_print ("gdk_win32_surface_get_root_coords: %p: %+d%+d %+d%+d\n",
+                          GDK_SURFACE_HWND (window),
+                          x * impl->window_scale,
+                          y * impl->window_scale,
+                          (tx + _gdk_offset_x) / impl->window_scale,
+                          (ty + _gdk_offset_y) / impl->window_scale));
+}
+
+static void
+gdk_win32_surface_restack_toplevel (GdkSurface *window,
+                                  GdkSurface *sibling,
+                                  gboolean   above)
+{
+       // ### TODO
+}
+
+static void
+gdk_win32_surface_get_frame_extents (GdkSurface    *window,
+                              GdkRectangle *rect)
+{
+  HWND hwnd;
+  RECT r;
+  GdkSurfaceImplWin32 *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (rect != NULL);
+
+  rect->x = 0;
+  rect->y = 0;
+  rect->width = 1;
+  rect->height = 1;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  /* FIXME: window is documented to be a toplevel GdkSurface, so is it really
+   * necessary to walk its parent chain?
+   */
+  while (window->parent && window->parent->parent)
+    window = window->parent;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+  hwnd = GDK_SURFACE_HWND (window);
+  API_CALL (GetWindowRect, (hwnd, &r));
+
+  /* Initialize to real, unscaled size */
+  rect->x = r.left + _gdk_offset_x * impl->window_scale;
+  rect->y = r.top + _gdk_offset_y * impl->window_scale;
+  rect->width = (r.right - r.left);
+  rect->height = (r.bottom - r.top);
+
+  /* Extend width and height to ensure that they cover the real size when de-scaled,
+   * and replace everyting with scaled values
+   */
+  rect->width = (rect->width + rect->x % impl->window_scale + impl->window_scale - 1) / impl->window_scale;
+  rect->height = (rect->height + rect->y % impl->window_scale + impl->window_scale - 1) / impl->window_scale;
+  rect->x = r.left / impl->window_scale + _gdk_offset_x;
+  rect->y = r.top / impl->window_scale + _gdk_offset_y;
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_get_frame_extents: %p: %ldx%ld@%+ld%+ld\n",
+                           GDK_SURFACE_HWND (window),
+                           rect->width,
+                           rect->height,
+                           rect->x, rect->y));
+}
+
+static gboolean
+gdk_surface_win32_get_device_state (GdkSurface       *window,
+                                   GdkDevice       *device,
+                                   gdouble         *x,
+                                   gdouble         *y,
+                                   GdkModifierType *mask)
+{
+  GdkSurface *child;
+
+  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), FALSE);
+
+  GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
+                                              &child,
+                                              NULL, NULL,
+                                              x, y, mask);
+  return (child != NULL);
+}
+
+void
+gdk_display_warp_device (GdkDisplay *display,
+                         GdkDevice  *device,
+                         gint        x,
+                         gint        y)
+{
+  g_return_if_fail (display == gdk_display_get_default ());
+  g_return_if_fail (GDK_IS_DEVICE (device));
+  g_return_if_fail (display == gdk_device_get_display (device));
+
+  GDK_DEVICE_GET_CLASS (device)->warp (device, x, y);
+}
+
+static GdkEventMask
+gdk_win32_surface_get_events (GdkSurface *window)
+{
+  GdkSurfaceImplWin32 *impl;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return 0;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  return impl->native_event_mask;
+}
+
+static void
+gdk_win32_surface_set_events (GdkSurface   *window,
+                            GdkEventMask event_mask)
+{
+  GdkSurfaceImplWin32 *impl;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  /* gdk_surface_new() always sets the GDK_STRUCTURE_MASK, so better
+   * set it here, too. Not that I know or remember why it is
+   * necessary, will have to test some day.
+   */
+  impl->native_event_mask = GDK_STRUCTURE_MASK | event_mask;
+}
+
+static void
+do_shape_combine_region (GdkSurface *window,
+                        HRGN       hrgn,
+                        gint       x, gint y)
+{
+  RECT rect;
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  GetClientRect (GDK_SURFACE_HWND (window), &rect);
+
+  _gdk_win32_adjust_client_rect (window, &rect);
+
+  OffsetRgn (hrgn, -rect.left, -rect.top);
+  OffsetRgn (hrgn, x, y);
+
+  /* If this is a top-level window, add the title bar to the region */
+  if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL)
+    {
+      HRGN tmp = CreateRectRgn (0, 0, rect.right - rect.left, -rect.top);
+      CombineRgn (hrgn, hrgn, tmp, RGN_OR);
+      DeleteObject (tmp);
+    }
+
+  SetWindowRgn (GDK_SURFACE_HWND (window), hrgn, TRUE);
+}
+
+static void
+gdk_win32_surface_set_accept_focus (GdkSurface *window,
+                            gboolean accept_focus)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  accept_focus = accept_focus != FALSE;
+
+  if (window->accept_focus != accept_focus)
+    window->accept_focus = accept_focus;
+}
+
+static void
+gdk_win32_surface_set_focus_on_map (GdkSurface *window,
+                            gboolean focus_on_map)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  focus_on_map = focus_on_map != FALSE;
+
+  if (window->focus_on_map != focus_on_map)
+    window->focus_on_map = focus_on_map;
+}
+
+static void
+gdk_win32_surface_set_icon_list (GdkSurface *window,
+                                GList     *textures)
+{
+  GdkTexture *big_texture, *small_texture;
+  gint big_diff, small_diff;
+  gint big_w, big_h, small_w, small_h;
+  gint w, h;
+  gint dw, dh, diff;
+  HICON small_hicon, big_hicon;
+  GdkSurfaceImplWin32 *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) || textures == NULL)
+    return;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  /* ideal sizes for small and large icons */
+  big_w = GetSystemMetrics (SM_CXICON);
+  big_h = GetSystemMetrics (SM_CYICON);
+  small_w = GetSystemMetrics (SM_CXSMICON);
+  small_h = GetSystemMetrics (SM_CYSMICON);
+
+  /* find closest sized icons in the list */
+  big_texture = NULL;
+  small_texture = NULL;
+  big_diff = 0;
+  small_diff = 0;
+
+  for (GList *l = textures; l; l = l->next)
+    {
+      GdkTexture *texture = l->data;
+      w = gdk_texture_get_width (texture);
+      h = gdk_texture_get_height (texture);
+
+      dw = ABS (w - big_w);
+      dh = ABS (h - big_h);
+      diff = dw*dw + dh*dh;
+      if (big_texture == NULL || diff < big_diff)
+        {
+          big_texture = texture;
+          big_diff = diff;
+        }
+
+      dw = ABS (w - small_w);
+      dh = ABS (h - small_h);
+      diff = dw*dw + dh*dh;
+      if (small_texture == NULL || diff < small_diff)
+        {
+          small_texture = texture;
+          small_diff = diff;
+        }
+
+      textures = textures->next;
+    }
+
+  /* Create the icons */
+  big_hicon = _gdk_win32_texture_to_hicon (big_texture);
+  g_object_unref (big_texture);
+  small_hicon = _gdk_win32_texture_to_hicon (small_texture);
+  g_object_unref (small_texture);
+
+  /* Set the icons */
+  SendMessageW (GDK_SURFACE_HWND (window), WM_SETICON, ICON_BIG,
+               (LPARAM)big_hicon);
+  SendMessageW (GDK_SURFACE_HWND (window), WM_SETICON, ICON_SMALL,
+               (LPARAM)small_hicon);
+
+  /* Store the icons, destroying any previous icons */
+  if (impl->hicon_big)
+    GDI_CALL (DestroyIcon, (impl->hicon_big));
+  impl->hicon_big = big_hicon;
+  if (impl->hicon_small)
+    GDI_CALL (DestroyIcon, (impl->hicon_small));
+  impl->hicon_small = small_hicon;
+}
+
+static void
+gdk_win32_surface_set_icon_name (GdkSurface   *window,
+                                const gchar *name)
+{
+  /* In case I manage to confuse this again (or somebody else does):
+   * Please note that "icon name" here really *does* mean the name or
+   * title of an window minimized as an icon on the desktop, or in the
+   * taskbar. It has nothing to do with the freedesktop.org icon
+   * naming stuff.
+   */
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+#if 0
+  /* This is not the correct thing to do. We should keep both the
+   * "normal" window title, and the icon name. When the window is
+   * minimized, call SetWindowText() with the icon name, and when the
+   * window is restored, with the normal window title. Also, the name
+   * is in UTF-8, so we should do the normal conversion to either wide
+   * chars or system codepage, and use either the W or A version of
+   * SetWindowText(), depending on Windows version.
+   */
+  API_CALL (SetWindowText, (GDK_SURFACE_HWND (window), name));
+#endif
+}
+
+static GdkSurface *
+gdk_win32_surface_get_group (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return NULL;
+
+  g_warning ("gdk_surface_get_group not yet implemented");
+
+  return NULL;
+}
+
+static void
+gdk_win32_surface_set_group (GdkSurface *window,
+                     GdkSurface *leader)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (leader == NULL || GDK_IS_SURFACE (leader));
+
+  if (GDK_SURFACE_DESTROYED (window) || GDK_SURFACE_DESTROYED (leader))
+    return;
+
+  g_warning ("gdk_surface_set_group not implemented");
+}
+
+static void
+update_single_bit (LONG    *style,
+                   gboolean all,
+                  int      gdk_bit,
+                  int      style_bit)
+{
+  /* all controls the interpretation of gdk_bit -- if all is TRUE,
+   * gdk_bit indicates whether style_bit is off; if all is FALSE, gdk
+   * bit indicate whether style_bit is on
+   */
+  if ((!all && gdk_bit) || (all && !gdk_bit))
+    *style |= style_bit;
+  else
+    *style &= ~style_bit;
+}
+
+/*
+ * Returns TRUE if window has no decorations.
+ * Usually it means CSD windows, because GTK
+ * calls gdk_surface_set_decorations (window, 0);
+ * This is used to decide whether a toplevel should
+ * be made layered, thus it
+ * only returns TRUE for toplevels (until GTK minimal
+ * system requirements are lifted to Windows 8 or newer,
+ * because only toplevels can be layered).
+ */
+gboolean
+_gdk_win32_surface_lacks_wm_decorations (GdkSurface *window)
+{
+  GdkSurfaceImplWin32 *impl;
+  LONG style;
+  gboolean has_any_decorations;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return FALSE;
+
+  /* only toplevels can be layered */
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return FALSE;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  /* This is because GTK calls gdk_surface_set_decorations (window, 0),
+   * even though GdkWMDecoration docs indicate that 0 does NOT mean
+   * "no decorations".
+   */
+  if (impl->decorations &&
+      *impl->decorations == 0)
+    return TRUE;
+
+  if (GDK_SURFACE_HWND (window) == 0)
+    return FALSE;
+
+  style = GetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE);
+
+  if (style == 0)
+    {
+      DWORD w32_error = GetLastError ();
+
+      GDK_NOTE (MISC, g_print ("Failed to get style of window %p (handle %p): %lu\n",
+                               window, GDK_SURFACE_HWND (window), w32_error));
+      return FALSE;
+    }
+
+  /* Keep this in sync with _gdk_win32_surface_update_style_bits() */
+  /* We don't check what get_effective_window_decorations()
+   * has to say, because it gives suggestions based on
+   * various hints, while we want *actual* decorations,
+   * or their absence.
+   */
+  has_any_decorations = FALSE;
+
+  if (style & (WS_BORDER | WS_THICKFRAME | WS_CAPTION |
+               WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX))
+    has_any_decorations = TRUE;
+  else
+    GDK_NOTE (MISC, g_print ("Window %p (handle %p): has no decorations (style %lx)\n",
+                             window, GDK_SURFACE_HWND (window), style));
+
+  return !has_any_decorations;
+}
+
+void
+_gdk_win32_surface_update_style_bits (GdkSurface *window)
+{
+  GdkSurfaceImplWin32 *impl = (GdkSurfaceImplWin32 *)window->impl;
+  GdkWMDecoration decorations;
+  LONG old_style, new_style, old_exstyle, new_exstyle;
+  gboolean all;
+  RECT rect, before, after;
+  gboolean was_topmost;
+  gboolean will_be_topmost;
+  HWND insert_after;
+  UINT flags;
+
+  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
+    return;
+
+  old_style = GetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE);
+  old_exstyle = GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE);
+
+  GetClientRect (GDK_SURFACE_HWND (window), &before);
+  after = before;
+  AdjustWindowRectEx (&before, old_style, FALSE, old_exstyle);
+
+  was_topmost = (old_exstyle & WS_EX_TOPMOST) ? TRUE : FALSE;
+  will_be_topmost = was_topmost;
+
+  old_exstyle &= ~WS_EX_TOPMOST;
+
+  new_style = old_style;
+  new_exstyle = old_exstyle;
+
+  if (window->window_type == GDK_SURFACE_TEMP)
+    {
+      new_exstyle |= WS_EX_TOOLWINDOW;
+      will_be_topmost = TRUE;
+    }
+  else if (impl->type_hint == GDK_SURFACE_TYPE_HINT_UTILITY)
+    {
+      new_exstyle |= WS_EX_TOOLWINDOW;
+    }
+  else
+    {
+      new_exstyle &= ~WS_EX_TOOLWINDOW;
+    }
+
+  /* We can get away with using layered windows
+   * only when no decorations are needed. It can mean
+   * CSD or borderless non-CSD windows (tooltips?).
+   *
+   * If this window cannot use layered windows, disable it always.
+   * This currently applies to windows using OpenGL, which
+   * does not work with layered windows.
+   */
+  if (impl->suppress_layered == 0)
+    {
+      if (_gdk_win32_surface_lacks_wm_decorations (window))
+        impl->layered = g_strcmp0 (g_getenv ("GDK_WIN32_LAYERED"), "0") != 0;
+    }
+  else
+    impl->layered = FALSE;
+
+  if (impl->layered)
+    new_exstyle |= WS_EX_LAYERED;
+  else
+    new_exstyle &= ~WS_EX_LAYERED;
+
+  if (get_effective_window_decorations (window, &decorations))
+    {
+      all = (decorations & GDK_DECOR_ALL);
+      /* Keep this in sync with the test in _gdk_win32_surface_lacks_wm_decorations() */
+      update_single_bit (&new_style, all, decorations & GDK_DECOR_BORDER, WS_BORDER);
+      update_single_bit (&new_style, all, decorations & GDK_DECOR_RESIZEH, WS_THICKFRAME);
+      update_single_bit (&new_style, all, decorations & GDK_DECOR_TITLE, WS_CAPTION);
+      update_single_bit (&new_style, all, decorations & GDK_DECOR_MENU, WS_SYSMENU);
+      update_single_bit (&new_style, all, decorations & GDK_DECOR_MINIMIZE, WS_MINIMIZEBOX);
+      update_single_bit (&new_style, all, decorations & GDK_DECOR_MAXIMIZE, WS_MAXIMIZEBOX);
+    }
+
+  if (old_style == new_style && old_exstyle == new_exstyle )
+    {
+      GDK_NOTE (MISC, g_print ("_gdk_win32_surface_update_style_bits: %p: no change\n",
+                              GDK_SURFACE_HWND (window)));
+      return;
+    }
+
+  if (old_style != new_style)
+    {
+      GDK_NOTE (MISC, g_print ("_gdk_win32_surface_update_style_bits: %p: STYLE: %s => %s\n",
+                              GDK_SURFACE_HWND (window),
+                              _gdk_win32_surface_style_to_string (old_style),
+                              _gdk_win32_surface_style_to_string (new_style)));
+
+      SetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE, new_style);
+    }
+
+  if (old_exstyle != new_exstyle)
+    {
+      GDK_NOTE (MISC, g_print ("_gdk_win32_surface_update_style_bits: %p: EXSTYLE: %s => %s\n",
+                              GDK_SURFACE_HWND (window),
+                              _gdk_win32_surface_exstyle_to_string (old_exstyle),
+                              _gdk_win32_surface_exstyle_to_string (new_exstyle)));
+
+      SetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE, new_exstyle);
+    }
+
+  AdjustWindowRectEx (&after, new_style, FALSE, new_exstyle);
+
+  GetWindowRect (GDK_SURFACE_HWND (window), &rect);
+  rect.left += after.left - before.left;
+  rect.top += after.top - before.top;
+  rect.right += after.right - before.right;
+  rect.bottom += after.bottom - before.bottom;
+
+  flags = SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOREPOSITION;
+
+  if (will_be_topmost && !was_topmost)
+    {
+      insert_after = HWND_TOPMOST;
+    }
+  else if (was_topmost && !will_be_topmost)
+    {
+      insert_after = HWND_NOTOPMOST;
+    }
+  else
+    {
+      flags |= SWP_NOZORDER;
+      insert_after = SWP_NOZORDER_SPECIFIED;
+    }
+
+  SetWindowPos (GDK_SURFACE_HWND (window), insert_after,
+               rect.left, rect.top,
+               rect.right - rect.left, rect.bottom - rect.top,
+               flags);
+}
+
+static void
+update_single_system_menu_entry (HMENU    hmenu,
+                                gboolean all,
+                                int      gdk_bit,
+                                int      menu_entry)
+{
+  /* all controls the interpretation of gdk_bit -- if all is TRUE,
+   * gdk_bit indicates whether menu entry is disabled; if all is
+   * FALSE, gdk bit indicate whether menu entry is enabled
+   */
+  if ((!all && gdk_bit) || (all && !gdk_bit))
+    EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_ENABLED);
+  else
+    EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_GRAYED);
+}
+
+static void
+update_system_menu (GdkSurface *window)
+{
+  GdkWMFunction functions;
+  BOOL all;
+
+  if (_gdk_surface_get_functions (window, &functions))
+    {
+      HMENU hmenu = GetSystemMenu (GDK_SURFACE_HWND (window), FALSE);
+
+      all = (functions & GDK_FUNC_ALL);
+      update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_RESIZE, SC_SIZE);
+      update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MOVE, SC_MOVE);
+      update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MINIMIZE, SC_MINIMIZE);
+      update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MAXIMIZE, SC_MAXIMIZE);
+      update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_CLOSE, SC_CLOSE);
+    }
+}
+
+static void
+gdk_win32_surface_set_decorations (GdkSurface      *window,
+                                 GdkWMDecoration decorations)
+{
+  GdkSurfaceImplWin32 *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_set_decorations: %p: %s %s%s%s%s%s%s\n",
+                          GDK_SURFACE_HWND (window),
+                          (decorations & GDK_DECOR_ALL ? "clearing" : "setting"),
+                          (decorations & GDK_DECOR_BORDER ? "BORDER " : ""),
+                          (decorations & GDK_DECOR_RESIZEH ? "RESIZEH " : ""),
+                          (decorations & GDK_DECOR_TITLE ? "TITLE " : ""),
+                          (decorations & GDK_DECOR_MENU ? "MENU " : ""),
+                          (decorations & GDK_DECOR_MINIMIZE ? "MINIMIZE " : ""),
+                          (decorations & GDK_DECOR_MAXIMIZE ? "MAXIMIZE " : "")));
+
+  if (!impl->decorations)
+    impl->decorations = g_malloc (sizeof (GdkWMDecoration));
+
+  *impl->decorations = decorations;
+
+  _gdk_win32_surface_update_style_bits (window);
+}
+
+static gboolean
+gdk_win32_surface_get_decorations (GdkSurface       *window,
+                                 GdkWMDecoration *decorations)
+{
+  GdkSurfaceImplWin32 *impl;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  if (impl->decorations == NULL)
+    return FALSE;
+
+  *decorations = *impl->decorations;
+
+  return TRUE;
+}
+
+static GQuark
+get_functions_quark ()
+{
+  static GQuark quark = 0;
+
+  if (!quark)
+    quark = g_quark_from_static_string ("gdk-window-functions");
+
+  return quark;
+}
+
+static void
+gdk_win32_surface_set_functions (GdkSurface    *window,
+                         GdkWMFunction functions)
+{
+  GdkWMFunction* functions_copy;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_set_functions: %p: %s %s%s%s%s%s\n",
+                          GDK_SURFACE_HWND (window),
+                          (functions & GDK_FUNC_ALL ? "clearing" : "setting"),
+                          (functions & GDK_FUNC_RESIZE ? "RESIZE " : ""),
+                          (functions & GDK_FUNC_MOVE ? "MOVE " : ""),
+                          (functions & GDK_FUNC_MINIMIZE ? "MINIMIZE " : ""),
+                          (functions & GDK_FUNC_MAXIMIZE ? "MAXIMIZE " : ""),
+                          (functions & GDK_FUNC_CLOSE ? "CLOSE " : "")));
+
+  functions_copy = g_malloc (sizeof (GdkWMFunction));
+  *functions_copy = functions;
+  g_object_set_qdata_full (G_OBJECT (window), get_functions_quark (), functions_copy, g_free);
+
+  update_system_menu (window);
+}
+
+gboolean
+_gdk_surface_get_functions (GdkSurface     *window,
+                          GdkWMFunction *functions)
+{
+  GdkWMFunction* functions_set;
+
+  functions_set = g_object_get_qdata (G_OBJECT (window), get_functions_quark ());
+  if (functions_set)
+    *functions = *functions_set;
+
+  return (functions_set != NULL);
+}
+
+#if defined(MORE_AEROSNAP_DEBUGGING)
+static void
+log_region (gchar *prefix, AeroSnapEdgeRegion *region)
+{
+  GDK_NOTE (MISC, g_print ("Region %s:\n"
+                           "edge %d x %d @ %d x %d\n"
+                           "trig %d x %d @ %d x %d\n",
+                           prefix,
+                           region->edge.width,
+                           region->edge.height,
+                           region->edge.x,
+                           region->edge.y,
+                           region->trigger.width,
+                           region->trigger.height,
+                           region->trigger.x,
+                           region->trigger.y));
+}
+#endif
+
+static void
+calculate_aerosnap_regions (GdkW32DragMoveResizeContext *context)
+{
+  GdkDisplay *display;
+  gint n_monitors, monitor_idx, other_monitor_idx;
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (context->window->impl);
+#if defined(MORE_AEROSNAP_DEBUGGING)
+  gint i;
+#endif
+
+  display = gdk_display_get_default ();
+  n_monitors = gdk_display_get_n_monitors (display);
+
+#define _M_UP 0
+#define _M_DOWN 1
+#define _M_LEFT 2
+#define _M_RIGHT 3
+
+  for (monitor_idx = 0; monitor_idx < n_monitors; monitor_idx++)
+    {
+      GdkRectangle wa;
+      GdkRectangle geometry;
+      AeroSnapEdgeRegion snap_region;
+      gboolean move_edge[4] = { TRUE, FALSE, TRUE, TRUE };
+      gboolean resize_edge[2] = { TRUE, TRUE };
+      gint diff;
+      gint thickness, trigger_thickness;
+      GdkMonitor *monitor;
+
+      monitor = gdk_display_get_monitor (display, monitor_idx);
+      gdk_monitor_get_workarea (monitor, &wa);
+      gdk_monitor_get_geometry (monitor, &geometry);
+
+      for (other_monitor_idx = 0;
+           other_monitor_idx < n_monitors &&
+           (move_edge[_M_UP] || move_edge[_M_LEFT] ||
+           move_edge[_M_RIGHT] || resize_edge[_M_DOWN]);
+           other_monitor_idx++)
+        {
+          GdkRectangle other_wa;
+          GdkMonitor *other_monitor;
+
+          if (other_monitor_idx == monitor_idx)
+            continue;
+
+          other_monitor = gdk_display_get_monitor (display, other_monitor_idx);
+          gdk_monitor_get_workarea (other_monitor, &other_wa);
+
+          /* An edge triggers AeroSnap only if there are no
+           * monitors beyond that edge.
+           * Even if there's another monitor, but it does not cover
+           * the whole edge (it's smaller or is not aligned to
+           * the corner of current monitor), that edge is still
+           * removed from the trigger list.
+           */
+          if (other_wa.x >= wa.x + wa.width)
+            move_edge[_M_RIGHT] = FALSE;
+
+          if (other_wa.x + other_wa.width <= wa.x)
+            move_edge[_M_LEFT] = FALSE;
+
+          if (other_wa.y + other_wa.height <= wa.y)
+            {
+              move_edge[_M_UP] = FALSE;
+              resize_edge[_M_UP] = FALSE;
+            }
+
+          if (other_wa.y >= wa.y + wa.height)
+            {
+              /* no move_edge for the bottom edge, just resize_edge */
+              resize_edge[_M_DOWN] = FALSE;
+            }
+        }
+
+      thickness = AEROSNAP_REGION_THICKNESS * impl->window_scale;
+      trigger_thickness = AEROSNAP_REGION_TRIGGER_THICKNESS * impl->window_scale;
+
+      snap_region.edge = wa;
+      snap_region.trigger = wa;
+      snap_region.edge.height = thickness;
+      snap_region.trigger.height = trigger_thickness;
+
+      /* Extend both regions into toolbar space.
+       * When there's no toolbar, diff == 0.
+       */
+      diff = wa.y - geometry.y;
+      snap_region.edge.height += diff;
+      snap_region.edge.y -= diff;
+      snap_region.trigger.height += diff;
+      snap_region.trigger.y -= diff;
+
+      if (move_edge[_M_UP])
+        g_array_append_val (context->maximize_regions, snap_region);
+
+      if (resize_edge[_M_UP])
+        g_array_append_val (context->fullup_regions, snap_region);
+
+      snap_region.edge = wa;
+      snap_region.trigger = wa;
+      snap_region.edge.width = thickness;
+      snap_region.trigger.width = trigger_thickness;
+
+      diff = wa.x - geometry.x;
+      snap_region.edge.width += diff;
+      snap_region.edge.x -= diff;
+      snap_region.trigger.width += diff;
+      snap_region.trigger.x -= diff;
+
+      if (move_edge[_M_LEFT])
+        g_array_append_val (context->halfleft_regions, snap_region);
+
+      snap_region.edge = wa;
+      snap_region.trigger = wa;
+      snap_region.edge.x += wa.width - thickness;
+      snap_region.edge.width = thickness;
+      snap_region.trigger.x += wa.width - trigger_thickness;
+      snap_region.trigger.width = trigger_thickness;
+
+      diff = (geometry.x + geometry.width) - (wa.x + wa.width);
+      snap_region.edge.width += diff;
+      snap_region.trigger.width += diff;
+
+      if (move_edge[_M_RIGHT])
+        g_array_append_val (context->halfright_regions, snap_region);
+
+      snap_region.edge = wa;
+      snap_region.trigger = wa;
+      snap_region.edge.y += wa.height - thickness;
+      snap_region.edge.height = thickness;
+      snap_region.trigger.y += wa.height - trigger_thickness;
+      snap_region.trigger.height = trigger_thickness;
+
+      diff = (geometry.y + geometry.height) - (wa.y + wa.height);
+      snap_region.edge.height += diff;
+      snap_region.trigger.height += diff;
+
+      if (resize_edge[_M_DOWN])
+        g_array_append_val (context->fullup_regions, snap_region);
+    }
+
+#undef _M_UP
+#undef _M_DOWN
+#undef _M_LEFT
+#undef _M_RIGHT
+
+#if defined(MORE_AEROSNAP_DEBUGGING)
+  for (i = 0; i < context->maximize_regions->len; i++)
+    log_region ("maximize", &g_array_index (context->maximize_regions, AeroSnapEdgeRegion, i));
+
+  for (i = 0; i < context->halfleft_regions->len; i++)
+    log_region ("halfleft", &g_array_index (context->halfleft_regions, AeroSnapEdgeRegion, i));
+
+  for (i = 0; i < context->halfright_regions->len; i++)
+    log_region ("halfright", &g_array_index (context->halfright_regions, AeroSnapEdgeRegion, i));
+
+  for (i = 0; i < context->fullup_regions->len; i++)
+    log_region ("fullup", &g_array_index (context->fullup_regions, AeroSnapEdgeRegion, i));
+#endif
+}
+
+static void
+discard_snapinfo (GdkSurface *window)
+{
+  GdkSurfaceImplWin32 *impl;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  impl->snap_state = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
+
+  if (impl->snap_stash == NULL)
+    return;
+
+  g_clear_pointer (&impl->snap_stash, g_free);
+  g_clear_pointer (&impl->snap_stash_int, g_free);
+}
+
+static void
+unsnap (GdkSurface  *window,
+        GdkMonitor *monitor)
+{
+  GdkSurfaceImplWin32 *impl;
+  GdkRectangle rect;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  impl->snap_state = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
+
+  if (impl->snap_stash == NULL)
+    return;
+
+  gdk_monitor_get_workarea (monitor, &rect);
+
+  GDK_NOTE (MISC, g_print ("Monitor work area %d x %d @ %d : %d\n", rect.width, rect.height, rect.x, rect.y));
+
+  if (rect.width >= impl->snap_stash_int->width &&
+      rect.height >= impl->snap_stash_int->height)
+    {
+      /* If the window fits into new work area without resizing it,
+       * place it into new work area without resizing it.
+       */
+      gdouble left, right, up, down, hratio, vratio;
+      gdouble hscale, vscale;
+      gdouble new_left, new_up;
+
+      left = impl->snap_stash->x;
+      right = 1.0 - (impl->snap_stash->x + impl->snap_stash->width);
+      up = impl->snap_stash->y;
+      down = 1.0 - (impl->snap_stash->y + impl->snap_stash->height);
+      hscale = 1.0;
+
+      if (right > 0.001)
+        {
+          hratio = left / right;
+          hscale = hratio / (1.0 + hratio);
+        }
+
+      new_left = (gdouble) (rect.width - impl->snap_stash_int->width) * hscale;
+
+      vscale = 1.0;
+
+      if (down > 0.001)
+        {
+          vratio = up / down;
+          vscale = vratio / (1.0 + vratio);
+        }
+
+      new_up = (gdouble) (rect.height - impl->snap_stash_int->height) * vscale;
+
+      rect.x = round (rect.x + new_left);
+      rect.y = round (rect.y + new_up);
+      rect.width = impl->snap_stash_int->width;
+      rect.height = impl->snap_stash_int->height;
+    }
+  else
+    {
+      /* Calculate actual unsnapped window size based on its
+       * old relative size. Same for position.
+       */
+      rect.x += round (rect.width * impl->snap_stash->x);
+      rect.y += round (rect.height * impl->snap_stash->y);
+      rect.width = round (rect.width * impl->snap_stash->width);
+      rect.height = round (rect.height * impl->snap_stash->height);
+    }
+
+  GDK_NOTE (MISC, g_print ("Unsnapped window size %d x %d @ %d : %d\n", rect.width, rect.height, rect.x, rect.y));
+
+  gdk_surface_move_resize (window, rect.x, rect.y,
+                          rect.width, rect.height);
+
+  g_clear_pointer (&impl->snap_stash, g_free);
+  g_clear_pointer (&impl->snap_stash_int, g_free);
+}
+
+static void
+stash_window (GdkSurface          *window,
+              GdkSurfaceImplWin32 *impl)
+{
+  gint x, y;
+  gint width, wwidth;
+  gint height, wheight;
+  WINDOWPLACEMENT placement;
+  HMONITOR hmonitor;
+  MONITORINFO hmonitor_info;
+
+  placement.length = sizeof(WINDOWPLACEMENT);
+
+  /* Use W32 API to get unmaximized window size, which GDK doesn't remember */
+  if (!GetWindowPlacement (GDK_SURFACE_HWND (window), &placement))
+    return;
+
+  /* MSDN is very vague, but in practice rcNormalPosition is the same as GetWindowRect(),
+   * only with adjustments for toolbars (which creates rather weird coodinate space issues).
+   * We need to get monitor info and apply workarea vs monitorarea diff to turn
+   * these into screen coordinates proper.
+   */
+  hmonitor = MonitorFromWindow (GDK_SURFACE_HWND (window), MONITOR_DEFAULTTONEAREST);
+  hmonitor_info.cbSize = sizeof (hmonitor_info);
+
+  if (!GetMonitorInfoA (hmonitor, &hmonitor_info))
+    return;
+
+  if (impl->snap_stash == NULL)
+    impl->snap_stash = g_new0 (GdkRectangleDouble, 1);
+
+  if (impl->snap_stash_int == NULL)
+    impl->snap_stash_int = g_new0 (GdkRectangle, 1);
+
+  GDK_NOTE (MISC, g_print ("monitor work area  %ld x %ld @ %ld : %ld\n",
+                           (hmonitor_info.rcWork.right - hmonitor_info.rcWork.left) / impl->window_scale,
+                           (hmonitor_info.rcWork.bottom - hmonitor_info.rcWork.top) / impl->window_scale,
+                           hmonitor_info.rcWork.left,
+                           hmonitor_info.rcWork.top));
+  GDK_NOTE (MISC, g_print ("monitor      area  %ld x %ld @ %ld : %ld\n",
+                           (hmonitor_info.rcMonitor.right - hmonitor_info.rcMonitor.left) / impl->window_scale,
+                           (hmonitor_info.rcMonitor.bottom - hmonitor_info.rcMonitor.top) / impl->window_scale,
+                           hmonitor_info.rcMonitor.left,
+                           hmonitor_info.rcMonitor.top));
+  GDK_NOTE (MISC, g_print ("window  work place %ld x %ld @ %ld : %ld\n",
+                           (placement.rcNormalPosition.right - placement.rcNormalPosition.left) / impl->window_scale,
+                           (placement.rcNormalPosition.bottom - placement.rcNormalPosition.top) / impl->window_scale,
+                           placement.rcNormalPosition.left,
+                           placement.rcNormalPosition.top));
+
+  width = (placement.rcNormalPosition.right - placement.rcNormalPosition.left) / impl->window_scale;
+  height = (placement.rcNormalPosition.bottom - placement.rcNormalPosition.top) / impl->window_scale;
+  x = (placement.rcNormalPosition.left - hmonitor_info.rcMonitor.left) / impl->window_scale;
+  y = (placement.rcNormalPosition.top - hmonitor_info.rcMonitor.top) / impl->window_scale;
+
+  wwidth = (hmonitor_info.rcWork.right - hmonitor_info.rcWork.left) / impl->window_scale;
+  wheight = (hmonitor_info.rcWork.bottom - hmonitor_info.rcWork.top) / impl->window_scale;
+
+  impl->snap_stash->x = (gdouble) (x) / (gdouble) (wwidth);
+  impl->snap_stash->y = (gdouble) (y) / (gdouble) (wheight);
+  impl->snap_stash->width = (gdouble) width / (gdouble) (wwidth);
+  impl->snap_stash->height = (gdouble) height / (gdouble) (wheight);
+
+  impl->snap_stash_int->x = x;
+  impl->snap_stash_int->y = y;
+  impl->snap_stash_int->width = width;
+  impl->snap_stash_int->height = height;
+
+  GDK_NOTE (MISC, g_print ("Stashed window %d x %d @ %d : %d as %f x %f @ %f : %f\n",
+                           width, height, x, y,
+                           impl->snap_stash->width, impl->snap_stash->height, impl->snap_stash->x, impl->snap_stash->y));
+}
+
+static void
+snap_up (GdkSurface *window)
+{
+  SHORT maxysize;
+  gint x, y;
+  gint width, height;
+  GdkSurfaceImplWin32 *impl;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  impl->snap_state = GDK_WIN32_AEROSNAP_STATE_FULLUP;
+
+  stash_window (window, impl);
+
+  maxysize = GetSystemMetrics (SM_CYVIRTUALSCREEN) / impl->window_scale;
+  gdk_surface_get_position (window, &x, &y);
+  width = gdk_surface_get_width (window);
+
+  y = 0;
+  height = maxysize;
+
+  x = x - impl->margins.left;
+  y = y - impl->margins.top;
+  width += impl->margins_x;
+  height += impl->margins_y;
+
+  gdk_surface_move_resize (window, x, y, width, height);
+}
+
+static void
+snap_left (GdkSurface  *window,
+           GdkMonitor *monitor,
+           GdkMonitor *snap_monitor)
+{
+  GdkRectangle rect;
+  GdkSurfaceImplWin32 *impl;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  impl->snap_state = GDK_WIN32_AEROSNAP_STATE_HALFLEFT;
+
+  gdk_monitor_get_workarea (snap_monitor, &rect);
+
+  stash_window (window, impl);
+
+  rect.width = rect.width / 2;
+
+  rect.x = rect.x - impl->margins.left;
+  rect.y = rect.y - impl->margins.top;
+  rect.width = rect.width + impl->margins_x;
+  rect.height = rect.height + impl->margins_y;
+
+  gdk_surface_move_resize (window, rect.x, rect.y, rect.width, rect.height);
+}
+
+static void
+snap_right (GdkSurface  *window,
+            GdkMonitor *monitor,
+            GdkMonitor *snap_monitor)
+{
+  GdkRectangle rect;
+  GdkSurfaceImplWin32 *impl;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  impl->snap_state = GDK_WIN32_AEROSNAP_STATE_HALFRIGHT;
+
+  gdk_monitor_get_workarea (snap_monitor, &rect);
+
+  stash_window (window, impl);
+
+  rect.width = rect.width / 2;
+  rect.x += rect.width;
+
+  rect.x = rect.x - impl->margins.left;
+  rect.y = rect.y - impl->margins.top;
+  rect.width = rect.width + impl->margins_x;
+  rect.height = rect.height + impl->margins_y;
+
+  gdk_surface_move_resize (window, rect.x, rect.y, rect.width, rect.height);
+}
+
+void
+_gdk_win32_surface_handle_aerosnap (GdkSurface            *window,
+                                   GdkWin32AeroSnapCombo combo)
+{
+  GdkSurfaceImplWin32 *impl;
+  GdkDisplay *display;
+  gint n_monitors;
+  GdkSurfaceState window_state = gdk_surface_get_state (window);
+  gboolean minimized = window_state & GDK_SURFACE_STATE_ICONIFIED;
+  gboolean maximized = window_state & GDK_SURFACE_STATE_MAXIMIZED;
+  gboolean halfsnapped;
+  GdkMonitor *monitor;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+  display = gdk_surface_get_display (window);
+  n_monitors = gdk_display_get_n_monitors (display);
+  monitor = gdk_display_get_monitor_at_window (display, window);
+
+  if (minimized && maximized)
+    minimized = FALSE;
+
+  halfsnapped = (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFRIGHT ||
+                 impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFLEFT ||
+                 impl->snap_state == GDK_WIN32_AEROSNAP_STATE_FULLUP);
+
+  switch (combo)
+    {
+    case GDK_WIN32_AEROSNAP_COMBO_NOTHING:
+      /* Do nothing */
+      break;
+    case GDK_WIN32_AEROSNAP_COMBO_UP:
+      if (!maximized)
+        {
+         unsnap (window, monitor);
+          gdk_surface_maximize (window);
+        }
+      break;
+    case GDK_WIN32_AEROSNAP_COMBO_DOWN:
+    case GDK_WIN32_AEROSNAP_COMBO_SHIFTDOWN:
+      if (maximized)
+        {
+         gdk_surface_unmaximize (window);
+         unsnap (window, monitor);
+        }
+      else if (halfsnapped)
+       unsnap (window, monitor);
+      else if (!minimized)
+       gdk_surface_iconify (window);
+      break;
+    case GDK_WIN32_AEROSNAP_COMBO_LEFT:
+      if (maximized)
+        gdk_surface_unmaximize (window);
+
+      if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_UNDETERMINED ||
+         impl->snap_state == GDK_WIN32_AEROSNAP_STATE_FULLUP)
+       {
+         unsnap (window, monitor);
+         snap_left (window, monitor, monitor);
+       }
+      else if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFLEFT)
+       {
+         unsnap (window, monitor);
+         snap_right (window,
+                     monitor,
+                     gdk_monitor_is_primary (monitor) ? monitor : gdk_display_get_monitor (display, n_monitors - 1));
+       }
+      else if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFRIGHT)
+       {
+         unsnap (window, monitor);
+       }
+      break;
+    case GDK_WIN32_AEROSNAP_COMBO_RIGHT:
+      if (maximized)
+        gdk_surface_unmaximize (window);
+
+      if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_UNDETERMINED ||
+         impl->snap_state == GDK_WIN32_AEROSNAP_STATE_FULLUP)
+       {
+         unsnap (window, monitor);
+         snap_right (window, monitor, monitor);
+       }
+      else if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFLEFT)
+       {
+         unsnap (window, monitor);
+       }
+      else if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFRIGHT)
+       {
+         gint i;
+
+         unsnap (window, monitor);
+         if (n_monitors == 1 ||
+             monitor == gdk_display_get_monitor (display, n_monitors - 1))
+           {
+             snap_left (window, monitor, monitor);
+           }
+         else
+           {
+             for (i = 0; i < n_monitors; i++)
+               {
+                 if (monitor == gdk_display_get_monitor (display, i))
+                   break;
+               }
+
+             snap_left (window, monitor, gdk_display_get_monitor (display, i + 1));
+           }
+       }
+      break;
+    case GDK_WIN32_AEROSNAP_COMBO_SHIFTUP:
+      if (!maximized &&
+          impl->snap_state == GDK_WIN32_AEROSNAP_STATE_UNDETERMINED)
+       {
+         snap_up (window);
+       }
+      break;
+    case GDK_WIN32_AEROSNAP_COMBO_SHIFTLEFT:
+    case GDK_WIN32_AEROSNAP_COMBO_SHIFTRIGHT:
+      /* No implementation needed at the moment */
+      break;
+    }
+}
+
+static void
+apply_snap (GdkSurface             *window,
+            GdkWin32AeroSnapState  snap)
+{
+  GdkMonitor *monitor;
+  GdkDisplay *display;
+
+  display = gdk_surface_get_display (window);
+  monitor = gdk_display_get_monitor_at_window (display, window);
+
+  switch (snap)
+    {
+    case GDK_WIN32_AEROSNAP_STATE_UNDETERMINED:
+      break;
+    case GDK_WIN32_AEROSNAP_STATE_MAXIMIZE:
+      unsnap (window, monitor);
+      gdk_surface_maximize (window);
+      break;
+    case GDK_WIN32_AEROSNAP_STATE_HALFLEFT:
+      unsnap (window, monitor);
+      snap_left (window, monitor, monitor);
+      break;
+    case GDK_WIN32_AEROSNAP_STATE_HALFRIGHT:
+      unsnap (window, monitor);
+      snap_right (window, monitor, monitor);
+      break;
+    case GDK_WIN32_AEROSNAP_STATE_FULLUP:
+      snap_up (window);
+      break;
+    }
+}
+
+/* Registers a dumb window class. This window
+ * has DefWindowProc() for a window procedure and
+ * does not do anything that GdkSurface-bound HWNDs do.
+ */
+static ATOM
+RegisterGdkDumbClass ()
+{
+  static ATOM klassDUMB = 0;
+  static WNDCLASSEXW wcl;
+  ATOM klass = 0;
+
+  wcl.cbSize = sizeof (WNDCLASSEX);
+  wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
+                  * on WM_SIZE and WM_MOVE. Flicker, Performance!
+                  */
+  wcl.lpfnWndProc = DefWindowProcW;
+  wcl.cbClsExtra = 0;
+  wcl.cbWndExtra = 0;
+  wcl.hInstance = _gdk_app_hmodule;
+  wcl.hIcon = 0;
+  wcl.hIconSm = 0;
+  wcl.lpszMenuName = NULL;
+  wcl.hbrBackground = NULL;
+  wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
+  wcl.style |= CS_OWNDC;
+  wcl.lpszClassName = L"gdkWindowDumb";
+
+  if (klassDUMB == 0)
+    klassDUMB = RegisterClassExW (&wcl);
+
+  klass = klassDUMB;
+
+  if (klass == 0)
+    {
+      WIN32_API_FAILED ("RegisterClassExW");
+      g_error ("That is a fatal error");
+    }
+
+  return klass;
+}
+
+static gboolean
+ensure_snap_indicator_exists (GdkW32DragMoveResizeContext *context)
+{
+  if (context->shape_indicator == NULL)
+    {
+      HWND handle;
+      ATOM klass;
+      klass = RegisterGdkDumbClass ();
+
+      handle = CreateWindowExW (WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOACTIVATE,
+                                MAKEINTRESOURCEW (klass),
+                                L"",
+                                WS_POPUP,
+                                0,
+                                0,
+                                0, 0,
+                                NULL,
+                                NULL,
+                                _gdk_app_hmodule,
+                                NULL);
+
+      context->shape_indicator = handle;
+    }
+
+  return context->shape_indicator != NULL;
+}
+
+static gboolean
+ensure_snap_indicator_surface (GdkW32DragMoveResizeContext *context,
+                          gint                         width,
+                          gint                         height,
+                          guint                        scale)
+{
+  if (context->indicator_surface != NULL &&
+      (context->indicator_surface_width < width ||
+       context->indicator_surface_height < height))
+    {
+      cairo_surface_destroy (context->indicator_surface);
+      context->indicator_surface = NULL;
+    }
+
+  if (context->indicator_surface == NULL)
+    context->indicator_surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
+                                                                      width * scale,
+                                                                      height * scale);
+
+  if (cairo_surface_status (context->indicator_surface) != CAIRO_STATUS_SUCCESS)
+    {
+      cairo_surface_destroy (context->indicator_surface);
+      context->indicator_surface = NULL;
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Indicator is drawn with some inward offset, so that it does
+ * not hug screen edges.
+ */
+static void
+adjust_indicator_rectangle (GdkRectangle *rect,
+                            gboolean      inward)
+{
+  gdouble inverter;
+  const gint gap = AEROSNAP_INDICATOR_EDGE_GAP;
+#if defined(MORE_AEROSNAP_DEBUGGING)
+  GdkRectangle cache = *rect;
+#endif
+
+  if (inward)
+    inverter = 1.0;
+  else
+    inverter = -1.0;
+
+  rect->x += (gap * inverter);
+  rect->y += (gap * inverter);
+  rect->width -= (gap * 2 * inverter);
+  rect->height -= (gap * 2 * inverter);
+
+#if defined(MORE_AEROSNAP_DEBUGGING)
+  GDK_NOTE (MISC, g_print ("Adjusted %d x %d @ %d : %d -> %d x %d @ %d : %d\n",
+                           cache.width, cache.height, cache.x, cache.y,
+                           rect->width, rect->height, rect->x, rect->y));
+#endif
+}
+
+static void
+rounded_rectangle (cairo_t  *cr,
+                   gint      x,
+                   gint      y,
+                   gint      width,
+                   gint      height,
+                   gdouble   radius,
+                   gdouble   line_width,
+                   GdkRGBA  *fill,
+                   GdkRGBA  *outline)
+{
+  gdouble degrees = M_PI / 180.0;
+
+  if (fill == NULL && outline == NULL)
+    return;
+
+  cairo_save (cr);
+  cairo_new_sub_path (cr);
+  cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees);
+  cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees);
+  cairo_arc (cr, (x + radius), y + height - radius, radius, 90 * degrees, 180 * degrees);
+  cairo_arc (cr, (x + radius), (y + radius), radius, 180 * degrees, 270 * degrees);
+  cairo_close_path (cr);
+
+  if (fill)
+    {
+      cairo_set_source_rgba (cr, fill->red, fill->green, fill->blue, fill->alpha);
+
+      if (outline)
+        cairo_fill_preserve (cr);
+      else
+        cairo_fill (cr);
+    }
+
+  if (outline)
+    {
+      cairo_set_source_rgba (cr, outline->red, outline->green, outline->blue, outline->alpha);
+      cairo_set_line_width (cr, line_width);
+      cairo_stroke (cr);
+    }
+
+  cairo_restore (cr);
+}
+
+/* Translates linear animation scale into some kind of curve */
+static gdouble
+curve (gdouble val)
+{
+  /* TODO: try different curves. For now it's just linear */
+  return val;
+}
+
+static gboolean
+draw_indicator (GdkW32DragMoveResizeContext *context,
+                gint64                       timestamp)
+{
+  cairo_t *cr;
+  GdkRGBA outline = {0, 0, 1.0, 1.0};
+  GdkRGBA fill = {0, 0, 1.0, 0.8};
+  GdkRectangle current_rect;
+  gint64 current_time = g_get_monotonic_time ();
+  gdouble animation_progress;
+  gboolean last_draw;
+  gdouble line_width;
+  gdouble corner_radius;
+  gint64 animation_duration;
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (context->window->impl);
+
+  line_width = AEROSNAP_INDICATOR_LINE_WIDTH * impl->window_scale;
+  corner_radius = AEROSNAP_INDICATOR_CORNER_RADIUS;
+  animation_duration = AEROSNAP_INDICATOR_ANIMATION_DURATION;
+  last_draw = FALSE;
+
+  if (timestamp == 0 &&
+      current_time - context->indicator_start_time > animation_duration)
+    {
+      timestamp = context->indicator_start_time + animation_duration;
+      last_draw = TRUE;
+    }
+
+  if (timestamp != 0)
+    current_time = timestamp;
+
+  animation_progress = (gdouble) (current_time - context->indicator_start_time) / animation_duration;
+
+  if (animation_progress > 1.0)
+    animation_progress = 1.0;
+
+  if (animation_progress < 0)
+    animation_progress = 0;
+
+  animation_progress = curve (animation_progress);
+
+  current_rect = context->indicator_start;
+  current_rect.x += (context->indicator_target.x - context->indicator_start.x) * animation_progress;
+  current_rect.y += (context->indicator_target.y - context->indicator_start.y) * animation_progress;
+  current_rect.width += (context->indicator_target.width - context->indicator_start.width) * animation_progress;
+  current_rect.height += (context->indicator_target.height - context->indicator_start.height) * animation_progress;
+
+  if (context->op == GDK_WIN32_DRAGOP_RESIZE && last_draw)
+    {
+      switch (context->edge)
+        {
+        case GDK_SURFACE_EDGE_NORTH_WEST:
+          current_rect.x = context->indicator_target.x + (context->indicator_target.width - current_rect.width);
+          current_rect.y = context->indicator_target.y + (context->indicator_target.height - current_rect.height);
+          break;
+        case GDK_SURFACE_EDGE_NORTH:
+          current_rect.y = context->indicator_target.y + (context->indicator_target.height - current_rect.height);
+          break;
+        case GDK_SURFACE_EDGE_WEST:
+          current_rect.x = context->indicator_target.x + (context->indicator_target.width - current_rect.width);
+          break;
+        case GDK_SURFACE_EDGE_SOUTH_WEST:
+          current_rect.x = context->indicator_target.x + (context->indicator_target.width - current_rect.width);
+          current_rect.y = context->indicator_target.y;
+          break;
+        case GDK_SURFACE_EDGE_NORTH_EAST:
+          current_rect.x = context->indicator_target.x;
+          current_rect.y = context->indicator_target.y + (context->indicator_target.height - current_rect.height);
+          break;
+        case GDK_SURFACE_EDGE_SOUTH_EAST:
+          current_rect.x = context->indicator_target.x;
+          current_rect.y = context->indicator_target.y;
+          break;
+        case GDK_SURFACE_EDGE_SOUTH:
+          current_rect.y = context->indicator_target.y;
+          break;
+        case GDK_SURFACE_EDGE_EAST:
+          current_rect.x = context->indicator_target.x;
+          break;
+        }
+    }
+
+  cr = cairo_create (context->indicator_surface);
+  rounded_rectangle (cr,
+                     (current_rect.x - context->indicator_window_rect.x) * impl->window_scale,
+                     (current_rect.y - context->indicator_window_rect.y) * impl->window_scale,
+                     current_rect.width * impl->window_scale,
+                     current_rect.height * impl->window_scale,
+                     corner_radius,
+                     line_width,
+                     &fill, &outline);
+  cairo_destroy (cr);
+
+#if defined(MORE_AEROSNAP_DEBUGGING)
+  GDK_NOTE (MISC, g_print ("Indicator is %d x %d @ %d : %d; current time is %" G_GINT64_FORMAT "\n",
+                           current_rect.width, current_rect.height,
+                           current_rect.x - context->indicator_window_rect.x,
+                           current_rect.y - context->indicator_window_rect.y,
+                           current_time));
+#endif
+
+  return last_draw;
+}
+
+static gboolean
+redraw_indicator (gpointer user_data)
+{
+  GdkW32DragMoveResizeContext *context = user_data;
+  POINT window_position;
+  SIZE window_size;
+  BLENDFUNCTION blender;
+  HDC hdc;
+  POINT source_point = { 0, 0 };
+  gboolean last_draw;
+  gdouble indicator_opacity;
+  GdkSurfaceImplWin32 *impl;
+  gboolean do_source_remove = FALSE;
+
+  indicator_opacity = AEROSNAP_INDICATOR_OPACITY;
+
+  if (GDK_SURFACE_DESTROYED (context->window) ||
+      !ensure_snap_indicator_exists (context))
+    {
+      do_source_remove = TRUE;
+    }
+
+  impl = GDK_SURFACE_IMPL_WIN32 (context->window->impl);
+
+  if (!ensure_snap_indicator_surface (context,
+                                      context->indicator_window_rect.width,
+                                      context->indicator_window_rect.height,
+                                      impl->window_scale))
+    {
+      do_source_remove = TRUE;
+    }
+
+  if (do_source_remove)
+    {
+      context->timer = 0;
+      return G_SOURCE_REMOVE;
+    }
+
+  last_draw = draw_indicator (context, context->draw_timestamp);
+
+  window_position.x = (context->indicator_window_rect.x - _gdk_offset_x) * impl->window_scale;
+  window_position.y = (context->indicator_window_rect.y - _gdk_offset_y) * impl->window_scale;
+  window_size.cx = context->indicator_window_rect.width * impl->window_scale;
+  window_size.cy = context->indicator_window_rect.height * impl->window_scale;
+
+  blender.BlendOp = AC_SRC_OVER;
+  blender.BlendFlags = 0;
+  blender.AlphaFormat = AC_SRC_ALPHA;
+  blender.SourceConstantAlpha = 255 * indicator_opacity;
+
+  hdc = cairo_win32_surface_get_dc (context->indicator_surface);
+
+  API_CALL (SetWindowPos, (context->shape_indicator,
+                           GDK_SURFACE_HWND (context->window),
+                           0, 0, 0, 0,
+                           SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW | SWP_SHOWWINDOW | SWP_NOACTIVATE));
+
+#if defined(MORE_AEROSNAP_DEBUGGING)
+  GDK_NOTE (MISC, g_print ("Indicator window position is %ld x %ld @ %ld : %ld\n",
+                           window_size.cx, window_size.cy,
+                           window_position.x, window_position.y));
+#endif
+
+  API_CALL (UpdateLayeredWindow, (context->shape_indicator, NULL,
+                                  &window_position, &window_size,
+                                  hdc, &source_point,
+                                  0, &blender, ULW_ALPHA));
+
+  if (last_draw)
+    context->timer = 0;
+
+  return last_draw ? G_SOURCE_REMOVE : G_SOURCE_CONTINUE;
+}
+
+static GdkRectangle
+unity_of_rects (GdkRectangle a,
+                GdkRectangle b)
+{
+  GdkRectangle u = b;
+
+  if (a.x < u.x)
+    {
+      u.width += u.x - a.x;
+      u.x = a.x;
+    }
+
+  if (a.y < u.y)
+    {
+      u.height += (u.y - a.y);
+      u.y = a.y;
+    }
+
+  if (a.x + a.width > u.x + u.width)
+    u.width += (a.x + a.width) - (u.x + u.width);
+
+  if (a.y + a.height > u.y + u.height)
+    u.height += (a.y + a.height) - (u.y + u.height);
+
+#if defined(MORE_AEROSNAP_DEBUGGING)
+  GDK_NOTE (MISC, g_print ("Unified 2 rects into %d x %d @ %d : %d\n",
+                           u.width, u.height, u.x, u.y));
+#endif
+
+  return u;
+}
+
+static void
+start_indicator_drawing (GdkW32DragMoveResizeContext *context,
+                         GdkRectangle                 from,
+                         GdkRectangle                 to,
+                         guint                        scale)
+{
+  GdkRectangle to_adjusted, from_adjusted, from_or_to;
+  gint64 indicator_animation_tick = AEROSNAP_INDICATOR_ANIMATION_TICK;
+
+  GDK_NOTE (MISC, g_print ("Start drawing snap indicator %d x %d @ %d : %d -> %d x %d @ %d : %d\n",
+                           from.width * scale, from.height * scale, from.x, from.y, to.width * scale, to.height * scale, to.x, to.y));
+
+  if (GDK_SURFACE_DESTROYED (context->window))
+    return;
+
+  if (!ensure_snap_indicator_exists (context))
+    return;
+
+  from_or_to = unity_of_rects (from, to);
+
+  if (!ensure_snap_indicator_surface (context, from_or_to.width, from_or_to.height, scale))
+    return;
+
+  to_adjusted = to;
+  adjust_indicator_rectangle (&to_adjusted, TRUE);
+
+  from_adjusted = from;
+  adjust_indicator_rectangle (&from_adjusted, TRUE);
+
+  context->draw_timestamp = 0;
+  context->indicator_start = from_adjusted;
+  context->indicator_target = to_adjusted;
+  context->indicator_window_rect = from_or_to;
+  context->indicator_start_time = g_get_monotonic_time ();
+
+  if (context->timer)
+    {
+      g_source_remove (context->timer);
+      context->timer = 0;
+    }
+
+  context->timer = g_timeout_add_full (G_PRIORITY_DEFAULT,
+                                       indicator_animation_tick,
+                                       redraw_indicator,
+                                       context,
+                                       NULL);
+}
+
+static void
+update_fullup_indicator (GdkSurface                   *window,
+                         GdkW32DragMoveResizeContext *context)
+{
+  SHORT maxysize;
+  GdkRectangle from, to;
+  GdkRectangle to_adjusted, from_adjusted, from_or_to;
+  GdkSurfaceImplWin32 *impl;
+
+  GDK_NOTE (MISC, g_print ("Update fullup indicator\n"));
+
+  if (GDK_SURFACE_DESTROYED (context->window))
+    return;
+
+  if (context->shape_indicator == NULL)
+    return;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+  maxysize = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+  gdk_surface_get_position (window, &to.x, &to.y);
+  to.width = gdk_surface_get_width (window);
+  to.height = gdk_surface_get_height (window);
+
+  to.y = 0;
+  to.height = maxysize;
+  from = context->indicator_target;
+
+  if (context->timer == 0)
+    {
+      from_adjusted = from;
+      adjust_indicator_rectangle (&from_adjusted, FALSE);
+
+      GDK_NOTE (MISC, g_print ("Restart fullup animation from %d x %d @ %d : %d -> %d x %d @ %d x %d\n",
+                               context->indicator_target.width, context->indicator_target.height,
+                               context->indicator_target.x, context->indicator_target.y,
+                               to.width, to.height, to.x, to.y));
+      start_indicator_drawing (context, from_adjusted, to, impl->window_scale);
+
+      return;
+    }
+
+  from_or_to = unity_of_rects (from, to);
+
+  to_adjusted = to;
+  adjust_indicator_rectangle (&to_adjusted, TRUE);
+
+  GDK_NOTE (MISC, g_print ("Retarget fullup animation %d x %d @ %d : %d -> %d x %d @ %d x %d\n",
+                           context->indicator_target.width, context->indicator_target.height,
+                           context->indicator_target.x, context->indicator_target.y,
+                           to_adjusted.width, to_adjusted.height, to_adjusted.x, to_adjusted.y));
+
+  context->indicator_target = to_adjusted;
+  context->indicator_window_rect = from_or_to;
+
+  ensure_snap_indicator_surface (context, from_or_to.width, from_or_to.height, impl->window_scale);
+}
+
+static void
+start_indicator (GdkSurface                   *window,
+                 GdkW32DragMoveResizeContext *context,
+                 gint                         x,
+                 gint                         y,
+                 GdkWin32AeroSnapState        state)
+{
+  GdkMonitor *monitor;
+  GdkRectangle workarea;
+  SHORT maxysize;
+  GdkRectangle start_size, end_size;
+  GdkDisplay *display;
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  display = gdk_surface_get_display (window);
+  monitor = gdk_display_get_monitor_at_point (display, x, y);
+  gdk_monitor_get_workarea (monitor, &workarea);
+
+  maxysize = GetSystemMetrics (SM_CYVIRTUALSCREEN) / impl->window_scale;
+  gdk_surface_get_position (window, &start_size.x, &start_size.y);
+  start_size.width = gdk_surface_get_width (window);
+  start_size.height = gdk_surface_get_height (window);
+
+  end_size = start_size;
+
+  switch (state)
+    {
+    case GDK_WIN32_AEROSNAP_STATE_UNDETERMINED:
+      return;
+    case GDK_WIN32_AEROSNAP_STATE_MAXIMIZE:
+      end_size.x = workarea.x;
+      end_size.y = workarea.y;
+      end_size.width = workarea.width;
+      end_size.height = workarea.height;
+      break;
+    case GDK_WIN32_AEROSNAP_STATE_HALFLEFT:
+      end_size.x = workarea.x;
+      end_size.y = workarea.y;
+      end_size.width = workarea.width / 2;
+      end_size.height = workarea.height;
+      break;
+    case GDK_WIN32_AEROSNAP_STATE_HALFRIGHT:
+      end_size.x = (workarea.x + workarea.width / 2);
+      end_size.y = workarea.y;
+      end_size.width = workarea.width / 2;
+      end_size.height = workarea.height;
+      break;
+    case GDK_WIN32_AEROSNAP_STATE_FULLUP:
+      end_size.y = 0;
+      end_size.height = maxysize;
+      break;
+    }
+
+  start_indicator_drawing (context, start_size, end_size, impl->window_scale);
+}
+
+static void
+stop_indicator (GdkSurface                   *window,
+                GdkW32DragMoveResizeContext *context)
+{
+  GDK_NOTE (MISC, g_print ("Stop drawing snap indicator\n"));
+
+  if (context->timer)
+    {
+      g_source_remove (context->timer);
+      context->timer = 0;
+    }
+
+  API_CALL (SetWindowPos, (context->shape_indicator,
+                           SWP_NOZORDER_SPECIFIED,
+                           0, 0, 0, 0,
+                           SWP_NOZORDER | SWP_NOMOVE |
+                           SWP_NOSIZE | SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_NOACTIVATE));
+}
+
+static gint
+point_in_aerosnap_region (gint                x,
+                          gint                y,
+                          AeroSnapEdgeRegion *region)
+{
+  gint edge, trigger;
+
+  edge = (x >= region->edge.x &&
+          y >= region->edge.y &&
+          x <= region->edge.x + region->edge.width &&
+          y <= region->edge.y + region->edge.height) ? 1 : 0;
+  trigger = (x >= region->trigger.x &&
+             y >= region->trigger.y &&
+             x <= region->trigger.x + region->trigger.width &&
+             y <= region->trigger.y + region->trigger.height) ? 1 : 0;
+  return edge + trigger;
+}
+
+static void
+handle_aerosnap_move_resize (GdkSurface                   *window,
+                             GdkW32DragMoveResizeContext *context,
+                             gint                         x,
+                             gint                         y)
+{
+  gint i;
+  AeroSnapEdgeRegion *reg;
+  gint maximize = 0;
+  gint halfleft = 0;
+  gint halfright = 0;
+  gint fullup = 0;
+  gboolean fullup_edge = FALSE;
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  if (context->op == GDK_WIN32_DRAGOP_RESIZE)
+    switch (context->edge)
+      {
+      case GDK_SURFACE_EDGE_NORTH_WEST:
+      case GDK_SURFACE_EDGE_NORTH_EAST:
+      case GDK_SURFACE_EDGE_WEST:
+      case GDK_SURFACE_EDGE_EAST:
+      case GDK_SURFACE_EDGE_SOUTH_WEST:
+      case GDK_SURFACE_EDGE_SOUTH_EAST:
+        break;
+      case GDK_SURFACE_EDGE_SOUTH:
+      case GDK_SURFACE_EDGE_NORTH:
+        fullup_edge = TRUE;
+        break;
+      }
+
+  for (i = 0; i < context->maximize_regions->len && maximize == 0; i++)
+    {
+      reg = &g_array_index (context->maximize_regions, AeroSnapEdgeRegion, i);
+      maximize = point_in_aerosnap_region (x, y, reg);
+    }
+
+  for (i = 0; i < context->halfleft_regions->len && halfleft == 0; i++)
+    {
+      reg = &g_array_index (context->halfleft_regions, AeroSnapEdgeRegion, i);
+      halfleft = point_in_aerosnap_region (x, y, reg);
+    }
+
+  for (i = 0; i < context->halfright_regions->len && halfright == 0; i++)
+    {
+      reg = &g_array_index (context->halfright_regions, AeroSnapEdgeRegion, i);
+      halfright = point_in_aerosnap_region (x, y, reg);
+    }
+
+  for (i = 0; i < context->fullup_regions->len && fullup == 0; i++)
+    {
+      reg = &g_array_index (context->fullup_regions, AeroSnapEdgeRegion, i);
+      fullup = point_in_aerosnap_region (x, y, reg);
+    }
+
+#if defined(MORE_AEROSNAP_DEBUGGING)
+  GDK_NOTE (MISC, g_print ("AeroSnap: point %d : %d - max: %d, left %d, right %d, up %d\n",
+                           x, y, maximize, halfleft, halfright, fullup));
+#endif
+
+  if (!context->revealed)
+    {
+      if (context->op == GDK_WIN32_DRAGOP_MOVE && maximize == 2)
+        {
+          context->revealed = TRUE;
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_MAXIMIZE;
+          start_indicator (window, context, x, y, context->current_snap);
+        }
+      else if (context->op == GDK_WIN32_DRAGOP_MOVE && halfleft == 2)
+        {
+          context->revealed = TRUE;
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFLEFT;
+          start_indicator (window, context, x, y, context->current_snap);
+        }
+      else if (context->op == GDK_WIN32_DRAGOP_MOVE && halfright == 2)
+        {
+          context->revealed = TRUE;
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFRIGHT;
+          start_indicator (window, context, x, y, context->current_snap);
+        }
+      else if (context->op == GDK_WIN32_DRAGOP_RESIZE && fullup == 2 && fullup_edge)
+        {
+          context->revealed = TRUE;
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_FULLUP;
+          start_indicator (window, context, x, y, context->current_snap);
+        }
+
+      return;
+    }
+
+  switch (context->current_snap)
+    {
+    case GDK_WIN32_AEROSNAP_STATE_UNDETERMINED:
+      if (context->op == GDK_WIN32_DRAGOP_RESIZE && fullup > 0)
+        {
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_FULLUP;
+          start_indicator (window, context, x, y, context->current_snap);
+        }
+      break;
+    case GDK_WIN32_AEROSNAP_STATE_MAXIMIZE:
+      if (context->op == GDK_WIN32_DRAGOP_MOVE && maximize > 0)
+        break;
+      if (context->op == GDK_WIN32_DRAGOP_MOVE && halfleft > 0)
+        {
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFLEFT;
+          start_indicator (window, context, x, y, context->current_snap);
+        }
+      else if (context->op == GDK_WIN32_DRAGOP_MOVE && halfright > 0)
+        {
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFRIGHT;
+          start_indicator (window, context, x, y, context->current_snap);
+        }
+      else
+        {
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
+          stop_indicator (window, context);
+          context->revealed = FALSE;
+        }
+      break;
+    case GDK_WIN32_AEROSNAP_STATE_HALFLEFT:
+      if (context->op == GDK_WIN32_DRAGOP_MOVE && halfleft > 0)
+        break;
+      if (context->op == GDK_WIN32_DRAGOP_MOVE && maximize > 0)
+        {
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_MAXIMIZE;
+          start_indicator (window, context, x, y, context->current_snap);
+        }
+      else if (context->op == GDK_WIN32_DRAGOP_MOVE && halfright > 0)
+        {
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFRIGHT;
+          start_indicator (window, context, x, y, context->current_snap);
+        }
+      else
+        {
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
+          stop_indicator (window, context);
+          context->revealed = FALSE;
+        }
+      break;
+    case GDK_WIN32_AEROSNAP_STATE_HALFRIGHT:
+      if (context->op == GDK_WIN32_DRAGOP_MOVE && halfright > 0)
+        break;
+      if (context->op == GDK_WIN32_DRAGOP_MOVE && maximize > 0)
+        {
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_MAXIMIZE;
+          start_indicator (window, context, x, y, context->current_snap);
+        }
+      else if (context->op == GDK_WIN32_DRAGOP_MOVE && halfleft > 0)
+        {
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFLEFT;
+          start_indicator (window, context, x, y, context->current_snap);
+        }
+      else
+        {
+          context->current_snap = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
+          stop_indicator (window, context);
+          context->revealed = FALSE;
+        }
+      break;
+    case GDK_WIN32_AEROSNAP_STATE_FULLUP:
+      if (context->op == GDK_WIN32_DRAGOP_RESIZE && fullup > 0 && fullup_edge)
+        {
+          update_fullup_indicator (window, context);
+          break;
+        }
+
+      context->current_snap = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
+      stop_indicator (window, context);
+      break;
+    }
+}
+
+
+static const gchar *
+get_cursor_name_from_op (GdkW32WindowDragOp op,
+                         GdkSurfaceEdge      edge)
+{
+  switch (op)
+    {
+    case GDK_WIN32_DRAGOP_MOVE:
+      return "move";
+    case GDK_WIN32_DRAGOP_RESIZE:
+      switch (edge)
+        {
+        case GDK_SURFACE_EDGE_NORTH_WEST:
+          return "nw-resize";
+        case GDK_SURFACE_EDGE_NORTH:
+          return "n-resize";
+        case GDK_SURFACE_EDGE_NORTH_EAST:
+          return "ne-resize";
+        case GDK_SURFACE_EDGE_WEST:
+          return "w-resize";
+        case GDK_SURFACE_EDGE_EAST:
+          return "e-resize";
+        case GDK_SURFACE_EDGE_SOUTH_WEST:
+          return "sw-resize";
+        case GDK_SURFACE_EDGE_SOUTH:
+          return "s-resize";
+        case GDK_SURFACE_EDGE_SOUTH_EAST:
+          return "se-resize";
+        }
+      /* default: warn about unhandled enum values,
+       * fallthrough to GDK_WIN32_DRAGOP_NONE case
+       */
+    case GDK_WIN32_DRAGOP_COUNT:
+      g_assert_not_reached ();
+    case GDK_WIN32_DRAGOP_NONE:
+      return "default";
+    /* default: warn about unhandled enum values */
+    }
+
+  g_assert_not_reached ();
+
+  return NULL;
+}
+
+static gboolean
+point_in_window (GdkSurface *window,
+                 gdouble    x,
+                 gdouble    y)
+{
+  return x >= 0 && x < window->width &&
+         y >= 0 && y < window->height &&
+         (window->shape == NULL ||
+          cairo_region_contains_point (window->shape, x, y)) &&
+         (window->input_shape == NULL ||
+          cairo_region_contains_point (window->input_shape, x, y));
+}
+
+static GdkSurface *
+child_window_at_coordinates (GdkSurface *window,
+                             gint       root_x,
+                             gint       root_y)
+{
+  gint x, y;
+  GList *l;
+  GList *children;
+
+  children = gdk_surface_peek_children (window);
+  gdk_surface_get_root_origin (window, &x, &y);
+  x = root_x - x;
+  y = root_y - y;
+
+  for (l = children; l; l = g_list_next (l))
+    {
+      GdkSurface *child = GDK_SURFACE (l->data);
+
+      if (point_in_window (child, x, y))
+        return child;
+    }
+
+  return window;
+}
+
+static void
+setup_drag_move_resize_context (GdkSurface                   *window,
+                                GdkW32DragMoveResizeContext *context,
+                                GdkW32WindowDragOp           op,
+                                GdkSurfaceEdge                edge,
+                                GdkDevice                   *device,
+                                gint                         button,
+                                gint                         root_x,
+                                gint                         root_y,
+                                guint32                      timestamp)
+{
+  RECT rect;
+  const gchar *cursor_name;
+  GdkSurface *pointer_window;
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+  GdkDisplay *display = gdk_device_get_display (device);
+  gboolean maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
+
+  /* Before we drag, we need to undo any maximization or snapping.
+   * AeroSnap behaviour:
+   *   If snapped halfleft/halfright:
+   *     horizontal resize:
+   *       resize
+   *       don't unsnap
+   *       keep stashed unsnapped size intact
+   *     vertical resize:
+   *       resize
+   *       unsnap to new size (merge cached unsnapped state with current
+   *                           snapped state in such a way that the gripped edge
+   *                           does not move)
+   *     diagonal resize:
+   *       difficult to test (first move is usually either purely
+   *                          horizontal or purely vertical, in which
+   *                          case the above behaviour applies)
+   *   If snapped up:
+   *     horizontal resize:
+   *       resize
+   *       don't unsnap
+   *       apply new width and x position to unsnapped cache,
+   *         so that unsnapped window only regains its height
+   *         and y position, but inherits x and width from
+   *         the fullup snapped state
+   *     vertical resize:
+   *       unsnap to new size (merge cached unsnapped state with current
+   *                           snapped state in such a way that the gripped edge
+   *                           does not move)
+   *
+   * This implementation behaviour:
+   *   If snapped halfleft/halfright/fullup:
+   *     any resize:
+   *       unsnap to current size, discard cached pre-snap state
+   *
+   * TODO: make this implementation behave as AeroSnap on resizes?
+   * There's also the case where
+   * a halfleft/halfright window isn't unsnapped when it's
+   * being moved horizontally, but it's more difficult to implement.
+   */
+  if (op == GDK_WIN32_DRAGOP_RESIZE &&
+      (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFRIGHT ||
+       impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFLEFT ||
+       impl->snap_state == GDK_WIN32_AEROSNAP_STATE_FULLUP))
+    {
+      discard_snapinfo (window);
+    }
+  else if (maximized ||
+           (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFRIGHT ||
+            impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFLEFT ||
+            impl->snap_state == GDK_WIN32_AEROSNAP_STATE_FULLUP))
+    {
+      GdkMonitor *monitor;
+      gint wx, wy, wwidth, wheight;
+      gint swx, swy, swwidth, swheight;
+      gboolean pointer_outside_of_window;
+      gint offsetx, offsety;
+      gboolean left_half;
+      GdkDisplay *display;
+
+      display = gdk_surface_get_display (window);
+      monitor = gdk_display_get_monitor_at_window (display, window);
+      gdk_surface_get_geometry (window, &wx, &wy, &wwidth, &wheight);
+
+      swx = wx;
+      swy = wy;
+      swwidth = wwidth;
+      swheight = wheight;
+
+      /* Subtract window shadow. We don't want pointer to go outside of
+       * the visible window during drag-move. For drag-resize it's OK.
+       * Don't take shadow into account if the window is maximized -
+       * maximized windows don't have shadows.
+       */
+      if (op == GDK_WIN32_DRAGOP_MOVE && !maximized)
+        {
+          swx += impl->margins.left / impl->window_scale;
+          swy += impl->margins.top / impl->window_scale;
+          swwidth -= impl->margins_x;
+          swheight -= impl->margins_y;
+        }
+
+      pointer_outside_of_window = root_x < swx || root_x > swx + swwidth ||
+                                  root_y < swy || root_y > swy + swheight;
+      /* Calculate the offset of the pointer relative to the window */
+      offsetx = root_x - swx;
+      offsety = root_y - swy;
+
+      /* Figure out in which half of the window the pointer is.
+       * The code currently only concerns itself with horizontal
+       * dimension (left/right halves).
+       * There's no upper/lower half, because usually window
+       * is dragged by its upper half anyway. If that changes, adjust
+       * accordingly.
+       */
+      left_half = (offsetx < swwidth / 2);
+
+      /* Inverse the offset for it to be from the right edge */
+      if (!left_half)
+        offsetx = swwidth - offsetx;
+
+      GDK_NOTE (MISC, g_print ("Pointer at %d : %d, this is %d : %d relative to the window's %s\n",
+                               root_x, root_y, offsetx, offsety,
+                               left_half ? "left half" : "right half"));
+
+      /* Move window in such a way that on unmaximization/unsnapping the pointer
+       * is still pointing at the appropriate half of the window,
+       * with the same offset from the left or right edge. If the new
+       * window size is too small, and adding that offset puts the pointer
+       * into the other half or even beyond, move the pointer to the middle.
+       */
+      if (!pointer_outside_of_window && maximized)
+        {
+          WINDOWPLACEMENT placement;
+          gint unmax_width, unmax_height;
+          gint shadow_unmax_width, shadow_unmax_height;
+
+          placement.length = sizeof (placement);
+          API_CALL (GetWindowPlacement, (GDK_SURFACE_HWND (window), &placement));
+
+          GDK_NOTE (MISC, g_print ("W32 WM unmaximized window placement is %ld x %ld @ %ld : %ld\n",
+                                   placement.rcNormalPosition.right - placement.rcNormalPosition.left,
+                                   placement.rcNormalPosition.bottom - placement.rcNormalPosition.top,
+                                   placement.rcNormalPosition.left + _gdk_offset_x * impl->window_scale,
+                                   placement.rcNormalPosition.top + _gdk_offset_y * impl->window_scale));
+
+          unmax_width = placement.rcNormalPosition.right - placement.rcNormalPosition.left;
+          unmax_height = placement.rcNormalPosition.bottom - placement.rcNormalPosition.top;
+
+          shadow_unmax_width = unmax_width - impl->margins_x * impl->window_scale;
+          shadow_unmax_height = unmax_height - impl->margins_y * impl->window_scale;
+
+          if (offsetx * impl->window_scale < (shadow_unmax_width / 2) &&
+              offsety * impl->window_scale < (shadow_unmax_height / 2))
+            {
+              placement.rcNormalPosition.top = (root_y - offsety + impl->margins.top - _gdk_offset_y) * impl->window_scale;
+              placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + unmax_height;
+
+              if (left_half)
+                {
+                  placement.rcNormalPosition.left = (root_x - offsetx + impl->margins.left - _gdk_offset_x) * impl->window_scale;
+                  placement.rcNormalPosition.right = placement.rcNormalPosition.left + unmax_width;
+                }
+              else
+                {
+                  placement.rcNormalPosition.right = (root_x + offsetx + impl->margins.right - _gdk_offset_x) * impl->window_scale;
+                  placement.rcNormalPosition.left = placement.rcNormalPosition.right - unmax_width;
+                }
+            }
+          else
+            {
+              placement.rcNormalPosition.left = (root_x * impl->window_scale) -
+                                                (unmax_width / 2) -
+                                                (_gdk_offset_x * impl->window_scale);
+
+              if (offsety * impl->window_scale < shadow_unmax_height / 2)
+                placement.rcNormalPosition.top = (root_y - offsety + impl->margins.top - _gdk_offset_y) * impl->window_scale;
+              else
+                placement.rcNormalPosition.top = (root_y * impl->window_scale) -
+                                                 (unmax_height / 2) -
+                                                 (_gdk_offset_y * impl->window_scale);
+
+              placement.rcNormalPosition.right = placement.rcNormalPosition.left + unmax_width;
+              placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + unmax_height;
+            }
+
+          GDK_NOTE (MISC, g_print ("Unmaximized window will be at %ld : %ld\n",
+                                   placement.rcNormalPosition.left + _gdk_offset_x * impl->window_scale,
+                                   placement.rcNormalPosition.top + _gdk_offset_y * impl->window_scale));
+
+          API_CALL (SetWindowPlacement, (GDK_SURFACE_HWND (window), &placement));
+        }
+      else if (!pointer_outside_of_window && impl->snap_stash_int)
+        {
+          GdkRectangle new_pos;
+          GdkRectangle snew_pos;
+
+          new_pos.width = impl->snap_stash_int->width;
+          new_pos.height = impl->snap_stash_int->height;
+          snew_pos = new_pos;
+
+          if (op == GDK_WIN32_DRAGOP_MOVE)
+            {
+              snew_pos.width -= impl->margins_x;
+              snew_pos.height -= impl->margins_y;
+            }
+
+          if (offsetx < snew_pos.width / 2 && offsety < snew_pos.height / 2)
+            {
+              new_pos.y = root_y - offsety + impl->margins.top / impl->window_scale;
+
+              if (left_half)
+                new_pos.x = root_x - offsetx + impl->margins.left / impl->window_scale;
+              else
+                new_pos.x = root_x + offsetx + impl->margins.left / impl->window_scale - new_pos.width;
+            }
+          else
+            {
+              new_pos.x = root_x - new_pos.width / 2;
+              new_pos.y = root_y - new_pos.height / 2;
+            }
+
+          GDK_NOTE (MISC, g_print ("Unsnapped window to %d : %d\n",
+                                   new_pos.x, new_pos.y));
+          discard_snapinfo (window);
+          gdk_surface_move_resize (window, new_pos.x, new_pos.y,
+                                  new_pos.width, new_pos.height);
+        }
+
+
+      if (maximized)
+        gdk_surface_unmaximize (window);
+      else
+        unsnap (window, monitor);
+
+      if (pointer_outside_of_window)
+        {
+          /* Pointer outside of the window, move pointer into window */
+          GDK_NOTE (MISC, g_print ("Pointer at %d : %d is outside of %d x %d @ %d : %d, move it to %d : %d\n",
+                                   root_x, root_y, wwidth, wheight, wx, wy, wx + wwidth / 2, wy + wheight / 2));
+          root_x = wx + wwidth / 2;
+          /* This is Gnome behaviour. Windows WM would put the pointer
+           * in the middle of the titlebar, but GDK doesn't know where
+           * the titlebar is, if any.
+           */
+          root_y = wy + wheight / 2;
+          gdk_device_warp (device, root_x, root_y);
+        }
+    }
+
+  _gdk_win32_get_window_rect (window, &rect);
+
+  cursor_name = get_cursor_name_from_op (op, edge);
+
+  context->cursor = gdk_cursor_new_from_name (cursor_name, NULL);
+
+  pointer_window = child_window_at_coordinates (window, root_x, root_y);
+
+  /* Note: This triggers a WM_CAPTURECHANGED, which will trigger
+   * gdk_win32_surface_end_move_resize_drag(), which will end
+   * our op before it even begins, but only if context->op is not NONE.
+   * This is why we first do the grab, *then* set the op.
+   */
+  gdk_device_grab (device, pointer_window,
+                   GDK_OWNERSHIP_NONE, FALSE,
+                   GDK_ALL_EVENTS_MASK,
+                   context->cursor,
+                   timestamp);
+
+  context->window = g_object_ref (window);
+  context->op = op;
+  context->edge = edge;
+  context->device = device;
+  context->button = button;
+  context->start_root_x = root_x;
+  context->start_root_y = root_y;
+  context->timestamp = timestamp;
+  context->start_rect = rect;
+
+  context->shape_indicator = NULL;
+  context->revealed = FALSE;
+  context->halfleft_regions = g_array_new (FALSE, FALSE, sizeof (AeroSnapEdgeRegion));
+  context->halfright_regions = g_array_new (FALSE, FALSE, sizeof (AeroSnapEdgeRegion));
+  context->maximize_regions = g_array_new (FALSE, FALSE, sizeof (AeroSnapEdgeRegion));
+  context->fullup_regions = g_array_new (FALSE, FALSE, sizeof (AeroSnapEdgeRegion));
+
+  calculate_aerosnap_regions (context);
+
+  GDK_NOTE (EVENTS,
+            g_print ("begin drag moveresize: window %p, toplevel %p, "
+                     "op %u, edge %d, device %p, "
+                     "button %d, coord %d:%d, time %u\n",
+                     pointer_window, gdk_surface_get_toplevel (window),
+                     context->op, context->edge, context->device,
+                     context->button, context->start_root_x,
+                     context->start_root_y, context->timestamp));
+}
+
+void
+gdk_win32_surface_end_move_resize_drag (GdkSurface *window)
+{
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+  GdkW32DragMoveResizeContext *context = &impl->drag_move_resize_context;
+
+  context->op = GDK_WIN32_DRAGOP_NONE;
+
+  gdk_device_ungrab (context->device, GDK_CURRENT_TIME);
+
+  g_clear_object (&context->cursor);
+
+  context->revealed = FALSE;
+
+  if (context->timer)
+    {
+      g_source_remove (context->timer);
+      context->timer = 0;
+    }
+
+  g_clear_object (&context->window);
+
+  if (context->indicator_surface)
+    {
+      cairo_surface_destroy (context->indicator_surface);
+      context->indicator_surface = NULL;
+    }
+
+  if (context->shape_indicator)
+    {
+      stop_indicator (window, context);
+      DestroyWindow (context->shape_indicator);
+      context->shape_indicator = NULL;
+    }
+
+  g_clear_pointer (&context->halfleft_regions, g_array_unref);
+  g_clear_pointer (&context->halfright_regions, g_array_unref);
+  g_clear_pointer (&context->maximize_regions, g_array_unref);
+  g_clear_pointer (&context->fullup_regions, g_array_unref);
+
+  GDK_NOTE (EVENTS,
+            g_print ("end drag moveresize: window %p, toplevel %p,"
+                     "op %u, edge %d, device %p, "
+                     "button %d, coord %d:%d, time %u\n",
+                     window, gdk_surface_get_toplevel (window),
+                     context->op, context->edge, context->device,
+                     context->button, context->start_root_x,
+                     context->start_root_y, context->timestamp));
+
+  if (context->current_snap != GDK_WIN32_AEROSNAP_STATE_UNDETERMINED)
+    apply_snap (window, context->current_snap);
+
+  context->current_snap = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
+}
+
+static void
+gdk_win32_get_window_size_and_position_from_client_rect (GdkSurface *window,
+                                                         RECT      *window_rect,
+                                                         SIZE      *window_size,
+                                                         POINT     *window_position)
+{
+  GdkSurfaceImplWin32 *impl;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  /* Turn client area into window area */
+  _gdk_win32_adjust_client_rect (window, window_rect);
+
+  /* Convert GDK screen coordinates to W32 desktop coordinates */
+  window_rect->left -= _gdk_offset_x * impl->window_scale;
+  window_rect->right -= _gdk_offset_x * impl->window_scale;
+  window_rect->top -= _gdk_offset_y * impl->window_scale;
+  window_rect->bottom -= _gdk_offset_y * impl->window_scale;
+
+  window_position->x = window_rect->left;
+  window_position->y = window_rect->top;
+  window_size->cx = window_rect->right - window_rect->left;
+  window_size->cy = window_rect->bottom - window_rect->top;
+}
+
+static void
+gdk_win32_update_layered_window_from_cache (GdkSurface *window,
+                                            RECT      *client_rect)
+{
+  POINT window_position;
+  SIZE window_size;
+  BLENDFUNCTION blender;
+  HDC hdc;
+  SIZE *window_size_ptr;
+  POINT source_point = { 0, 0 };
+  POINT *source_point_ptr;
+  GdkSurfaceImplWin32 *impl;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  gdk_win32_get_window_size_and_position_from_client_rect (window,
+                                                           client_rect,
+                                                           &window_size,
+                                                           &window_position);
+
+  blender.BlendOp = AC_SRC_OVER;
+  blender.BlendFlags = 0;
+  blender.AlphaFormat = AC_SRC_ALPHA;
+  blender.SourceConstantAlpha = impl->layered_opacity * 255;
+
+  /* Size didn't change, so move immediately, no need to wait for redraw */
+  /* Strictly speaking, we don't need to supply hdc, source_point and
+   * window_size here. However, without these arguments
+   * the window moves but does not update its contents on Windows 7 when
+   * desktop composition is off. This forces us to provide hdc and
+   * source_point. window_size is here to avoid the function
+   * inexplicably failing with error 317.
+   */
+  if (gdk_display_is_composited (gdk_surface_get_display (window)))
+    {
+      hdc = NULL;
+      window_size_ptr = NULL;
+      source_point_ptr = NULL;
+    }
+  else
+    {
+      hdc = cairo_win32_surface_get_dc (impl->cache_surface);
+      window_size_ptr = &window_size;
+      source_point_ptr = &source_point;
+    }
+
+  API_CALL (UpdateLayeredWindow, (GDK_SURFACE_HWND (window), NULL,
+                                  &window_position, window_size_ptr,
+                                  hdc, source_point_ptr,
+                                  0, &blender, ULW_ALPHA));
+}
+
+void
+gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
+                                      gint       x,
+                                      gint       y)
+{
+  RECT rect;
+  RECT new_rect;
+  gint diffy, diffx;
+  MINMAXINFO mmi;
+  GdkSurfaceImplWin32 *impl;
+  GdkW32DragMoveResizeContext *context;
+  gint width;
+  gint height;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+  context = &impl->drag_move_resize_context;
+
+  if (!_gdk_win32_get_window_rect (window, &rect))
+    return;
+
+  new_rect = context->start_rect;
+  diffx = (x - context->start_root_x) * impl->window_scale;
+  diffy = (y - context->start_root_y) * impl->window_scale;
+
+  switch (context->op)
+    {
+    case GDK_WIN32_DRAGOP_RESIZE:
+
+      switch (context->edge)
+        {
+        case GDK_SURFACE_EDGE_NORTH_WEST:
+          new_rect.left += diffx;
+          new_rect.top += diffy;
+          break;
+
+        case GDK_SURFACE_EDGE_NORTH:
+          new_rect.top += diffy;
+          break;
+
+        case GDK_SURFACE_EDGE_NORTH_EAST:
+          new_rect.right += diffx;
+          new_rect.top += diffy;
+          break;
+
+        case GDK_SURFACE_EDGE_WEST:
+          new_rect.left += diffx;
+          break;
+
+        case GDK_SURFACE_EDGE_EAST:
+          new_rect.right += diffx;
+          break;
+
+        case GDK_SURFACE_EDGE_SOUTH_WEST:
+          new_rect.left += diffx;
+          new_rect.bottom += diffy;
+          break;
+
+        case GDK_SURFACE_EDGE_SOUTH:
+          new_rect.bottom += diffy;
+          break;
+
+        case GDK_SURFACE_EDGE_SOUTH_EAST:
+        default:
+          new_rect.right += diffx;
+          new_rect.bottom += diffy;
+          break;
+        }
+
+      /* When handling WM_GETMINMAXINFO, mmi is already populated
+       * by W32 WM and we apply our stuff on top of that.
+       * Here it isn't, so we should at least clear it.
+       */
+      memset (&mmi, 0, sizeof (mmi));
+
+      if (!_gdk_win32_surface_fill_min_max_info (window, &mmi))
+        break;
+
+      width = new_rect.right - new_rect.left;
+      height = new_rect.bottom - new_rect.top;
+
+      if (width > mmi.ptMaxTrackSize.x)
+        {
+          switch (context->edge)
+            {
+            case GDK_SURFACE_EDGE_NORTH_WEST:
+            case GDK_SURFACE_EDGE_WEST:
+            case GDK_SURFACE_EDGE_SOUTH_WEST:
+              new_rect.left = new_rect.right - mmi.ptMaxTrackSize.x;
+              break;
+
+            case GDK_SURFACE_EDGE_NORTH_EAST:
+            case GDK_SURFACE_EDGE_EAST:
+            case GDK_SURFACE_EDGE_SOUTH_EAST:
+            default:
+              new_rect.right = new_rect.left + mmi.ptMaxTrackSize.x;
+              break;
+            }
+        }
+      else if (width < mmi.ptMinTrackSize.x)
+        {
+          switch (context->edge)
+            {
+            case GDK_SURFACE_EDGE_NORTH_WEST:
+            case GDK_SURFACE_EDGE_WEST:
+            case GDK_SURFACE_EDGE_SOUTH_WEST:
+              new_rect.left = new_rect.right - mmi.ptMinTrackSize.x;
+              break;
+
+            case GDK_SURFACE_EDGE_NORTH_EAST:
+            case GDK_SURFACE_EDGE_EAST:
+            case GDK_SURFACE_EDGE_SOUTH_EAST:
+            default:
+              new_rect.right = new_rect.left + mmi.ptMinTrackSize.x;
+              break;
+            }
+        }
+
+      if (height > mmi.ptMaxTrackSize.y)
+        {
+          switch (context->edge)
+            {
+            case GDK_SURFACE_EDGE_NORTH_WEST:
+            case GDK_SURFACE_EDGE_NORTH:
+            case GDK_SURFACE_EDGE_NORTH_EAST:
+              new_rect.top = new_rect.bottom - mmi.ptMaxTrackSize.y;
+
+            case GDK_SURFACE_EDGE_SOUTH_WEST:
+            case GDK_SURFACE_EDGE_SOUTH:
+            case GDK_SURFACE_EDGE_SOUTH_EAST:
+            default:
+              new_rect.bottom = new_rect.top + mmi.ptMaxTrackSize.y;
+              break;
+            }
+        }
+      else if (height < mmi.ptMinTrackSize.y)
+        {
+          switch (context->edge)
+            {
+            case GDK_SURFACE_EDGE_NORTH_WEST:
+            case GDK_SURFACE_EDGE_NORTH:
+            case GDK_SURFACE_EDGE_NORTH_EAST:
+              new_rect.top = new_rect.bottom - mmi.ptMinTrackSize.y;
+
+            case GDK_SURFACE_EDGE_SOUTH_WEST:
+            case GDK_SURFACE_EDGE_SOUTH:
+            case GDK_SURFACE_EDGE_SOUTH_EAST:
+            default:
+              new_rect.bottom = new_rect.top + mmi.ptMinTrackSize.y;
+              break;
+            }
+        }
+
+      break;
+    case GDK_WIN32_DRAGOP_MOVE:
+      new_rect.left += diffx;
+      new_rect.top += diffy;
+      new_rect.right += diffx;
+      new_rect.bottom += diffy;
+      break;
+    default:
+      break;
+    }
+
+  if (context->op == GDK_WIN32_DRAGOP_RESIZE &&
+      (rect.left != new_rect.left ||
+       rect.right != new_rect.right ||
+       rect.top != new_rect.top ||
+       rect.bottom != new_rect.bottom))
+    {
+      context->native_move_resize_pending = TRUE;
+      _gdk_win32_do_emit_configure_event (window, new_rect);
+    }
+  else if (context->op == GDK_WIN32_DRAGOP_MOVE &&
+           (rect.left != new_rect.left ||
+            rect.top != new_rect.top))
+    {
+      context->native_move_resize_pending = FALSE;
+
+      _gdk_win32_do_emit_configure_event (window, new_rect);
+
+      if (impl->layered)
+        {
+          gdk_win32_update_layered_window_from_cache (window, &new_rect);
+        }
+      else
+        {
+          SIZE window_size;
+          POINT window_position;
+
+          gdk_win32_get_window_size_and_position_from_client_rect (window,
+                                                                   &new_rect,
+                                                                   &window_size,
+                                                                   &window_position);
+
+          API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                                   SWP_NOZORDER_SPECIFIED,
+                                   window_position.x, window_position.y,
+                                   0, 0,
+                                   SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE));
+        }
+    }
+
+  if (context->op == GDK_WIN32_DRAGOP_RESIZE ||
+      context->op == GDK_WIN32_DRAGOP_MOVE)
+    handle_aerosnap_move_resize (window, context, x, y);
+}
+
+static void
+gdk_win32_surface_begin_resize_drag (GdkSurface     *window,
+                                    GdkSurfaceEdge  edge,
+                                    GdkDevice     *device,
+                                    gint           button,
+                                    gint           root_x,
+                                    gint           root_y,
+                                    guint32        timestamp)
+{
+  GdkSurfaceImplWin32 *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      IsIconic (GDK_SURFACE_HWND (window)))
+    return;
+
+  /* Tell Windows to start interactively resizing the window by pretending that
+   * the left pointer button was clicked in the suitable edge or corner. This
+   * will only work if the button is down when this function is called, and
+   * will only work with button 1 (left), since Windows only allows window
+   * dragging using the left mouse button.
+   */
+
+  if (button != 1)
+    return;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
+    gdk_win32_surface_end_move_resize_drag (window);
+
+  setup_drag_move_resize_context (window, &impl->drag_move_resize_context,
+                                  GDK_WIN32_DRAGOP_RESIZE, edge, device,
+                                  button, root_x, root_y, timestamp);
+}
+
+static void
+gdk_win32_surface_begin_move_drag (GdkSurface *window,
+                                  GdkDevice *device,
+                                  gint       button,
+                                  gint       root_x,
+                                  gint       root_y,
+                                  guint32    timestamp)
+{
+  GdkSurfaceImplWin32 *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      IsIconic (GDK_SURFACE_HWND (window)))
+    return;
+
+  /* Tell Windows to start interactively moving the window by pretending that
+   * the left pointer button was clicked in the titlebar. This will only work
+   * if the button is down when this function is called, and will only work
+   * with button 1 (left), since Windows only allows window dragging using the
+   * left mouse button.
+   */
+  if (button != 1)
+    return;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
+    gdk_win32_surface_end_move_resize_drag (window);
+
+  setup_drag_move_resize_context (window, &impl->drag_move_resize_context,
+                                  GDK_WIN32_DRAGOP_MOVE, GDK_SURFACE_EDGE_NORTH_WEST,
+                                  device, button, root_x, root_y, timestamp);
+}
+
+
+/*
+ * Setting window states
+ */
+static void
+gdk_win32_surface_iconify (GdkSurface *window)
+{
+  HWND old_active_window;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_iconify: %p: %s\n",
+                          GDK_SURFACE_HWND (window),
+                          _gdk_win32_surface_state_to_string (window->state)));
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      old_active_window = GetActiveWindow ();
+      GtkShowWindow (window, SW_MINIMIZE);
+      if (old_active_window != GDK_SURFACE_HWND (window))
+       SetActiveWindow (old_active_window);
+    }
+  else
+    {
+      gdk_synthesize_window_state (window,
+                                   0,
+                                   GDK_SURFACE_STATE_ICONIFIED);
+    }
+}
+
+static void
+gdk_win32_surface_deiconify (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_deiconify: %p: %s\n",
+                          GDK_SURFACE_HWND (window),
+                          _gdk_win32_surface_state_to_string (window->state)));
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      show_window_internal (window, GDK_SURFACE_IS_MAPPED (window), TRUE);
+    }
+  else
+    {
+      gdk_synthesize_window_state (window,
+                                   GDK_SURFACE_STATE_ICONIFIED,
+                                   0);
+    }
+}
+
+static void
+gdk_win32_surface_stick (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  /* FIXME: Do something? */
+}
+
+static void
+gdk_win32_surface_unstick (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  /* FIXME: Do something? */
+}
+
+static void
+gdk_win32_surface_maximize (GdkSurface *window)
+{
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_maximize: %p: %s\n",
+                          GDK_SURFACE_HWND (window),
+                          _gdk_win32_surface_state_to_string (window->state)));
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    GtkShowWindow (window, SW_MAXIMIZE);
+  else
+    gdk_synthesize_window_state (window,
+                                0,
+                                GDK_SURFACE_STATE_MAXIMIZED);
+}
+
+static void
+gdk_win32_surface_unmaximize (GdkSurface *window)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_unmaximize: %p: %s\n",
+                          GDK_SURFACE_HWND (window),
+                          _gdk_win32_surface_state_to_string (window->state)));
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    GtkShowWindow (window, SW_RESTORE);
+  else
+    gdk_synthesize_window_state (window,
+                                GDK_SURFACE_STATE_MAXIMIZED,
+                                0);
+}
+
+static void
+gdk_win32_surface_fullscreen (GdkSurface *window)
+{
+  gint x, y, width, height;
+  FullscreenInfo *fi;
+  HMONITOR monitor;
+  MONITORINFO mi;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  fi = g_new (FullscreenInfo, 1);
+
+  if (!GetWindowRect (GDK_SURFACE_HWND (window), &(fi->r)))
+    g_free (fi);
+  else
+    {
+      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+      monitor = MonitorFromWindow (GDK_SURFACE_HWND (window), MONITOR_DEFAULTTONEAREST);
+      mi.cbSize = sizeof (mi);
+      if (monitor && GetMonitorInfo (monitor, &mi))
+       {
+         x = mi.rcMonitor.left;
+         y = mi.rcMonitor.top;
+         width = mi.rcMonitor.right - x;
+         height = mi.rcMonitor.bottom - y;
+       }
+      else
+       {
+         x = y = 0;
+         width = GetSystemMetrics (SM_CXSCREEN);
+         height = GetSystemMetrics (SM_CYSCREEN);
+       }
+
+      /* remember for restoring */
+      fi->hint_flags = impl->hint_flags;
+      impl->hint_flags &= ~GDK_HINT_MAX_SIZE;
+      g_object_set_data (G_OBJECT (window), "fullscreen-info", fi);
+      fi->style = GetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE);
+
+      /* Send state change before configure event */
+      gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
+
+      SetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE,
+                     (fi->style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP);
+
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOP,
+                x, y, width, height,
+                SWP_NOCOPYBITS | SWP_SHOWWINDOW));
+    }
+}
+
+static void
+gdk_win32_surface_unfullscreen (GdkSurface *window)
+{
+  FullscreenInfo *fi;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
+  if (fi)
+    {
+      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+      gdk_synthesize_window_state (window, GDK_SURFACE_STATE_FULLSCREEN, 0);
+
+      impl->hint_flags = fi->hint_flags;
+      SetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE, fi->style);
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_NOTOPMOST,
+                              fi->r.left, fi->r.top,
+                              fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
+                              SWP_NOCOPYBITS | SWP_SHOWWINDOW));
+
+      g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL);
+      g_free (fi);
+      _gdk_win32_surface_update_style_bits (window);
+    }
+}
+
+static void
+gdk_win32_surface_set_keep_above (GdkSurface *window,
+                          gboolean   setting)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_set_keep_above: %p: %s\n",
+                          GDK_SURFACE_HWND (window),
+                          setting ? "YES" : "NO"));
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                              setting ? HWND_TOPMOST : HWND_NOTOPMOST,
+                              0, 0, 0, 0,
+                              SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
+    }
+
+  gdk_synthesize_window_state (window,
+                              setting ? GDK_SURFACE_STATE_BELOW : GDK_SURFACE_STATE_ABOVE,
+                              setting ? GDK_SURFACE_STATE_ABOVE : 0);
+}
+
+static void
+gdk_win32_surface_set_keep_below (GdkSurface *window,
+                          gboolean   setting)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_set_keep_below: %p: %s\n",
+                          GDK_SURFACE_HWND (window),
+                          setting ? "YES" : "NO"));
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                              setting ? HWND_BOTTOM : HWND_NOTOPMOST,
+                              0, 0, 0, 0,
+                              SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
+    }
+
+  gdk_synthesize_window_state (window,
+                              setting ? GDK_SURFACE_STATE_ABOVE : GDK_SURFACE_STATE_BELOW,
+                              setting ? GDK_SURFACE_STATE_BELOW : 0);
+}
+
+static void
+gdk_win32_surface_focus (GdkSurface *window,
+                       guint32    timestamp)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_focus: %p: %s\n",
+                          GDK_SURFACE_HWND (window),
+                          _gdk_win32_surface_state_to_string (window->state)));
+
+  if (window->state & GDK_SURFACE_STATE_MAXIMIZED)
+    GtkShowWindow (window, SW_SHOWMAXIMIZED);
+  else if (window->state & GDK_SURFACE_STATE_ICONIFIED)
+    GtkShowWindow (window, SW_RESTORE);
+  else if (!IsWindowVisible (GDK_SURFACE_HWND (window)))
+    GtkShowWindow (window, SW_SHOWNORMAL);
+  else
+    GtkShowWindow (window, SW_SHOW);
+
+  SetFocus (GDK_SURFACE_HWND (window));
+}
+
+static void
+gdk_win32_surface_set_modal_hint (GdkSurface *window,
+                          gboolean   modal)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_set_modal_hint: %p: %s\n",
+                          GDK_SURFACE_HWND (window),
+                          modal ? "YES" : "NO"));
+
+  if (modal == window->modal_hint)
+    return;
+
+  window->modal_hint = modal;
+
+#if 0
+  /* Not sure about this one.. -- Cody */
+  if (GDK_SURFACE_IS_MAPPED (window))
+    API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
+                            modal ? HWND_TOPMOST : HWND_NOTOPMOST,
+                            0, 0, 0, 0,
+                            SWP_NOMOVE | SWP_NOSIZE));
+#else
+
+  if (modal)
+    {
+      _gdk_push_modal_window (window);
+      gdk_surface_raise (window);
+    }
+  else
+    {
+      _gdk_remove_modal_window (window);
+    }
+
+#endif
+}
+
+static void
+gdk_win32_surface_set_skip_taskbar_hint (GdkSurface *window,
+                                 gboolean   skips_taskbar)
+{
+  static GdkSurface *owner = NULL;
+  //GdkSurfaceAttr wa;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_set_skip_taskbar_hint: %p: %s, doing nothing\n",
+                          GDK_SURFACE_HWND (window),
+                          skips_taskbar ? "YES" : "NO"));
+
+  // ### TODO: Need to figure out what to do here.
+  return;
+
+  if (skips_taskbar)
+    {
+#if 0
+      if (owner == NULL)
+               {
+                 wa.window_type = GDK_SURFACE_TEMP;
+                 wa.wclass = GDK_INPUT_OUTPUT;
+                 wa.width = wa.height = 1;
+                 wa.event_mask = 0;
+                 owner = gdk_surface_new_internal (NULL, &wa, 0, TRUE);
+               }
+#endif
+
+      SetWindowLongPtr (GDK_SURFACE_HWND (window), GWLP_HWNDPARENT, (LONG_PTR) GDK_SURFACE_HWND (owner));
+
+#if 0 /* Should we also turn off the minimize and maximize buttons? */
+      SetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE,
+                    GetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE) & ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU));
+
+      SetWindowPos (GDK_SURFACE_HWND (window), SWP_NOZORDER_SPECIFIED,
+                   0, 0, 0, 0,
+                   SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
+                   SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
+#endif
+    }
+  else
+    {
+      SetWindowLongPtr (GDK_SURFACE_HWND (window), GWLP_HWNDPARENT, 0);
+    }
+}
+
+static void
+gdk_win32_surface_set_skip_pager_hint (GdkSurface *window,
+                               gboolean   skips_pager)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  GDK_NOTE (MISC, g_print ("gdk_surface_set_skip_pager_hint: %p: %s, doing nothing\n",
+                          GDK_SURFACE_HWND (window),
+                          skips_pager ? "YES" : "NO"));
+}
+
+static void
+gdk_win32_surface_set_type_hint (GdkSurface        *window,
+                         GdkSurfaceTypeHint hint)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC,
+           G_STMT_START{
+             static GEnumClass *class = NULL;
+             if (!class)
+               class = g_type_class_ref (GDK_TYPE_SURFACE_TYPE_HINT);
+             g_print ("gdk_surface_set_type_hint: %p: %s\n",
+                      GDK_SURFACE_HWND (window),
+                      g_enum_get_value (class, hint)->value_name);
+           }G_STMT_END);
+
+  ((GdkSurfaceImplWin32 *)window->impl)->type_hint = hint;
+
+  _gdk_win32_surface_update_style_bits (window);
+}
+
+static GdkSurfaceTypeHint
+gdk_win32_surface_get_type_hint (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), GDK_SURFACE_TYPE_HINT_NORMAL);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return GDK_SURFACE_TYPE_HINT_NORMAL;
+
+  return GDK_SURFACE_IMPL_WIN32 (window->impl)->type_hint;
+}
+
+static HRGN
+cairo_region_to_hrgn (const cairo_region_t *region,
+                     gint                  x_origin,
+                     gint                  y_origin,
+                     guint                 scale)
+{
+  HRGN hrgn;
+  RGNDATA *rgndata;
+  RECT *rect;
+  cairo_rectangle_int_t r;
+  const int nrects = cairo_region_num_rectangles (region);
+  guint nbytes =
+    sizeof (RGNDATAHEADER) + (sizeof (RECT) * nrects);
+  int i;
+
+  rgndata = g_malloc (nbytes);
+  rgndata->rdh.dwSize = sizeof (RGNDATAHEADER);
+  rgndata->rdh.iType = RDH_RECTANGLES;
+  rgndata->rdh.nCount = rgndata->rdh.nRgnSize = 0;
+  SetRect (&rgndata->rdh.rcBound,
+          G_MAXLONG, G_MAXLONG, G_MINLONG, G_MINLONG);
+
+  for (i = 0; i < nrects; i++)
+    {
+      rect = ((RECT *) rgndata->Buffer) + rgndata->rdh.nCount++;
+
+      cairo_region_get_rectangle (region, i, &r);
+      rect->left = (r.x + x_origin) * scale;
+      rect->right = (rect->left + r.width) * scale;
+      rect->top = (r.y + y_origin) * scale;
+      rect->bottom = (rect->top + r.height) * scale;
+
+      if (rect->left < rgndata->rdh.rcBound.left)
+       rgndata->rdh.rcBound.left = rect->left;
+      if (rect->right > rgndata->rdh.rcBound.right)
+       rgndata->rdh.rcBound.right = rect->right;
+      if (rect->top < rgndata->rdh.rcBound.top)
+       rgndata->rdh.rcBound.top = rect->top;
+      if (rect->bottom > rgndata->rdh.rcBound.bottom)
+       rgndata->rdh.rcBound.bottom = rect->bottom;
+    }
+  if ((hrgn = ExtCreateRegion (NULL, nbytes, rgndata)) == NULL)
+    WIN32_API_FAILED ("ExtCreateRegion");
+
+  g_free (rgndata);
+
+  return (hrgn);
+}
+
+static void
+gdk_win32_surface_shape_combine_region (GdkSurface       *window,
+                                      const cairo_region_t *shape_region,
+                                      gint             offset_x,
+                                      gint             offset_y)
+{
+  GdkSurfaceImplWin32 *impl;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (!shape_region)
+    {
+      GDK_NOTE (MISC, g_print ("gdk_win32_surface_shape_combine_region: %p: none\n",
+                              GDK_SURFACE_HWND (window)));
+      SetWindowRgn (GDK_SURFACE_HWND (window), NULL, TRUE);
+    }
+  else
+    {
+      HRGN hrgn;
+      impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+      hrgn = cairo_region_to_hrgn (shape_region, 0, 0, impl->window_scale);
+
+      GDK_NOTE (MISC, g_print ("gdk_win32_surface_shape_combine_region: %p: %p\n",
+                              GDK_SURFACE_HWND (window),
+                              hrgn));
+
+      do_shape_combine_region (window, hrgn, offset_x, offset_y);
+    }
+}
+
+GdkSurface *
+gdk_win32_surface_lookup_for_display (GdkDisplay *display,
+                                     HWND        anid)
+{
+  g_return_val_if_fail (display == gdk_display_get_default (), NULL);
+
+  return (GdkSurface*) gdk_win32_handle_table_lookup (anid);
+}
+
+static void
+gdk_win32_surface_set_opacity (GdkSurface *window,
+                       gdouble    opacity)
+{
+  LONG exstyle;
+  typedef BOOL (WINAPI *PFN_SetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
+  PFN_SetLayeredWindowAttributes setLayeredWindowAttributes = NULL;
+  GdkSurfaceImplWin32 *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (!WINDOW_IS_TOPLEVEL (window) || GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (opacity < 0)
+    opacity = 0;
+  else if (opacity > 1)
+    opacity = 1;
+
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  if (impl->layered)
+    {
+      if (impl->layered_opacity != opacity)
+        {
+          RECT window_rect;
+
+          impl->layered_opacity = opacity;
+
+          gdk_win32_get_window_client_area_rect (window, impl->window_scale, &window_rect);
+          gdk_win32_update_layered_window_from_cache (window, &window_rect);
+        }
+
+      return;
+    }
+
+  exstyle = GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE);
+
+  if (!(exstyle & WS_EX_LAYERED))
+    SetWindowLong (GDK_SURFACE_HWND (window),
+                   GWL_EXSTYLE,
+                   exstyle | WS_EX_LAYERED);
+
+  setLayeredWindowAttributes =
+    (PFN_SetLayeredWindowAttributes)GetProcAddress (GetModuleHandle ("user32.dll"), "SetLayeredWindowAttributes");
+
+  if (setLayeredWindowAttributes)
+    {
+      API_CALL (setLayeredWindowAttributes, (GDK_SURFACE_HWND (window),
+                                            0,
+                                            opacity * 0xff,
+                                            LWA_ALPHA));
+    }
+}
+
+gboolean
+gdk_win32_surface_is_win32 (GdkSurface *window)
+{
+  return GDK_SURFACE_IS_WIN32 (window);
+}
+
+static gboolean
+gdk_win32_surface_show_window_menu (GdkSurface *window,
+                                   GdkEvent  *event)
+{
+  double event_x, event_y;
+  gint x, y;
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  switch (event->type)
+    {
+    case GDK_BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+    case GDK_TOUCH_BEGIN:
+    case GDK_TOUCH_END:
+      break;
+    default:
+      return FALSE;
+    }
+
+  gdk_event_get_root_coords (event, &event_x, &event_y);
+  x = event_x - _gdk_offset_x;
+  y = event_y - _gdk_offset_y;
+
+  SendMessage (GDK_SURFACE_HWND (window),
+               WM_SYSMENU,
+               0,
+               MAKELPARAM (x * impl->window_scale, y * impl->window_scale));
+
+  return TRUE;
+}
+
+/**
+ * _gdk_win32_acquire_dc
+ * @impl: a Win32 #GdkSurfaceImplWin32 implementation
+ *
+ * Gets a DC with the given drawable selected into it.
+ *
+ * Returns: The DC, on success. Otherwise
+ *  %NULL. If this function succeeded
+ *  _gdk_win32_impl_release_dc()  must be called
+ *  release the DC when you are done using it.
+ **/
+static HDC
+_gdk_win32_impl_acquire_dc (GdkSurfaceImplWin32 *impl)
+{
+  if (GDK_IS_SURFACE_IMPL_WIN32 (impl) &&
+      GDK_SURFACE_DESTROYED (impl->wrapper))
+    return NULL;
+
+  /* We don't call this function for layered windows, but
+   * in case we do...
+   */
+  if (impl->layered)
+    return NULL;
+
+  if (!impl->hdc)
+    {
+      impl->hdc = GetDC (impl->handle);
+      if (!impl->hdc)
+       WIN32_GDI_FAILED ("GetDC");
+    }
+
+  if (impl->hdc)
+    {
+      impl->hdc_count++;
+      return impl->hdc;
+    }
+  else
+    {
+      return NULL;
+    }
+}
+
+/**
+ * _gdk_win32_impl_release_dc
+ * @impl: a Win32 #GdkSurfaceImplWin32 implementation
+ *
+ * Releases the reference count for the DC
+ * from _gdk_win32_impl_acquire_dc()
+ **/
+static void
+_gdk_win32_impl_release_dc (GdkSurfaceImplWin32 *impl)
+{
+  if (impl->layered)
+    return;
+
+  g_return_if_fail (impl->hdc_count > 0);
+
+  impl->hdc_count--;
+  if (impl->hdc_count == 0)
+    {
+      if (impl->saved_dc_bitmap)
+       {
+         GDI_CALL (SelectObject, (impl->hdc, impl->saved_dc_bitmap));
+         impl->saved_dc_bitmap = NULL;
+       }
+
+      if (impl->hdc)
+       {
+         GDI_CALL (ReleaseDC, (impl->handle, impl->hdc));
+         impl->hdc = NULL;
+       }
+    }
+}
+
+HWND
+gdk_win32_surface_get_impl_hwnd (GdkSurface *window)
+{
+  if (GDK_SURFACE_IS_WIN32 (window))
+    return GDK_SURFACE_HWND (window);
+  return NULL;
+}
+
+static void
+gdk_win32_cairo_surface_destroy (void *data)
+{
+  GdkSurfaceImplWin32 *impl = data;
+
+  _gdk_win32_impl_release_dc (impl);
+  impl->cairo_surface = NULL;
+}
+
+static cairo_surface_t *
+gdk_win32_ref_cairo_surface_layered (GdkSurface          *window,
+                                     GdkSurfaceImplWin32 *impl)
+{
+  gint width, height;
+  RECT window_rect;
+
+  gdk_win32_get_window_client_area_rect (window, impl->window_scale, &window_rect);
+
+  /* Turn client area into window area */
+  _gdk_win32_adjust_client_rect (window, &window_rect);
+
+  width = window_rect.right - window_rect.left;
+  height = window_rect.bottom - window_rect.top;
+
+  if (width > impl->dib_width ||
+      height > impl->dib_height)
+    {
+      cairo_surface_t *new_cache;
+      cairo_t *cr;
+
+      /* Create larger cache surface, copy old cache surface over it */
+      new_cache = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
+                                                       width,
+                                                       height);
+
+      if (impl->cache_surface)
+        {
+          cr = cairo_create (new_cache);
+          cairo_set_source_surface (cr, impl->cache_surface, 0, 0);
+          cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+          cairo_paint (cr);
+          cairo_destroy (cr);
+          cairo_surface_flush (new_cache);
+
+          cairo_surface_destroy (impl->cache_surface);
+        }
+
+      impl->cache_surface = new_cache;
+
+      cairo_surface_set_device_scale (impl->cache_surface,
+                                      impl->window_scale,
+                                      impl->window_scale);
+
+      if (impl->cairo_surface)
+        cairo_surface_destroy (impl->cairo_surface);
+
+      impl->cairo_surface = NULL;
+    }
+
+  /* This is separate, because cairo_surface gets killed
+   * off frequently by outside code, whereas cache_surface
+   * is only killed by us, above.
+   */
+  if (!impl->cairo_surface)
+    {
+      impl->cairo_surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
+                                                                 width,
+                                                                 height);
+      impl->dib_width = width;
+      impl->dib_height = height;
+
+      cairo_surface_set_device_scale (impl->cairo_surface,
+                                      impl->window_scale,
+                                      impl->window_scale);
+
+      cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
+                                  impl, gdk_win32_cairo_surface_destroy);
+    }
+  else
+    {
+      cairo_surface_reference (impl->cairo_surface);
+    }
+
+  return impl->cairo_surface;
+}
+
+static cairo_surface_t *
+gdk_win32_ref_cairo_surface (GdkSurface *window)
+{
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  if (GDK_IS_SURFACE_IMPL_WIN32 (impl) &&
+      GDK_SURFACE_DESTROYED (impl->wrapper))
+    return NULL;
+
+  if (impl->layered)
+    return gdk_win32_ref_cairo_surface_layered (window, impl);
+
+  if (!impl->cairo_surface)
+    {
+      HDC hdc = _gdk_win32_impl_acquire_dc (impl);
+      if (!hdc)
+       return NULL;
+
+      impl->cairo_surface = cairo_win32_surface_create_with_format (hdc, CAIRO_FORMAT_ARGB32);
+      cairo_surface_set_device_scale (impl->cairo_surface,
+                                      impl->window_scale,
+                                      impl->window_scale);
+
+      cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
+                                  impl, gdk_win32_cairo_surface_destroy);
+    }
+  else
+    cairo_surface_reference (impl->cairo_surface);
+
+  return impl->cairo_surface;
+}
+
+BOOL WINAPI
+GtkShowWindow (GdkSurface *window,
+               int        cmd_show)
+{
+  cairo_t *cr;
+  cairo_surface_t *surface;
+  RECT window_rect;
+  HDC hdc;
+  POINT window_position;
+  SIZE window_size;
+  POINT source_point;
+  BLENDFUNCTION blender;
+
+  HWND hwnd = GDK_SURFACE_HWND (window);
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  switch (cmd_show)
+    {
+    case SW_FORCEMINIMIZE:
+    case SW_HIDE:
+    case SW_MINIMIZE:
+      break;
+    case SW_MAXIMIZE:
+    case SW_RESTORE:
+    case SW_SHOW:
+    case SW_SHOWDEFAULT:
+    case SW_SHOWMINIMIZED:
+    case SW_SHOWMINNOACTIVE:
+    case SW_SHOWNA:
+    case SW_SHOWNOACTIVATE:
+    case SW_SHOWNORMAL:
+      if (IsWindowVisible (hwnd))
+        break;
+
+      if ((WS_EX_LAYERED & GetWindowLongPtr (hwnd, GWL_EXSTYLE)) != WS_EX_LAYERED)
+        break;
+
+      /* Window was hidden, will be shown. Erase it, GDK will repaint soon,
+       * but not soon enough, so it's possible to see old content before
+       * the next redraw, unless we erase the window first.
+       */
+      GetWindowRect (hwnd, &window_rect);
+      source_point.x = source_point.y = 0;
+
+      window_position.x = window_rect.left;
+      window_position.y = window_rect.top;
+      window_size.cx = window_rect.right - window_rect.left;
+      window_size.cy = window_rect.bottom - window_rect.top;
+
+      blender.BlendOp = AC_SRC_OVER;
+      blender.BlendFlags = 0;
+      blender.AlphaFormat = AC_SRC_ALPHA;
+      blender.SourceConstantAlpha = 255;
+
+      /* Create a surface of appropriate size and clear it */
+      surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
+                                                     window_size.cx,
+                                                     window_size.cy);
+      cairo_surface_set_device_scale (surface, impl->window_scale, impl->window_scale);
+      cr = cairo_create (surface);
+      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+      cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
+      cairo_paint (cr);
+      cairo_destroy (cr);
+      cairo_surface_flush (surface);
+      hdc = cairo_win32_surface_get_dc (surface);
+
+      /* No API_CALL() wrapper, don't check for errors */
+      UpdateLayeredWindow (hwnd, NULL,
+                           &window_position, &window_size,
+                           hdc, &source_point,
+                           0, &blender, ULW_ALPHA);
+
+      cairo_surface_destroy (surface);
+
+      break;
+    }
+
+  /* Ensure that maximized window size is corrected later on */
+  if (cmd_show == SW_MAXIMIZE)
+    impl->maximizing = TRUE;
+
+  return ShowWindow (hwnd, cmd_show);
+}
+
+static void
+gdk_win32_surface_set_shadow_width (GdkSurface *window,
+                                   gint       left,
+                                   gint       right,
+                                   gint       top,
+                                   gint       bottom)
+{
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  GDK_NOTE (MISC, g_print ("gdk_win32_surface_set_shadow_width: window %p, "
+                           "left %d, top %d, right %d, bottom %d\n",
+                           window, left, top, right, bottom));
+
+  impl->zero_margins = left == 0 && right == 0 && top == 0 && bottom == 0;
+
+  if (impl->zero_margins)
+    return;
+
+  impl->margins.left = left;
+  impl->margins.right = right * impl->window_scale;
+  impl->margins.top = top;
+  impl->margins.bottom = bottom * impl->window_scale;
+  impl->margins_x = left + right;
+  impl->margins_y = top + bottom;
+}
+
+
+gint
+_gdk_win32_surface_get_scale_factor (GdkSurface *window)
+{
+  GdkDisplay *display;
+  GdkSurfaceImplWin32 *impl;
+
+  GdkWin32Display *win32_display;
+  UINT dpix, dpiy;
+  gboolean is_scale_acquired;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return 1;
+
+  g_return_val_if_fail (window != NULL, 1);
+
+  display = gdk_surface_get_display (window);
+  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  win32_display = GDK_WIN32_DISPLAY (display);
+
+  if (win32_display->dpi_aware_type != PROCESS_DPI_UNAWARE)
+    {
+      if (win32_display->has_fixed_scale)
+        impl->window_scale = win32_display->window_scale;
+      else
+        impl->window_scale = _gdk_win32_display_get_monitor_scale_factor (win32_display,
+                                                                          NULL,
+                                                                          GDK_SURFACE_HWND (window),
+                                                                          NULL);
+
+      return impl->window_scale;
+    }
+  else
+    {
+      if (win32_display->has_fixed_scale)
+        {
+          static gsize hidpi_msg_displayed = 0;
+
+          if (g_once_init_enter (&hidpi_msg_displayed))
+            {
+              g_message ("Note: GDK_SCALE is ignored as HiDPI awareness is disabled.");
+              g_once_init_leave (&hidpi_msg_displayed, 1);
+            }
+        }
+
+      /* Application is not DPI aware, don't bother */
+      return 1;
+    }
+}
+
+void
+_gdk_win32_surface_get_unscaled_size (GdkSurface *window,
+                                    gint      *unscaled_width,
+                                    gint      *unscaled_height)
+{
+  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
+
+  if (unscaled_width)
+    *unscaled_width = impl->unscaled_width;
+  if (unscaled_height)
+    *unscaled_height = impl->unscaled_height;
+}
+
+static void
+gdk_win32_input_shape_combine_region (GdkSurface            *window,
+                                      const cairo_region_t *shape_region,
+                                      gint                  offset_x,
+                                      gint                  offset_y)
+{
+  /* Partial input shape support is implemented by handling the
+   * NC_NCHITTEST message
+   */
+}
+
+static void
+gdk_surface_impl_win32_class_init (GdkSurfaceImplWin32Class *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_CLASS (klass);
+
+  parent_class = g_type_class_peek_parent (klass);
+
+  object_class->finalize = gdk_surface_impl_win32_finalize;
+
+  impl_class->ref_cairo_surface = gdk_win32_ref_cairo_surface;
+
+  impl_class->show = gdk_win32_surface_show;
+  impl_class->hide = gdk_win32_surface_hide;
+  impl_class->withdraw = gdk_win32_surface_withdraw;
+  impl_class->set_events = gdk_win32_surface_set_events;
+  impl_class->get_events = gdk_win32_surface_get_events;
+  impl_class->raise = gdk_win32_surface_raise;
+  impl_class->lower = gdk_win32_surface_lower;
+  impl_class->restack_toplevel = gdk_win32_surface_restack_toplevel;
+  impl_class->move_resize = gdk_win32_surface_move_resize;
+  impl_class->get_geometry = gdk_win32_surface_get_geometry;
+  impl_class->get_device_state = gdk_surface_win32_get_device_state;
+  impl_class->get_root_coords = gdk_win32_surface_get_root_coords;
+
+  impl_class->shape_combine_region = gdk_win32_surface_shape_combine_region;
+  impl_class->input_shape_combine_region = gdk_win32_input_shape_combine_region;
+  impl_class->destroy = gdk_win32_surface_destroy;
+  impl_class->begin_paint = gdk_win32_surface_begin_paint;
+  impl_class->end_paint = gdk_win32_surface_end_paint;
+
+  //impl_class->beep = gdk_x11_surface_beep;
+
+
+  impl_class->show_window_menu = gdk_win32_surface_show_window_menu;
+  impl_class->focus = gdk_win32_surface_focus;
+  impl_class->set_type_hint = gdk_win32_surface_set_type_hint;
+  impl_class->get_type_hint = gdk_win32_surface_get_type_hint;
+  impl_class->set_modal_hint = gdk_win32_surface_set_modal_hint;
+  impl_class->set_skip_taskbar_hint = gdk_win32_surface_set_skip_taskbar_hint;
+  impl_class->set_skip_pager_hint = gdk_win32_surface_set_skip_pager_hint;
+  impl_class->set_urgency_hint = gdk_win32_surface_set_urgency_hint;
+  impl_class->set_geometry_hints = gdk_win32_surface_set_geometry_hints;
+  impl_class->set_title = gdk_win32_surface_set_title;
+  impl_class->set_role = gdk_win32_surface_set_role;
+  //impl_class->set_startup_id = gdk_x11_surface_set_startup_id;
+  impl_class->set_transient_for = gdk_win32_surface_set_transient_for;
+  impl_class->get_frame_extents = gdk_win32_surface_get_frame_extents;
+  impl_class->set_accept_focus = gdk_win32_surface_set_accept_focus;
+  impl_class->set_focus_on_map = gdk_win32_surface_set_focus_on_map;
+  impl_class->set_icon_list = gdk_win32_surface_set_icon_list;
+  impl_class->set_icon_name = gdk_win32_surface_set_icon_name;
+  impl_class->iconify = gdk_win32_surface_iconify;
+  impl_class->deiconify = gdk_win32_surface_deiconify;
+  impl_class->stick = gdk_win32_surface_stick;
+  impl_class->unstick = gdk_win32_surface_unstick;
+  impl_class->maximize = gdk_win32_surface_maximize;
+  impl_class->unmaximize = gdk_win32_surface_unmaximize;
+  impl_class->fullscreen = gdk_win32_surface_fullscreen;
+  impl_class->unfullscreen = gdk_win32_surface_unfullscreen;
+  impl_class->set_keep_above = gdk_win32_surface_set_keep_above;
+  impl_class->set_keep_below = gdk_win32_surface_set_keep_below;
+  impl_class->get_group = gdk_win32_surface_get_group;
+  impl_class->set_group = gdk_win32_surface_set_group;
+  impl_class->set_decorations = gdk_win32_surface_set_decorations;
+  impl_class->get_decorations = gdk_win32_surface_get_decorations;
+  impl_class->set_functions = gdk_win32_surface_set_functions;
+
+  impl_class->set_shadow_width = gdk_win32_surface_set_shadow_width;
+  impl_class->begin_resize_drag = gdk_win32_surface_begin_resize_drag;
+  impl_class->begin_move_drag = gdk_win32_surface_begin_move_drag;
+  impl_class->set_opacity = gdk_win32_surface_set_opacity;
+  impl_class->destroy_notify = gdk_win32_surface_destroy_notify;
+  impl_class->register_dnd = _gdk_win32_surface_register_dnd;
+  impl_class->drag_begin = _gdk_win32_surface_drag_begin;
+  impl_class->create_gl_context = _gdk_win32_surface_create_gl_context;
+  impl_class->get_scale_factor = _gdk_win32_surface_get_scale_factor;
+  impl_class->get_unscaled_size = _gdk_win32_surface_get_unscaled_size;
+}
+
+HGDIOBJ
+gdk_win32_surface_get_handle (GdkSurface *window)
+{
+  if (!GDK_SURFACE_IS_WIN32 (window))
+    {
+      g_warning (G_STRLOC " window is not a native Win32 window");
+      return NULL;
+    }
+
+  return GDK_SURFACE_HWND (window);
+}
diff --git a/gdk/win32/gdksurface-win32.h b/gdk/win32/gdksurface-win32.h
new file mode 100644 (file)
index 0000000..684690f
--- /dev/null
@@ -0,0 +1,376 @@
+/* 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 Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __GDK_SURFACE_WIN32_H__
+#define __GDK_SURFACE_WIN32_H__
+
+#include "gdk/win32/gdkprivate-win32.h"
+#include "gdk/gdksurfaceimpl.h"
+#include "gdk/gdkcursor.h"
+
+#include <windows.h>
+
+G_BEGIN_DECLS
+
+/* Window implementation for Win32
+ */
+
+typedef struct _GdkSurfaceImplWin32 GdkSurfaceImplWin32;
+typedef struct _GdkSurfaceImplWin32Class GdkSurfaceImplWin32Class;
+
+#define GDK_TYPE_SURFACE_IMPL_WIN32              (_gdk_surface_impl_win32_get_type ())
+#define GDK_SURFACE_IMPL_WIN32(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_WIN32, GdkSurfaceImplWin32))
+#define GDK_SURFACE_IMPL_WIN32_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_WIN32, GdkSurfaceImplWin32Class))
+#define GDK_IS_SURFACE_IMPL_WIN32(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_WIN32))
+#define GDK_IS_SURFACE_IMPL_WIN32_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_WIN32))
+#define GDK_SURFACE_IMPL_WIN32_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_WIN32, GdkSurfaceImplWin32Class))
+
+enum _GdkWin32AeroSnapCombo
+{
+  GDK_WIN32_AEROSNAP_COMBO_NOTHING = 0,
+  GDK_WIN32_AEROSNAP_COMBO_UP,
+  GDK_WIN32_AEROSNAP_COMBO_DOWN,
+  GDK_WIN32_AEROSNAP_COMBO_LEFT,
+  GDK_WIN32_AEROSNAP_COMBO_RIGHT,
+  /* Same order as non-shift variants. We use it to do things like:
+   * AEROSNAP_UP + 4 = AEROSNAP_SHIFTUP
+   */
+  GDK_WIN32_AEROSNAP_COMBO_SHIFTUP,
+  GDK_WIN32_AEROSNAP_COMBO_SHIFTDOWN,
+  GDK_WIN32_AEROSNAP_COMBO_SHIFTLEFT,
+  GDK_WIN32_AEROSNAP_COMBO_SHIFTRIGHT
+};
+
+typedef enum _GdkWin32AeroSnapCombo GdkWin32AeroSnapCombo;
+
+enum _GdkWin32AeroSnapState
+{
+  GDK_WIN32_AEROSNAP_STATE_UNDETERMINED = 0,
+  GDK_WIN32_AEROSNAP_STATE_HALFLEFT,
+  GDK_WIN32_AEROSNAP_STATE_HALFRIGHT,
+  GDK_WIN32_AEROSNAP_STATE_FULLUP,
+  /* Maximize state is only used by edge-snap */
+  GDK_WIN32_AEROSNAP_STATE_MAXIMIZE
+};
+
+typedef enum _GdkWin32AeroSnapState GdkWin32AeroSnapState;
+
+struct _GdkRectangleDouble
+{
+  gdouble x;
+  gdouble y;
+  gdouble width;
+  gdouble height;
+};
+
+typedef struct _GdkRectangleDouble GdkRectangleDouble;
+
+enum _GdkW32WindowDragOp
+{
+  GDK_WIN32_DRAGOP_NONE = 0,
+  GDK_WIN32_DRAGOP_RESIZE,
+  GDK_WIN32_DRAGOP_MOVE,
+  GDK_WIN32_DRAGOP_COUNT
+};
+
+typedef enum _GdkW32WindowDragOp GdkW32WindowDragOp;
+
+typedef enum _GdkWin32MonitorDpiType
+{
+  MDT_EFFECTIVE_DPI  = 0,
+  MDT_ANGULAR_DPI    = 1,
+  MDT_RAW_DPI        = 2,
+  MDT_DEFAULT        = MDT_EFFECTIVE_DPI
+} GdkWin32MonitorDpiType;
+
+struct _GdkW32DragMoveResizeContext
+{
+  /* The window that is being moved/resized */
+  GdkSurface         *window;
+
+  /* The kind of drag-operation going on. */
+  GdkW32WindowDragOp op;
+
+  /* The edge that was grabbed for resizing. Not used for moving. */
+  GdkSurfaceEdge      edge;
+
+  /* The device used to initiate the op.
+   * We grab it at the beginning and ungrab it at the end.
+   */
+  GdkDevice         *device;
+
+  /* The button pressed down to initiate the op.
+   * The op will be canceled only when *this* button
+   * is released.
+   */
+  gint               button;
+
+  /* Initial cursor position when the operation began.
+   * Current cursor position is subtracted from it to find how far
+   * to move window border(s).
+   */
+  gint               start_root_x;
+  gint               start_root_y;
+
+  /* Initial window rectangle (position and size).
+   * The window is resized/moved relative to this (see start_root_*).
+   */
+  RECT               start_rect;
+
+  /* Not used */
+  guint32            timestamp;
+
+  /* TRUE if during the next redraw we should call SetWindowPos() to push
+   * the window size and poistion to the native window.
+   */
+  gboolean           native_move_resize_pending;
+
+  /* The cursor we should use while the operation is running. */
+  GdkCursor         *cursor;
+
+  /* This window looks like an outline and is drawn under the window
+   * that is being dragged. It indicates the shape the dragged window
+   * will take if released at a particular point.
+   * Indicator window size always matches the target indicator shape,
+   * the the actual indicator drawn on it might not, depending on
+   * how much time elapsed since the animation started.
+   */
+  HWND               shape_indicator;
+
+  /* Used to draw the indicator */
+  cairo_surface_t   *indicator_surface;
+  gint               indicator_surface_width;
+  gint               indicator_surface_height;
+
+  /* Size/position of shape_indicator */
+  GdkRectangle       indicator_window_rect;
+
+  /* Indicator will animate to occupy this rectangle */
+  GdkRectangle       indicator_target;
+
+  /* Indicator will start animating from this rectangle */
+  GdkRectangle       indicator_start;
+
+  /* Timestamp of the animation start */
+  gint64             indicator_start_time;
+
+  /* Timer that drives the animation */
+  guint              timer;
+
+  /* A special timestamp, if we want to draw not how
+   * the animation should look *now*, but how it should
+   * look at arbitrary moment of time.
+   * Set to 0 to tell GDK to use current time.
+   */
+  gint64             draw_timestamp;
+
+  /* Indicates that a transformation was revealed:
+   *
+   * For drag-resize: If it's FALSE,
+   * then the pointer have not yet hit a trigger that triggers fullup.
+   * If TRUE, then the pointer did hit a trigger that triggers fullup
+   * at some point during this drag op.
+   * This is used to prevent drag-resize from triggering
+   * a transformation when first approaching a trigger of the work area -
+   * one must drag it all the way to the very trigger to trigger; afterwards
+   * a transformation will start triggering at some distance from the trigger
+   * for as long as the op is still running. This is how AeroSnap works.
+   *
+   * For drag-move: If it's FALSE,
+   * then the pointer have not yet hit a trigger, even if it is
+   * already within a edge region.
+   * If it's TRUE, then the pointer did hit a trigger within an
+   * edge region, and have not yet left an edge region
+   * (passing from one edge region into another doesn't count).
+   */
+  gboolean           revealed;
+
+  /* Arrays of GdkRectangle pairs, describing the areas of the virtual
+   * desktop that trigger various AeroSnap window transofrmations
+   * Coordinates are GDK screen coordinates.
+   */
+  GArray            *halfleft_regions;
+  GArray            *halfright_regions;
+  GArray            *maximize_regions;
+  GArray            *fullup_regions;
+
+  /* Current pointer position will result in this kind of snapping,
+   * if the drag op is finished.
+   */
+  GdkWin32AeroSnapState current_snap;
+};
+
+typedef struct _GdkW32DragMoveResizeContext GdkW32DragMoveResizeContext;
+
+struct _GdkSurfaceImplWin32
+{
+  GdkSurfaceImpl parent_instance;
+
+  GdkSurface *wrapper;
+  HANDLE handle;
+
+  gint8 toplevel_window_type;
+
+  HICON   hicon_big;
+  HICON   hicon_small;
+
+  /* When VK_PACKET sends us a leading surrogate, it's stashed here.
+   * Later, when another VK_PACKET sends a tailing surrogate, we make up
+   * a full unicode character from them, or discard the leading surrogate,
+   * if the next key is not a tailing surrogate.
+   */
+  wchar_t leading_surrogate_keydown;
+  wchar_t leading_surrogate_keyup;
+
+  /* Window size hints */
+  gint hint_flags;
+  GdkGeometry hints;
+
+  GdkEventMask native_event_mask;
+
+  GdkSurfaceTypeHint type_hint;
+
+  GdkSurface *transient_owner;
+  GSList    *transient_children;
+  gint       num_transients;
+  gboolean   changing_state;
+
+  gint initial_x;
+  gint initial_y;
+
+  /* left/right/top/bottom width of the shadow/resize-grip around the window */
+  RECT margins;
+
+  /* left+right and top+bottom from @margins */
+  gint margins_x;
+  gint margins_y;
+
+  /* Set to TRUE when GTK tells us that margins are 0 everywhere.
+   * We don't actually set margins to 0, we just set this bit.
+   */
+  guint zero_margins : 1;
+  guint no_bg : 1;
+  guint inhibit_configure : 1;
+
+  /* Set to TRUE if window is using true layered mode adjustments
+   * via UpdateLayeredWindow().
+   * Layered windows that get SetLayeredWindowAttributes() called
+   * on them are not true layered windows.
+   */
+  guint layered : 1;
+
+  /* If TRUE, the @temp_styles is set to the styles that were temporarily
+   * added to this window.
+   */
+  guint have_temp_styles : 1;
+
+  /* If TRUE, the window is in the process of being maximized.
+   * This is set by WM_SYSCOMMAND and by gdk_win32_surface_maximize (),
+   * and is unset when WM_WINDOWPOSCHANGING is handled.
+   */
+  guint maximizing : 1;
+
+  /* GDK does not keep window contents around, it just draws new
+   * stuff over the window where changes occurred.
+   * cache_surface retains old window contents, because
+   * UpdateLayeredWindow() doesn't do partial redraws.
+   */
+  cairo_surface_t *cache_surface;
+  cairo_surface_t *cairo_surface;
+
+  /* Unlike window-backed surfaces, DIB-backed surface
+   * does not provide a way to query its size,
+   * so we have to remember it ourselves.
+   */
+  gint             dib_width;
+  gint             dib_height;
+
+  /* If the client wants uniformly-transparent window,
+   * we remember the opacity value here and apply it
+   * during UpdateLayredWindow() call, for layered windows.
+   */
+  gdouble          layered_opacity;
+
+  HDC              hdc;
+  int              hdc_count;
+  HBITMAP          saved_dc_bitmap; /* Original bitmap for dc */
+
+  GdkW32DragMoveResizeContext drag_move_resize_context;
+
+  /* Remembers where the window was snapped.
+   * Some snap operations change their meaning if
+   * the window is already snapped.
+   */
+  GdkWin32AeroSnapState snap_state;
+
+  /* Remembers window position before it was snapped.
+   * This is used to unsnap it.
+   * Position and size are percentages of the workarea
+   * of the monitor on which the window was before it was snapped.
+   */
+  GdkRectangleDouble *snap_stash;
+
+  /* Also remember the same position, but in absolute form. */
+  GdkRectangle *snap_stash_int;
+
+  /* Decorations set by gdk_surface_set_decorations() or NULL if unset */
+  GdkWMDecoration* decorations;
+
+  /* No. of windows to force layered windows off */
+  guint suppress_layered;
+
+  /* Temporary styles that this window got for the purpose of
+   * handling WM_SYSMENU.
+   * They are removed at the first opportunity (usually WM_INITMENU).
+   */
+  LONG_PTR temp_styles;
+
+  /* scale of window on HiDPI */
+  gint window_scale;
+  gint unscaled_width;
+  gint unscaled_height;
+};
+
+struct _GdkSurfaceImplWin32Class
+{
+  GdkSurfaceImplClass parent_class;
+};
+
+GType _gdk_surface_impl_win32_get_type (void);
+
+void  _gdk_win32_surface_tmp_unset_bg  (GdkSurface *window,
+                                      gboolean   recurse);
+void  _gdk_win32_surface_tmp_reset_bg  (GdkSurface *window,
+                                      gboolean   recurse);
+
+void  _gdk_win32_surface_tmp_unset_parent_bg (GdkSurface *window);
+void  _gdk_win32_surface_tmp_reset_parent_bg (GdkSurface *window);
+
+void  _gdk_win32_surface_update_style_bits   (GdkSurface *window);
+
+gint  _gdk_win32_surface_get_scale_factor    (GdkSurface *window);
+
+G_END_DECLS
+
+#endif /* __GDK_SURFACE_WIN32_H__ */
index e098366e0f216f13f49a50393d799afe0fefd2a9..f4001dabb5bd84390a12310adde898886998ea61 100644 (file)
@@ -33,7 +33,7 @@
 #include <gdk/win32/gdkwin32dnd.h>
 #include <gdk/win32/gdkwin32keys.h>
 #include <gdk/win32/gdkwin32screen.h>
-#include <gdk/win32/gdkwin32window.h>
+#include <gdk/win32/gdkwin32surface.h>
 #include <gdk/win32/gdkwin32misc.h>
 #include <gdk/win32/gdkwin32monitor.h>
 #include <gdk/win32/gdkwin32glcontext.h>
diff --git a/gdk/win32/gdkwin32surface.h b/gdk/win32/gdkwin32surface.h
new file mode 100644 (file)
index 0000000..9dda179
--- /dev/null
@@ -0,0 +1,55 @@
+/* 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __GDK_WIN32_SURFACE_H__
+#define __GDK_WIN32_SURFACE_H__
+
+#if !defined (__GDKWIN32_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdkwin32.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_WIN32_SURFACE              (gdk_win32_surface_get_type ())
+#define GDK_WIN32_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WIN32_SURFACE, GdkWin32Surface))
+#define GDK_WIN32_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WIN32_SURFACE, GdkWin32SurfaceClass))
+#define GDK_IS_WIN32_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WIN32_SURFACE))
+#define GDK_IS_WIN32_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WIN32_SURFACE))
+#define GDK_WIN32_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WIN32_SURFACE, GdkWin32SurfaceClass))
+
+#ifdef GDK_COMPILATION
+typedef struct _GdkWin32Surface GdkWin32Surface;
+#else
+typedef GdkSurface GdkWin32Surface;
+#endif
+typedef struct _GdkWin32SurfaceClass GdkWin32SurfaceClass;
+
+GDK_AVAILABLE_IN_ALL
+GType    gdk_win32_surface_get_type          (void);
+
+G_END_DECLS
+
+#endif /* __GDK_X11_SURFACE_H__ */
diff --git a/gdk/win32/gdkwin32window.h b/gdk/win32/gdkwin32window.h
deleted file mode 100644 (file)
index 9dda179..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-#ifndef __GDK_WIN32_SURFACE_H__
-#define __GDK_WIN32_SURFACE_H__
-
-#if !defined (__GDKWIN32_H_INSIDE__) && !defined (GDK_COMPILATION)
-#error "Only <gdk/gdkwin32.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_WIN32_SURFACE              (gdk_win32_surface_get_type ())
-#define GDK_WIN32_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WIN32_SURFACE, GdkWin32Surface))
-#define GDK_WIN32_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WIN32_SURFACE, GdkWin32SurfaceClass))
-#define GDK_IS_WIN32_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WIN32_SURFACE))
-#define GDK_IS_WIN32_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WIN32_SURFACE))
-#define GDK_WIN32_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WIN32_SURFACE, GdkWin32SurfaceClass))
-
-#ifdef GDK_COMPILATION
-typedef struct _GdkWin32Surface GdkWin32Surface;
-#else
-typedef GdkSurface GdkWin32Surface;
-#endif
-typedef struct _GdkWin32SurfaceClass GdkWin32SurfaceClass;
-
-GDK_AVAILABLE_IN_ALL
-GType    gdk_win32_surface_get_type          (void);
-
-G_END_DECLS
-
-#endif /* __GDK_X11_SURFACE_H__ */
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
deleted file mode 100644 (file)
index 7d51af7..0000000
+++ /dev/null
@@ -1,5959 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 1998-2004 Tor Lillqvist
- * Copyright (C) 2001-2011 Hans Breuer
- * Copyright (C) 2007-2009 Cody Russell
- *
- * 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-#include "config.h"
-#include <stdlib.h>
-
-#include "gdk.h"
-#include "gdkwindowimpl.h"
-#include "gdkprivate-win32.h"
-#include "gdkdeviceprivate.h"
-#include "gdkdevicemanager-win32.h"
-#include "gdkenumtypes.h"
-#include "gdkwin32.h"
-#include "gdkdisplayprivate.h"
-#include "gdkmonitorprivate.h"
-#include "gdkwin32window.h"
-#include "gdkglcontext-win32.h"
-#include "gdkdisplay-win32.h"
-
-#include <cairo-win32.h>
-#include <dwmapi.h>
-#include <math.h>
-#include "fallback-c89.c"
-
-static void gdk_surface_impl_win32_init       (GdkSurfaceImplWin32      *window);
-static void gdk_surface_impl_win32_class_init (GdkSurfaceImplWin32Class *klass);
-static void gdk_surface_impl_win32_finalize   (GObject                 *object);
-
-static gpointer parent_class = NULL;
-static GSList *modal_window_stack = NULL;
-
-static const cairo_user_data_key_t gdk_win32_cairo_key;
-typedef struct _FullscreenInfo FullscreenInfo;
-
-struct _FullscreenInfo
-{
-  RECT  r;
-  guint hint_flags;
-  LONG  style;
-};
-
-struct _AeroSnapEdgeRegion
-{
-  /* The rectangle along the edge of the desktop
-   * that allows application of the snap transformation.
-   */
-  GdkRectangle edge;
-
-  /* A subregion of the "edge". When the pointer hits
-   * this region, the transformation is revealed.
-   * Usually it is 1-pixel thick and is located at the
-   * very edge of the screen. When there's a toolbar
-   * at that edge, the "trigger" and the "edge" regions
-   * are extended to cover that toolbar.
-   */
-  GdkRectangle trigger;
-};
-
-typedef struct _AeroSnapEdgeRegion AeroSnapEdgeRegion;
-
-/* Use this for hWndInsertAfter (2nd argument to SetWindowPos()) if
- * SWP_NOZORDER flag is used. Otherwise it's unobvious why a particular
- * argument is used. Using NULL is misleading, because
- * NULL is equivalent to HWND_TOP.
- */
-#define SWP_NOZORDER_SPECIFIED HWND_TOP
-
-/* Size of the regions at the edges of the desktop where
- * snapping can take place (in pixels)
- */
-#define AEROSNAP_REGION_THICKNESS (20)
-/* Size of the subregions that actually trigger the snapping prompt
- * (in pixels).
- */
-#define AEROSNAP_REGION_TRIGGER_THICKNESS (1)
-
-/* The gap between the snap indicator and the edge of the work area
- * (in pixels).
- */
-#define AEROSNAP_INDICATOR_EDGE_GAP (10)
-
-/* Width of the outline of the snap indicator
- * (in pixels).
- */
-#define AEROSNAP_INDICATOR_LINE_WIDTH (3.0)
-
-/* Corner radius of the snap indicator.
- */
-#define AEROSNAP_INDICATOR_CORNER_RADIUS (3.0)
-
-/* The time it takes for snap indicator to expand/shrink
- * from current window size to future position of the
- * snapped window (in microseconds).
- */
-#define AEROSNAP_INDICATOR_ANIMATION_DURATION (200 * 1000)
-
-/* Opacity if the snap indicator. */
-#define AEROSNAP_INDICATOR_OPACITY (0.5)
-
-/* The interval between snap indicator redraws (in milliseconds).
- * 16 is ~ 1/60 of a second, for ~60 FPS.
- */
-#define AEROSNAP_INDICATOR_ANIMATION_TICK (16)
-
-static gboolean _gdk_surface_get_functions (GdkSurface         *window,
-                                           GdkWMFunction     *functions);
-static HDC     _gdk_win32_impl_acquire_dc (GdkSurfaceImplWin32 *impl);
-static void    _gdk_win32_impl_release_dc (GdkSurfaceImplWin32 *impl);
-
-#define WINDOW_IS_TOPLEVEL(window)                \
-  (GDK_SURFACE_TYPE (window) != GDK_SURFACE_FOREIGN)
-
-struct _GdkWin32Surface {
-  GdkSurface parent;
-};
-
-struct _GdkWin32SurfaceClass {
-  GdkSurfaceClass parent_class;
-};
-
-G_DEFINE_TYPE (GdkWin32Surface, gdk_win32_surface, GDK_TYPE_SURFACE)
-
-static void
-gdk_win32_surface_class_init (GdkWin32SurfaceClass *window_class)
-{
-}
-
-static void
-gdk_win32_surface_init (GdkWin32Surface *window)
-{
-}
-
-
-G_DEFINE_TYPE (GdkSurfaceImplWin32, gdk_surface_impl_win32, GDK_TYPE_SURFACE_IMPL)
-
-GType
-_gdk_surface_impl_win32_get_type (void)
-{
-  static GType object_type = 0;
-
-  if (!object_type)
-    {
-      const GTypeInfo object_info =
-      {
-        sizeof (GdkSurfaceImplWin32Class),
-        (GBaseInitFunc) NULL,
-        (GBaseFinalizeFunc) NULL,
-        (GClassInitFunc) gdk_surface_impl_win32_class_init,
-        NULL,           /* class_finalize */
-        NULL,           /* class_data */
-        sizeof (GdkSurfaceImplWin32),
-        0,              /* n_preallocs */
-        (GInstanceInitFunc) gdk_surface_impl_win32_init,
-      };
-
-      object_type = g_type_register_static (GDK_TYPE_SURFACE_IMPL,
-                                            "GdkSurfaceImplWin32",
-                                            &object_info, 0);
-    }
-
-  return object_type;
-}
-
-static void
-gdk_surface_impl_win32_init (GdkSurfaceImplWin32 *impl)
-{
-  GdkDisplay *display = gdk_display_get_default ();
-
-  impl->toplevel_window_type = -1;
-  impl->hicon_big = NULL;
-  impl->hicon_small = NULL;
-  impl->hint_flags = 0;
-  impl->type_hint = GDK_SURFACE_TYPE_HINT_NORMAL;
-  impl->transient_owner = NULL;
-  impl->transient_children = NULL;
-  impl->num_transients = 0;
-  impl->changing_state = FALSE;
-  impl->window_scale = 1;
-}
-
-static void
-gdk_surface_impl_win32_finalize (GObject *object)
-{
-  GdkSurface *wrapper;
-  GdkSurfaceImplWin32 *window_impl;
-
-  g_return_if_fail (GDK_IS_SURFACE_IMPL_WIN32 (object));
-
-  window_impl = GDK_SURFACE_IMPL_WIN32 (object);
-
-  wrapper = window_impl->wrapper;
-
-  if (!GDK_SURFACE_DESTROYED (wrapper))
-    {
-      gdk_win32_handle_table_remove (window_impl->handle);
-    }
-
-  g_clear_pointer (&window_impl->snap_stash, g_free);
-  g_clear_pointer (&window_impl->snap_stash_int, g_free);
-
-  if (window_impl->hicon_big != NULL)
-    {
-      GDI_CALL (DestroyIcon, (window_impl->hicon_big));
-      window_impl->hicon_big = NULL;
-    }
-
-  if (window_impl->hicon_small != NULL)
-    {
-      GDI_CALL (DestroyIcon, (window_impl->hicon_small));
-      window_impl->hicon_small = NULL;
-    }
-
-  g_free (window_impl->decorations);
-
-  if (window_impl->cache_surface)
-    {
-      cairo_surface_destroy (window_impl->cache_surface);
-      window_impl->cache_surface = NULL;
-    }
-
-  if (window_impl->cairo_surface)
-    {
-      cairo_surface_destroy (window_impl->cairo_surface);
-      window_impl->cairo_surface = NULL;
-    }
-
-  g_assert (window_impl->transient_owner == NULL);
-  g_assert (window_impl->transient_children == NULL);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gdk_win32_get_window_client_area_rect (GdkSurface *window,
-                                       gint       scale,
-                                       RECT      *rect)
-{
-  gint x, y, width, height;
-
-  gdk_surface_get_position (window, &x, &y);
-  width = gdk_surface_get_width (window);
-  height = gdk_surface_get_height (window);
-  rect->left = x * scale;
-  rect->top = y * scale;
-  rect->right = rect->left + width * scale;
-  rect->bottom = rect->top + height * scale;
-}
-
-static void
-gdk_win32_surface_get_queued_window_rect (GdkSurface *window,
-                                         RECT      *return_window_rect)
-{
-  RECT window_rect;
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  gdk_win32_get_window_client_area_rect (window, impl->window_scale, &window_rect);
-
-  /* Turn client area into window area */
-  _gdk_win32_adjust_client_rect (window, &window_rect);
-
-  /* Convert GDK screen coordinates to W32 desktop coordinates */
-  window_rect.left -= _gdk_offset_x * impl->window_scale;
-  window_rect.right -= _gdk_offset_x * impl->window_scale;
-  window_rect.top -= _gdk_offset_y * impl->window_scale;
-  window_rect.bottom -= _gdk_offset_y * impl->window_scale;
-
-  *return_window_rect = window_rect;
-}
-
-static void
-gdk_win32_surface_apply_queued_move_resize (GdkSurface *window,
-                                           RECT       window_rect)
-{
-  if (!IsIconic (GDK_SURFACE_HWND (window)))
-    {
-      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-      GDK_NOTE (EVENTS, g_print ("Setting window position ... "));
-
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                               SWP_NOZORDER_SPECIFIED,
-                               window_rect.left, window_rect.top,
-                               window_rect.right - window_rect.left,
-                               window_rect.bottom - window_rect.top,
-                               SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW));
-
-      GDK_NOTE (EVENTS, g_print (" ... set window position\n"));
-
-      return;
-    }
-
-  /* Don't move iconic windows */
-  /* TODO: use SetWindowPlacement() to change non-minimized window position */
-}
-
-static gboolean
-gdk_win32_surface_begin_paint (GdkSurface *window)
-{
-  GdkSurfaceImplWin32 *impl;
-  RECT window_rect;
-
-  if (window == NULL || GDK_SURFACE_DESTROYED (window))
-    return TRUE;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  /* Layered windows are moved *after* repaint.
-   * We supply our own surface, return FALSE to make GDK use it.
-   */
-  if (impl->layered)
-    return FALSE;
-
-  /* FIXME: Possibly remove the following lines when we transition to GL
-   *        drawing fully.  This will probably mean that we won't
-   *        be able to use layered windows, as layered windows seem
-   *        to support only up to OpenGL 1.1, which is not enough for our
-   *        needs here.
-   */
-
-  /* Non-GL windows are moved *after* repaint.
-   * We don't supply our own surface, return TRUE to make GDK create
-   * one by itself.
-   *//*
-  if (!window->current_paint.use_gl)
-    return TRUE;*/
-
-  /* GL windows are moved *before* repaint (otherwise
-   * repainting doesn't work), but if there's no move queued up,
-   * return immediately. Doesn't matter what we return, GDK
-   * will create a surface anyway, as if we returned TRUE.
-   */
-  if (!impl->drag_move_resize_context.native_move_resize_pending)
-    return TRUE;
-
-  impl->drag_move_resize_context.native_move_resize_pending = FALSE;
-
-  /* Get the position/size of the window that GDK wants,
-   * apply it.
-   */
-  gdk_win32_surface_get_queued_window_rect (window, &window_rect);
-  gdk_win32_surface_apply_queued_move_resize (window, window_rect);
-
-  return TRUE;
-}
-
-static void
-gdk_win32_surface_end_paint (GdkSurface *window)
-{
-  /* FIXME: Possibly make gdk_win32_surface_end_paint() a
-   *        no-op stub, like what is done in Wayland, as
-   *        the items here rely on layered window usage,
-   *        when we transition to full GL drawing, as
-   *        layered windows do not support enough GL
-   *        for our needs here
-   */
-  GdkSurfaceImplWin32 *impl;
-  RECT window_rect;
-  HDC hdc;
-  POINT window_position;
-  SIZE window_size;
-  POINT source_point;
-  BLENDFUNCTION blender;
-  cairo_t *cr;
-
-  if (window == NULL || GDK_SURFACE_DESTROYED (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  /* GL windows are moved *before* repaint */
-  /*if (window->current_paint.use_gl)
-    return;*/
-
-  /* No move/resize is queued up, and we don't need to update
-   * the contents of a layered window, so return immediately.
-   */
-  if (!impl->layered &&
-      !impl->drag_move_resize_context.native_move_resize_pending)
-    return;
-
-  impl->drag_move_resize_context.native_move_resize_pending = FALSE;
-
-  /* Get the position/size of the window that GDK wants. */
-  gdk_win32_surface_get_queued_window_rect (window, &window_rect);
-
-  if (!impl->layered)
-    {
-      gdk_win32_surface_apply_queued_move_resize (window, window_rect);
-
-      return;
-    }
-
-  window_position.x = window_rect.left;
-  window_position.y = window_rect.top;
-
-  window_size.cx = window_rect.right - window_rect.left;
-  window_size.cy = window_rect.bottom - window_rect.top;
-
-  cairo_surface_flush (impl->cairo_surface);
-
-  /* we always draw in the top-left corner of the surface */
-  source_point.x = source_point.y = 0;
-
-  blender.BlendOp = AC_SRC_OVER;
-  blender.BlendFlags = 0;
-  blender.AlphaFormat = AC_SRC_ALPHA;
-  blender.SourceConstantAlpha = impl->layered_opacity * 255;
-
-  /* Update cache surface contents */
-  cr = cairo_create (impl->cache_surface);
-
-  cairo_set_source_surface (cr, window->current_paint.surface, 0, 0);
-  gdk_cairo_region (cr, window->current_paint.region);
-  cairo_clip (cr);
-
-  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-  cairo_paint (cr);
-
-  cairo_destroy (cr);
-
-  cairo_surface_flush (impl->cache_surface);
-  hdc = cairo_win32_surface_get_dc (impl->cache_surface);
-
-  /* Don't use UpdateLayeredWindow on minimized windows */
-  if (IsIconic (GDK_SURFACE_HWND (window)))
-    {
-      gdk_win32_surface_apply_queued_move_resize (window, window_rect);
-
-      return;
-    }
-
-  /* Move, resize and redraw layered window in one call */
-  API_CALL (UpdateLayeredWindow, (GDK_SURFACE_HWND (window), NULL,
-                                  &window_position, &window_size,
-                                  hdc, &source_point,
-                                  0, &blender, ULW_ALPHA));
-}
-
-void
-_gdk_win32_adjust_client_rect (GdkSurface *window,
-                              RECT      *rect)
-{
-  LONG style, exstyle;
-
-  style = GetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE);
-  exstyle = GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE);
-  API_CALL (AdjustWindowRectEx, (rect, style, FALSE, exstyle));
-}
-
-gboolean
-_gdk_win32_surface_enable_transparency (GdkSurface *window)
-{
-  GdkSurfaceImplWin32 *impl;
-  DWM_BLURBEHIND blur_behind;
-  HRGN empty_region;
-  HRESULT call_result;
-  HWND parent, thiswindow;
-
-  if (window == NULL || GDK_SURFACE_HWND (window) == NULL)
-    return FALSE;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  /* layered windows don't need blurbehind for transparency */
-  if (impl->layered)
-    return TRUE;
-
-  if (!gdk_display_is_composited (gdk_surface_get_display (window)))
-    return FALSE;
-
-  thiswindow = GDK_SURFACE_HWND (window);
-
-  /* Blurbehind only works on toplevel windows */
-  parent = GetAncestor (thiswindow, GA_PARENT);
-  if (!(GetWindowLong (thiswindow, GWL_STYLE) & WS_POPUP) &&
-      (parent == NULL || parent != GetDesktopWindow ()))
-    return FALSE;
-
-  empty_region = CreateRectRgn (0, 0, -1, -1);
-
-  if (empty_region == NULL)
-    return FALSE;
-
-  memset (&blur_behind, 0, sizeof (blur_behind));
-  blur_behind.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
-  blur_behind.hRgnBlur = empty_region;
-  blur_behind.fEnable = TRUE;
-  call_result = DwmEnableBlurBehindWindow (thiswindow, &blur_behind);
-
-  if (!SUCCEEDED (call_result))
-    g_warning ("%s: %s (%p) failed: %" G_GINT32_MODIFIER "x",
-        G_STRLOC, "DwmEnableBlurBehindWindow", thiswindow, (guint32) call_result);
-
-  DeleteObject (empty_region);
-
-  return SUCCEEDED (call_result);
-}
-
-static const gchar *
-get_default_title (void)
-{
-  const char *title;
-  title = g_get_application_name ();
-  if (!title)
-    title = g_get_prgname ();
-
-  return title;
-}
-
-/* RegisterGdkClass
- *   is a wrapper function for RegisterWindowClassEx.
- *   It creates at least one unique class for every
- *   GdkSurfaceType. If support for single window-specific icons
- *   is ever needed (e.g Dialog specific), every such window should
- *   get its own class
- */
-static ATOM
-RegisterGdkClass (GdkSurfaceType wtype, GdkSurfaceTypeHint wtype_hint)
-{
-  static ATOM klassTOPLEVEL   = 0;
-  static ATOM klassCHILD      = 0;
-  static ATOM klassTEMP       = 0;
-  static ATOM klassTEMPSHADOW = 0;
-  static HICON hAppIcon = NULL;
-  static HICON hAppIconSm = NULL;
-  static WNDCLASSEXW wcl;
-  ATOM klass = 0;
-
-  wcl.cbSize = sizeof (WNDCLASSEX);
-  wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
-                  * on WM_SIZE and WM_MOVE. Flicker, Performance!
-                  */
-  wcl.lpfnWndProc = _gdk_win32_surface_procedure;
-  wcl.cbClsExtra = 0;
-  wcl.cbWndExtra = 0;
-  wcl.hInstance = _gdk_app_hmodule;
-  wcl.hIcon = 0;
-  wcl.hIconSm = 0;
-
-  /* initialize once! */
-  if (0 == hAppIcon && 0 == hAppIconSm)
-    {
-      gchar sLoc [MAX_PATH+1];
-
-      if (0 != GetModuleFileName (_gdk_app_hmodule, sLoc, MAX_PATH))
-        {
-          ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
-
-          if (0 == hAppIcon && 0 == hAppIconSm)
-            {
-              if (0 != GetModuleFileName (_gdk_dll_hinstance, sLoc, MAX_PATH))
-               {
-                 ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
-               }
-            }
-        }
-
-      if (0 == hAppIcon && 0 == hAppIconSm)
-        {
-          hAppIcon = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
-                                GetSystemMetrics (SM_CXICON),
-                                GetSystemMetrics (SM_CYICON), 0);
-          hAppIconSm = LoadImage (NULL, IDI_APPLICATION, IMAGE_ICON,
-                                  GetSystemMetrics (SM_CXSMICON),
-                                  GetSystemMetrics (SM_CYSMICON), 0);
-        }
-    }
-
-  if (0 == hAppIcon)
-    hAppIcon = hAppIconSm;
-  else if (0 == hAppIconSm)
-    hAppIconSm = hAppIcon;
-
-  wcl.lpszMenuName = NULL;
-
-  /* initialize once per class */
-  /*
-   * HB: Setting the background brush leads to flicker, because we
-   * don't get asked how to clear the background. This is not what
-   * we want, at least not for input_only windows ...
-   */
-#define ONCE_PER_CLASS() \
-  wcl.hIcon = CopyIcon (hAppIcon); \
-  wcl.hIconSm = CopyIcon (hAppIconSm); \
-  wcl.hbrBackground = NULL; \
-  wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
-
-  switch (wtype)
-    {
-    case GDK_SURFACE_TOPLEVEL:
-      /* MSDN: CS_OWNDC is needed for OpenGL contexts */
-      wcl.style |= CS_OWNDC;
-      if (0 == klassTOPLEVEL)
-        {
-          wcl.lpszClassName = L"gdkWindowToplevel";
-
-          ONCE_PER_CLASS ();
-          klassTOPLEVEL = RegisterClassExW (&wcl);
-        }
-      klass = klassTOPLEVEL;
-      break;
-
-    case GDK_SURFACE_TEMP:
-      if ((wtype_hint == GDK_SURFACE_TYPE_HINT_MENU) ||
-          (wtype_hint == GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU) ||
-          (wtype_hint == GDK_SURFACE_TYPE_HINT_POPUP_MENU))
-        {
-          if (klassTEMPSHADOW == 0)
-            {
-              wcl.lpszClassName = L"gdkWindowTempShadow";
-              wcl.style |= CS_SAVEBITS;
-              wcl.style |= 0x00020000; /* CS_DROPSHADOW */
-
-              ONCE_PER_CLASS ();
-              klassTEMPSHADOW = RegisterClassExW (&wcl);
-            }
-
-          klass = klassTEMPSHADOW;
-        }
-       else
-        {
-          if (klassTEMP == 0)
-            {
-              wcl.lpszClassName = L"gdkWindowTemp";
-              wcl.style |= CS_SAVEBITS;
-              ONCE_PER_CLASS ();
-              klassTEMP = RegisterClassExW (&wcl);
-            }
-
-          klass = klassTEMP;
-        }
-      break;
-
-    case GDK_SURFACE_CHILD:
-    default:
-      g_assert_not_reached ();
-      break;
-    }
-
-  if (klass == 0)
-    {
-      WIN32_API_FAILED ("RegisterClassExW");
-      g_error ("That is a fatal error");
-    }
-  return klass;
-}
-
-/*
- * Create native windows.
- *
- * With the default Gdk the created windows are mostly toplevel windows.
- *
- * Placement of the window is derived from the passed in window,
- * except for toplevel window where OS/Window Manager placement
- * is used.
- *
- * From attributes the only things used is: colormap, title,
- * wmclass and type_hint. [1]. We are checking redundant information
- * and complain if that changes, which would break this implementation
- * again.
- *
- * [1] http://mail.gnome.org/archives/gtk-devel-list/2010-August/msg00214.html
- */
-void
-_gdk_win32_display_create_window_impl (GdkDisplay    *display,
-                                      GdkSurface     *window,
-                                      GdkSurface     *real_parent,
-                                      GdkEventMask   event_mask,
-                                      GdkSurfaceAttr *attributes)
-{
-  HWND hwndNew;
-  HANDLE hparent;
-  ATOM klass = 0;
-  DWORD dwStyle = 0, dwExStyle;
-  RECT rect;
-  GdkSurfaceImplWin32 *impl;
-  GdkWin32Display *display_win32;
-  const gchar *title;
-  wchar_t *wtitle;
-  gint window_width, window_height;
-  gint offset_x = 0, offset_y = 0;
-  gint x, y, real_x = 0, real_y = 0;
-
-  g_return_if_fail (display == _gdk_display);
-
-  GDK_NOTE (MISC,
-            g_print ("_gdk_surface_impl_new: %s %s\n", (window->window_type == GDK_SURFACE_TOPLEVEL ? "TOPLEVEL" :
-                                                       (window->window_type == GDK_SURFACE_TEMP ? "TEMP" : "???")),
-                                                       (attributes->wclass == GDK_INPUT_OUTPUT ? "" : "input-only")));
-
-  hparent = (real_parent != NULL) ? GDK_SURFACE_HWND (real_parent) : NULL;
-
-  impl = g_object_new (GDK_TYPE_SURFACE_IMPL_WIN32, NULL);
-  impl->wrapper = GDK_SURFACE (window);
-  window->impl = GDK_SURFACE_IMPL (impl);
-
-  impl->layered = FALSE;
-  impl->layered_opacity = 1.0;
-
-  display_win32 = GDK_WIN32_DISPLAY (display);
-  impl->window_scale = _gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL, NULL);
-  impl->unscaled_width = window->width * impl->window_scale;
-  impl->unscaled_height = window->height * impl->window_scale;
-
-  if (!window->input_only)
-    {
-      dwExStyle = 0;
-    }
-  else
-    {
-      /* I very much doubt using WS_EX_TRANSPARENT actually
-       * corresponds to how X11 InputOnly windows work, but it appears
-       * to work well enough for the actual use cases in gtk.
-       */
-      dwExStyle = WS_EX_TRANSPARENT;
-      GDK_NOTE (MISC, g_print ("... GDK_INPUT_ONLY\n"));
-    }
-
-  switch (window->window_type)
-    {
-    case GDK_SURFACE_TOPLEVEL:
-      if (window->parent)
-       {
-         /* The common code warns for this case. */
-         hparent = GetDesktopWindow ();
-       }
-      /* Children of foreign windows aren't toplevel windows */
-      if (real_parent != NULL && GDK_SURFACE_TYPE (real_parent) == GDK_SURFACE_FOREIGN)
-       {
-         dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN;
-       }
-      else
-       {
-         /* MSDN: We need WS_CLIPCHILDREN and WS_CLIPSIBLINGS for GL Context Creation */
-         if (window->window_type == GDK_SURFACE_TOPLEVEL)
-           dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
-         else
-           dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
-
-         offset_x = _gdk_offset_x;
-         offset_y = _gdk_offset_y;
-       }
-      break;
-
-    case GDK_SURFACE_TEMP:
-      /* A temp window is not necessarily a top level window */
-      dwStyle = real_parent == NULL ? WS_POPUP : WS_CHILDWINDOW;
-      dwStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
-      dwExStyle |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
-      offset_x = _gdk_offset_x;
-      offset_y = _gdk_offset_y;
-      break;
-
-
-    case GDK_SURFACE_CHILD:
-    default:
-      g_assert_not_reached ();
-    }
-
-  rect.left = window->x * impl->window_scale;
-  rect.top = window->y * impl->window_scale;
-  rect.right = rect.left + window->width * impl->window_scale;
-  rect.bottom = rect.top + window->height * impl->window_scale;
-
-  AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
-
-  real_x = (window->x - offset_x) * impl->window_scale;
-  real_y = (window->y - offset_y) * impl->window_scale;
-
-  if (window->window_type == GDK_SURFACE_TOPLEVEL)
-    {
-      /* We initially place it at default so that we can get the
-         default window positioning if we want */
-      x = y = CW_USEDEFAULT;
-    }
-  else
-         {
-      /* TEMP, FOREIGN: Put these where requested */
-      x = real_x;
-      y = real_y;
-    }
-
-  window_width = rect.right - rect.left;
-  window_height = rect.bottom - rect.top;
-
-  title = get_default_title ();
-  if (!title || !*title)
-    title = "";
-
-  impl->native_event_mask = GDK_STRUCTURE_MASK | event_mask;
-
-  if (impl->type_hint == GDK_SURFACE_TYPE_HINT_UTILITY)
-    dwExStyle |= WS_EX_TOOLWINDOW;
-
-  /* WS_EX_TRANSPARENT means "try draw this window last, and ignore input".
-   * It's the last part we're after. We don't want DND indicator to accept
-   * input, because that will make it a potential drop target, and if it's
-   * under the mouse cursor, this will kill any DND.
-   */
-  if (impl->type_hint == GDK_SURFACE_TYPE_HINT_DND)
-    dwExStyle |= WS_EX_TRANSPARENT;
-
-  klass = RegisterGdkClass (window->window_type, impl->type_hint);
-
-  wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
-
-  hwndNew = CreateWindowExW (dwExStyle,
-                            MAKEINTRESOURCEW (klass),
-                            wtitle,
-                            dwStyle,
-                            x,
-                            y,
-                            window_width, window_height,
-                            hparent,
-                            NULL,
-                            _gdk_app_hmodule,
-                            window);
-  if (GDK_SURFACE_HWND (window) != hwndNew)
-    {
-      g_warning ("gdk_surface_new: gdk_event_translate::WM_CREATE (%p, %p) HWND mismatch.",
-                GDK_SURFACE_HWND (window),
-                hwndNew);
-
-      /* HB: IHMO due to a race condition the handle was increased by
-       * one, which causes much trouble. Because I can't find the
-       * real bug, try to workaround it ...
-       * To reproduce: compile with MSVC 5, DEBUG=1
-       */
-# if 0
-      gdk_win32_handle_table_remove (GDK_SURFACE_HWND (window));
-      GDK_SURFACE_HWND (window) = hwndNew;
-      gdk_win32_handle_table_insert (&GDK_SURFACE_HWND (window), window);
-# else
-      /* the old behaviour, but with warning */
-      impl->handle = hwndNew;
-# endif
-
-    }
-
-  GetWindowRect (GDK_SURFACE_HWND (window), &rect);
-  impl->initial_x = rect.left;
-  impl->initial_y = rect.top;
-
-  /* Now we know the initial position, move to actually specified position */
-  if (real_x != x || real_y != y)
-    {
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                SWP_NOZORDER_SPECIFIED,
-                real_x, real_y, 0, 0,
-                SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
-    }
-
-  g_object_ref (window);
-  gdk_win32_handle_table_insert (&GDK_SURFACE_HWND (window), window);
-
-  GDK_NOTE (MISC, g_print ("... \"%s\" %dx%d@%+d%+d %p = %p\n",
-                          title,
-                          window_width, window_height,
-                          window->x - offset_x,
-                          window->y - offset_y,
-                          hparent,
-                          GDK_SURFACE_HWND (window)));
-
-  /* Add window handle to title */
-  GDK_NOTE (MISC_OR_EVENTS, gdk_surface_set_title (window, title));
-
-  g_free (wtitle);
-
-  if (impl->handle == NULL)
-    {
-      WIN32_API_FAILED ("CreateWindowExW");
-      g_object_unref (window);
-      return;
-    }
-
-//  if (!from_set_skip_taskbar_hint && window->window_type == GDK_SURFACE_TEMP)
-//    gdk_surface_set_skip_taskbar_hint (window, TRUE);
-
-  _gdk_win32_surface_enable_transparency (window);
-}
-
-GdkSurface *
-gdk_win32_surface_foreign_new_for_display (GdkDisplay *display,
-                                          HWND        anid)
-{
-  GdkSurface *window;
-  GdkSurfaceImplWin32 *impl;
-
-  HANDLE parent;
-  RECT rect;
-  POINT point;
-
-  if ((window = gdk_win32_surface_lookup_for_display (display, anid)) != NULL)
-    return g_object_ref (window);
-
-  window = _gdk_display_create_window (display);
-  window->impl = g_object_new (GDK_TYPE_SURFACE_IMPL_WIN32, NULL);
-  window->impl_window = window;
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-  impl->wrapper = window;
-  parent = GetParent (anid);
-
-  /* Always treat foreigns as toplevels */
-  window->parent = NULL;
-
-  GetClientRect ((HWND) anid, &rect);
-  point.x = rect.left;
-  point.y = rect.right;
-  ClientToScreen ((HWND) anid, &point);
-  if (parent != GetDesktopWindow ())
-    ScreenToClient (parent, &point);
-  window->x = point.x / impl->window_scale;
-  window->y = point.y / impl->window_scale;
-  impl->unscaled_width = rect.right - rect.left;
-  impl->unscaled_height = rect.bottom - rect.top;
-  window->width = (impl->unscaled_width + impl->window_scale - 1) / impl->window_scale;
-  window->height = (impl->unscaled_height + impl->window_scale - 1) / impl->window_scale;
-  window->window_type = GDK_SURFACE_FOREIGN;
-  window->destroyed = FALSE;
-  window->event_mask = GDK_ALL_EVENTS_MASK; /* XXX */
-  if (IsWindowVisible ((HWND) anid))
-    window->state &= (~GDK_SURFACE_STATE_WITHDRAWN);
-  else
-    window->state |= GDK_SURFACE_STATE_WITHDRAWN;
-  if (GetWindowLong ((HWND)anid, GWL_EXSTYLE) & WS_EX_TOPMOST)
-    window->state |= GDK_SURFACE_STATE_ABOVE;
-  else
-    window->state &= (~GDK_SURFACE_STATE_ABOVE);
-  window->state &= (~GDK_SURFACE_STATE_BELOW);
-  window->viewable = TRUE;
-
-  GDK_SURFACE_HWND (window) = anid;
-
-  g_object_ref (window);
-  gdk_win32_handle_table_insert (&GDK_SURFACE_HWND (window), window);
-
-  GDK_NOTE (MISC, g_print ("gdk_win32_surface_foreign_new_for_display: %p: %s@%+d%+d\n",
-                          (HWND) anid,
-                          _gdk_win32_surface_description (window),
-                          window->x, window->y));
-
-  return window;
-}
-
-static void
-gdk_win32_surface_destroy (GdkSurface *window,
-                         gboolean   recursing,
-                         gboolean   foreign_destroy)
-{
-  GdkSurfaceImplWin32 *window_impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-  GSList *tmp;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  GDK_NOTE (MISC, g_print ("gdk_win32_surface_destroy: %p\n",
-                          GDK_SURFACE_HWND (window)));
-
-  /* Remove ourself from the modal stack */
-  _gdk_remove_modal_window (window);
-
-  /* Remove all our transient children */
-  tmp = window_impl->transient_children;
-  while (tmp != NULL)
-    {
-      GdkSurface *child = tmp->data;
-      GdkSurfaceImplWin32 *child_impl = GDK_SURFACE_IMPL_WIN32 (GDK_SURFACE (child)->impl);
-
-      child_impl->transient_owner = NULL;
-      tmp = tmp->next;
-    }
-  g_slist_free (window_impl->transient_children);
-  window_impl->transient_children = NULL;
-
-  /* Remove ourself from our transient owner */
-  if (window_impl->transient_owner != NULL)
-    {
-      gdk_surface_set_transient_for (window, NULL);
-    }
-
-  if (!recursing && !foreign_destroy)
-    {
-      window->destroyed = TRUE;
-      DestroyWindow (GDK_SURFACE_HWND (window));
-    }
-}
-
-/* This function is called when the window really gone.
- */
-static void
-gdk_win32_surface_destroy_notify (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  GDK_NOTE (EVENTS,
-           g_print ("gdk_surface_destroy_notify: %p%s\n",
-                    GDK_SURFACE_HWND (window),
-                    (GDK_SURFACE_DESTROYED (window) ? " (destroyed)" : "")));
-
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      if (GDK_SURFACE_TYPE (window) != GDK_SURFACE_FOREIGN)
-       g_warning ("window %p unexpectedly destroyed",
-                  GDK_SURFACE_HWND (window));
-
-      _gdk_surface_destroy (window, TRUE);
-    }
-
-  gdk_win32_handle_table_remove (GDK_SURFACE_HWND (window));
-  g_object_unref (window);
-}
-
-static void
-get_outer_rect (GdkSurface *window,
-               gint       width,
-               gint       height,
-               RECT      *rect)
-{
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  rect->left = rect->top = 0;
-  rect->right = width * impl->window_scale;
-  rect->bottom = height * impl->window_scale;
-
-  _gdk_win32_adjust_client_rect (window, rect);
-}
-
-static void
-adjust_for_gravity_hints (GdkSurface *window,
-                         RECT      *outer_rect,
-                         gint          *x,
-                         gint          *y)
-{
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  if (impl->hint_flags & GDK_HINT_WIN_GRAVITY)
-    {
-#ifdef G_ENABLE_DEBUG
-      gint orig_x = *x, orig_y = *y;
-#endif
-
-      switch (impl->hints.win_gravity)
-       {
-       case GDK_GRAVITY_NORTH:
-       case GDK_GRAVITY_CENTER:
-       case GDK_GRAVITY_SOUTH:
-         *x -= (outer_rect->right - outer_rect->left / 2) / impl->window_scale;
-         *x += window->width / 2;
-         break;
-
-       case GDK_GRAVITY_SOUTH_EAST:
-       case GDK_GRAVITY_EAST:
-       case GDK_GRAVITY_NORTH_EAST:
-         *x -= (outer_rect->right - outer_rect->left) / impl->window_scale;
-         *x += window->width;
-         break;
-
-       case GDK_GRAVITY_STATIC:
-         *x += outer_rect->left / impl->window_scale;
-         break;
-
-       default:
-         break;
-       }
-
-      switch (impl->hints.win_gravity)
-       {
-       case GDK_GRAVITY_WEST:
-       case GDK_GRAVITY_CENTER:
-       case GDK_GRAVITY_EAST:
-         *y -= ((outer_rect->bottom - outer_rect->top) / 2) / impl->window_scale;
-         *y += window->height / 2;
-         break;
-
-       case GDK_GRAVITY_SOUTH_WEST:
-       case GDK_GRAVITY_SOUTH:
-       case GDK_GRAVITY_SOUTH_EAST:
-         *y -= (outer_rect->bottom - outer_rect->top) / impl->window_scale;
-         *y += window->height;
-         break;
-
-       case GDK_GRAVITY_STATIC:
-         *y += outer_rect->top * impl->window_scale;
-         break;
-
-       default:
-         break;
-       }
-      GDK_NOTE (MISC,
-               (orig_x != *x || orig_y != *y) ?
-               g_print ("adjust_for_gravity_hints: x: %d->%d, y: %d->%d\n",
-                        orig_x, *x, orig_y, *y)
-                 : (void) 0);
-    }
-}
-
-static void
-show_window_internal (GdkSurface *window,
-                      gboolean   already_mapped,
-                     gboolean   deiconify)
-{
-  GdkSurfaceImplWin32 *window_impl;
-  gboolean focus_on_map = FALSE;
-  DWORD exstyle;
-
-  if (window->destroyed)
-    return;
-
-  GDK_NOTE (MISC, g_print ("show_window_internal: %p: %s%s\n",
-                          GDK_SURFACE_HWND (window),
-                          _gdk_win32_surface_state_to_string (window->state),
-                          (deiconify ? " deiconify" : "")));
-
-  /* If asked to show (not deiconify) an withdrawn and iconified
-   * window, do that.
-   */
-  if (!deiconify &&
-      !already_mapped &&
-      (window->state & GDK_SURFACE_STATE_ICONIFIED))
-    {
-      GtkShowWindow (window, SW_SHOWMINNOACTIVE);
-      return;
-    }
-
-  /* If asked to just show an iconified window, do nothing. */
-  if (!deiconify && (window->state & GDK_SURFACE_STATE_ICONIFIED))
-    return;
-
-  /* If asked to deiconify an already noniconified window, do
-   * nothing. (Especially, don't cause the window to rise and
-   * activate. There are different calls for that.)
-   */
-  if (deiconify && !(window->state & GDK_SURFACE_STATE_ICONIFIED))
-    return;
-
-  /* If asked to show (but not raise) a window that is already
-   * visible, do nothing.
-   */
-  if (!deiconify && !already_mapped && IsWindowVisible (GDK_SURFACE_HWND (window)))
-    return;
-
-  /* Other cases */
-
-  if (!already_mapped)
-    focus_on_map = window->focus_on_map;
-
-  exstyle = GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE);
-
-  /* Use SetWindowPos to show transparent windows so automatic redraws
-   * in other windows can be suppressed.
-   */
-  if (exstyle & WS_EX_TRANSPARENT)
-    {
-      UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
-
-      if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP || !focus_on_map)
-       flags |= SWP_NOACTIVATE;
-
-      SetWindowPos (GDK_SURFACE_HWND (window),
-                   SWP_NOZORDER_SPECIFIED, 0, 0, 0, 0, flags);
-
-      return;
-    }
-
-  /* For initial map of "normal" windows we want to emulate WM window
-   * positioning behaviour, which means:
-   * + Use user specified position if GDK_HINT_POS or GDK_HINT_USER_POS
-   * otherwise:
-   * + default to the initial CW_USEDEFAULT placement,
-   *   no matter if the user moved the window before showing it.
-   * + Certain window types and hints have more elaborate positioning
-   *   schemes.
-   */
-  window_impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-  if (!already_mapped &&
-      GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL &&
-      (window_impl->hint_flags & (GDK_HINT_POS | GDK_HINT_USER_POS)) == 0)
-    {
-      gboolean center = FALSE;
-      RECT window_rect, center_on_rect;
-      int x, y;
-
-      x = window_impl->initial_x;
-      y = window_impl->initial_y;
-
-      if (window_impl->type_hint == GDK_SURFACE_TYPE_HINT_SPLASHSCREEN)
-       {
-         HMONITOR monitor;
-         MONITORINFO mi;
-
-         monitor = MonitorFromWindow (GDK_SURFACE_HWND (window), MONITOR_DEFAULTTONEAREST);
-         mi.cbSize = sizeof (mi);
-         if (monitor && GetMonitorInfo (monitor, &mi))
-           center_on_rect = mi.rcMonitor;
-         else
-           {
-             center_on_rect.left = 0;
-             center_on_rect.top = 0;
-             center_on_rect.right = GetSystemMetrics (SM_CXSCREEN);
-             center_on_rect.bottom = GetSystemMetrics (SM_CYSCREEN);
-           }
-         center = TRUE;
-       }
-      else if (window_impl->transient_owner != NULL &&
-              GDK_SURFACE_IS_MAPPED (window_impl->transient_owner))
-       {
-         GdkSurface *owner = window_impl->transient_owner;
-         /* Center on transient parent */
-         center_on_rect.left = (owner->x - _gdk_offset_x) * window_impl->window_scale;
-         center_on_rect.top = (owner->y - _gdk_offset_y) * window_impl->window_scale;
-         center_on_rect.right = center_on_rect.left + owner->width * window_impl->window_scale;
-         center_on_rect.bottom = center_on_rect.top + owner->height * window_impl->window_scale;
-
-         _gdk_win32_adjust_client_rect (GDK_SURFACE (owner), &center_on_rect);
-         center = TRUE;
-       }
-
-      if (center)
-       {
-         window_rect.left = 0;
-         window_rect.top = 0;
-         window_rect.right = window->width * window_impl->window_scale;
-         window_rect.bottom = window->height * window_impl->window_scale;
-         _gdk_win32_adjust_client_rect (window, &window_rect);
-
-         x = center_on_rect.left + ((center_on_rect.right - center_on_rect.left) - (window_rect.right - window_rect.left)) / 2;
-         y = center_on_rect.top + ((center_on_rect.bottom - center_on_rect.top) - (window_rect.bottom - window_rect.top)) / 2;
-       }
-
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                              SWP_NOZORDER_SPECIFIED,
-                              x, y, 0, 0,
-                              SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
-    }
-
-  if (!already_mapped &&
-      GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL)
-    {
-      /* Ensure new windows are fully onscreen */
-      RECT window_rect;
-      HMONITOR monitor;
-      MONITORINFO mi;
-      int x, y;
-
-      GetWindowRect (GDK_SURFACE_HWND (window), &window_rect);
-
-      monitor = MonitorFromWindow (GDK_SURFACE_HWND (window), MONITOR_DEFAULTTONEAREST);
-      mi.cbSize = sizeof (mi);
-      if (monitor && GetMonitorInfo (monitor, &mi))
-       {
-         x = window_rect.left;
-         y = window_rect.top;
-
-         if (window_rect.right > mi.rcWork.right)
-           {
-             window_rect.left -= (window_rect.right - mi.rcWork.right);
-             window_rect.right -= (window_rect.right - mi.rcWork.right);
-           }
-
-         if (window_rect.bottom > mi.rcWork.bottom)
-           {
-             window_rect.top -= (window_rect.bottom - mi.rcWork.bottom);
-             window_rect.bottom -= (window_rect.bottom - mi.rcWork.bottom);
-           }
-
-         if (window_rect.left < mi.rcWork.left)
-           {
-             window_rect.right += (mi.rcWork.left - window_rect.left);
-             window_rect.left += (mi.rcWork.left - window_rect.left);
-           }
-
-         if (window_rect.top < mi.rcWork.top)
-           {
-             window_rect.bottom += (mi.rcWork.top - window_rect.top);
-             window_rect.top += (mi.rcWork.top - window_rect.top);
-           }
-
-         if (x != window_rect.left || y != window_rect.top)
-           API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                                    SWP_NOZORDER_SPECIFIED,
-                                    window_rect.left, window_rect.top, 0, 0,
-                                    SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
-       }
-    }
-
-
-  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
-    {
-      gdk_surface_fullscreen (window);
-    }
-  else if (window->state & GDK_SURFACE_STATE_MAXIMIZED)
-    {
-      GtkShowWindow (window, SW_MAXIMIZE);
-    }
-  else if (window->state & GDK_SURFACE_STATE_ICONIFIED)
-    {
-      if (focus_on_map)
-        GtkShowWindow (window, SW_RESTORE);
-      else
-        GtkShowWindow (window, SW_SHOWNOACTIVATE);
-    }
-  else if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP || !focus_on_map)
-    {
-      if (!IsWindowVisible (GDK_SURFACE_HWND (window)))
-        GtkShowWindow (window, SW_SHOWNOACTIVATE);
-      else
-        GtkShowWindow (window, SW_SHOWNA);
-    }
-  else if (!IsWindowVisible (GDK_SURFACE_HWND (window)))
-    {
-      GtkShowWindow (window, SW_SHOWNORMAL);
-    }
-  else
-    {
-      GtkShowWindow (window, SW_SHOW);
-    }
-
-  /* Sync STATE_ABOVE to TOPMOST */
-  if (GDK_SURFACE_TYPE (window) != GDK_SURFACE_TEMP &&
-      (((window->state & GDK_SURFACE_STATE_ABOVE) &&
-       !(exstyle & WS_EX_TOPMOST)) ||
-       (!(window->state & GDK_SURFACE_STATE_ABOVE) &&
-       (exstyle & WS_EX_TOPMOST))))
-    {
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                              (window->state & GDK_SURFACE_STATE_ABOVE)?HWND_TOPMOST:HWND_NOTOPMOST,
-                              0, 0, 0, 0,
-                              SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
-    }
-}
-
-static void
-gdk_win32_surface_show (GdkSurface *window,
-                      gboolean already_mapped)
-{
-  show_window_internal (window, FALSE, FALSE);
-}
-
-static void
-gdk_win32_surface_hide (GdkSurface *window)
-{
-  if (window->destroyed)
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_win32_surface_hide: %p: %s\n",
-                          GDK_SURFACE_HWND (window),
-                          _gdk_win32_surface_state_to_string (window->state)));
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    gdk_synthesize_window_state (window,
-                                0,
-                                GDK_SURFACE_STATE_WITHDRAWN);
-
-  _gdk_surface_clear_update_area (window);
-
-  if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL)
-    ShowOwnedPopups (GDK_SURFACE_HWND (window), FALSE);
-
-  /* Use SetWindowPos to hide transparent windows so automatic redraws
-   * in other windows can be suppressed.
-   */
-  if (GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE) & WS_EX_TRANSPARENT)
-    {
-      SetWindowPos (GDK_SURFACE_HWND (window), SWP_NOZORDER_SPECIFIED,
-                   0, 0, 0, 0,
-                   SWP_HIDEWINDOW | SWP_NOREDRAW | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
-    }
-  else
-    {
-      GtkShowWindow (window, SW_HIDE);
-    }
-}
-
-static void
-gdk_win32_surface_withdraw (GdkSurface *window)
-{
-  if (window->destroyed)
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_win32_surface_withdraw: %p: %s\n",
-                          GDK_SURFACE_HWND (window),
-                          _gdk_win32_surface_state_to_string (window->state)));
-
-  gdk_surface_hide (window);   /* ??? */
-}
-
-static void
-gdk_win32_surface_move (GdkSurface *window,
-                      gint x, gint y)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_win32_surface_move: %p: %+d%+d\n",
-                           GDK_SURFACE_HWND (window), x, y));
-
-  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
-    return;
-
-  /* Don't check GDK_SURFACE_TYPE (window) == GDK_SURFACE_CHILD.
-   * Foreign windows (another app's windows) might be children of our
-   * windows! Especially in the case of gtkplug/socket.
-   */
-  if (GetAncestor (GDK_SURFACE_HWND (window), GA_PARENT) != GetDesktopWindow ())
-    {
-      _gdk_surface_move_resize_child (window, x, y, window->width, window->height);
-    }
-  else
-    {
-      RECT outer_rect;
-      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-      get_outer_rect (window, window->width, window->height, &outer_rect);
-
-      adjust_for_gravity_hints (window, &outer_rect, &x, &y);
-
-      GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,0,0,"
-                               "NOACTIVATE|NOSIZE|NOZORDER)\n",
-                               GDK_SURFACE_HWND (window),
-                               (x - _gdk_offset_x) * impl->window_scale,
-                               (y - _gdk_offset_y) * impl->window_scale));
-
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                              SWP_NOZORDER_SPECIFIED,
-                               (x - _gdk_offset_x) * impl->window_scale,
-                               (y - _gdk_offset_y) * impl->window_scale,
-                               0, 0,
-                               SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER));
-    }
-}
-
-static void
-gdk_win32_surface_resize (GdkSurface *window,
-                        gint width, gint height)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (width < 1)
-    width = 1;
-  if (height < 1)
-    height = 1;
-
-  GDK_NOTE (MISC, g_print ("gdk_win32_surface_resize: %p: %dx%d\n",
-                           GDK_SURFACE_HWND (window), width, height));
-
-  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
-    return;
-
-  if (GetAncestor (GDK_SURFACE_HWND (window), GA_PARENT) != GetDesktopWindow ())
-    {
-      _gdk_surface_move_resize_child (window, window->x, window->y, width, height);
-    }
-  else
-    {
-      RECT outer_rect;
-      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-      get_outer_rect (window, width, height, &outer_rect);
-
-      GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,0,0,%ld,%ld,"
-                               "NOACTIVATE|NOMOVE|NOZORDER)\n",
-                               GDK_SURFACE_HWND (window),
-                               outer_rect.right - outer_rect.left,
-                               outer_rect.bottom - outer_rect.top));
-
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                              SWP_NOZORDER_SPECIFIED,
-                               0, 0,
-                               outer_rect.right - outer_rect.left,
-                               outer_rect.bottom - outer_rect.top,
-                               SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER));
-      window->resize_count += 1;
-    }
-}
-
-static void
-gdk_win32_surface_move_resize_internal (GdkSurface *window,
-                                      gint       x,
-                                      gint       y,
-                                      gint       width,
-                                      gint       height)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (width < 1)
-    width = 1;
-  if (height < 1)
-    height = 1;
-
-  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_win32_surface_move_resize: %p: %dx%d@%+d%+d\n",
-                           GDK_SURFACE_HWND (window),
-                           width, height, x, y));
-
-  if (GetAncestor (GDK_SURFACE_HWND (window), GA_PARENT) != GetDesktopWindow ())
-    {
-      _gdk_surface_move_resize_child (window, x, y, width, height);
-    }
-  else
-    {
-      RECT outer_rect;
-      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-      get_outer_rect (window, width, height, &outer_rect);
-
-      adjust_for_gravity_hints (window, &outer_rect, &x, &y);
-
-      GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%ld,%ld,"
-                               "NOACTIVATE|NOZORDER)\n",
-                               GDK_SURFACE_HWND (window),
-                               (x - _gdk_offset_x) * impl->window_scale,
-                               (y - _gdk_offset_y) * impl->window_scale,
-                               outer_rect.right - outer_rect.left,
-                               outer_rect.bottom - outer_rect.top));
-
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                              SWP_NOZORDER_SPECIFIED,
-                               (x - _gdk_offset_x) * impl->window_scale,
-                               (y - _gdk_offset_y) * impl->window_scale,
-                               outer_rect.right - outer_rect.left,
-                               outer_rect.bottom - outer_rect.top,
-                               SWP_NOACTIVATE | SWP_NOZORDER));
-    }
-}
-
-static void
-gdk_win32_surface_move_resize (GdkSurface *window,
-                             gboolean   with_move,
-                             gint       x,
-                             gint       y,
-                             gint       width,
-                             gint       height)
-{
-  GdkSurfaceImplWin32 *window_impl;
-
-  window_impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-  window_impl->inhibit_configure = TRUE;
-
-  /* We ignore changes to the window being moved or resized by the
-     user, as we don't want to fight the user */
-  if (GDK_SURFACE_HWND (window) == _modal_move_resize_window)
-    goto out;
-
-  if (with_move && (width < 0 && height < 0))
-    {
-      gdk_win32_surface_move (window, x, y);
-    }
-  else
-    {
-      if (with_move)
-       {
-         gdk_win32_surface_move_resize_internal (window, x, y, width, height);
-       }
-      else
-       {
-         gdk_win32_surface_resize (window, width, height);
-       }
-    }
-
- out:
-  window_impl->inhibit_configure = FALSE;
-
-  if (WINDOW_IS_TOPLEVEL (window))
-    _gdk_win32_emit_configure_event (window);
-}
-
-static void
-gdk_win32_surface_raise (GdkSurface *window)
-{
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      GDK_NOTE (MISC, g_print ("gdk_win32_surface_raise: %p\n",
-                              GDK_SURFACE_HWND (window)));
-
-      if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP)
-        API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOPMOST,
-                                0, 0, 0, 0,
-                                SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
-      else if (window->accept_focus)
-        /* Do not wrap this in an API_CALL macro as SetForegroundWindow might
-         * fail when for example dragging a window belonging to a different
-         * application at the time of a gtk_window_present() call due to focus
-         * stealing prevention. */
-        SetForegroundWindow (GDK_SURFACE_HWND (window));
-      else
-        API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOP,
-                                0, 0, 0, 0,
-                                SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
-    }
-}
-
-static void
-gdk_win32_surface_lower (GdkSurface *window)
-{
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      GDK_NOTE (MISC, g_print ("gdk_win32_surface_lower: %p\n"
-                              "... SetWindowPos(%p,HWND_BOTTOM,0,0,0,0,"
-                              "NOACTIVATE|NOMOVE|NOSIZE)\n",
-                              GDK_SURFACE_HWND (window),
-                              GDK_SURFACE_HWND (window)));
-
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_BOTTOM,
-                              0, 0, 0, 0,
-                              SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
-    }
-}
-
-static void
-gdk_win32_surface_set_urgency_hint (GdkSurface *window,
-                            gboolean   urgent)
-{
-  FLASHWINFO flashwinfo;
-  typedef BOOL (WINAPI *PFN_FlashWindowEx) (FLASHWINFO*);
-  PFN_FlashWindowEx flashWindowEx = NULL;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  flashWindowEx = (PFN_FlashWindowEx) GetProcAddress (GetModuleHandle ("user32.dll"), "FlashWindowEx");
-
-  if (flashWindowEx)
-    {
-      flashwinfo.cbSize = sizeof (flashwinfo);
-      flashwinfo.hwnd = GDK_SURFACE_HWND (window);
-      if (urgent)
-       flashwinfo.dwFlags = FLASHW_ALL | FLASHW_TIMER;
-      else
-       flashwinfo.dwFlags = FLASHW_STOP;
-      flashwinfo.uCount = 0;
-      flashwinfo.dwTimeout = 0;
-
-      flashWindowEx (&flashwinfo);
-    }
-  else
-    {
-      FlashWindow (GDK_SURFACE_HWND (window), urgent);
-    }
-}
-
-static gboolean
-get_effective_window_decorations (GdkSurface       *window,
-                                  GdkWMDecoration *decoration)
-{
-  GdkSurfaceImplWin32 *impl;
-
-  impl = (GdkSurfaceImplWin32 *)window->impl;
-
-  if (gdk_surface_get_decorations (window, decoration))
-    return TRUE;
-
-  if (window->window_type != GDK_SURFACE_TOPLEVEL)
-    {
-      return FALSE;
-    }
-
-  if ((impl->hint_flags & GDK_HINT_MIN_SIZE) &&
-      (impl->hint_flags & GDK_HINT_MAX_SIZE) &&
-      impl->hints.min_width == impl->hints.max_width &&
-      impl->hints.min_height == impl->hints.max_height)
-    {
-      *decoration = GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MAXIMIZE;
-
-      if (impl->type_hint == GDK_SURFACE_TYPE_HINT_DIALOG ||
-         impl->type_hint == GDK_SURFACE_TYPE_HINT_MENU ||
-         impl->type_hint == GDK_SURFACE_TYPE_HINT_TOOLBAR)
-       {
-         *decoration |= GDK_DECOR_MINIMIZE;
-       }
-      else if (impl->type_hint == GDK_SURFACE_TYPE_HINT_SPLASHSCREEN)
-       {
-         *decoration |= GDK_DECOR_MENU | GDK_DECOR_MINIMIZE;
-       }
-
-      return TRUE;
-    }
-  else if (impl->hint_flags & GDK_HINT_MAX_SIZE)
-    {
-      *decoration = GDK_DECOR_ALL | GDK_DECOR_MAXIMIZE;
-      if (impl->type_hint == GDK_SURFACE_TYPE_HINT_DIALOG ||
-         impl->type_hint == GDK_SURFACE_TYPE_HINT_MENU ||
-         impl->type_hint == GDK_SURFACE_TYPE_HINT_TOOLBAR)
-       {
-         *decoration |= GDK_DECOR_MINIMIZE;
-       }
-
-      return TRUE;
-    }
-  else
-    {
-      switch (impl->type_hint)
-       {
-       case GDK_SURFACE_TYPE_HINT_DIALOG:
-         *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
-         return TRUE;
-
-       case GDK_SURFACE_TYPE_HINT_MENU:
-         *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
-         return TRUE;
-
-       case GDK_SURFACE_TYPE_HINT_TOOLBAR:
-       case GDK_SURFACE_TYPE_HINT_UTILITY:
-         gdk_surface_set_skip_taskbar_hint (window, TRUE);
-         gdk_surface_set_skip_pager_hint (window, TRUE);
-         *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
-         return TRUE;
-
-       case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
-         *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MENU |
-                        GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
-         return TRUE;
-
-       case GDK_SURFACE_TYPE_HINT_DOCK:
-         return FALSE;
-
-       case GDK_SURFACE_TYPE_HINT_DESKTOP:
-         return FALSE;
-
-       default:
-         /* Fall thru */
-       case GDK_SURFACE_TYPE_HINT_NORMAL:
-         *decoration = GDK_DECOR_ALL;
-         return TRUE;
-       }
-    }
-
-  return FALSE;
-}
-
-static void
-gdk_win32_surface_set_geometry_hints (GdkSurface         *window,
-                              const GdkGeometry *geometry,
-                              GdkSurfaceHints     geom_mask)
-{
-  GdkSurfaceImplWin32 *impl;
-  FullscreenInfo *fi;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_set_geometry_hints: %p\n",
-                          GDK_SURFACE_HWND (window)));
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
-  if (fi)
-    fi->hint_flags = geom_mask;
-  else
-    impl->hint_flags = geom_mask;
-  impl->hints = *geometry;
-
-  if (geom_mask & GDK_HINT_POS)
-    {
-      /* even the X11 mplementation doesn't care */
-    }
-
-  if (geom_mask & GDK_HINT_MIN_SIZE)
-    {
-      GDK_NOTE (MISC, g_print ("... MIN_SIZE: %dx%d\n",
-                              geometry->min_width, geometry->min_height));
-    }
-
-  if (geom_mask & GDK_HINT_MAX_SIZE)
-    {
-      GDK_NOTE (MISC, g_print ("... MAX_SIZE: %dx%d\n",
-                              geometry->max_width, geometry->max_height));
-    }
-
-  if (geom_mask & GDK_HINT_BASE_SIZE)
-    {
-      GDK_NOTE (MISC, g_print ("... BASE_SIZE: %dx%d\n",
-                              geometry->base_width, geometry->base_height));
-    }
-
-  if (geom_mask & GDK_HINT_RESIZE_INC)
-    {
-      GDK_NOTE (MISC, g_print ("... RESIZE_INC: (%d,%d)\n",
-                              geometry->width_inc, geometry->height_inc));
-    }
-
-  if (geom_mask & GDK_HINT_ASPECT)
-    {
-      GDK_NOTE (MISC, g_print ("... ASPECT: %g--%g\n",
-                              geometry->min_aspect, geometry->max_aspect));
-    }
-
-  if (geom_mask & GDK_HINT_WIN_GRAVITY)
-    {
-      GDK_NOTE (MISC, g_print ("... GRAVITY: %d\n", geometry->win_gravity));
-    }
-
-  _gdk_win32_surface_update_style_bits (window);
-}
-
-static void
-gdk_win32_surface_set_title (GdkSurface   *window,
-                     const gchar *title)
-{
-  wchar_t *wtitle;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (title != NULL);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  /* Empty window titles not allowed, so set it to just a period. */
-  if (!title[0])
-    title = ".";
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_set_title: %p: %s\n",
-                          GDK_SURFACE_HWND (window), title));
-
-  GDK_NOTE (MISC_OR_EVENTS, title = g_strdup_printf ("%p %s", GDK_SURFACE_HWND (window), title));
-
-  wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
-  API_CALL (SetWindowTextW, (GDK_SURFACE_HWND (window), wtitle));
-  g_free (wtitle);
-
-  GDK_NOTE (MISC_OR_EVENTS, g_free ((char *) title));
-}
-
-static void
-gdk_win32_surface_set_role (GdkSurface   *window,
-                    const gchar *role)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_set_role: %p: %s\n",
-                          GDK_SURFACE_HWND (window),
-                          (role ? role : "NULL")));
-  /* XXX */
-}
-
-static void
-gdk_win32_surface_set_transient_for (GdkSurface *window,
-                             GdkSurface *parent)
-{
-  HWND window_id, parent_id;
-  LONG_PTR old_ptr;
-  DWORD w32_error;
-  GdkSurfaceImplWin32 *window_impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-  GdkSurfaceImplWin32 *parent_impl = NULL;
-  GSList *item;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  window_id = GDK_SURFACE_HWND (window);
-  parent_id = parent != NULL ? GDK_SURFACE_HWND (parent) : NULL;
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_set_transient_for: %p: %p\n", window_id, parent_id));
-
-  if (GDK_SURFACE_DESTROYED (window) || (parent && GDK_SURFACE_DESTROYED (parent)))
-    {
-      if (GDK_SURFACE_DESTROYED (window))
-       GDK_NOTE (MISC, g_print ("... destroyed!\n"));
-      else
-       GDK_NOTE (MISC, g_print ("... owner destroyed!\n"));
-
-      return;
-    }
-
-  if (parent == NULL)
-    {
-      GdkSurfaceImplWin32 *trans_impl = GDK_SURFACE_IMPL_WIN32 (window_impl->transient_owner->impl);
-      if (trans_impl->transient_children != NULL)
-        {
-          item = g_slist_find (trans_impl->transient_children, window);
-          item->data = NULL;
-          trans_impl->transient_children = g_slist_delete_link (trans_impl->transient_children, item);
-          trans_impl->num_transients--;
-
-          if (!trans_impl->num_transients)
-            {
-              trans_impl->transient_children = NULL;
-            }
-        }
-      g_object_unref (G_OBJECT (window_impl->transient_owner));
-      g_object_unref (G_OBJECT (window));
-
-      window_impl->transient_owner = NULL;
-    }
-  else
-    {
-      parent_impl = GDK_SURFACE_IMPL_WIN32 (parent->impl);
-
-      parent_impl->transient_children = g_slist_append (parent_impl->transient_children, window);
-      g_object_ref (G_OBJECT (window));
-      parent_impl->num_transients++;
-      window_impl->transient_owner = parent;
-      g_object_ref (G_OBJECT (parent));
-    }
-
-  SetLastError (0);
-  old_ptr = GetWindowLongPtr (window_id, GWLP_HWNDPARENT);
-  w32_error = GetLastError ();
-
-  /* Don't re-set GWLP_HWNDPARENT to the same value */
-  if ((HWND) old_ptr == parent_id && w32_error == NO_ERROR)
-    return;
-
-  /* Don't return if it failed, try SetWindowLongPtr() anyway */
-  if (old_ptr == 0 && w32_error != NO_ERROR)
-    WIN32_API_FAILED ("GetWindowLongPtr");
-
-  /* This changes the *owner* of the window, despite the misleading
-   * name. (Owner and parent are unrelated concepts.) At least that's
-   * what people who seem to know what they talk about say on
-   * USENET. Search on Google.
-   */
-  SetLastError (0);
-  old_ptr = SetWindowLongPtr (window_id, GWLP_HWNDPARENT, (LONG_PTR) parent_id);
-  w32_error = GetLastError ();
-
-  if (old_ptr == 0 && w32_error != NO_ERROR)
-    WIN32_API_FAILED ("SetWindowLongPtr");
-}
-
-void
-_gdk_push_modal_window (GdkSurface *window)
-{
-  modal_window_stack = g_slist_prepend (modal_window_stack,
-                                        window);
-}
-
-void
-_gdk_remove_modal_window (GdkSurface *window)
-{
-  GSList *tmp;
-
-  g_return_if_fail (window != NULL);
-
-  /* It's possible to be NULL here if someone sets the modal hint of the window
-   * to FALSE before a modal window stack has ever been created. */
-  if (modal_window_stack == NULL)
-    return;
-
-  /* Find the requested window in the stack and remove it.  Yeah, I realize this
-   * means we're not a 'real stack', strictly speaking.  Sue me. :) */
-  tmp = g_slist_find (modal_window_stack, window);
-  if (tmp != NULL)
-    {
-      modal_window_stack = g_slist_delete_link (modal_window_stack, tmp);
-    }
-}
-
-gboolean
-_gdk_modal_blocked (GdkSurface *window)
-{
-  GSList *l;
-  gboolean found_any = FALSE;
-
-  for (l = modal_window_stack; l != NULL; l = l->next)
-    {
-      GdkSurface *modal = l->data;
-
-      if (modal == window)
-       return FALSE;
-
-      if (GDK_SURFACE_IS_MAPPED (modal))
-       found_any = TRUE;
-    }
-
-  return found_any;
-}
-
-GdkSurface *
-_gdk_modal_current (void)
-{
-  GSList *l;
-
-  for (l = modal_window_stack; l != NULL; l = l->next)
-    {
-      GdkSurface *modal = l->data;
-
-      if (GDK_SURFACE_IS_MAPPED (modal))
-       return modal;
-    }
-
-  return NULL;
-}
-
-static void
-gdk_win32_surface_get_geometry (GdkSurface *window,
-                              gint      *x,
-                              gint      *y,
-                              gint      *width,
-                              gint      *height)
-{
-  GdkDisplay *display;
-  gboolean window_is_root;
-
-  display = gdk_surface_get_display (window);
-
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      RECT rect;
-      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-      API_CALL (GetClientRect, (GDK_SURFACE_HWND (window), &rect));
-
-         POINT pt;
-         GdkSurface *parent = gdk_surface_get_parent (window);
-
-         pt.x = rect.left;
-         pt.y = rect.top;
-         ClientToScreen (GDK_SURFACE_HWND (window), &pt);
-          if (parent)
-           ScreenToClient (GDK_SURFACE_HWND (parent), &pt);
-         rect.left = pt.x;
-         rect.top = pt.y;
-
-         pt.x = rect.right;
-         pt.y = rect.bottom;
-         ClientToScreen (GDK_SURFACE_HWND (window), &pt);
-          if (parent)
-           ScreenToClient (GDK_SURFACE_HWND (parent), &pt);
-         rect.right = pt.x;
-         rect.bottom = pt.y;
-
-         if (parent == NULL)
-           {
-             rect.left += _gdk_offset_x * impl->window_scale;
-             rect.top += _gdk_offset_y * impl->window_scale;
-             rect.right += _gdk_offset_x * impl->window_scale;
-             rect.bottom += _gdk_offset_y * impl->window_scale;
-           }
-
-      if (x)
-       *x = rect.left / impl->window_scale;
-      if (y)
-       *y = rect.top / impl->window_scale;
-      if (width)
-       *width = (rect.right - rect.left) / impl->window_scale;
-      if (height)
-       *height = (rect.bottom - rect.top) / impl->window_scale;
-
-      GDK_NOTE (MISC, g_print ("gdk_win32_surface_get_geometry: %p: %ldx%ld@%+ld%\n",
-                              GDK_SURFACE_HWND (window),
-                              (rect.right - rect.left) / impl->window_scale,
-                              (rect.bottom - rect.top) / impl->window_scale,
-                              rect.left, rect.top));
-    }
-}
-
-static void
-gdk_win32_surface_get_root_coords (GdkSurface *window,
-                                 gint       x,
-                                 gint       y,
-                                 gint      *root_x,
-                                 gint      *root_y)
-{
-  gint tx;
-  gint ty;
-  POINT pt;
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  pt.x = x * impl->window_scale;
-  pt.y = y * impl->window_scale;
-  ClientToScreen (GDK_SURFACE_HWND (window), &pt);
-  tx = pt.x;
-  ty = pt.y;
-
-  if (root_x)
-    *root_x = (tx + _gdk_offset_x) / impl->window_scale;
-  if (root_y)
-    *root_y = (ty + _gdk_offset_y) / impl->window_scale;
-
-  GDK_NOTE (MISC, g_print ("gdk_win32_surface_get_root_coords: %p: %+d%+d %+d%+d\n",
-                          GDK_SURFACE_HWND (window),
-                          x * impl->window_scale,
-                          y * impl->window_scale,
-                          (tx + _gdk_offset_x) / impl->window_scale,
-                          (ty + _gdk_offset_y) / impl->window_scale));
-}
-
-static void
-gdk_win32_surface_restack_toplevel (GdkSurface *window,
-                                  GdkSurface *sibling,
-                                  gboolean   above)
-{
-       // ### TODO
-}
-
-static void
-gdk_win32_surface_get_frame_extents (GdkSurface    *window,
-                              GdkRectangle *rect)
-{
-  HWND hwnd;
-  RECT r;
-  GdkSurfaceImplWin32 *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (rect != NULL);
-
-  rect->x = 0;
-  rect->y = 0;
-  rect->width = 1;
-  rect->height = 1;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  /* FIXME: window is documented to be a toplevel GdkSurface, so is it really
-   * necessary to walk its parent chain?
-   */
-  while (window->parent && window->parent->parent)
-    window = window->parent;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-  hwnd = GDK_SURFACE_HWND (window);
-  API_CALL (GetWindowRect, (hwnd, &r));
-
-  /* Initialize to real, unscaled size */
-  rect->x = r.left + _gdk_offset_x * impl->window_scale;
-  rect->y = r.top + _gdk_offset_y * impl->window_scale;
-  rect->width = (r.right - r.left);
-  rect->height = (r.bottom - r.top);
-
-  /* Extend width and height to ensure that they cover the real size when de-scaled,
-   * and replace everyting with scaled values
-   */
-  rect->width = (rect->width + rect->x % impl->window_scale + impl->window_scale - 1) / impl->window_scale;
-  rect->height = (rect->height + rect->y % impl->window_scale + impl->window_scale - 1) / impl->window_scale;
-  rect->x = r.left / impl->window_scale + _gdk_offset_x;
-  rect->y = r.top / impl->window_scale + _gdk_offset_y;
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_get_frame_extents: %p: %ldx%ld@%+ld%+ld\n",
-                           GDK_SURFACE_HWND (window),
-                           rect->width,
-                           rect->height,
-                           rect->x, rect->y));
-}
-
-static gboolean
-gdk_surface_win32_get_device_state (GdkSurface       *window,
-                                   GdkDevice       *device,
-                                   gdouble         *x,
-                                   gdouble         *y,
-                                   GdkModifierType *mask)
-{
-  GdkSurface *child;
-
-  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), FALSE);
-
-  GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
-                                              &child,
-                                              NULL, NULL,
-                                              x, y, mask);
-  return (child != NULL);
-}
-
-void
-gdk_display_warp_device (GdkDisplay *display,
-                         GdkDevice  *device,
-                         gint        x,
-                         gint        y)
-{
-  g_return_if_fail (display == gdk_display_get_default ());
-  g_return_if_fail (GDK_IS_DEVICE (device));
-  g_return_if_fail (display == gdk_device_get_display (device));
-
-  GDK_DEVICE_GET_CLASS (device)->warp (device, x, y);
-}
-
-static GdkEventMask
-gdk_win32_surface_get_events (GdkSurface *window)
-{
-  GdkSurfaceImplWin32 *impl;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return 0;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  return impl->native_event_mask;
-}
-
-static void
-gdk_win32_surface_set_events (GdkSurface   *window,
-                            GdkEventMask event_mask)
-{
-  GdkSurfaceImplWin32 *impl;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  /* gdk_surface_new() always sets the GDK_STRUCTURE_MASK, so better
-   * set it here, too. Not that I know or remember why it is
-   * necessary, will have to test some day.
-   */
-  impl->native_event_mask = GDK_STRUCTURE_MASK | event_mask;
-}
-
-static void
-do_shape_combine_region (GdkSurface *window,
-                        HRGN       hrgn,
-                        gint       x, gint y)
-{
-  RECT rect;
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  GetClientRect (GDK_SURFACE_HWND (window), &rect);
-
-  _gdk_win32_adjust_client_rect (window, &rect);
-
-  OffsetRgn (hrgn, -rect.left, -rect.top);
-  OffsetRgn (hrgn, x, y);
-
-  /* If this is a top-level window, add the title bar to the region */
-  if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL)
-    {
-      HRGN tmp = CreateRectRgn (0, 0, rect.right - rect.left, -rect.top);
-      CombineRgn (hrgn, hrgn, tmp, RGN_OR);
-      DeleteObject (tmp);
-    }
-
-  SetWindowRgn (GDK_SURFACE_HWND (window), hrgn, TRUE);
-}
-
-static void
-gdk_win32_surface_set_accept_focus (GdkSurface *window,
-                            gboolean accept_focus)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  accept_focus = accept_focus != FALSE;
-
-  if (window->accept_focus != accept_focus)
-    window->accept_focus = accept_focus;
-}
-
-static void
-gdk_win32_surface_set_focus_on_map (GdkSurface *window,
-                            gboolean focus_on_map)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  focus_on_map = focus_on_map != FALSE;
-
-  if (window->focus_on_map != focus_on_map)
-    window->focus_on_map = focus_on_map;
-}
-
-static void
-gdk_win32_surface_set_icon_list (GdkSurface *window,
-                                GList     *textures)
-{
-  GdkTexture *big_texture, *small_texture;
-  gint big_diff, small_diff;
-  gint big_w, big_h, small_w, small_h;
-  gint w, h;
-  gint dw, dh, diff;
-  HICON small_hicon, big_hicon;
-  GdkSurfaceImplWin32 *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) || textures == NULL)
-    return;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  /* ideal sizes for small and large icons */
-  big_w = GetSystemMetrics (SM_CXICON);
-  big_h = GetSystemMetrics (SM_CYICON);
-  small_w = GetSystemMetrics (SM_CXSMICON);
-  small_h = GetSystemMetrics (SM_CYSMICON);
-
-  /* find closest sized icons in the list */
-  big_texture = NULL;
-  small_texture = NULL;
-  big_diff = 0;
-  small_diff = 0;
-
-  for (GList *l = textures; l; l = l->next)
-    {
-      GdkTexture *texture = l->data;
-      w = gdk_texture_get_width (texture);
-      h = gdk_texture_get_height (texture);
-
-      dw = ABS (w - big_w);
-      dh = ABS (h - big_h);
-      diff = dw*dw + dh*dh;
-      if (big_texture == NULL || diff < big_diff)
-        {
-          big_texture = texture;
-          big_diff = diff;
-        }
-
-      dw = ABS (w - small_w);
-      dh = ABS (h - small_h);
-      diff = dw*dw + dh*dh;
-      if (small_texture == NULL || diff < small_diff)
-        {
-          small_texture = texture;
-          small_diff = diff;
-        }
-
-      textures = textures->next;
-    }
-
-  /* Create the icons */
-  big_hicon = _gdk_win32_texture_to_hicon (big_texture);
-  g_object_unref (big_texture);
-  small_hicon = _gdk_win32_texture_to_hicon (small_texture);
-  g_object_unref (small_texture);
-
-  /* Set the icons */
-  SendMessageW (GDK_SURFACE_HWND (window), WM_SETICON, ICON_BIG,
-               (LPARAM)big_hicon);
-  SendMessageW (GDK_SURFACE_HWND (window), WM_SETICON, ICON_SMALL,
-               (LPARAM)small_hicon);
-
-  /* Store the icons, destroying any previous icons */
-  if (impl->hicon_big)
-    GDI_CALL (DestroyIcon, (impl->hicon_big));
-  impl->hicon_big = big_hicon;
-  if (impl->hicon_small)
-    GDI_CALL (DestroyIcon, (impl->hicon_small));
-  impl->hicon_small = small_hicon;
-}
-
-static void
-gdk_win32_surface_set_icon_name (GdkSurface   *window,
-                                const gchar *name)
-{
-  /* In case I manage to confuse this again (or somebody else does):
-   * Please note that "icon name" here really *does* mean the name or
-   * title of an window minimized as an icon on the desktop, or in the
-   * taskbar. It has nothing to do with the freedesktop.org icon
-   * naming stuff.
-   */
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-#if 0
-  /* This is not the correct thing to do. We should keep both the
-   * "normal" window title, and the icon name. When the window is
-   * minimized, call SetWindowText() with the icon name, and when the
-   * window is restored, with the normal window title. Also, the name
-   * is in UTF-8, so we should do the normal conversion to either wide
-   * chars or system codepage, and use either the W or A version of
-   * SetWindowText(), depending on Windows version.
-   */
-  API_CALL (SetWindowText, (GDK_SURFACE_HWND (window), name));
-#endif
-}
-
-static GdkSurface *
-gdk_win32_surface_get_group (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  g_warning ("gdk_surface_get_group not yet implemented");
-
-  return NULL;
-}
-
-static void
-gdk_win32_surface_set_group (GdkSurface *window,
-                     GdkSurface *leader)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (leader == NULL || GDK_IS_SURFACE (leader));
-
-  if (GDK_SURFACE_DESTROYED (window) || GDK_SURFACE_DESTROYED (leader))
-    return;
-
-  g_warning ("gdk_surface_set_group not implemented");
-}
-
-static void
-update_single_bit (LONG    *style,
-                   gboolean all,
-                  int      gdk_bit,
-                  int      style_bit)
-{
-  /* all controls the interpretation of gdk_bit -- if all is TRUE,
-   * gdk_bit indicates whether style_bit is off; if all is FALSE, gdk
-   * bit indicate whether style_bit is on
-   */
-  if ((!all && gdk_bit) || (all && !gdk_bit))
-    *style |= style_bit;
-  else
-    *style &= ~style_bit;
-}
-
-/*
- * Returns TRUE if window has no decorations.
- * Usually it means CSD windows, because GTK
- * calls gdk_surface_set_decorations (window, 0);
- * This is used to decide whether a toplevel should
- * be made layered, thus it
- * only returns TRUE for toplevels (until GTK minimal
- * system requirements are lifted to Windows 8 or newer,
- * because only toplevels can be layered).
- */
-gboolean
-_gdk_win32_surface_lacks_wm_decorations (GdkSurface *window)
-{
-  GdkSurfaceImplWin32 *impl;
-  LONG style;
-  gboolean has_any_decorations;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return FALSE;
-
-  /* only toplevels can be layered */
-  if (!WINDOW_IS_TOPLEVEL (window))
-    return FALSE;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  /* This is because GTK calls gdk_surface_set_decorations (window, 0),
-   * even though GdkWMDecoration docs indicate that 0 does NOT mean
-   * "no decorations".
-   */
-  if (impl->decorations &&
-      *impl->decorations == 0)
-    return TRUE;
-
-  if (GDK_SURFACE_HWND (window) == 0)
-    return FALSE;
-
-  style = GetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE);
-
-  if (style == 0)
-    {
-      DWORD w32_error = GetLastError ();
-
-      GDK_NOTE (MISC, g_print ("Failed to get style of window %p (handle %p): %lu\n",
-                               window, GDK_SURFACE_HWND (window), w32_error));
-      return FALSE;
-    }
-
-  /* Keep this in sync with _gdk_win32_surface_update_style_bits() */
-  /* We don't check what get_effective_window_decorations()
-   * has to say, because it gives suggestions based on
-   * various hints, while we want *actual* decorations,
-   * or their absence.
-   */
-  has_any_decorations = FALSE;
-
-  if (style & (WS_BORDER | WS_THICKFRAME | WS_CAPTION |
-               WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX))
-    has_any_decorations = TRUE;
-  else
-    GDK_NOTE (MISC, g_print ("Window %p (handle %p): has no decorations (style %lx)\n",
-                             window, GDK_SURFACE_HWND (window), style));
-
-  return !has_any_decorations;
-}
-
-void
-_gdk_win32_surface_update_style_bits (GdkSurface *window)
-{
-  GdkSurfaceImplWin32 *impl = (GdkSurfaceImplWin32 *)window->impl;
-  GdkWMDecoration decorations;
-  LONG old_style, new_style, old_exstyle, new_exstyle;
-  gboolean all;
-  RECT rect, before, after;
-  gboolean was_topmost;
-  gboolean will_be_topmost;
-  HWND insert_after;
-  UINT flags;
-
-  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
-    return;
-
-  old_style = GetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE);
-  old_exstyle = GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE);
-
-  GetClientRect (GDK_SURFACE_HWND (window), &before);
-  after = before;
-  AdjustWindowRectEx (&before, old_style, FALSE, old_exstyle);
-
-  was_topmost = (old_exstyle & WS_EX_TOPMOST) ? TRUE : FALSE;
-  will_be_topmost = was_topmost;
-
-  old_exstyle &= ~WS_EX_TOPMOST;
-
-  new_style = old_style;
-  new_exstyle = old_exstyle;
-
-  if (window->window_type == GDK_SURFACE_TEMP)
-    {
-      new_exstyle |= WS_EX_TOOLWINDOW;
-      will_be_topmost = TRUE;
-    }
-  else if (impl->type_hint == GDK_SURFACE_TYPE_HINT_UTILITY)
-    {
-      new_exstyle |= WS_EX_TOOLWINDOW;
-    }
-  else
-    {
-      new_exstyle &= ~WS_EX_TOOLWINDOW;
-    }
-
-  /* We can get away with using layered windows
-   * only when no decorations are needed. It can mean
-   * CSD or borderless non-CSD windows (tooltips?).
-   *
-   * If this window cannot use layered windows, disable it always.
-   * This currently applies to windows using OpenGL, which
-   * does not work with layered windows.
-   */
-  if (impl->suppress_layered == 0)
-    {
-      if (_gdk_win32_surface_lacks_wm_decorations (window))
-        impl->layered = g_strcmp0 (g_getenv ("GDK_WIN32_LAYERED"), "0") != 0;
-    }
-  else
-    impl->layered = FALSE;
-
-  if (impl->layered)
-    new_exstyle |= WS_EX_LAYERED;
-  else
-    new_exstyle &= ~WS_EX_LAYERED;
-
-  if (get_effective_window_decorations (window, &decorations))
-    {
-      all = (decorations & GDK_DECOR_ALL);
-      /* Keep this in sync with the test in _gdk_win32_surface_lacks_wm_decorations() */
-      update_single_bit (&new_style, all, decorations & GDK_DECOR_BORDER, WS_BORDER);
-      update_single_bit (&new_style, all, decorations & GDK_DECOR_RESIZEH, WS_THICKFRAME);
-      update_single_bit (&new_style, all, decorations & GDK_DECOR_TITLE, WS_CAPTION);
-      update_single_bit (&new_style, all, decorations & GDK_DECOR_MENU, WS_SYSMENU);
-      update_single_bit (&new_style, all, decorations & GDK_DECOR_MINIMIZE, WS_MINIMIZEBOX);
-      update_single_bit (&new_style, all, decorations & GDK_DECOR_MAXIMIZE, WS_MAXIMIZEBOX);
-    }
-
-  if (old_style == new_style && old_exstyle == new_exstyle )
-    {
-      GDK_NOTE (MISC, g_print ("_gdk_win32_surface_update_style_bits: %p: no change\n",
-                              GDK_SURFACE_HWND (window)));
-      return;
-    }
-
-  if (old_style != new_style)
-    {
-      GDK_NOTE (MISC, g_print ("_gdk_win32_surface_update_style_bits: %p: STYLE: %s => %s\n",
-                              GDK_SURFACE_HWND (window),
-                              _gdk_win32_surface_style_to_string (old_style),
-                              _gdk_win32_surface_style_to_string (new_style)));
-
-      SetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE, new_style);
-    }
-
-  if (old_exstyle != new_exstyle)
-    {
-      GDK_NOTE (MISC, g_print ("_gdk_win32_surface_update_style_bits: %p: EXSTYLE: %s => %s\n",
-                              GDK_SURFACE_HWND (window),
-                              _gdk_win32_surface_exstyle_to_string (old_exstyle),
-                              _gdk_win32_surface_exstyle_to_string (new_exstyle)));
-
-      SetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE, new_exstyle);
-    }
-
-  AdjustWindowRectEx (&after, new_style, FALSE, new_exstyle);
-
-  GetWindowRect (GDK_SURFACE_HWND (window), &rect);
-  rect.left += after.left - before.left;
-  rect.top += after.top - before.top;
-  rect.right += after.right - before.right;
-  rect.bottom += after.bottom - before.bottom;
-
-  flags = SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOREPOSITION;
-
-  if (will_be_topmost && !was_topmost)
-    {
-      insert_after = HWND_TOPMOST;
-    }
-  else if (was_topmost && !will_be_topmost)
-    {
-      insert_after = HWND_NOTOPMOST;
-    }
-  else
-    {
-      flags |= SWP_NOZORDER;
-      insert_after = SWP_NOZORDER_SPECIFIED;
-    }
-
-  SetWindowPos (GDK_SURFACE_HWND (window), insert_after,
-               rect.left, rect.top,
-               rect.right - rect.left, rect.bottom - rect.top,
-               flags);
-}
-
-static void
-update_single_system_menu_entry (HMENU    hmenu,
-                                gboolean all,
-                                int      gdk_bit,
-                                int      menu_entry)
-{
-  /* all controls the interpretation of gdk_bit -- if all is TRUE,
-   * gdk_bit indicates whether menu entry is disabled; if all is
-   * FALSE, gdk bit indicate whether menu entry is enabled
-   */
-  if ((!all && gdk_bit) || (all && !gdk_bit))
-    EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_ENABLED);
-  else
-    EnableMenuItem (hmenu, menu_entry, MF_BYCOMMAND | MF_GRAYED);
-}
-
-static void
-update_system_menu (GdkSurface *window)
-{
-  GdkWMFunction functions;
-  BOOL all;
-
-  if (_gdk_surface_get_functions (window, &functions))
-    {
-      HMENU hmenu = GetSystemMenu (GDK_SURFACE_HWND (window), FALSE);
-
-      all = (functions & GDK_FUNC_ALL);
-      update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_RESIZE, SC_SIZE);
-      update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MOVE, SC_MOVE);
-      update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MINIMIZE, SC_MINIMIZE);
-      update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_MAXIMIZE, SC_MAXIMIZE);
-      update_single_system_menu_entry (hmenu, all, functions & GDK_FUNC_CLOSE, SC_CLOSE);
-    }
-}
-
-static void
-gdk_win32_surface_set_decorations (GdkSurface      *window,
-                                 GdkWMDecoration decorations)
-{
-  GdkSurfaceImplWin32 *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_set_decorations: %p: %s %s%s%s%s%s%s\n",
-                          GDK_SURFACE_HWND (window),
-                          (decorations & GDK_DECOR_ALL ? "clearing" : "setting"),
-                          (decorations & GDK_DECOR_BORDER ? "BORDER " : ""),
-                          (decorations & GDK_DECOR_RESIZEH ? "RESIZEH " : ""),
-                          (decorations & GDK_DECOR_TITLE ? "TITLE " : ""),
-                          (decorations & GDK_DECOR_MENU ? "MENU " : ""),
-                          (decorations & GDK_DECOR_MINIMIZE ? "MINIMIZE " : ""),
-                          (decorations & GDK_DECOR_MAXIMIZE ? "MAXIMIZE " : "")));
-
-  if (!impl->decorations)
-    impl->decorations = g_malloc (sizeof (GdkWMDecoration));
-
-  *impl->decorations = decorations;
-
-  _gdk_win32_surface_update_style_bits (window);
-}
-
-static gboolean
-gdk_win32_surface_get_decorations (GdkSurface       *window,
-                                 GdkWMDecoration *decorations)
-{
-  GdkSurfaceImplWin32 *impl;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), FALSE);
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  if (impl->decorations == NULL)
-    return FALSE;
-
-  *decorations = *impl->decorations;
-
-  return TRUE;
-}
-
-static GQuark
-get_functions_quark ()
-{
-  static GQuark quark = 0;
-
-  if (!quark)
-    quark = g_quark_from_static_string ("gdk-window-functions");
-
-  return quark;
-}
-
-static void
-gdk_win32_surface_set_functions (GdkSurface    *window,
-                         GdkWMFunction functions)
-{
-  GdkWMFunction* functions_copy;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_set_functions: %p: %s %s%s%s%s%s\n",
-                          GDK_SURFACE_HWND (window),
-                          (functions & GDK_FUNC_ALL ? "clearing" : "setting"),
-                          (functions & GDK_FUNC_RESIZE ? "RESIZE " : ""),
-                          (functions & GDK_FUNC_MOVE ? "MOVE " : ""),
-                          (functions & GDK_FUNC_MINIMIZE ? "MINIMIZE " : ""),
-                          (functions & GDK_FUNC_MAXIMIZE ? "MAXIMIZE " : ""),
-                          (functions & GDK_FUNC_CLOSE ? "CLOSE " : "")));
-
-  functions_copy = g_malloc (sizeof (GdkWMFunction));
-  *functions_copy = functions;
-  g_object_set_qdata_full (G_OBJECT (window), get_functions_quark (), functions_copy, g_free);
-
-  update_system_menu (window);
-}
-
-gboolean
-_gdk_surface_get_functions (GdkSurface     *window,
-                          GdkWMFunction *functions)
-{
-  GdkWMFunction* functions_set;
-
-  functions_set = g_object_get_qdata (G_OBJECT (window), get_functions_quark ());
-  if (functions_set)
-    *functions = *functions_set;
-
-  return (functions_set != NULL);
-}
-
-#if defined(MORE_AEROSNAP_DEBUGGING)
-static void
-log_region (gchar *prefix, AeroSnapEdgeRegion *region)
-{
-  GDK_NOTE (MISC, g_print ("Region %s:\n"
-                           "edge %d x %d @ %d x %d\n"
-                           "trig %d x %d @ %d x %d\n",
-                           prefix,
-                           region->edge.width,
-                           region->edge.height,
-                           region->edge.x,
-                           region->edge.y,
-                           region->trigger.width,
-                           region->trigger.height,
-                           region->trigger.x,
-                           region->trigger.y));
-}
-#endif
-
-static void
-calculate_aerosnap_regions (GdkW32DragMoveResizeContext *context)
-{
-  GdkDisplay *display;
-  gint n_monitors, monitor_idx, other_monitor_idx;
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (context->window->impl);
-#if defined(MORE_AEROSNAP_DEBUGGING)
-  gint i;
-#endif
-
-  display = gdk_display_get_default ();
-  n_monitors = gdk_display_get_n_monitors (display);
-
-#define _M_UP 0
-#define _M_DOWN 1
-#define _M_LEFT 2
-#define _M_RIGHT 3
-
-  for (monitor_idx = 0; monitor_idx < n_monitors; monitor_idx++)
-    {
-      GdkRectangle wa;
-      GdkRectangle geometry;
-      AeroSnapEdgeRegion snap_region;
-      gboolean move_edge[4] = { TRUE, FALSE, TRUE, TRUE };
-      gboolean resize_edge[2] = { TRUE, TRUE };
-      gint diff;
-      gint thickness, trigger_thickness;
-      GdkMonitor *monitor;
-
-      monitor = gdk_display_get_monitor (display, monitor_idx);
-      gdk_monitor_get_workarea (monitor, &wa);
-      gdk_monitor_get_geometry (monitor, &geometry);
-
-      for (other_monitor_idx = 0;
-           other_monitor_idx < n_monitors &&
-           (move_edge[_M_UP] || move_edge[_M_LEFT] ||
-           move_edge[_M_RIGHT] || resize_edge[_M_DOWN]);
-           other_monitor_idx++)
-        {
-          GdkRectangle other_wa;
-          GdkMonitor *other_monitor;
-
-          if (other_monitor_idx == monitor_idx)
-            continue;
-
-          other_monitor = gdk_display_get_monitor (display, other_monitor_idx);
-          gdk_monitor_get_workarea (other_monitor, &other_wa);
-
-          /* An edge triggers AeroSnap only if there are no
-           * monitors beyond that edge.
-           * Even if there's another monitor, but it does not cover
-           * the whole edge (it's smaller or is not aligned to
-           * the corner of current monitor), that edge is still
-           * removed from the trigger list.
-           */
-          if (other_wa.x >= wa.x + wa.width)
-            move_edge[_M_RIGHT] = FALSE;
-
-          if (other_wa.x + other_wa.width <= wa.x)
-            move_edge[_M_LEFT] = FALSE;
-
-          if (other_wa.y + other_wa.height <= wa.y)
-            {
-              move_edge[_M_UP] = FALSE;
-              resize_edge[_M_UP] = FALSE;
-            }
-
-          if (other_wa.y >= wa.y + wa.height)
-            {
-              /* no move_edge for the bottom edge, just resize_edge */
-              resize_edge[_M_DOWN] = FALSE;
-            }
-        }
-
-      thickness = AEROSNAP_REGION_THICKNESS * impl->window_scale;
-      trigger_thickness = AEROSNAP_REGION_TRIGGER_THICKNESS * impl->window_scale;
-
-      snap_region.edge = wa;
-      snap_region.trigger = wa;
-      snap_region.edge.height = thickness;
-      snap_region.trigger.height = trigger_thickness;
-
-      /* Extend both regions into toolbar space.
-       * When there's no toolbar, diff == 0.
-       */
-      diff = wa.y - geometry.y;
-      snap_region.edge.height += diff;
-      snap_region.edge.y -= diff;
-      snap_region.trigger.height += diff;
-      snap_region.trigger.y -= diff;
-
-      if (move_edge[_M_UP])
-        g_array_append_val (context->maximize_regions, snap_region);
-
-      if (resize_edge[_M_UP])
-        g_array_append_val (context->fullup_regions, snap_region);
-
-      snap_region.edge = wa;
-      snap_region.trigger = wa;
-      snap_region.edge.width = thickness;
-      snap_region.trigger.width = trigger_thickness;
-
-      diff = wa.x - geometry.x;
-      snap_region.edge.width += diff;
-      snap_region.edge.x -= diff;
-      snap_region.trigger.width += diff;
-      snap_region.trigger.x -= diff;
-
-      if (move_edge[_M_LEFT])
-        g_array_append_val (context->halfleft_regions, snap_region);
-
-      snap_region.edge = wa;
-      snap_region.trigger = wa;
-      snap_region.edge.x += wa.width - thickness;
-      snap_region.edge.width = thickness;
-      snap_region.trigger.x += wa.width - trigger_thickness;
-      snap_region.trigger.width = trigger_thickness;
-
-      diff = (geometry.x + geometry.width) - (wa.x + wa.width);
-      snap_region.edge.width += diff;
-      snap_region.trigger.width += diff;
-
-      if (move_edge[_M_RIGHT])
-        g_array_append_val (context->halfright_regions, snap_region);
-
-      snap_region.edge = wa;
-      snap_region.trigger = wa;
-      snap_region.edge.y += wa.height - thickness;
-      snap_region.edge.height = thickness;
-      snap_region.trigger.y += wa.height - trigger_thickness;
-      snap_region.trigger.height = trigger_thickness;
-
-      diff = (geometry.y + geometry.height) - (wa.y + wa.height);
-      snap_region.edge.height += diff;
-      snap_region.trigger.height += diff;
-
-      if (resize_edge[_M_DOWN])
-        g_array_append_val (context->fullup_regions, snap_region);
-    }
-
-#undef _M_UP
-#undef _M_DOWN
-#undef _M_LEFT
-#undef _M_RIGHT
-
-#if defined(MORE_AEROSNAP_DEBUGGING)
-  for (i = 0; i < context->maximize_regions->len; i++)
-    log_region ("maximize", &g_array_index (context->maximize_regions, AeroSnapEdgeRegion, i));
-
-  for (i = 0; i < context->halfleft_regions->len; i++)
-    log_region ("halfleft", &g_array_index (context->halfleft_regions, AeroSnapEdgeRegion, i));
-
-  for (i = 0; i < context->halfright_regions->len; i++)
-    log_region ("halfright", &g_array_index (context->halfright_regions, AeroSnapEdgeRegion, i));
-
-  for (i = 0; i < context->fullup_regions->len; i++)
-    log_region ("fullup", &g_array_index (context->fullup_regions, AeroSnapEdgeRegion, i));
-#endif
-}
-
-static void
-discard_snapinfo (GdkSurface *window)
-{
-  GdkSurfaceImplWin32 *impl;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  impl->snap_state = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
-
-  if (impl->snap_stash == NULL)
-    return;
-
-  g_clear_pointer (&impl->snap_stash, g_free);
-  g_clear_pointer (&impl->snap_stash_int, g_free);
-}
-
-static void
-unsnap (GdkSurface  *window,
-        GdkMonitor *monitor)
-{
-  GdkSurfaceImplWin32 *impl;
-  GdkRectangle rect;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  impl->snap_state = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
-
-  if (impl->snap_stash == NULL)
-    return;
-
-  gdk_monitor_get_workarea (monitor, &rect);
-
-  GDK_NOTE (MISC, g_print ("Monitor work area %d x %d @ %d : %d\n", rect.width, rect.height, rect.x, rect.y));
-
-  if (rect.width >= impl->snap_stash_int->width &&
-      rect.height >= impl->snap_stash_int->height)
-    {
-      /* If the window fits into new work area without resizing it,
-       * place it into new work area without resizing it.
-       */
-      gdouble left, right, up, down, hratio, vratio;
-      gdouble hscale, vscale;
-      gdouble new_left, new_up;
-
-      left = impl->snap_stash->x;
-      right = 1.0 - (impl->snap_stash->x + impl->snap_stash->width);
-      up = impl->snap_stash->y;
-      down = 1.0 - (impl->snap_stash->y + impl->snap_stash->height);
-      hscale = 1.0;
-
-      if (right > 0.001)
-        {
-          hratio = left / right;
-          hscale = hratio / (1.0 + hratio);
-        }
-
-      new_left = (gdouble) (rect.width - impl->snap_stash_int->width) * hscale;
-
-      vscale = 1.0;
-
-      if (down > 0.001)
-        {
-          vratio = up / down;
-          vscale = vratio / (1.0 + vratio);
-        }
-
-      new_up = (gdouble) (rect.height - impl->snap_stash_int->height) * vscale;
-
-      rect.x = round (rect.x + new_left);
-      rect.y = round (rect.y + new_up);
-      rect.width = impl->snap_stash_int->width;
-      rect.height = impl->snap_stash_int->height;
-    }
-  else
-    {
-      /* Calculate actual unsnapped window size based on its
-       * old relative size. Same for position.
-       */
-      rect.x += round (rect.width * impl->snap_stash->x);
-      rect.y += round (rect.height * impl->snap_stash->y);
-      rect.width = round (rect.width * impl->snap_stash->width);
-      rect.height = round (rect.height * impl->snap_stash->height);
-    }
-
-  GDK_NOTE (MISC, g_print ("Unsnapped window size %d x %d @ %d : %d\n", rect.width, rect.height, rect.x, rect.y));
-
-  gdk_surface_move_resize (window, rect.x, rect.y,
-                          rect.width, rect.height);
-
-  g_clear_pointer (&impl->snap_stash, g_free);
-  g_clear_pointer (&impl->snap_stash_int, g_free);
-}
-
-static void
-stash_window (GdkSurface          *window,
-              GdkSurfaceImplWin32 *impl)
-{
-  gint x, y;
-  gint width, wwidth;
-  gint height, wheight;
-  WINDOWPLACEMENT placement;
-  HMONITOR hmonitor;
-  MONITORINFO hmonitor_info;
-
-  placement.length = sizeof(WINDOWPLACEMENT);
-
-  /* Use W32 API to get unmaximized window size, which GDK doesn't remember */
-  if (!GetWindowPlacement (GDK_SURFACE_HWND (window), &placement))
-    return;
-
-  /* MSDN is very vague, but in practice rcNormalPosition is the same as GetWindowRect(),
-   * only with adjustments for toolbars (which creates rather weird coodinate space issues).
-   * We need to get monitor info and apply workarea vs monitorarea diff to turn
-   * these into screen coordinates proper.
-   */
-  hmonitor = MonitorFromWindow (GDK_SURFACE_HWND (window), MONITOR_DEFAULTTONEAREST);
-  hmonitor_info.cbSize = sizeof (hmonitor_info);
-
-  if (!GetMonitorInfoA (hmonitor, &hmonitor_info))
-    return;
-
-  if (impl->snap_stash == NULL)
-    impl->snap_stash = g_new0 (GdkRectangleDouble, 1);
-
-  if (impl->snap_stash_int == NULL)
-    impl->snap_stash_int = g_new0 (GdkRectangle, 1);
-
-  GDK_NOTE (MISC, g_print ("monitor work area  %ld x %ld @ %ld : %ld\n",
-                           (hmonitor_info.rcWork.right - hmonitor_info.rcWork.left) / impl->window_scale,
-                           (hmonitor_info.rcWork.bottom - hmonitor_info.rcWork.top) / impl->window_scale,
-                           hmonitor_info.rcWork.left,
-                           hmonitor_info.rcWork.top));
-  GDK_NOTE (MISC, g_print ("monitor      area  %ld x %ld @ %ld : %ld\n",
-                           (hmonitor_info.rcMonitor.right - hmonitor_info.rcMonitor.left) / impl->window_scale,
-                           (hmonitor_info.rcMonitor.bottom - hmonitor_info.rcMonitor.top) / impl->window_scale,
-                           hmonitor_info.rcMonitor.left,
-                           hmonitor_info.rcMonitor.top));
-  GDK_NOTE (MISC, g_print ("window  work place %ld x %ld @ %ld : %ld\n",
-                           (placement.rcNormalPosition.right - placement.rcNormalPosition.left) / impl->window_scale,
-                           (placement.rcNormalPosition.bottom - placement.rcNormalPosition.top) / impl->window_scale,
-                           placement.rcNormalPosition.left,
-                           placement.rcNormalPosition.top));
-
-  width = (placement.rcNormalPosition.right - placement.rcNormalPosition.left) / impl->window_scale;
-  height = (placement.rcNormalPosition.bottom - placement.rcNormalPosition.top) / impl->window_scale;
-  x = (placement.rcNormalPosition.left - hmonitor_info.rcMonitor.left) / impl->window_scale;
-  y = (placement.rcNormalPosition.top - hmonitor_info.rcMonitor.top) / impl->window_scale;
-
-  wwidth = (hmonitor_info.rcWork.right - hmonitor_info.rcWork.left) / impl->window_scale;
-  wheight = (hmonitor_info.rcWork.bottom - hmonitor_info.rcWork.top) / impl->window_scale;
-
-  impl->snap_stash->x = (gdouble) (x) / (gdouble) (wwidth);
-  impl->snap_stash->y = (gdouble) (y) / (gdouble) (wheight);
-  impl->snap_stash->width = (gdouble) width / (gdouble) (wwidth);
-  impl->snap_stash->height = (gdouble) height / (gdouble) (wheight);
-
-  impl->snap_stash_int->x = x;
-  impl->snap_stash_int->y = y;
-  impl->snap_stash_int->width = width;
-  impl->snap_stash_int->height = height;
-
-  GDK_NOTE (MISC, g_print ("Stashed window %d x %d @ %d : %d as %f x %f @ %f : %f\n",
-                           width, height, x, y,
-                           impl->snap_stash->width, impl->snap_stash->height, impl->snap_stash->x, impl->snap_stash->y));
-}
-
-static void
-snap_up (GdkSurface *window)
-{
-  SHORT maxysize;
-  gint x, y;
-  gint width, height;
-  GdkSurfaceImplWin32 *impl;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  impl->snap_state = GDK_WIN32_AEROSNAP_STATE_FULLUP;
-
-  stash_window (window, impl);
-
-  maxysize = GetSystemMetrics (SM_CYVIRTUALSCREEN) / impl->window_scale;
-  gdk_surface_get_position (window, &x, &y);
-  width = gdk_surface_get_width (window);
-
-  y = 0;
-  height = maxysize;
-
-  x = x - impl->margins.left;
-  y = y - impl->margins.top;
-  width += impl->margins_x;
-  height += impl->margins_y;
-
-  gdk_surface_move_resize (window, x, y, width, height);
-}
-
-static void
-snap_left (GdkSurface  *window,
-           GdkMonitor *monitor,
-           GdkMonitor *snap_monitor)
-{
-  GdkRectangle rect;
-  GdkSurfaceImplWin32 *impl;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  impl->snap_state = GDK_WIN32_AEROSNAP_STATE_HALFLEFT;
-
-  gdk_monitor_get_workarea (snap_monitor, &rect);
-
-  stash_window (window, impl);
-
-  rect.width = rect.width / 2;
-
-  rect.x = rect.x - impl->margins.left;
-  rect.y = rect.y - impl->margins.top;
-  rect.width = rect.width + impl->margins_x;
-  rect.height = rect.height + impl->margins_y;
-
-  gdk_surface_move_resize (window, rect.x, rect.y, rect.width, rect.height);
-}
-
-static void
-snap_right (GdkSurface  *window,
-            GdkMonitor *monitor,
-            GdkMonitor *snap_monitor)
-{
-  GdkRectangle rect;
-  GdkSurfaceImplWin32 *impl;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  impl->snap_state = GDK_WIN32_AEROSNAP_STATE_HALFRIGHT;
-
-  gdk_monitor_get_workarea (snap_monitor, &rect);
-
-  stash_window (window, impl);
-
-  rect.width = rect.width / 2;
-  rect.x += rect.width;
-
-  rect.x = rect.x - impl->margins.left;
-  rect.y = rect.y - impl->margins.top;
-  rect.width = rect.width + impl->margins_x;
-  rect.height = rect.height + impl->margins_y;
-
-  gdk_surface_move_resize (window, rect.x, rect.y, rect.width, rect.height);
-}
-
-void
-_gdk_win32_surface_handle_aerosnap (GdkSurface            *window,
-                                   GdkWin32AeroSnapCombo combo)
-{
-  GdkSurfaceImplWin32 *impl;
-  GdkDisplay *display;
-  gint n_monitors;
-  GdkSurfaceState window_state = gdk_surface_get_state (window);
-  gboolean minimized = window_state & GDK_SURFACE_STATE_ICONIFIED;
-  gboolean maximized = window_state & GDK_SURFACE_STATE_MAXIMIZED;
-  gboolean halfsnapped;
-  GdkMonitor *monitor;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-  display = gdk_surface_get_display (window);
-  n_monitors = gdk_display_get_n_monitors (display);
-  monitor = gdk_display_get_monitor_at_window (display, window);
-
-  if (minimized && maximized)
-    minimized = FALSE;
-
-  halfsnapped = (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFRIGHT ||
-                 impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFLEFT ||
-                 impl->snap_state == GDK_WIN32_AEROSNAP_STATE_FULLUP);
-
-  switch (combo)
-    {
-    case GDK_WIN32_AEROSNAP_COMBO_NOTHING:
-      /* Do nothing */
-      break;
-    case GDK_WIN32_AEROSNAP_COMBO_UP:
-      if (!maximized)
-        {
-         unsnap (window, monitor);
-          gdk_surface_maximize (window);
-        }
-      break;
-    case GDK_WIN32_AEROSNAP_COMBO_DOWN:
-    case GDK_WIN32_AEROSNAP_COMBO_SHIFTDOWN:
-      if (maximized)
-        {
-         gdk_surface_unmaximize (window);
-         unsnap (window, monitor);
-        }
-      else if (halfsnapped)
-       unsnap (window, monitor);
-      else if (!minimized)
-       gdk_surface_iconify (window);
-      break;
-    case GDK_WIN32_AEROSNAP_COMBO_LEFT:
-      if (maximized)
-        gdk_surface_unmaximize (window);
-
-      if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_UNDETERMINED ||
-         impl->snap_state == GDK_WIN32_AEROSNAP_STATE_FULLUP)
-       {
-         unsnap (window, monitor);
-         snap_left (window, monitor, monitor);
-       }
-      else if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFLEFT)
-       {
-         unsnap (window, monitor);
-         snap_right (window,
-                     monitor,
-                     gdk_monitor_is_primary (monitor) ? monitor : gdk_display_get_monitor (display, n_monitors - 1));
-       }
-      else if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFRIGHT)
-       {
-         unsnap (window, monitor);
-       }
-      break;
-    case GDK_WIN32_AEROSNAP_COMBO_RIGHT:
-      if (maximized)
-        gdk_surface_unmaximize (window);
-
-      if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_UNDETERMINED ||
-         impl->snap_state == GDK_WIN32_AEROSNAP_STATE_FULLUP)
-       {
-         unsnap (window, monitor);
-         snap_right (window, monitor, monitor);
-       }
-      else if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFLEFT)
-       {
-         unsnap (window, monitor);
-       }
-      else if (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFRIGHT)
-       {
-         gint i;
-
-         unsnap (window, monitor);
-         if (n_monitors == 1 ||
-             monitor == gdk_display_get_monitor (display, n_monitors - 1))
-           {
-             snap_left (window, monitor, monitor);
-           }
-         else
-           {
-             for (i = 0; i < n_monitors; i++)
-               {
-                 if (monitor == gdk_display_get_monitor (display, i))
-                   break;
-               }
-
-             snap_left (window, monitor, gdk_display_get_monitor (display, i + 1));
-           }
-       }
-      break;
-    case GDK_WIN32_AEROSNAP_COMBO_SHIFTUP:
-      if (!maximized &&
-          impl->snap_state == GDK_WIN32_AEROSNAP_STATE_UNDETERMINED)
-       {
-         snap_up (window);
-       }
-      break;
-    case GDK_WIN32_AEROSNAP_COMBO_SHIFTLEFT:
-    case GDK_WIN32_AEROSNAP_COMBO_SHIFTRIGHT:
-      /* No implementation needed at the moment */
-      break;
-    }
-}
-
-static void
-apply_snap (GdkSurface             *window,
-            GdkWin32AeroSnapState  snap)
-{
-  GdkMonitor *monitor;
-  GdkDisplay *display;
-
-  display = gdk_surface_get_display (window);
-  monitor = gdk_display_get_monitor_at_window (display, window);
-
-  switch (snap)
-    {
-    case GDK_WIN32_AEROSNAP_STATE_UNDETERMINED:
-      break;
-    case GDK_WIN32_AEROSNAP_STATE_MAXIMIZE:
-      unsnap (window, monitor);
-      gdk_surface_maximize (window);
-      break;
-    case GDK_WIN32_AEROSNAP_STATE_HALFLEFT:
-      unsnap (window, monitor);
-      snap_left (window, monitor, monitor);
-      break;
-    case GDK_WIN32_AEROSNAP_STATE_HALFRIGHT:
-      unsnap (window, monitor);
-      snap_right (window, monitor, monitor);
-      break;
-    case GDK_WIN32_AEROSNAP_STATE_FULLUP:
-      snap_up (window);
-      break;
-    }
-}
-
-/* Registers a dumb window class. This window
- * has DefWindowProc() for a window procedure and
- * does not do anything that GdkSurface-bound HWNDs do.
- */
-static ATOM
-RegisterGdkDumbClass ()
-{
-  static ATOM klassDUMB = 0;
-  static WNDCLASSEXW wcl;
-  ATOM klass = 0;
-
-  wcl.cbSize = sizeof (WNDCLASSEX);
-  wcl.style = 0; /* DON'T set CS_<H,V>REDRAW. It causes total redraw
-                  * on WM_SIZE and WM_MOVE. Flicker, Performance!
-                  */
-  wcl.lpfnWndProc = DefWindowProcW;
-  wcl.cbClsExtra = 0;
-  wcl.cbWndExtra = 0;
-  wcl.hInstance = _gdk_app_hmodule;
-  wcl.hIcon = 0;
-  wcl.hIconSm = 0;
-  wcl.lpszMenuName = NULL;
-  wcl.hbrBackground = NULL;
-  wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
-  wcl.style |= CS_OWNDC;
-  wcl.lpszClassName = L"gdkWindowDumb";
-
-  if (klassDUMB == 0)
-    klassDUMB = RegisterClassExW (&wcl);
-
-  klass = klassDUMB;
-
-  if (klass == 0)
-    {
-      WIN32_API_FAILED ("RegisterClassExW");
-      g_error ("That is a fatal error");
-    }
-
-  return klass;
-}
-
-static gboolean
-ensure_snap_indicator_exists (GdkW32DragMoveResizeContext *context)
-{
-  if (context->shape_indicator == NULL)
-    {
-      HWND handle;
-      ATOM klass;
-      klass = RegisterGdkDumbClass ();
-
-      handle = CreateWindowExW (WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOACTIVATE,
-                                MAKEINTRESOURCEW (klass),
-                                L"",
-                                WS_POPUP,
-                                0,
-                                0,
-                                0, 0,
-                                NULL,
-                                NULL,
-                                _gdk_app_hmodule,
-                                NULL);
-
-      context->shape_indicator = handle;
-    }
-
-  return context->shape_indicator != NULL;
-}
-
-static gboolean
-ensure_snap_indicator_surface (GdkW32DragMoveResizeContext *context,
-                          gint                         width,
-                          gint                         height,
-                          guint                        scale)
-{
-  if (context->indicator_surface != NULL &&
-      (context->indicator_surface_width < width ||
-       context->indicator_surface_height < height))
-    {
-      cairo_surface_destroy (context->indicator_surface);
-      context->indicator_surface = NULL;
-    }
-
-  if (context->indicator_surface == NULL)
-    context->indicator_surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
-                                                                      width * scale,
-                                                                      height * scale);
-
-  if (cairo_surface_status (context->indicator_surface) != CAIRO_STATUS_SUCCESS)
-    {
-      cairo_surface_destroy (context->indicator_surface);
-      context->indicator_surface = NULL;
-
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
-/* Indicator is drawn with some inward offset, so that it does
- * not hug screen edges.
- */
-static void
-adjust_indicator_rectangle (GdkRectangle *rect,
-                            gboolean      inward)
-{
-  gdouble inverter;
-  const gint gap = AEROSNAP_INDICATOR_EDGE_GAP;
-#if defined(MORE_AEROSNAP_DEBUGGING)
-  GdkRectangle cache = *rect;
-#endif
-
-  if (inward)
-    inverter = 1.0;
-  else
-    inverter = -1.0;
-
-  rect->x += (gap * inverter);
-  rect->y += (gap * inverter);
-  rect->width -= (gap * 2 * inverter);
-  rect->height -= (gap * 2 * inverter);
-
-#if defined(MORE_AEROSNAP_DEBUGGING)
-  GDK_NOTE (MISC, g_print ("Adjusted %d x %d @ %d : %d -> %d x %d @ %d : %d\n",
-                           cache.width, cache.height, cache.x, cache.y,
-                           rect->width, rect->height, rect->x, rect->y));
-#endif
-}
-
-static void
-rounded_rectangle (cairo_t  *cr,
-                   gint      x,
-                   gint      y,
-                   gint      width,
-                   gint      height,
-                   gdouble   radius,
-                   gdouble   line_width,
-                   GdkRGBA  *fill,
-                   GdkRGBA  *outline)
-{
-  gdouble degrees = M_PI / 180.0;
-
-  if (fill == NULL && outline == NULL)
-    return;
-
-  cairo_save (cr);
-  cairo_new_sub_path (cr);
-  cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees);
-  cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees);
-  cairo_arc (cr, (x + radius), y + height - radius, radius, 90 * degrees, 180 * degrees);
-  cairo_arc (cr, (x + radius), (y + radius), radius, 180 * degrees, 270 * degrees);
-  cairo_close_path (cr);
-
-  if (fill)
-    {
-      cairo_set_source_rgba (cr, fill->red, fill->green, fill->blue, fill->alpha);
-
-      if (outline)
-        cairo_fill_preserve (cr);
-      else
-        cairo_fill (cr);
-    }
-
-  if (outline)
-    {
-      cairo_set_source_rgba (cr, outline->red, outline->green, outline->blue, outline->alpha);
-      cairo_set_line_width (cr, line_width);
-      cairo_stroke (cr);
-    }
-
-  cairo_restore (cr);
-}
-
-/* Translates linear animation scale into some kind of curve */
-static gdouble
-curve (gdouble val)
-{
-  /* TODO: try different curves. For now it's just linear */
-  return val;
-}
-
-static gboolean
-draw_indicator (GdkW32DragMoveResizeContext *context,
-                gint64                       timestamp)
-{
-  cairo_t *cr;
-  GdkRGBA outline = {0, 0, 1.0, 1.0};
-  GdkRGBA fill = {0, 0, 1.0, 0.8};
-  GdkRectangle current_rect;
-  gint64 current_time = g_get_monotonic_time ();
-  gdouble animation_progress;
-  gboolean last_draw;
-  gdouble line_width;
-  gdouble corner_radius;
-  gint64 animation_duration;
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (context->window->impl);
-
-  line_width = AEROSNAP_INDICATOR_LINE_WIDTH * impl->window_scale;
-  corner_radius = AEROSNAP_INDICATOR_CORNER_RADIUS;
-  animation_duration = AEROSNAP_INDICATOR_ANIMATION_DURATION;
-  last_draw = FALSE;
-
-  if (timestamp == 0 &&
-      current_time - context->indicator_start_time > animation_duration)
-    {
-      timestamp = context->indicator_start_time + animation_duration;
-      last_draw = TRUE;
-    }
-
-  if (timestamp != 0)
-    current_time = timestamp;
-
-  animation_progress = (gdouble) (current_time - context->indicator_start_time) / animation_duration;
-
-  if (animation_progress > 1.0)
-    animation_progress = 1.0;
-
-  if (animation_progress < 0)
-    animation_progress = 0;
-
-  animation_progress = curve (animation_progress);
-
-  current_rect = context->indicator_start;
-  current_rect.x += (context->indicator_target.x - context->indicator_start.x) * animation_progress;
-  current_rect.y += (context->indicator_target.y - context->indicator_start.y) * animation_progress;
-  current_rect.width += (context->indicator_target.width - context->indicator_start.width) * animation_progress;
-  current_rect.height += (context->indicator_target.height - context->indicator_start.height) * animation_progress;
-
-  if (context->op == GDK_WIN32_DRAGOP_RESIZE && last_draw)
-    {
-      switch (context->edge)
-        {
-        case GDK_SURFACE_EDGE_NORTH_WEST:
-          current_rect.x = context->indicator_target.x + (context->indicator_target.width - current_rect.width);
-          current_rect.y = context->indicator_target.y + (context->indicator_target.height - current_rect.height);
-          break;
-        case GDK_SURFACE_EDGE_NORTH:
-          current_rect.y = context->indicator_target.y + (context->indicator_target.height - current_rect.height);
-          break;
-        case GDK_SURFACE_EDGE_WEST:
-          current_rect.x = context->indicator_target.x + (context->indicator_target.width - current_rect.width);
-          break;
-        case GDK_SURFACE_EDGE_SOUTH_WEST:
-          current_rect.x = context->indicator_target.x + (context->indicator_target.width - current_rect.width);
-          current_rect.y = context->indicator_target.y;
-          break;
-        case GDK_SURFACE_EDGE_NORTH_EAST:
-          current_rect.x = context->indicator_target.x;
-          current_rect.y = context->indicator_target.y + (context->indicator_target.height - current_rect.height);
-          break;
-        case GDK_SURFACE_EDGE_SOUTH_EAST:
-          current_rect.x = context->indicator_target.x;
-          current_rect.y = context->indicator_target.y;
-          break;
-        case GDK_SURFACE_EDGE_SOUTH:
-          current_rect.y = context->indicator_target.y;
-          break;
-        case GDK_SURFACE_EDGE_EAST:
-          current_rect.x = context->indicator_target.x;
-          break;
-        }
-    }
-
-  cr = cairo_create (context->indicator_surface);
-  rounded_rectangle (cr,
-                     (current_rect.x - context->indicator_window_rect.x) * impl->window_scale,
-                     (current_rect.y - context->indicator_window_rect.y) * impl->window_scale,
-                     current_rect.width * impl->window_scale,
-                     current_rect.height * impl->window_scale,
-                     corner_radius,
-                     line_width,
-                     &fill, &outline);
-  cairo_destroy (cr);
-
-#if defined(MORE_AEROSNAP_DEBUGGING)
-  GDK_NOTE (MISC, g_print ("Indicator is %d x %d @ %d : %d; current time is %" G_GINT64_FORMAT "\n",
-                           current_rect.width, current_rect.height,
-                           current_rect.x - context->indicator_window_rect.x,
-                           current_rect.y - context->indicator_window_rect.y,
-                           current_time));
-#endif
-
-  return last_draw;
-}
-
-static gboolean
-redraw_indicator (gpointer user_data)
-{
-  GdkW32DragMoveResizeContext *context = user_data;
-  POINT window_position;
-  SIZE window_size;
-  BLENDFUNCTION blender;
-  HDC hdc;
-  POINT source_point = { 0, 0 };
-  gboolean last_draw;
-  gdouble indicator_opacity;
-  GdkSurfaceImplWin32 *impl;
-  gboolean do_source_remove = FALSE;
-
-  indicator_opacity = AEROSNAP_INDICATOR_OPACITY;
-
-  if (GDK_SURFACE_DESTROYED (context->window) ||
-      !ensure_snap_indicator_exists (context))
-    {
-      do_source_remove = TRUE;
-    }
-
-  impl = GDK_SURFACE_IMPL_WIN32 (context->window->impl);
-
-  if (!ensure_snap_indicator_surface (context,
-                                      context->indicator_window_rect.width,
-                                      context->indicator_window_rect.height,
-                                      impl->window_scale))
-    {
-      do_source_remove = TRUE;
-    }
-
-  if (do_source_remove)
-    {
-      context->timer = 0;
-      return G_SOURCE_REMOVE;
-    }
-
-  last_draw = draw_indicator (context, context->draw_timestamp);
-
-  window_position.x = (context->indicator_window_rect.x - _gdk_offset_x) * impl->window_scale;
-  window_position.y = (context->indicator_window_rect.y - _gdk_offset_y) * impl->window_scale;
-  window_size.cx = context->indicator_window_rect.width * impl->window_scale;
-  window_size.cy = context->indicator_window_rect.height * impl->window_scale;
-
-  blender.BlendOp = AC_SRC_OVER;
-  blender.BlendFlags = 0;
-  blender.AlphaFormat = AC_SRC_ALPHA;
-  blender.SourceConstantAlpha = 255 * indicator_opacity;
-
-  hdc = cairo_win32_surface_get_dc (context->indicator_surface);
-
-  API_CALL (SetWindowPos, (context->shape_indicator,
-                           GDK_SURFACE_HWND (context->window),
-                           0, 0, 0, 0,
-                           SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW | SWP_SHOWWINDOW | SWP_NOACTIVATE));
-
-#if defined(MORE_AEROSNAP_DEBUGGING)
-  GDK_NOTE (MISC, g_print ("Indicator window position is %ld x %ld @ %ld : %ld\n",
-                           window_size.cx, window_size.cy,
-                           window_position.x, window_position.y));
-#endif
-
-  API_CALL (UpdateLayeredWindow, (context->shape_indicator, NULL,
-                                  &window_position, &window_size,
-                                  hdc, &source_point,
-                                  0, &blender, ULW_ALPHA));
-
-  if (last_draw)
-    context->timer = 0;
-
-  return last_draw ? G_SOURCE_REMOVE : G_SOURCE_CONTINUE;
-}
-
-static GdkRectangle
-unity_of_rects (GdkRectangle a,
-                GdkRectangle b)
-{
-  GdkRectangle u = b;
-
-  if (a.x < u.x)
-    {
-      u.width += u.x - a.x;
-      u.x = a.x;
-    }
-
-  if (a.y < u.y)
-    {
-      u.height += (u.y - a.y);
-      u.y = a.y;
-    }
-
-  if (a.x + a.width > u.x + u.width)
-    u.width += (a.x + a.width) - (u.x + u.width);
-
-  if (a.y + a.height > u.y + u.height)
-    u.height += (a.y + a.height) - (u.y + u.height);
-
-#if defined(MORE_AEROSNAP_DEBUGGING)
-  GDK_NOTE (MISC, g_print ("Unified 2 rects into %d x %d @ %d : %d\n",
-                           u.width, u.height, u.x, u.y));
-#endif
-
-  return u;
-}
-
-static void
-start_indicator_drawing (GdkW32DragMoveResizeContext *context,
-                         GdkRectangle                 from,
-                         GdkRectangle                 to,
-                         guint                        scale)
-{
-  GdkRectangle to_adjusted, from_adjusted, from_or_to;
-  gint64 indicator_animation_tick = AEROSNAP_INDICATOR_ANIMATION_TICK;
-
-  GDK_NOTE (MISC, g_print ("Start drawing snap indicator %d x %d @ %d : %d -> %d x %d @ %d : %d\n",
-                           from.width * scale, from.height * scale, from.x, from.y, to.width * scale, to.height * scale, to.x, to.y));
-
-  if (GDK_SURFACE_DESTROYED (context->window))
-    return;
-
-  if (!ensure_snap_indicator_exists (context))
-    return;
-
-  from_or_to = unity_of_rects (from, to);
-
-  if (!ensure_snap_indicator_surface (context, from_or_to.width, from_or_to.height, scale))
-    return;
-
-  to_adjusted = to;
-  adjust_indicator_rectangle (&to_adjusted, TRUE);
-
-  from_adjusted = from;
-  adjust_indicator_rectangle (&from_adjusted, TRUE);
-
-  context->draw_timestamp = 0;
-  context->indicator_start = from_adjusted;
-  context->indicator_target = to_adjusted;
-  context->indicator_window_rect = from_or_to;
-  context->indicator_start_time = g_get_monotonic_time ();
-
-  if (context->timer)
-    {
-      g_source_remove (context->timer);
-      context->timer = 0;
-    }
-
-  context->timer = g_timeout_add_full (G_PRIORITY_DEFAULT,
-                                       indicator_animation_tick,
-                                       redraw_indicator,
-                                       context,
-                                       NULL);
-}
-
-static void
-update_fullup_indicator (GdkSurface                   *window,
-                         GdkW32DragMoveResizeContext *context)
-{
-  SHORT maxysize;
-  GdkRectangle from, to;
-  GdkRectangle to_adjusted, from_adjusted, from_or_to;
-  GdkSurfaceImplWin32 *impl;
-
-  GDK_NOTE (MISC, g_print ("Update fullup indicator\n"));
-
-  if (GDK_SURFACE_DESTROYED (context->window))
-    return;
-
-  if (context->shape_indicator == NULL)
-    return;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-  maxysize = GetSystemMetrics (SM_CYVIRTUALSCREEN);
-  gdk_surface_get_position (window, &to.x, &to.y);
-  to.width = gdk_surface_get_width (window);
-  to.height = gdk_surface_get_height (window);
-
-  to.y = 0;
-  to.height = maxysize;
-  from = context->indicator_target;
-
-  if (context->timer == 0)
-    {
-      from_adjusted = from;
-      adjust_indicator_rectangle (&from_adjusted, FALSE);
-
-      GDK_NOTE (MISC, g_print ("Restart fullup animation from %d x %d @ %d : %d -> %d x %d @ %d x %d\n",
-                               context->indicator_target.width, context->indicator_target.height,
-                               context->indicator_target.x, context->indicator_target.y,
-                               to.width, to.height, to.x, to.y));
-      start_indicator_drawing (context, from_adjusted, to, impl->window_scale);
-
-      return;
-    }
-
-  from_or_to = unity_of_rects (from, to);
-
-  to_adjusted = to;
-  adjust_indicator_rectangle (&to_adjusted, TRUE);
-
-  GDK_NOTE (MISC, g_print ("Retarget fullup animation %d x %d @ %d : %d -> %d x %d @ %d x %d\n",
-                           context->indicator_target.width, context->indicator_target.height,
-                           context->indicator_target.x, context->indicator_target.y,
-                           to_adjusted.width, to_adjusted.height, to_adjusted.x, to_adjusted.y));
-
-  context->indicator_target = to_adjusted;
-  context->indicator_window_rect = from_or_to;
-
-  ensure_snap_indicator_surface (context, from_or_to.width, from_or_to.height, impl->window_scale);
-}
-
-static void
-start_indicator (GdkSurface                   *window,
-                 GdkW32DragMoveResizeContext *context,
-                 gint                         x,
-                 gint                         y,
-                 GdkWin32AeroSnapState        state)
-{
-  GdkMonitor *monitor;
-  GdkRectangle workarea;
-  SHORT maxysize;
-  GdkRectangle start_size, end_size;
-  GdkDisplay *display;
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  display = gdk_surface_get_display (window);
-  monitor = gdk_display_get_monitor_at_point (display, x, y);
-  gdk_monitor_get_workarea (monitor, &workarea);
-
-  maxysize = GetSystemMetrics (SM_CYVIRTUALSCREEN) / impl->window_scale;
-  gdk_surface_get_position (window, &start_size.x, &start_size.y);
-  start_size.width = gdk_surface_get_width (window);
-  start_size.height = gdk_surface_get_height (window);
-
-  end_size = start_size;
-
-  switch (state)
-    {
-    case GDK_WIN32_AEROSNAP_STATE_UNDETERMINED:
-      return;
-    case GDK_WIN32_AEROSNAP_STATE_MAXIMIZE:
-      end_size.x = workarea.x;
-      end_size.y = workarea.y;
-      end_size.width = workarea.width;
-      end_size.height = workarea.height;
-      break;
-    case GDK_WIN32_AEROSNAP_STATE_HALFLEFT:
-      end_size.x = workarea.x;
-      end_size.y = workarea.y;
-      end_size.width = workarea.width / 2;
-      end_size.height = workarea.height;
-      break;
-    case GDK_WIN32_AEROSNAP_STATE_HALFRIGHT:
-      end_size.x = (workarea.x + workarea.width / 2);
-      end_size.y = workarea.y;
-      end_size.width = workarea.width / 2;
-      end_size.height = workarea.height;
-      break;
-    case GDK_WIN32_AEROSNAP_STATE_FULLUP:
-      end_size.y = 0;
-      end_size.height = maxysize;
-      break;
-    }
-
-  start_indicator_drawing (context, start_size, end_size, impl->window_scale);
-}
-
-static void
-stop_indicator (GdkSurface                   *window,
-                GdkW32DragMoveResizeContext *context)
-{
-  GDK_NOTE (MISC, g_print ("Stop drawing snap indicator\n"));
-
-  if (context->timer)
-    {
-      g_source_remove (context->timer);
-      context->timer = 0;
-    }
-
-  API_CALL (SetWindowPos, (context->shape_indicator,
-                           SWP_NOZORDER_SPECIFIED,
-                           0, 0, 0, 0,
-                           SWP_NOZORDER | SWP_NOMOVE |
-                           SWP_NOSIZE | SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_NOACTIVATE));
-}
-
-static gint
-point_in_aerosnap_region (gint                x,
-                          gint                y,
-                          AeroSnapEdgeRegion *region)
-{
-  gint edge, trigger;
-
-  edge = (x >= region->edge.x &&
-          y >= region->edge.y &&
-          x <= region->edge.x + region->edge.width &&
-          y <= region->edge.y + region->edge.height) ? 1 : 0;
-  trigger = (x >= region->trigger.x &&
-             y >= region->trigger.y &&
-             x <= region->trigger.x + region->trigger.width &&
-             y <= region->trigger.y + region->trigger.height) ? 1 : 0;
-  return edge + trigger;
-}
-
-static void
-handle_aerosnap_move_resize (GdkSurface                   *window,
-                             GdkW32DragMoveResizeContext *context,
-                             gint                         x,
-                             gint                         y)
-{
-  gint i;
-  AeroSnapEdgeRegion *reg;
-  gint maximize = 0;
-  gint halfleft = 0;
-  gint halfright = 0;
-  gint fullup = 0;
-  gboolean fullup_edge = FALSE;
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  if (context->op == GDK_WIN32_DRAGOP_RESIZE)
-    switch (context->edge)
-      {
-      case GDK_SURFACE_EDGE_NORTH_WEST:
-      case GDK_SURFACE_EDGE_NORTH_EAST:
-      case GDK_SURFACE_EDGE_WEST:
-      case GDK_SURFACE_EDGE_EAST:
-      case GDK_SURFACE_EDGE_SOUTH_WEST:
-      case GDK_SURFACE_EDGE_SOUTH_EAST:
-        break;
-      case GDK_SURFACE_EDGE_SOUTH:
-      case GDK_SURFACE_EDGE_NORTH:
-        fullup_edge = TRUE;
-        break;
-      }
-
-  for (i = 0; i < context->maximize_regions->len && maximize == 0; i++)
-    {
-      reg = &g_array_index (context->maximize_regions, AeroSnapEdgeRegion, i);
-      maximize = point_in_aerosnap_region (x, y, reg);
-    }
-
-  for (i = 0; i < context->halfleft_regions->len && halfleft == 0; i++)
-    {
-      reg = &g_array_index (context->halfleft_regions, AeroSnapEdgeRegion, i);
-      halfleft = point_in_aerosnap_region (x, y, reg);
-    }
-
-  for (i = 0; i < context->halfright_regions->len && halfright == 0; i++)
-    {
-      reg = &g_array_index (context->halfright_regions, AeroSnapEdgeRegion, i);
-      halfright = point_in_aerosnap_region (x, y, reg);
-    }
-
-  for (i = 0; i < context->fullup_regions->len && fullup == 0; i++)
-    {
-      reg = &g_array_index (context->fullup_regions, AeroSnapEdgeRegion, i);
-      fullup = point_in_aerosnap_region (x, y, reg);
-    }
-
-#if defined(MORE_AEROSNAP_DEBUGGING)
-  GDK_NOTE (MISC, g_print ("AeroSnap: point %d : %d - max: %d, left %d, right %d, up %d\n",
-                           x, y, maximize, halfleft, halfright, fullup));
-#endif
-
-  if (!context->revealed)
-    {
-      if (context->op == GDK_WIN32_DRAGOP_MOVE && maximize == 2)
-        {
-          context->revealed = TRUE;
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_MAXIMIZE;
-          start_indicator (window, context, x, y, context->current_snap);
-        }
-      else if (context->op == GDK_WIN32_DRAGOP_MOVE && halfleft == 2)
-        {
-          context->revealed = TRUE;
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFLEFT;
-          start_indicator (window, context, x, y, context->current_snap);
-        }
-      else if (context->op == GDK_WIN32_DRAGOP_MOVE && halfright == 2)
-        {
-          context->revealed = TRUE;
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFRIGHT;
-          start_indicator (window, context, x, y, context->current_snap);
-        }
-      else if (context->op == GDK_WIN32_DRAGOP_RESIZE && fullup == 2 && fullup_edge)
-        {
-          context->revealed = TRUE;
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_FULLUP;
-          start_indicator (window, context, x, y, context->current_snap);
-        }
-
-      return;
-    }
-
-  switch (context->current_snap)
-    {
-    case GDK_WIN32_AEROSNAP_STATE_UNDETERMINED:
-      if (context->op == GDK_WIN32_DRAGOP_RESIZE && fullup > 0)
-        {
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_FULLUP;
-          start_indicator (window, context, x, y, context->current_snap);
-        }
-      break;
-    case GDK_WIN32_AEROSNAP_STATE_MAXIMIZE:
-      if (context->op == GDK_WIN32_DRAGOP_MOVE && maximize > 0)
-        break;
-      if (context->op == GDK_WIN32_DRAGOP_MOVE && halfleft > 0)
-        {
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFLEFT;
-          start_indicator (window, context, x, y, context->current_snap);
-        }
-      else if (context->op == GDK_WIN32_DRAGOP_MOVE && halfright > 0)
-        {
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFRIGHT;
-          start_indicator (window, context, x, y, context->current_snap);
-        }
-      else
-        {
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
-          stop_indicator (window, context);
-          context->revealed = FALSE;
-        }
-      break;
-    case GDK_WIN32_AEROSNAP_STATE_HALFLEFT:
-      if (context->op == GDK_WIN32_DRAGOP_MOVE && halfleft > 0)
-        break;
-      if (context->op == GDK_WIN32_DRAGOP_MOVE && maximize > 0)
-        {
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_MAXIMIZE;
-          start_indicator (window, context, x, y, context->current_snap);
-        }
-      else if (context->op == GDK_WIN32_DRAGOP_MOVE && halfright > 0)
-        {
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFRIGHT;
-          start_indicator (window, context, x, y, context->current_snap);
-        }
-      else
-        {
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
-          stop_indicator (window, context);
-          context->revealed = FALSE;
-        }
-      break;
-    case GDK_WIN32_AEROSNAP_STATE_HALFRIGHT:
-      if (context->op == GDK_WIN32_DRAGOP_MOVE && halfright > 0)
-        break;
-      if (context->op == GDK_WIN32_DRAGOP_MOVE && maximize > 0)
-        {
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_MAXIMIZE;
-          start_indicator (window, context, x, y, context->current_snap);
-        }
-      else if (context->op == GDK_WIN32_DRAGOP_MOVE && halfleft > 0)
-        {
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_HALFLEFT;
-          start_indicator (window, context, x, y, context->current_snap);
-        }
-      else
-        {
-          context->current_snap = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
-          stop_indicator (window, context);
-          context->revealed = FALSE;
-        }
-      break;
-    case GDK_WIN32_AEROSNAP_STATE_FULLUP:
-      if (context->op == GDK_WIN32_DRAGOP_RESIZE && fullup > 0 && fullup_edge)
-        {
-          update_fullup_indicator (window, context);
-          break;
-        }
-
-      context->current_snap = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
-      stop_indicator (window, context);
-      break;
-    }
-}
-
-
-static const gchar *
-get_cursor_name_from_op (GdkW32WindowDragOp op,
-                         GdkSurfaceEdge      edge)
-{
-  switch (op)
-    {
-    case GDK_WIN32_DRAGOP_MOVE:
-      return "move";
-    case GDK_WIN32_DRAGOP_RESIZE:
-      switch (edge)
-        {
-        case GDK_SURFACE_EDGE_NORTH_WEST:
-          return "nw-resize";
-        case GDK_SURFACE_EDGE_NORTH:
-          return "n-resize";
-        case GDK_SURFACE_EDGE_NORTH_EAST:
-          return "ne-resize";
-        case GDK_SURFACE_EDGE_WEST:
-          return "w-resize";
-        case GDK_SURFACE_EDGE_EAST:
-          return "e-resize";
-        case GDK_SURFACE_EDGE_SOUTH_WEST:
-          return "sw-resize";
-        case GDK_SURFACE_EDGE_SOUTH:
-          return "s-resize";
-        case GDK_SURFACE_EDGE_SOUTH_EAST:
-          return "se-resize";
-        }
-      /* default: warn about unhandled enum values,
-       * fallthrough to GDK_WIN32_DRAGOP_NONE case
-       */
-    case GDK_WIN32_DRAGOP_COUNT:
-      g_assert_not_reached ();
-    case GDK_WIN32_DRAGOP_NONE:
-      return "default";
-    /* default: warn about unhandled enum values */
-    }
-
-  g_assert_not_reached ();
-
-  return NULL;
-}
-
-static gboolean
-point_in_window (GdkSurface *window,
-                 gdouble    x,
-                 gdouble    y)
-{
-  return x >= 0 && x < window->width &&
-         y >= 0 && y < window->height &&
-         (window->shape == NULL ||
-          cairo_region_contains_point (window->shape, x, y)) &&
-         (window->input_shape == NULL ||
-          cairo_region_contains_point (window->input_shape, x, y));
-}
-
-static GdkSurface *
-child_window_at_coordinates (GdkSurface *window,
-                             gint       root_x,
-                             gint       root_y)
-{
-  gint x, y;
-  GList *l;
-  GList *children;
-
-  children = gdk_surface_peek_children (window);
-  gdk_surface_get_root_origin (window, &x, &y);
-  x = root_x - x;
-  y = root_y - y;
-
-  for (l = children; l; l = g_list_next (l))
-    {
-      GdkSurface *child = GDK_SURFACE (l->data);
-
-      if (point_in_window (child, x, y))
-        return child;
-    }
-
-  return window;
-}
-
-static void
-setup_drag_move_resize_context (GdkSurface                   *window,
-                                GdkW32DragMoveResizeContext *context,
-                                GdkW32WindowDragOp           op,
-                                GdkSurfaceEdge                edge,
-                                GdkDevice                   *device,
-                                gint                         button,
-                                gint                         root_x,
-                                gint                         root_y,
-                                guint32                      timestamp)
-{
-  RECT rect;
-  const gchar *cursor_name;
-  GdkSurface *pointer_window;
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-  GdkDisplay *display = gdk_device_get_display (device);
-  gboolean maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
-
-  /* Before we drag, we need to undo any maximization or snapping.
-   * AeroSnap behaviour:
-   *   If snapped halfleft/halfright:
-   *     horizontal resize:
-   *       resize
-   *       don't unsnap
-   *       keep stashed unsnapped size intact
-   *     vertical resize:
-   *       resize
-   *       unsnap to new size (merge cached unsnapped state with current
-   *                           snapped state in such a way that the gripped edge
-   *                           does not move)
-   *     diagonal resize:
-   *       difficult to test (first move is usually either purely
-   *                          horizontal or purely vertical, in which
-   *                          case the above behaviour applies)
-   *   If snapped up:
-   *     horizontal resize:
-   *       resize
-   *       don't unsnap
-   *       apply new width and x position to unsnapped cache,
-   *         so that unsnapped window only regains its height
-   *         and y position, but inherits x and width from
-   *         the fullup snapped state
-   *     vertical resize:
-   *       unsnap to new size (merge cached unsnapped state with current
-   *                           snapped state in such a way that the gripped edge
-   *                           does not move)
-   *
-   * This implementation behaviour:
-   *   If snapped halfleft/halfright/fullup:
-   *     any resize:
-   *       unsnap to current size, discard cached pre-snap state
-   *
-   * TODO: make this implementation behave as AeroSnap on resizes?
-   * There's also the case where
-   * a halfleft/halfright window isn't unsnapped when it's
-   * being moved horizontally, but it's more difficult to implement.
-   */
-  if (op == GDK_WIN32_DRAGOP_RESIZE &&
-      (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFRIGHT ||
-       impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFLEFT ||
-       impl->snap_state == GDK_WIN32_AEROSNAP_STATE_FULLUP))
-    {
-      discard_snapinfo (window);
-    }
-  else if (maximized ||
-           (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFRIGHT ||
-            impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFLEFT ||
-            impl->snap_state == GDK_WIN32_AEROSNAP_STATE_FULLUP))
-    {
-      GdkMonitor *monitor;
-      gint wx, wy, wwidth, wheight;
-      gint swx, swy, swwidth, swheight;
-      gboolean pointer_outside_of_window;
-      gint offsetx, offsety;
-      gboolean left_half;
-      GdkDisplay *display;
-
-      display = gdk_surface_get_display (window);
-      monitor = gdk_display_get_monitor_at_window (display, window);
-      gdk_surface_get_geometry (window, &wx, &wy, &wwidth, &wheight);
-
-      swx = wx;
-      swy = wy;
-      swwidth = wwidth;
-      swheight = wheight;
-
-      /* Subtract window shadow. We don't want pointer to go outside of
-       * the visible window during drag-move. For drag-resize it's OK.
-       * Don't take shadow into account if the window is maximized -
-       * maximized windows don't have shadows.
-       */
-      if (op == GDK_WIN32_DRAGOP_MOVE && !maximized)
-        {
-          swx += impl->margins.left / impl->window_scale;
-          swy += impl->margins.top / impl->window_scale;
-          swwidth -= impl->margins_x;
-          swheight -= impl->margins_y;
-        }
-
-      pointer_outside_of_window = root_x < swx || root_x > swx + swwidth ||
-                                  root_y < swy || root_y > swy + swheight;
-      /* Calculate the offset of the pointer relative to the window */
-      offsetx = root_x - swx;
-      offsety = root_y - swy;
-
-      /* Figure out in which half of the window the pointer is.
-       * The code currently only concerns itself with horizontal
-       * dimension (left/right halves).
-       * There's no upper/lower half, because usually window
-       * is dragged by its upper half anyway. If that changes, adjust
-       * accordingly.
-       */
-      left_half = (offsetx < swwidth / 2);
-
-      /* Inverse the offset for it to be from the right edge */
-      if (!left_half)
-        offsetx = swwidth - offsetx;
-
-      GDK_NOTE (MISC, g_print ("Pointer at %d : %d, this is %d : %d relative to the window's %s\n",
-                               root_x, root_y, offsetx, offsety,
-                               left_half ? "left half" : "right half"));
-
-      /* Move window in such a way that on unmaximization/unsnapping the pointer
-       * is still pointing at the appropriate half of the window,
-       * with the same offset from the left or right edge. If the new
-       * window size is too small, and adding that offset puts the pointer
-       * into the other half or even beyond, move the pointer to the middle.
-       */
-      if (!pointer_outside_of_window && maximized)
-        {
-          WINDOWPLACEMENT placement;
-          gint unmax_width, unmax_height;
-          gint shadow_unmax_width, shadow_unmax_height;
-
-          placement.length = sizeof (placement);
-          API_CALL (GetWindowPlacement, (GDK_SURFACE_HWND (window), &placement));
-
-          GDK_NOTE (MISC, g_print ("W32 WM unmaximized window placement is %ld x %ld @ %ld : %ld\n",
-                                   placement.rcNormalPosition.right - placement.rcNormalPosition.left,
-                                   placement.rcNormalPosition.bottom - placement.rcNormalPosition.top,
-                                   placement.rcNormalPosition.left + _gdk_offset_x * impl->window_scale,
-                                   placement.rcNormalPosition.top + _gdk_offset_y * impl->window_scale));
-
-          unmax_width = placement.rcNormalPosition.right - placement.rcNormalPosition.left;
-          unmax_height = placement.rcNormalPosition.bottom - placement.rcNormalPosition.top;
-
-          shadow_unmax_width = unmax_width - impl->margins_x * impl->window_scale;
-          shadow_unmax_height = unmax_height - impl->margins_y * impl->window_scale;
-
-          if (offsetx * impl->window_scale < (shadow_unmax_width / 2) &&
-              offsety * impl->window_scale < (shadow_unmax_height / 2))
-            {
-              placement.rcNormalPosition.top = (root_y - offsety + impl->margins.top - _gdk_offset_y) * impl->window_scale;
-              placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + unmax_height;
-
-              if (left_half)
-                {
-                  placement.rcNormalPosition.left = (root_x - offsetx + impl->margins.left - _gdk_offset_x) * impl->window_scale;
-                  placement.rcNormalPosition.right = placement.rcNormalPosition.left + unmax_width;
-                }
-              else
-                {
-                  placement.rcNormalPosition.right = (root_x + offsetx + impl->margins.right - _gdk_offset_x) * impl->window_scale;
-                  placement.rcNormalPosition.left = placement.rcNormalPosition.right - unmax_width;
-                }
-            }
-          else
-            {
-              placement.rcNormalPosition.left = (root_x * impl->window_scale) -
-                                                (unmax_width / 2) -
-                                                (_gdk_offset_x * impl->window_scale);
-
-              if (offsety * impl->window_scale < shadow_unmax_height / 2)
-                placement.rcNormalPosition.top = (root_y - offsety + impl->margins.top - _gdk_offset_y) * impl->window_scale;
-              else
-                placement.rcNormalPosition.top = (root_y * impl->window_scale) -
-                                                 (unmax_height / 2) -
-                                                 (_gdk_offset_y * impl->window_scale);
-
-              placement.rcNormalPosition.right = placement.rcNormalPosition.left + unmax_width;
-              placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + unmax_height;
-            }
-
-          GDK_NOTE (MISC, g_print ("Unmaximized window will be at %ld : %ld\n",
-                                   placement.rcNormalPosition.left + _gdk_offset_x * impl->window_scale,
-                                   placement.rcNormalPosition.top + _gdk_offset_y * impl->window_scale));
-
-          API_CALL (SetWindowPlacement, (GDK_SURFACE_HWND (window), &placement));
-        }
-      else if (!pointer_outside_of_window && impl->snap_stash_int)
-        {
-          GdkRectangle new_pos;
-          GdkRectangle snew_pos;
-
-          new_pos.width = impl->snap_stash_int->width;
-          new_pos.height = impl->snap_stash_int->height;
-          snew_pos = new_pos;
-
-          if (op == GDK_WIN32_DRAGOP_MOVE)
-            {
-              snew_pos.width -= impl->margins_x;
-              snew_pos.height -= impl->margins_y;
-            }
-
-          if (offsetx < snew_pos.width / 2 && offsety < snew_pos.height / 2)
-            {
-              new_pos.y = root_y - offsety + impl->margins.top / impl->window_scale;
-
-              if (left_half)
-                new_pos.x = root_x - offsetx + impl->margins.left / impl->window_scale;
-              else
-                new_pos.x = root_x + offsetx + impl->margins.left / impl->window_scale - new_pos.width;
-            }
-          else
-            {
-              new_pos.x = root_x - new_pos.width / 2;
-              new_pos.y = root_y - new_pos.height / 2;
-            }
-
-          GDK_NOTE (MISC, g_print ("Unsnapped window to %d : %d\n",
-                                   new_pos.x, new_pos.y));
-          discard_snapinfo (window);
-          gdk_surface_move_resize (window, new_pos.x, new_pos.y,
-                                  new_pos.width, new_pos.height);
-        }
-
-
-      if (maximized)
-        gdk_surface_unmaximize (window);
-      else
-        unsnap (window, monitor);
-
-      if (pointer_outside_of_window)
-        {
-          /* Pointer outside of the window, move pointer into window */
-          GDK_NOTE (MISC, g_print ("Pointer at %d : %d is outside of %d x %d @ %d : %d, move it to %d : %d\n",
-                                   root_x, root_y, wwidth, wheight, wx, wy, wx + wwidth / 2, wy + wheight / 2));
-          root_x = wx + wwidth / 2;
-          /* This is Gnome behaviour. Windows WM would put the pointer
-           * in the middle of the titlebar, but GDK doesn't know where
-           * the titlebar is, if any.
-           */
-          root_y = wy + wheight / 2;
-          gdk_device_warp (device, root_x, root_y);
-        }
-    }
-
-  _gdk_win32_get_window_rect (window, &rect);
-
-  cursor_name = get_cursor_name_from_op (op, edge);
-
-  context->cursor = gdk_cursor_new_from_name (cursor_name, NULL);
-
-  pointer_window = child_window_at_coordinates (window, root_x, root_y);
-
-  /* Note: This triggers a WM_CAPTURECHANGED, which will trigger
-   * gdk_win32_surface_end_move_resize_drag(), which will end
-   * our op before it even begins, but only if context->op is not NONE.
-   * This is why we first do the grab, *then* set the op.
-   */
-  gdk_device_grab (device, pointer_window,
-                   GDK_OWNERSHIP_NONE, FALSE,
-                   GDK_ALL_EVENTS_MASK,
-                   context->cursor,
-                   timestamp);
-
-  context->window = g_object_ref (window);
-  context->op = op;
-  context->edge = edge;
-  context->device = device;
-  context->button = button;
-  context->start_root_x = root_x;
-  context->start_root_y = root_y;
-  context->timestamp = timestamp;
-  context->start_rect = rect;
-
-  context->shape_indicator = NULL;
-  context->revealed = FALSE;
-  context->halfleft_regions = g_array_new (FALSE, FALSE, sizeof (AeroSnapEdgeRegion));
-  context->halfright_regions = g_array_new (FALSE, FALSE, sizeof (AeroSnapEdgeRegion));
-  context->maximize_regions = g_array_new (FALSE, FALSE, sizeof (AeroSnapEdgeRegion));
-  context->fullup_regions = g_array_new (FALSE, FALSE, sizeof (AeroSnapEdgeRegion));
-
-  calculate_aerosnap_regions (context);
-
-  GDK_NOTE (EVENTS,
-            g_print ("begin drag moveresize: window %p, toplevel %p, "
-                     "op %u, edge %d, device %p, "
-                     "button %d, coord %d:%d, time %u\n",
-                     pointer_window, gdk_surface_get_toplevel (window),
-                     context->op, context->edge, context->device,
-                     context->button, context->start_root_x,
-                     context->start_root_y, context->timestamp));
-}
-
-void
-gdk_win32_surface_end_move_resize_drag (GdkSurface *window)
-{
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-  GdkW32DragMoveResizeContext *context = &impl->drag_move_resize_context;
-
-  context->op = GDK_WIN32_DRAGOP_NONE;
-
-  gdk_device_ungrab (context->device, GDK_CURRENT_TIME);
-
-  g_clear_object (&context->cursor);
-
-  context->revealed = FALSE;
-
-  if (context->timer)
-    {
-      g_source_remove (context->timer);
-      context->timer = 0;
-    }
-
-  g_clear_object (&context->window);
-
-  if (context->indicator_surface)
-    {
-      cairo_surface_destroy (context->indicator_surface);
-      context->indicator_surface = NULL;
-    }
-
-  if (context->shape_indicator)
-    {
-      stop_indicator (window, context);
-      DestroyWindow (context->shape_indicator);
-      context->shape_indicator = NULL;
-    }
-
-  g_clear_pointer (&context->halfleft_regions, g_array_unref);
-  g_clear_pointer (&context->halfright_regions, g_array_unref);
-  g_clear_pointer (&context->maximize_regions, g_array_unref);
-  g_clear_pointer (&context->fullup_regions, g_array_unref);
-
-  GDK_NOTE (EVENTS,
-            g_print ("end drag moveresize: window %p, toplevel %p,"
-                     "op %u, edge %d, device %p, "
-                     "button %d, coord %d:%d, time %u\n",
-                     window, gdk_surface_get_toplevel (window),
-                     context->op, context->edge, context->device,
-                     context->button, context->start_root_x,
-                     context->start_root_y, context->timestamp));
-
-  if (context->current_snap != GDK_WIN32_AEROSNAP_STATE_UNDETERMINED)
-    apply_snap (window, context->current_snap);
-
-  context->current_snap = GDK_WIN32_AEROSNAP_STATE_UNDETERMINED;
-}
-
-static void
-gdk_win32_get_window_size_and_position_from_client_rect (GdkSurface *window,
-                                                         RECT      *window_rect,
-                                                         SIZE      *window_size,
-                                                         POINT     *window_position)
-{
-  GdkSurfaceImplWin32 *impl;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  /* Turn client area into window area */
-  _gdk_win32_adjust_client_rect (window, window_rect);
-
-  /* Convert GDK screen coordinates to W32 desktop coordinates */
-  window_rect->left -= _gdk_offset_x * impl->window_scale;
-  window_rect->right -= _gdk_offset_x * impl->window_scale;
-  window_rect->top -= _gdk_offset_y * impl->window_scale;
-  window_rect->bottom -= _gdk_offset_y * impl->window_scale;
-
-  window_position->x = window_rect->left;
-  window_position->y = window_rect->top;
-  window_size->cx = window_rect->right - window_rect->left;
-  window_size->cy = window_rect->bottom - window_rect->top;
-}
-
-static void
-gdk_win32_update_layered_window_from_cache (GdkSurface *window,
-                                            RECT      *client_rect)
-{
-  POINT window_position;
-  SIZE window_size;
-  BLENDFUNCTION blender;
-  HDC hdc;
-  SIZE *window_size_ptr;
-  POINT source_point = { 0, 0 };
-  POINT *source_point_ptr;
-  GdkSurfaceImplWin32 *impl;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  gdk_win32_get_window_size_and_position_from_client_rect (window,
-                                                           client_rect,
-                                                           &window_size,
-                                                           &window_position);
-
-  blender.BlendOp = AC_SRC_OVER;
-  blender.BlendFlags = 0;
-  blender.AlphaFormat = AC_SRC_ALPHA;
-  blender.SourceConstantAlpha = impl->layered_opacity * 255;
-
-  /* Size didn't change, so move immediately, no need to wait for redraw */
-  /* Strictly speaking, we don't need to supply hdc, source_point and
-   * window_size here. However, without these arguments
-   * the window moves but does not update its contents on Windows 7 when
-   * desktop composition is off. This forces us to provide hdc and
-   * source_point. window_size is here to avoid the function
-   * inexplicably failing with error 317.
-   */
-  if (gdk_display_is_composited (gdk_surface_get_display (window)))
-    {
-      hdc = NULL;
-      window_size_ptr = NULL;
-      source_point_ptr = NULL;
-    }
-  else
-    {
-      hdc = cairo_win32_surface_get_dc (impl->cache_surface);
-      window_size_ptr = &window_size;
-      source_point_ptr = &source_point;
-    }
-
-  API_CALL (UpdateLayeredWindow, (GDK_SURFACE_HWND (window), NULL,
-                                  &window_position, window_size_ptr,
-                                  hdc, source_point_ptr,
-                                  0, &blender, ULW_ALPHA));
-}
-
-void
-gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
-                                      gint       x,
-                                      gint       y)
-{
-  RECT rect;
-  RECT new_rect;
-  gint diffy, diffx;
-  MINMAXINFO mmi;
-  GdkSurfaceImplWin32 *impl;
-  GdkW32DragMoveResizeContext *context;
-  gint width;
-  gint height;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-  context = &impl->drag_move_resize_context;
-
-  if (!_gdk_win32_get_window_rect (window, &rect))
-    return;
-
-  new_rect = context->start_rect;
-  diffx = (x - context->start_root_x) * impl->window_scale;
-  diffy = (y - context->start_root_y) * impl->window_scale;
-
-  switch (context->op)
-    {
-    case GDK_WIN32_DRAGOP_RESIZE:
-
-      switch (context->edge)
-        {
-        case GDK_SURFACE_EDGE_NORTH_WEST:
-          new_rect.left += diffx;
-          new_rect.top += diffy;
-          break;
-
-        case GDK_SURFACE_EDGE_NORTH:
-          new_rect.top += diffy;
-          break;
-
-        case GDK_SURFACE_EDGE_NORTH_EAST:
-          new_rect.right += diffx;
-          new_rect.top += diffy;
-          break;
-
-        case GDK_SURFACE_EDGE_WEST:
-          new_rect.left += diffx;
-          break;
-
-        case GDK_SURFACE_EDGE_EAST:
-          new_rect.right += diffx;
-          break;
-
-        case GDK_SURFACE_EDGE_SOUTH_WEST:
-          new_rect.left += diffx;
-          new_rect.bottom += diffy;
-          break;
-
-        case GDK_SURFACE_EDGE_SOUTH:
-          new_rect.bottom += diffy;
-          break;
-
-        case GDK_SURFACE_EDGE_SOUTH_EAST:
-        default:
-          new_rect.right += diffx;
-          new_rect.bottom += diffy;
-          break;
-        }
-
-      /* When handling WM_GETMINMAXINFO, mmi is already populated
-       * by W32 WM and we apply our stuff on top of that.
-       * Here it isn't, so we should at least clear it.
-       */
-      memset (&mmi, 0, sizeof (mmi));
-
-      if (!_gdk_win32_surface_fill_min_max_info (window, &mmi))
-        break;
-
-      width = new_rect.right - new_rect.left;
-      height = new_rect.bottom - new_rect.top;
-
-      if (width > mmi.ptMaxTrackSize.x)
-        {
-          switch (context->edge)
-            {
-            case GDK_SURFACE_EDGE_NORTH_WEST:
-            case GDK_SURFACE_EDGE_WEST:
-            case GDK_SURFACE_EDGE_SOUTH_WEST:
-              new_rect.left = new_rect.right - mmi.ptMaxTrackSize.x;
-              break;
-
-            case GDK_SURFACE_EDGE_NORTH_EAST:
-            case GDK_SURFACE_EDGE_EAST:
-            case GDK_SURFACE_EDGE_SOUTH_EAST:
-            default:
-              new_rect.right = new_rect.left + mmi.ptMaxTrackSize.x;
-              break;
-            }
-        }
-      else if (width < mmi.ptMinTrackSize.x)
-        {
-          switch (context->edge)
-            {
-            case GDK_SURFACE_EDGE_NORTH_WEST:
-            case GDK_SURFACE_EDGE_WEST:
-            case GDK_SURFACE_EDGE_SOUTH_WEST:
-              new_rect.left = new_rect.right - mmi.ptMinTrackSize.x;
-              break;
-
-            case GDK_SURFACE_EDGE_NORTH_EAST:
-            case GDK_SURFACE_EDGE_EAST:
-            case GDK_SURFACE_EDGE_SOUTH_EAST:
-            default:
-              new_rect.right = new_rect.left + mmi.ptMinTrackSize.x;
-              break;
-            }
-        }
-
-      if (height > mmi.ptMaxTrackSize.y)
-        {
-          switch (context->edge)
-            {
-            case GDK_SURFACE_EDGE_NORTH_WEST:
-            case GDK_SURFACE_EDGE_NORTH:
-            case GDK_SURFACE_EDGE_NORTH_EAST:
-              new_rect.top = new_rect.bottom - mmi.ptMaxTrackSize.y;
-
-            case GDK_SURFACE_EDGE_SOUTH_WEST:
-            case GDK_SURFACE_EDGE_SOUTH:
-            case GDK_SURFACE_EDGE_SOUTH_EAST:
-            default:
-              new_rect.bottom = new_rect.top + mmi.ptMaxTrackSize.y;
-              break;
-            }
-        }
-      else if (height < mmi.ptMinTrackSize.y)
-        {
-          switch (context->edge)
-            {
-            case GDK_SURFACE_EDGE_NORTH_WEST:
-            case GDK_SURFACE_EDGE_NORTH:
-            case GDK_SURFACE_EDGE_NORTH_EAST:
-              new_rect.top = new_rect.bottom - mmi.ptMinTrackSize.y;
-
-            case GDK_SURFACE_EDGE_SOUTH_WEST:
-            case GDK_SURFACE_EDGE_SOUTH:
-            case GDK_SURFACE_EDGE_SOUTH_EAST:
-            default:
-              new_rect.bottom = new_rect.top + mmi.ptMinTrackSize.y;
-              break;
-            }
-        }
-
-      break;
-    case GDK_WIN32_DRAGOP_MOVE:
-      new_rect.left += diffx;
-      new_rect.top += diffy;
-      new_rect.right += diffx;
-      new_rect.bottom += diffy;
-      break;
-    default:
-      break;
-    }
-
-  if (context->op == GDK_WIN32_DRAGOP_RESIZE &&
-      (rect.left != new_rect.left ||
-       rect.right != new_rect.right ||
-       rect.top != new_rect.top ||
-       rect.bottom != new_rect.bottom))
-    {
-      context->native_move_resize_pending = TRUE;
-      _gdk_win32_do_emit_configure_event (window, new_rect);
-    }
-  else if (context->op == GDK_WIN32_DRAGOP_MOVE &&
-           (rect.left != new_rect.left ||
-            rect.top != new_rect.top))
-    {
-      context->native_move_resize_pending = FALSE;
-
-      _gdk_win32_do_emit_configure_event (window, new_rect);
-
-      if (impl->layered)
-        {
-          gdk_win32_update_layered_window_from_cache (window, &new_rect);
-        }
-      else
-        {
-          SIZE window_size;
-          POINT window_position;
-
-          gdk_win32_get_window_size_and_position_from_client_rect (window,
-                                                                   &new_rect,
-                                                                   &window_size,
-                                                                   &window_position);
-
-          API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                                   SWP_NOZORDER_SPECIFIED,
-                                   window_position.x, window_position.y,
-                                   0, 0,
-                                   SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE));
-        }
-    }
-
-  if (context->op == GDK_WIN32_DRAGOP_RESIZE ||
-      context->op == GDK_WIN32_DRAGOP_MOVE)
-    handle_aerosnap_move_resize (window, context, x, y);
-}
-
-static void
-gdk_win32_surface_begin_resize_drag (GdkSurface     *window,
-                                    GdkSurfaceEdge  edge,
-                                    GdkDevice     *device,
-                                    gint           button,
-                                    gint           root_x,
-                                    gint           root_y,
-                                    guint32        timestamp)
-{
-  GdkSurfaceImplWin32 *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      IsIconic (GDK_SURFACE_HWND (window)))
-    return;
-
-  /* Tell Windows to start interactively resizing the window by pretending that
-   * the left pointer button was clicked in the suitable edge or corner. This
-   * will only work if the button is down when this function is called, and
-   * will only work with button 1 (left), since Windows only allows window
-   * dragging using the left mouse button.
-   */
-
-  if (button != 1)
-    return;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
-    gdk_win32_surface_end_move_resize_drag (window);
-
-  setup_drag_move_resize_context (window, &impl->drag_move_resize_context,
-                                  GDK_WIN32_DRAGOP_RESIZE, edge, device,
-                                  button, root_x, root_y, timestamp);
-}
-
-static void
-gdk_win32_surface_begin_move_drag (GdkSurface *window,
-                                  GdkDevice *device,
-                                  gint       button,
-                                  gint       root_x,
-                                  gint       root_y,
-                                  guint32    timestamp)
-{
-  GdkSurfaceImplWin32 *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      IsIconic (GDK_SURFACE_HWND (window)))
-    return;
-
-  /* Tell Windows to start interactively moving the window by pretending that
-   * the left pointer button was clicked in the titlebar. This will only work
-   * if the button is down when this function is called, and will only work
-   * with button 1 (left), since Windows only allows window dragging using the
-   * left mouse button.
-   */
-  if (button != 1)
-    return;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
-    gdk_win32_surface_end_move_resize_drag (window);
-
-  setup_drag_move_resize_context (window, &impl->drag_move_resize_context,
-                                  GDK_WIN32_DRAGOP_MOVE, GDK_SURFACE_EDGE_NORTH_WEST,
-                                  device, button, root_x, root_y, timestamp);
-}
-
-
-/*
- * Setting window states
- */
-static void
-gdk_win32_surface_iconify (GdkSurface *window)
-{
-  HWND old_active_window;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_iconify: %p: %s\n",
-                          GDK_SURFACE_HWND (window),
-                          _gdk_win32_surface_state_to_string (window->state)));
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      old_active_window = GetActiveWindow ();
-      GtkShowWindow (window, SW_MINIMIZE);
-      if (old_active_window != GDK_SURFACE_HWND (window))
-       SetActiveWindow (old_active_window);
-    }
-  else
-    {
-      gdk_synthesize_window_state (window,
-                                   0,
-                                   GDK_SURFACE_STATE_ICONIFIED);
-    }
-}
-
-static void
-gdk_win32_surface_deiconify (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_deiconify: %p: %s\n",
-                          GDK_SURFACE_HWND (window),
-                          _gdk_win32_surface_state_to_string (window->state)));
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      show_window_internal (window, GDK_SURFACE_IS_MAPPED (window), TRUE);
-    }
-  else
-    {
-      gdk_synthesize_window_state (window,
-                                   GDK_SURFACE_STATE_ICONIFIED,
-                                   0);
-    }
-}
-
-static void
-gdk_win32_surface_stick (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  /* FIXME: Do something? */
-}
-
-static void
-gdk_win32_surface_unstick (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  /* FIXME: Do something? */
-}
-
-static void
-gdk_win32_surface_maximize (GdkSurface *window)
-{
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_maximize: %p: %s\n",
-                          GDK_SURFACE_HWND (window),
-                          _gdk_win32_surface_state_to_string (window->state)));
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    GtkShowWindow (window, SW_MAXIMIZE);
-  else
-    gdk_synthesize_window_state (window,
-                                0,
-                                GDK_SURFACE_STATE_MAXIMIZED);
-}
-
-static void
-gdk_win32_surface_unmaximize (GdkSurface *window)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_unmaximize: %p: %s\n",
-                          GDK_SURFACE_HWND (window),
-                          _gdk_win32_surface_state_to_string (window->state)));
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    GtkShowWindow (window, SW_RESTORE);
-  else
-    gdk_synthesize_window_state (window,
-                                GDK_SURFACE_STATE_MAXIMIZED,
-                                0);
-}
-
-static void
-gdk_win32_surface_fullscreen (GdkSurface *window)
-{
-  gint x, y, width, height;
-  FullscreenInfo *fi;
-  HMONITOR monitor;
-  MONITORINFO mi;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  fi = g_new (FullscreenInfo, 1);
-
-  if (!GetWindowRect (GDK_SURFACE_HWND (window), &(fi->r)))
-    g_free (fi);
-  else
-    {
-      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-      monitor = MonitorFromWindow (GDK_SURFACE_HWND (window), MONITOR_DEFAULTTONEAREST);
-      mi.cbSize = sizeof (mi);
-      if (monitor && GetMonitorInfo (monitor, &mi))
-       {
-         x = mi.rcMonitor.left;
-         y = mi.rcMonitor.top;
-         width = mi.rcMonitor.right - x;
-         height = mi.rcMonitor.bottom - y;
-       }
-      else
-       {
-         x = y = 0;
-         width = GetSystemMetrics (SM_CXSCREEN);
-         height = GetSystemMetrics (SM_CYSCREEN);
-       }
-
-      /* remember for restoring */
-      fi->hint_flags = impl->hint_flags;
-      impl->hint_flags &= ~GDK_HINT_MAX_SIZE;
-      g_object_set_data (G_OBJECT (window), "fullscreen-info", fi);
-      fi->style = GetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE);
-
-      /* Send state change before configure event */
-      gdk_synthesize_window_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
-
-      SetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE,
-                     (fi->style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP);
-
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOP,
-                x, y, width, height,
-                SWP_NOCOPYBITS | SWP_SHOWWINDOW));
-    }
-}
-
-static void
-gdk_win32_surface_unfullscreen (GdkSurface *window)
-{
-  FullscreenInfo *fi;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  fi = g_object_get_data (G_OBJECT (window), "fullscreen-info");
-  if (fi)
-    {
-      GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-      gdk_synthesize_window_state (window, GDK_SURFACE_STATE_FULLSCREEN, 0);
-
-      impl->hint_flags = fi->hint_flags;
-      SetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE, fi->style);
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_NOTOPMOST,
-                              fi->r.left, fi->r.top,
-                              fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
-                              SWP_NOCOPYBITS | SWP_SHOWWINDOW));
-
-      g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL);
-      g_free (fi);
-      _gdk_win32_surface_update_style_bits (window);
-    }
-}
-
-static void
-gdk_win32_surface_set_keep_above (GdkSurface *window,
-                          gboolean   setting)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_set_keep_above: %p: %s\n",
-                          GDK_SURFACE_HWND (window),
-                          setting ? "YES" : "NO"));
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                              setting ? HWND_TOPMOST : HWND_NOTOPMOST,
-                              0, 0, 0, 0,
-                              SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
-    }
-
-  gdk_synthesize_window_state (window,
-                              setting ? GDK_SURFACE_STATE_BELOW : GDK_SURFACE_STATE_ABOVE,
-                              setting ? GDK_SURFACE_STATE_ABOVE : 0);
-}
-
-static void
-gdk_win32_surface_set_keep_below (GdkSurface *window,
-                          gboolean   setting)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_set_keep_below: %p: %s\n",
-                          GDK_SURFACE_HWND (window),
-                          setting ? "YES" : "NO"));
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                              setting ? HWND_BOTTOM : HWND_NOTOPMOST,
-                              0, 0, 0, 0,
-                              SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
-    }
-
-  gdk_synthesize_window_state (window,
-                              setting ? GDK_SURFACE_STATE_ABOVE : GDK_SURFACE_STATE_BELOW,
-                              setting ? GDK_SURFACE_STATE_BELOW : 0);
-}
-
-static void
-gdk_win32_surface_focus (GdkSurface *window,
-                       guint32    timestamp)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_focus: %p: %s\n",
-                          GDK_SURFACE_HWND (window),
-                          _gdk_win32_surface_state_to_string (window->state)));
-
-  if (window->state & GDK_SURFACE_STATE_MAXIMIZED)
-    GtkShowWindow (window, SW_SHOWMAXIMIZED);
-  else if (window->state & GDK_SURFACE_STATE_ICONIFIED)
-    GtkShowWindow (window, SW_RESTORE);
-  else if (!IsWindowVisible (GDK_SURFACE_HWND (window)))
-    GtkShowWindow (window, SW_SHOWNORMAL);
-  else
-    GtkShowWindow (window, SW_SHOW);
-
-  SetFocus (GDK_SURFACE_HWND (window));
-}
-
-static void
-gdk_win32_surface_set_modal_hint (GdkSurface *window,
-                          gboolean   modal)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_set_modal_hint: %p: %s\n",
-                          GDK_SURFACE_HWND (window),
-                          modal ? "YES" : "NO"));
-
-  if (modal == window->modal_hint)
-    return;
-
-  window->modal_hint = modal;
-
-#if 0
-  /* Not sure about this one.. -- Cody */
-  if (GDK_SURFACE_IS_MAPPED (window))
-    API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
-                            modal ? HWND_TOPMOST : HWND_NOTOPMOST,
-                            0, 0, 0, 0,
-                            SWP_NOMOVE | SWP_NOSIZE));
-#else
-
-  if (modal)
-    {
-      _gdk_push_modal_window (window);
-      gdk_surface_raise (window);
-    }
-  else
-    {
-      _gdk_remove_modal_window (window);
-    }
-
-#endif
-}
-
-static void
-gdk_win32_surface_set_skip_taskbar_hint (GdkSurface *window,
-                                 gboolean   skips_taskbar)
-{
-  static GdkSurface *owner = NULL;
-  //GdkSurfaceAttr wa;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_set_skip_taskbar_hint: %p: %s, doing nothing\n",
-                          GDK_SURFACE_HWND (window),
-                          skips_taskbar ? "YES" : "NO"));
-
-  // ### TODO: Need to figure out what to do here.
-  return;
-
-  if (skips_taskbar)
-    {
-#if 0
-      if (owner == NULL)
-               {
-                 wa.window_type = GDK_SURFACE_TEMP;
-                 wa.wclass = GDK_INPUT_OUTPUT;
-                 wa.width = wa.height = 1;
-                 wa.event_mask = 0;
-                 owner = gdk_surface_new_internal (NULL, &wa, 0, TRUE);
-               }
-#endif
-
-      SetWindowLongPtr (GDK_SURFACE_HWND (window), GWLP_HWNDPARENT, (LONG_PTR) GDK_SURFACE_HWND (owner));
-
-#if 0 /* Should we also turn off the minimize and maximize buttons? */
-      SetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE,
-                    GetWindowLong (GDK_SURFACE_HWND (window), GWL_STYLE) & ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU));
-
-      SetWindowPos (GDK_SURFACE_HWND (window), SWP_NOZORDER_SPECIFIED,
-                   0, 0, 0, 0,
-                   SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
-                   SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
-#endif
-    }
-  else
-    {
-      SetWindowLongPtr (GDK_SURFACE_HWND (window), GWLP_HWNDPARENT, 0);
-    }
-}
-
-static void
-gdk_win32_surface_set_skip_pager_hint (GdkSurface *window,
-                               gboolean   skips_pager)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  GDK_NOTE (MISC, g_print ("gdk_surface_set_skip_pager_hint: %p: %s, doing nothing\n",
-                          GDK_SURFACE_HWND (window),
-                          skips_pager ? "YES" : "NO"));
-}
-
-static void
-gdk_win32_surface_set_type_hint (GdkSurface        *window,
-                         GdkSurfaceTypeHint hint)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC,
-           G_STMT_START{
-             static GEnumClass *class = NULL;
-             if (!class)
-               class = g_type_class_ref (GDK_TYPE_SURFACE_TYPE_HINT);
-             g_print ("gdk_surface_set_type_hint: %p: %s\n",
-                      GDK_SURFACE_HWND (window),
-                      g_enum_get_value (class, hint)->value_name);
-           }G_STMT_END);
-
-  ((GdkSurfaceImplWin32 *)window->impl)->type_hint = hint;
-
-  _gdk_win32_surface_update_style_bits (window);
-}
-
-static GdkSurfaceTypeHint
-gdk_win32_surface_get_type_hint (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), GDK_SURFACE_TYPE_HINT_NORMAL);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return GDK_SURFACE_TYPE_HINT_NORMAL;
-
-  return GDK_SURFACE_IMPL_WIN32 (window->impl)->type_hint;
-}
-
-static HRGN
-cairo_region_to_hrgn (const cairo_region_t *region,
-                     gint                  x_origin,
-                     gint                  y_origin,
-                     guint                 scale)
-{
-  HRGN hrgn;
-  RGNDATA *rgndata;
-  RECT *rect;
-  cairo_rectangle_int_t r;
-  const int nrects = cairo_region_num_rectangles (region);
-  guint nbytes =
-    sizeof (RGNDATAHEADER) + (sizeof (RECT) * nrects);
-  int i;
-
-  rgndata = g_malloc (nbytes);
-  rgndata->rdh.dwSize = sizeof (RGNDATAHEADER);
-  rgndata->rdh.iType = RDH_RECTANGLES;
-  rgndata->rdh.nCount = rgndata->rdh.nRgnSize = 0;
-  SetRect (&rgndata->rdh.rcBound,
-          G_MAXLONG, G_MAXLONG, G_MINLONG, G_MINLONG);
-
-  for (i = 0; i < nrects; i++)
-    {
-      rect = ((RECT *) rgndata->Buffer) + rgndata->rdh.nCount++;
-
-      cairo_region_get_rectangle (region, i, &r);
-      rect->left = (r.x + x_origin) * scale;
-      rect->right = (rect->left + r.width) * scale;
-      rect->top = (r.y + y_origin) * scale;
-      rect->bottom = (rect->top + r.height) * scale;
-
-      if (rect->left < rgndata->rdh.rcBound.left)
-       rgndata->rdh.rcBound.left = rect->left;
-      if (rect->right > rgndata->rdh.rcBound.right)
-       rgndata->rdh.rcBound.right = rect->right;
-      if (rect->top < rgndata->rdh.rcBound.top)
-       rgndata->rdh.rcBound.top = rect->top;
-      if (rect->bottom > rgndata->rdh.rcBound.bottom)
-       rgndata->rdh.rcBound.bottom = rect->bottom;
-    }
-  if ((hrgn = ExtCreateRegion (NULL, nbytes, rgndata)) == NULL)
-    WIN32_API_FAILED ("ExtCreateRegion");
-
-  g_free (rgndata);
-
-  return (hrgn);
-}
-
-static void
-gdk_win32_surface_shape_combine_region (GdkSurface       *window,
-                                      const cairo_region_t *shape_region,
-                                      gint             offset_x,
-                                      gint             offset_y)
-{
-  GdkSurfaceImplWin32 *impl;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (!shape_region)
-    {
-      GDK_NOTE (MISC, g_print ("gdk_win32_surface_shape_combine_region: %p: none\n",
-                              GDK_SURFACE_HWND (window)));
-      SetWindowRgn (GDK_SURFACE_HWND (window), NULL, TRUE);
-    }
-  else
-    {
-      HRGN hrgn;
-      impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-      hrgn = cairo_region_to_hrgn (shape_region, 0, 0, impl->window_scale);
-
-      GDK_NOTE (MISC, g_print ("gdk_win32_surface_shape_combine_region: %p: %p\n",
-                              GDK_SURFACE_HWND (window),
-                              hrgn));
-
-      do_shape_combine_region (window, hrgn, offset_x, offset_y);
-    }
-}
-
-GdkSurface *
-gdk_win32_surface_lookup_for_display (GdkDisplay *display,
-                                     HWND        anid)
-{
-  g_return_val_if_fail (display == gdk_display_get_default (), NULL);
-
-  return (GdkSurface*) gdk_win32_handle_table_lookup (anid);
-}
-
-static void
-gdk_win32_surface_set_opacity (GdkSurface *window,
-                       gdouble    opacity)
-{
-  LONG exstyle;
-  typedef BOOL (WINAPI *PFN_SetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
-  PFN_SetLayeredWindowAttributes setLayeredWindowAttributes = NULL;
-  GdkSurfaceImplWin32 *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (!WINDOW_IS_TOPLEVEL (window) || GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (opacity < 0)
-    opacity = 0;
-  else if (opacity > 1)
-    opacity = 1;
-
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  if (impl->layered)
-    {
-      if (impl->layered_opacity != opacity)
-        {
-          RECT window_rect;
-
-          impl->layered_opacity = opacity;
-
-          gdk_win32_get_window_client_area_rect (window, impl->window_scale, &window_rect);
-          gdk_win32_update_layered_window_from_cache (window, &window_rect);
-        }
-
-      return;
-    }
-
-  exstyle = GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE);
-
-  if (!(exstyle & WS_EX_LAYERED))
-    SetWindowLong (GDK_SURFACE_HWND (window),
-                   GWL_EXSTYLE,
-                   exstyle | WS_EX_LAYERED);
-
-  setLayeredWindowAttributes =
-    (PFN_SetLayeredWindowAttributes)GetProcAddress (GetModuleHandle ("user32.dll"), "SetLayeredWindowAttributes");
-
-  if (setLayeredWindowAttributes)
-    {
-      API_CALL (setLayeredWindowAttributes, (GDK_SURFACE_HWND (window),
-                                            0,
-                                            opacity * 0xff,
-                                            LWA_ALPHA));
-    }
-}
-
-gboolean
-gdk_win32_surface_is_win32 (GdkSurface *window)
-{
-  return GDK_SURFACE_IS_WIN32 (window);
-}
-
-static gboolean
-gdk_win32_surface_show_window_menu (GdkSurface *window,
-                                   GdkEvent  *event)
-{
-  double event_x, event_y;
-  gint x, y;
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  switch (event->type)
-    {
-    case GDK_BUTTON_PRESS:
-    case GDK_BUTTON_RELEASE:
-    case GDK_TOUCH_BEGIN:
-    case GDK_TOUCH_END:
-      break;
-    default:
-      return FALSE;
-    }
-
-  gdk_event_get_root_coords (event, &event_x, &event_y);
-  x = event_x - _gdk_offset_x;
-  y = event_y - _gdk_offset_y;
-
-  SendMessage (GDK_SURFACE_HWND (window),
-               WM_SYSMENU,
-               0,
-               MAKELPARAM (x * impl->window_scale, y * impl->window_scale));
-
-  return TRUE;
-}
-
-/**
- * _gdk_win32_acquire_dc
- * @impl: a Win32 #GdkSurfaceImplWin32 implementation
- *
- * Gets a DC with the given drawable selected into it.
- *
- * Returns: The DC, on success. Otherwise
- *  %NULL. If this function succeeded
- *  _gdk_win32_impl_release_dc()  must be called
- *  release the DC when you are done using it.
- **/
-static HDC
-_gdk_win32_impl_acquire_dc (GdkSurfaceImplWin32 *impl)
-{
-  if (GDK_IS_SURFACE_IMPL_WIN32 (impl) &&
-      GDK_SURFACE_DESTROYED (impl->wrapper))
-    return NULL;
-
-  /* We don't call this function for layered windows, but
-   * in case we do...
-   */
-  if (impl->layered)
-    return NULL;
-
-  if (!impl->hdc)
-    {
-      impl->hdc = GetDC (impl->handle);
-      if (!impl->hdc)
-       WIN32_GDI_FAILED ("GetDC");
-    }
-
-  if (impl->hdc)
-    {
-      impl->hdc_count++;
-      return impl->hdc;
-    }
-  else
-    {
-      return NULL;
-    }
-}
-
-/**
- * _gdk_win32_impl_release_dc
- * @impl: a Win32 #GdkSurfaceImplWin32 implementation
- *
- * Releases the reference count for the DC
- * from _gdk_win32_impl_acquire_dc()
- **/
-static void
-_gdk_win32_impl_release_dc (GdkSurfaceImplWin32 *impl)
-{
-  if (impl->layered)
-    return;
-
-  g_return_if_fail (impl->hdc_count > 0);
-
-  impl->hdc_count--;
-  if (impl->hdc_count == 0)
-    {
-      if (impl->saved_dc_bitmap)
-       {
-         GDI_CALL (SelectObject, (impl->hdc, impl->saved_dc_bitmap));
-         impl->saved_dc_bitmap = NULL;
-       }
-
-      if (impl->hdc)
-       {
-         GDI_CALL (ReleaseDC, (impl->handle, impl->hdc));
-         impl->hdc = NULL;
-       }
-    }
-}
-
-HWND
-gdk_win32_surface_get_impl_hwnd (GdkSurface *window)
-{
-  if (GDK_SURFACE_IS_WIN32 (window))
-    return GDK_SURFACE_HWND (window);
-  return NULL;
-}
-
-static void
-gdk_win32_cairo_surface_destroy (void *data)
-{
-  GdkSurfaceImplWin32 *impl = data;
-
-  _gdk_win32_impl_release_dc (impl);
-  impl->cairo_surface = NULL;
-}
-
-static cairo_surface_t *
-gdk_win32_ref_cairo_surface_layered (GdkSurface          *window,
-                                     GdkSurfaceImplWin32 *impl)
-{
-  gint width, height;
-  RECT window_rect;
-
-  gdk_win32_get_window_client_area_rect (window, impl->window_scale, &window_rect);
-
-  /* Turn client area into window area */
-  _gdk_win32_adjust_client_rect (window, &window_rect);
-
-  width = window_rect.right - window_rect.left;
-  height = window_rect.bottom - window_rect.top;
-
-  if (width > impl->dib_width ||
-      height > impl->dib_height)
-    {
-      cairo_surface_t *new_cache;
-      cairo_t *cr;
-
-      /* Create larger cache surface, copy old cache surface over it */
-      new_cache = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
-                                                       width,
-                                                       height);
-
-      if (impl->cache_surface)
-        {
-          cr = cairo_create (new_cache);
-          cairo_set_source_surface (cr, impl->cache_surface, 0, 0);
-          cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-          cairo_paint (cr);
-          cairo_destroy (cr);
-          cairo_surface_flush (new_cache);
-
-          cairo_surface_destroy (impl->cache_surface);
-        }
-
-      impl->cache_surface = new_cache;
-
-      cairo_surface_set_device_scale (impl->cache_surface,
-                                      impl->window_scale,
-                                      impl->window_scale);
-
-      if (impl->cairo_surface)
-        cairo_surface_destroy (impl->cairo_surface);
-
-      impl->cairo_surface = NULL;
-    }
-
-  /* This is separate, because cairo_surface gets killed
-   * off frequently by outside code, whereas cache_surface
-   * is only killed by us, above.
-   */
-  if (!impl->cairo_surface)
-    {
-      impl->cairo_surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
-                                                                 width,
-                                                                 height);
-      impl->dib_width = width;
-      impl->dib_height = height;
-
-      cairo_surface_set_device_scale (impl->cairo_surface,
-                                      impl->window_scale,
-                                      impl->window_scale);
-
-      cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
-                                  impl, gdk_win32_cairo_surface_destroy);
-    }
-  else
-    {
-      cairo_surface_reference (impl->cairo_surface);
-    }
-
-  return impl->cairo_surface;
-}
-
-static cairo_surface_t *
-gdk_win32_ref_cairo_surface (GdkSurface *window)
-{
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  if (GDK_IS_SURFACE_IMPL_WIN32 (impl) &&
-      GDK_SURFACE_DESTROYED (impl->wrapper))
-    return NULL;
-
-  if (impl->layered)
-    return gdk_win32_ref_cairo_surface_layered (window, impl);
-
-  if (!impl->cairo_surface)
-    {
-      HDC hdc = _gdk_win32_impl_acquire_dc (impl);
-      if (!hdc)
-       return NULL;
-
-      impl->cairo_surface = cairo_win32_surface_create_with_format (hdc, CAIRO_FORMAT_ARGB32);
-      cairo_surface_set_device_scale (impl->cairo_surface,
-                                      impl->window_scale,
-                                      impl->window_scale);
-
-      cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
-                                  impl, gdk_win32_cairo_surface_destroy);
-    }
-  else
-    cairo_surface_reference (impl->cairo_surface);
-
-  return impl->cairo_surface;
-}
-
-BOOL WINAPI
-GtkShowWindow (GdkSurface *window,
-               int        cmd_show)
-{
-  cairo_t *cr;
-  cairo_surface_t *surface;
-  RECT window_rect;
-  HDC hdc;
-  POINT window_position;
-  SIZE window_size;
-  POINT source_point;
-  BLENDFUNCTION blender;
-
-  HWND hwnd = GDK_SURFACE_HWND (window);
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  switch (cmd_show)
-    {
-    case SW_FORCEMINIMIZE:
-    case SW_HIDE:
-    case SW_MINIMIZE:
-      break;
-    case SW_MAXIMIZE:
-    case SW_RESTORE:
-    case SW_SHOW:
-    case SW_SHOWDEFAULT:
-    case SW_SHOWMINIMIZED:
-    case SW_SHOWMINNOACTIVE:
-    case SW_SHOWNA:
-    case SW_SHOWNOACTIVATE:
-    case SW_SHOWNORMAL:
-      if (IsWindowVisible (hwnd))
-        break;
-
-      if ((WS_EX_LAYERED & GetWindowLongPtr (hwnd, GWL_EXSTYLE)) != WS_EX_LAYERED)
-        break;
-
-      /* Window was hidden, will be shown. Erase it, GDK will repaint soon,
-       * but not soon enough, so it's possible to see old content before
-       * the next redraw, unless we erase the window first.
-       */
-      GetWindowRect (hwnd, &window_rect);
-      source_point.x = source_point.y = 0;
-
-      window_position.x = window_rect.left;
-      window_position.y = window_rect.top;
-      window_size.cx = window_rect.right - window_rect.left;
-      window_size.cy = window_rect.bottom - window_rect.top;
-
-      blender.BlendOp = AC_SRC_OVER;
-      blender.BlendFlags = 0;
-      blender.AlphaFormat = AC_SRC_ALPHA;
-      blender.SourceConstantAlpha = 255;
-
-      /* Create a surface of appropriate size and clear it */
-      surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
-                                                     window_size.cx,
-                                                     window_size.cy);
-      cairo_surface_set_device_scale (surface, impl->window_scale, impl->window_scale);
-      cr = cairo_create (surface);
-      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-      cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
-      cairo_paint (cr);
-      cairo_destroy (cr);
-      cairo_surface_flush (surface);
-      hdc = cairo_win32_surface_get_dc (surface);
-
-      /* No API_CALL() wrapper, don't check for errors */
-      UpdateLayeredWindow (hwnd, NULL,
-                           &window_position, &window_size,
-                           hdc, &source_point,
-                           0, &blender, ULW_ALPHA);
-
-      cairo_surface_destroy (surface);
-
-      break;
-    }
-
-  /* Ensure that maximized window size is corrected later on */
-  if (cmd_show == SW_MAXIMIZE)
-    impl->maximizing = TRUE;
-
-  return ShowWindow (hwnd, cmd_show);
-}
-
-static void
-gdk_win32_surface_set_shadow_width (GdkSurface *window,
-                                   gint       left,
-                                   gint       right,
-                                   gint       top,
-                                   gint       bottom)
-{
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  GDK_NOTE (MISC, g_print ("gdk_win32_surface_set_shadow_width: window %p, "
-                           "left %d, top %d, right %d, bottom %d\n",
-                           window, left, top, right, bottom));
-
-  impl->zero_margins = left == 0 && right == 0 && top == 0 && bottom == 0;
-
-  if (impl->zero_margins)
-    return;
-
-  impl->margins.left = left;
-  impl->margins.right = right * impl->window_scale;
-  impl->margins.top = top;
-  impl->margins.bottom = bottom * impl->window_scale;
-  impl->margins_x = left + right;
-  impl->margins_y = top + bottom;
-}
-
-
-gint
-_gdk_win32_surface_get_scale_factor (GdkSurface *window)
-{
-  GdkDisplay *display;
-  GdkSurfaceImplWin32 *impl;
-
-  GdkWin32Display *win32_display;
-  UINT dpix, dpiy;
-  gboolean is_scale_acquired;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return 1;
-
-  g_return_val_if_fail (window != NULL, 1);
-
-  display = gdk_surface_get_display (window);
-  impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  win32_display = GDK_WIN32_DISPLAY (display);
-
-  if (win32_display->dpi_aware_type != PROCESS_DPI_UNAWARE)
-    {
-      if (win32_display->has_fixed_scale)
-        impl->window_scale = win32_display->window_scale;
-      else
-        impl->window_scale = _gdk_win32_display_get_monitor_scale_factor (win32_display,
-                                                                          NULL,
-                                                                          GDK_SURFACE_HWND (window),
-                                                                          NULL);
-
-      return impl->window_scale;
-    }
-  else
-    {
-      if (win32_display->has_fixed_scale)
-        {
-          static gsize hidpi_msg_displayed = 0;
-
-          if (g_once_init_enter (&hidpi_msg_displayed))
-            {
-              g_message ("Note: GDK_SCALE is ignored as HiDPI awareness is disabled.");
-              g_once_init_leave (&hidpi_msg_displayed, 1);
-            }
-        }
-
-      /* Application is not DPI aware, don't bother */
-      return 1;
-    }
-}
-
-void
-_gdk_win32_surface_get_unscaled_size (GdkSurface *window,
-                                    gint      *unscaled_width,
-                                    gint      *unscaled_height)
-{
-  GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
-
-  if (unscaled_width)
-    *unscaled_width = impl->unscaled_width;
-  if (unscaled_height)
-    *unscaled_height = impl->unscaled_height;
-}
-
-static void
-gdk_win32_input_shape_combine_region (GdkSurface            *window,
-                                      const cairo_region_t *shape_region,
-                                      gint                  offset_x,
-                                      gint                  offset_y)
-{
-  /* Partial input shape support is implemented by handling the
-   * NC_NCHITTEST message
-   */
-}
-
-static void
-gdk_surface_impl_win32_class_init (GdkSurfaceImplWin32Class *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_CLASS (klass);
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  object_class->finalize = gdk_surface_impl_win32_finalize;
-
-  impl_class->ref_cairo_surface = gdk_win32_ref_cairo_surface;
-
-  impl_class->show = gdk_win32_surface_show;
-  impl_class->hide = gdk_win32_surface_hide;
-  impl_class->withdraw = gdk_win32_surface_withdraw;
-  impl_class->set_events = gdk_win32_surface_set_events;
-  impl_class->get_events = gdk_win32_surface_get_events;
-  impl_class->raise = gdk_win32_surface_raise;
-  impl_class->lower = gdk_win32_surface_lower;
-  impl_class->restack_toplevel = gdk_win32_surface_restack_toplevel;
-  impl_class->move_resize = gdk_win32_surface_move_resize;
-  impl_class->get_geometry = gdk_win32_surface_get_geometry;
-  impl_class->get_device_state = gdk_surface_win32_get_device_state;
-  impl_class->get_root_coords = gdk_win32_surface_get_root_coords;
-
-  impl_class->shape_combine_region = gdk_win32_surface_shape_combine_region;
-  impl_class->input_shape_combine_region = gdk_win32_input_shape_combine_region;
-  impl_class->destroy = gdk_win32_surface_destroy;
-  impl_class->begin_paint = gdk_win32_surface_begin_paint;
-  impl_class->end_paint = gdk_win32_surface_end_paint;
-
-  //impl_class->beep = gdk_x11_surface_beep;
-
-
-  impl_class->show_window_menu = gdk_win32_surface_show_window_menu;
-  impl_class->focus = gdk_win32_surface_focus;
-  impl_class->set_type_hint = gdk_win32_surface_set_type_hint;
-  impl_class->get_type_hint = gdk_win32_surface_get_type_hint;
-  impl_class->set_modal_hint = gdk_win32_surface_set_modal_hint;
-  impl_class->set_skip_taskbar_hint = gdk_win32_surface_set_skip_taskbar_hint;
-  impl_class->set_skip_pager_hint = gdk_win32_surface_set_skip_pager_hint;
-  impl_class->set_urgency_hint = gdk_win32_surface_set_urgency_hint;
-  impl_class->set_geometry_hints = gdk_win32_surface_set_geometry_hints;
-  impl_class->set_title = gdk_win32_surface_set_title;
-  impl_class->set_role = gdk_win32_surface_set_role;
-  //impl_class->set_startup_id = gdk_x11_surface_set_startup_id;
-  impl_class->set_transient_for = gdk_win32_surface_set_transient_for;
-  impl_class->get_frame_extents = gdk_win32_surface_get_frame_extents;
-  impl_class->set_accept_focus = gdk_win32_surface_set_accept_focus;
-  impl_class->set_focus_on_map = gdk_win32_surface_set_focus_on_map;
-  impl_class->set_icon_list = gdk_win32_surface_set_icon_list;
-  impl_class->set_icon_name = gdk_win32_surface_set_icon_name;
-  impl_class->iconify = gdk_win32_surface_iconify;
-  impl_class->deiconify = gdk_win32_surface_deiconify;
-  impl_class->stick = gdk_win32_surface_stick;
-  impl_class->unstick = gdk_win32_surface_unstick;
-  impl_class->maximize = gdk_win32_surface_maximize;
-  impl_class->unmaximize = gdk_win32_surface_unmaximize;
-  impl_class->fullscreen = gdk_win32_surface_fullscreen;
-  impl_class->unfullscreen = gdk_win32_surface_unfullscreen;
-  impl_class->set_keep_above = gdk_win32_surface_set_keep_above;
-  impl_class->set_keep_below = gdk_win32_surface_set_keep_below;
-  impl_class->get_group = gdk_win32_surface_get_group;
-  impl_class->set_group = gdk_win32_surface_set_group;
-  impl_class->set_decorations = gdk_win32_surface_set_decorations;
-  impl_class->get_decorations = gdk_win32_surface_get_decorations;
-  impl_class->set_functions = gdk_win32_surface_set_functions;
-
-  impl_class->set_shadow_width = gdk_win32_surface_set_shadow_width;
-  impl_class->begin_resize_drag = gdk_win32_surface_begin_resize_drag;
-  impl_class->begin_move_drag = gdk_win32_surface_begin_move_drag;
-  impl_class->set_opacity = gdk_win32_surface_set_opacity;
-  impl_class->destroy_notify = gdk_win32_surface_destroy_notify;
-  impl_class->register_dnd = _gdk_win32_surface_register_dnd;
-  impl_class->drag_begin = _gdk_win32_surface_drag_begin;
-  impl_class->create_gl_context = _gdk_win32_surface_create_gl_context;
-  impl_class->get_scale_factor = _gdk_win32_surface_get_scale_factor;
-  impl_class->get_unscaled_size = _gdk_win32_surface_get_unscaled_size;
-}
-
-HGDIOBJ
-gdk_win32_surface_get_handle (GdkSurface *window)
-{
-  if (!GDK_SURFACE_IS_WIN32 (window))
-    {
-      g_warning (G_STRLOC " window is not a native Win32 window");
-      return NULL;
-    }
-
-  return GDK_SURFACE_HWND (window);
-}
diff --git a/gdk/win32/gdkwindow-win32.h b/gdk/win32/gdkwindow-win32.h
deleted file mode 100644 (file)
index 4856287..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/* 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 Library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-#ifndef __GDK_SURFACE_WIN32_H__
-#define __GDK_SURFACE_WIN32_H__
-
-#include "gdk/win32/gdkprivate-win32.h"
-#include "gdk/gdkwindowimpl.h"
-#include "gdk/gdkcursor.h"
-
-#include <windows.h>
-
-G_BEGIN_DECLS
-
-/* Window implementation for Win32
- */
-
-typedef struct _GdkSurfaceImplWin32 GdkSurfaceImplWin32;
-typedef struct _GdkSurfaceImplWin32Class GdkSurfaceImplWin32Class;
-
-#define GDK_TYPE_SURFACE_IMPL_WIN32              (_gdk_surface_impl_win32_get_type ())
-#define GDK_SURFACE_IMPL_WIN32(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_WIN32, GdkSurfaceImplWin32))
-#define GDK_SURFACE_IMPL_WIN32_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_WIN32, GdkSurfaceImplWin32Class))
-#define GDK_IS_SURFACE_IMPL_WIN32(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_WIN32))
-#define GDK_IS_SURFACE_IMPL_WIN32_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_WIN32))
-#define GDK_SURFACE_IMPL_WIN32_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_WIN32, GdkSurfaceImplWin32Class))
-
-enum _GdkWin32AeroSnapCombo
-{
-  GDK_WIN32_AEROSNAP_COMBO_NOTHING = 0,
-  GDK_WIN32_AEROSNAP_COMBO_UP,
-  GDK_WIN32_AEROSNAP_COMBO_DOWN,
-  GDK_WIN32_AEROSNAP_COMBO_LEFT,
-  GDK_WIN32_AEROSNAP_COMBO_RIGHT,
-  /* Same order as non-shift variants. We use it to do things like:
-   * AEROSNAP_UP + 4 = AEROSNAP_SHIFTUP
-   */
-  GDK_WIN32_AEROSNAP_COMBO_SHIFTUP,
-  GDK_WIN32_AEROSNAP_COMBO_SHIFTDOWN,
-  GDK_WIN32_AEROSNAP_COMBO_SHIFTLEFT,
-  GDK_WIN32_AEROSNAP_COMBO_SHIFTRIGHT
-};
-
-typedef enum _GdkWin32AeroSnapCombo GdkWin32AeroSnapCombo;
-
-enum _GdkWin32AeroSnapState
-{
-  GDK_WIN32_AEROSNAP_STATE_UNDETERMINED = 0,
-  GDK_WIN32_AEROSNAP_STATE_HALFLEFT,
-  GDK_WIN32_AEROSNAP_STATE_HALFRIGHT,
-  GDK_WIN32_AEROSNAP_STATE_FULLUP,
-  /* Maximize state is only used by edge-snap */
-  GDK_WIN32_AEROSNAP_STATE_MAXIMIZE
-};
-
-typedef enum _GdkWin32AeroSnapState GdkWin32AeroSnapState;
-
-struct _GdkRectangleDouble
-{
-  gdouble x;
-  gdouble y;
-  gdouble width;
-  gdouble height;
-};
-
-typedef struct _GdkRectangleDouble GdkRectangleDouble;
-
-enum _GdkW32WindowDragOp
-{
-  GDK_WIN32_DRAGOP_NONE = 0,
-  GDK_WIN32_DRAGOP_RESIZE,
-  GDK_WIN32_DRAGOP_MOVE,
-  GDK_WIN32_DRAGOP_COUNT
-};
-
-typedef enum _GdkW32WindowDragOp GdkW32WindowDragOp;
-
-typedef enum _GdkWin32MonitorDpiType
-{
-  MDT_EFFECTIVE_DPI  = 0,
-  MDT_ANGULAR_DPI    = 1,
-  MDT_RAW_DPI        = 2,
-  MDT_DEFAULT        = MDT_EFFECTIVE_DPI
-} GdkWin32MonitorDpiType;
-
-struct _GdkW32DragMoveResizeContext
-{
-  /* The window that is being moved/resized */
-  GdkSurface         *window;
-
-  /* The kind of drag-operation going on. */
-  GdkW32WindowDragOp op;
-
-  /* The edge that was grabbed for resizing. Not used for moving. */
-  GdkSurfaceEdge      edge;
-
-  /* The device used to initiate the op.
-   * We grab it at the beginning and ungrab it at the end.
-   */
-  GdkDevice         *device;
-
-  /* The button pressed down to initiate the op.
-   * The op will be canceled only when *this* button
-   * is released.
-   */
-  gint               button;
-
-  /* Initial cursor position when the operation began.
-   * Current cursor position is subtracted from it to find how far
-   * to move window border(s).
-   */
-  gint               start_root_x;
-  gint               start_root_y;
-
-  /* Initial window rectangle (position and size).
-   * The window is resized/moved relative to this (see start_root_*).
-   */
-  RECT               start_rect;
-
-  /* Not used */
-  guint32            timestamp;
-
-  /* TRUE if during the next redraw we should call SetWindowPos() to push
-   * the window size and poistion to the native window.
-   */
-  gboolean           native_move_resize_pending;
-
-  /* The cursor we should use while the operation is running. */
-  GdkCursor         *cursor;
-
-  /* This window looks like an outline and is drawn under the window
-   * that is being dragged. It indicates the shape the dragged window
-   * will take if released at a particular point.
-   * Indicator window size always matches the target indicator shape,
-   * the the actual indicator drawn on it might not, depending on
-   * how much time elapsed since the animation started.
-   */
-  HWND               shape_indicator;
-
-  /* Used to draw the indicator */
-  cairo_surface_t   *indicator_surface;
-  gint               indicator_surface_width;
-  gint               indicator_surface_height;
-
-  /* Size/position of shape_indicator */
-  GdkRectangle       indicator_window_rect;
-
-  /* Indicator will animate to occupy this rectangle */
-  GdkRectangle       indicator_target;
-
-  /* Indicator will start animating from this rectangle */
-  GdkRectangle       indicator_start;
-
-  /* Timestamp of the animation start */
-  gint64             indicator_start_time;
-
-  /* Timer that drives the animation */
-  guint              timer;
-
-  /* A special timestamp, if we want to draw not how
-   * the animation should look *now*, but how it should
-   * look at arbitrary moment of time.
-   * Set to 0 to tell GDK to use current time.
-   */
-  gint64             draw_timestamp;
-
-  /* Indicates that a transformation was revealed:
-   *
-   * For drag-resize: If it's FALSE,
-   * then the pointer have not yet hit a trigger that triggers fullup.
-   * If TRUE, then the pointer did hit a trigger that triggers fullup
-   * at some point during this drag op.
-   * This is used to prevent drag-resize from triggering
-   * a transformation when first approaching a trigger of the work area -
-   * one must drag it all the way to the very trigger to trigger; afterwards
-   * a transformation will start triggering at some distance from the trigger
-   * for as long as the op is still running. This is how AeroSnap works.
-   *
-   * For drag-move: If it's FALSE,
-   * then the pointer have not yet hit a trigger, even if it is
-   * already within a edge region.
-   * If it's TRUE, then the pointer did hit a trigger within an
-   * edge region, and have not yet left an edge region
-   * (passing from one edge region into another doesn't count).
-   */
-  gboolean           revealed;
-
-  /* Arrays of GdkRectangle pairs, describing the areas of the virtual
-   * desktop that trigger various AeroSnap window transofrmations
-   * Coordinates are GDK screen coordinates.
-   */
-  GArray            *halfleft_regions;
-  GArray            *halfright_regions;
-  GArray            *maximize_regions;
-  GArray            *fullup_regions;
-
-  /* Current pointer position will result in this kind of snapping,
-   * if the drag op is finished.
-   */
-  GdkWin32AeroSnapState current_snap;
-};
-
-typedef struct _GdkW32DragMoveResizeContext GdkW32DragMoveResizeContext;
-
-struct _GdkSurfaceImplWin32
-{
-  GdkSurfaceImpl parent_instance;
-
-  GdkSurface *wrapper;
-  HANDLE handle;
-
-  gint8 toplevel_window_type;
-
-  HICON   hicon_big;
-  HICON   hicon_small;
-
-  /* When VK_PACKET sends us a leading surrogate, it's stashed here.
-   * Later, when another VK_PACKET sends a tailing surrogate, we make up
-   * a full unicode character from them, or discard the leading surrogate,
-   * if the next key is not a tailing surrogate.
-   */
-  wchar_t leading_surrogate_keydown;
-  wchar_t leading_surrogate_keyup;
-
-  /* Window size hints */
-  gint hint_flags;
-  GdkGeometry hints;
-
-  GdkEventMask native_event_mask;
-
-  GdkSurfaceTypeHint type_hint;
-
-  GdkSurface *transient_owner;
-  GSList    *transient_children;
-  gint       num_transients;
-  gboolean   changing_state;
-
-  gint initial_x;
-  gint initial_y;
-
-  /* left/right/top/bottom width of the shadow/resize-grip around the window */
-  RECT margins;
-
-  /* left+right and top+bottom from @margins */
-  gint margins_x;
-  gint margins_y;
-
-  /* Set to TRUE when GTK tells us that margins are 0 everywhere.
-   * We don't actually set margins to 0, we just set this bit.
-   */
-  guint zero_margins : 1;
-  guint no_bg : 1;
-  guint inhibit_configure : 1;
-
-  /* Set to TRUE if window is using true layered mode adjustments
-   * via UpdateLayeredWindow().
-   * Layered windows that get SetLayeredWindowAttributes() called
-   * on them are not true layered windows.
-   */
-  guint layered : 1;
-
-  /* If TRUE, the @temp_styles is set to the styles that were temporarily
-   * added to this window.
-   */
-  guint have_temp_styles : 1;
-
-  /* If TRUE, the window is in the process of being maximized.
-   * This is set by WM_SYSCOMMAND and by gdk_win32_surface_maximize (),
-   * and is unset when WM_WINDOWPOSCHANGING is handled.
-   */
-  guint maximizing : 1;
-
-  /* GDK does not keep window contents around, it just draws new
-   * stuff over the window where changes occurred.
-   * cache_surface retains old window contents, because
-   * UpdateLayeredWindow() doesn't do partial redraws.
-   */
-  cairo_surface_t *cache_surface;
-  cairo_surface_t *cairo_surface;
-
-  /* Unlike window-backed surfaces, DIB-backed surface
-   * does not provide a way to query its size,
-   * so we have to remember it ourselves.
-   */
-  gint             dib_width;
-  gint             dib_height;
-
-  /* If the client wants uniformly-transparent window,
-   * we remember the opacity value here and apply it
-   * during UpdateLayredWindow() call, for layered windows.
-   */
-  gdouble          layered_opacity;
-
-  HDC              hdc;
-  int              hdc_count;
-  HBITMAP          saved_dc_bitmap; /* Original bitmap for dc */
-
-  GdkW32DragMoveResizeContext drag_move_resize_context;
-
-  /* Remembers where the window was snapped.
-   * Some snap operations change their meaning if
-   * the window is already snapped.
-   */
-  GdkWin32AeroSnapState snap_state;
-
-  /* Remembers window position before it was snapped.
-   * This is used to unsnap it.
-   * Position and size are percentages of the workarea
-   * of the monitor on which the window was before it was snapped.
-   */
-  GdkRectangleDouble *snap_stash;
-
-  /* Also remember the same position, but in absolute form. */
-  GdkRectangle *snap_stash_int;
-
-  /* Decorations set by gdk_surface_set_decorations() or NULL if unset */
-  GdkWMDecoration* decorations;
-
-  /* No. of windows to force layered windows off */
-  guint suppress_layered;
-
-  /* Temporary styles that this window got for the purpose of
-   * handling WM_SYSMENU.
-   * They are removed at the first opportunity (usually WM_INITMENU).
-   */
-  LONG_PTR temp_styles;
-
-  /* scale of window on HiDPI */
-  gint window_scale;
-  gint unscaled_width;
-  gint unscaled_height;
-};
-
-struct _GdkSurfaceImplWin32Class
-{
-  GdkSurfaceImplClass parent_class;
-};
-
-GType _gdk_surface_impl_win32_get_type (void);
-
-void  _gdk_win32_surface_tmp_unset_bg  (GdkSurface *window,
-                                      gboolean   recurse);
-void  _gdk_win32_surface_tmp_reset_bg  (GdkSurface *window,
-                                      gboolean   recurse);
-
-void  _gdk_win32_surface_tmp_unset_parent_bg (GdkSurface *window);
-void  _gdk_win32_surface_tmp_reset_parent_bg (GdkSurface *window);
-
-void  _gdk_win32_surface_update_style_bits   (GdkSurface *window);
-
-gint  _gdk_win32_surface_get_scale_factor    (GdkSurface *window);
-
-G_END_DECLS
-
-#endif /* __GDK_SURFACE_WIN32_H__ */
index c99f60981b0184a7fe0cf80cf1c64f1cf64cf2cf..d609ca8d0337c4b815686dff2098e321aab08125 100644 (file)
@@ -21,7 +21,7 @@ gdk_win32_sources = files([
   'gdkwin32cursor.h',
   'gdkwin32display.h',
   'gdkwin32id.c',
-  'gdkwindow-win32.c',
+  'gdksurface-win32.c',
 ])
 
 gdk_win32_public_headers = files([
@@ -34,7 +34,7 @@ gdk_win32_public_headers = files([
   'gdkwin32misc.h',
   'gdkwin32monitor.h',
   'gdkwin32screen.h',
-  'gdkwin32window.h',
+  'gdkwin32surface.h',
 ])
 
 install_headers(gdk_win32_public_headers, subdir: 'gtk-4.0/gdk/win32/')
index 6bbdda66938495930e33106c07e30bade259e804..055fa593ace0b5cdf334d55f6bee6d721e6bf18f 100644 (file)
@@ -22,7 +22,7 @@
 #include "gdkdeviceprivate.h"
 
 #include "gdkinternals.h"
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkprivate-x11.h"
 #include "gdkdisplay-x11.h"
 #include "gdkasync.h"
index ed08da2ff14dcc5cdec50d8bdf5a5518621daa6f..c4cc9e61b79fd3f92938f56b5a65c9424f55297a 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "gdkdisplayprivate.h"
 #include "gdkkeys.h"
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkinternals.h"
 #include "gdkx11devicemanager.h"
 #include "gdkx11display.h"
index 2a26669c1ac61a99bf427be6512ed8ed90ecae56..168e33cfb8c2eb29c7b9ce3fcde5960da891aae9 100644 (file)
@@ -20,7 +20,7 @@
 #include "gdkeventsource.h"
 
 #include "gdkinternals.h"
-#include "gdkwindow-x11.h"
+#include "gdksurface-x11.h"
 #include "gdkprivate-x11.h"
 #include "gdkdisplay-x11.h"
 #include "xsettings-client.h"
index 96c2ed99571d75dfc85734276debf28fc7734b6d..579c59ae23fa932c3a97fbed9455c8402338d1ef 100644 (file)
@@ -18,7 +18,7 @@
 #include "config.h"
 
 #include "gdkeventtranslator.h"
-#include "gdkwindow-x11.h"
+#include "gdksurface-x11.h"
 
 typedef GdkEventTranslatorIface GdkEventTranslatorInterface;
 G_DEFINE_INTERFACE (GdkEventTranslator, _gdk_x11_event_translator, G_TYPE_OBJECT);
index 208704c3603ef98f7ce3bbed89dfd688363f04a7..d75acffbd66af15eda6dc442130c787772e47de8 100644 (file)
@@ -22,7 +22,7 @@
 #include "gdkprivate-x11.h"
 #include "gdkscreen-x11.h"
 #include "gdkdisplay-x11.h"
-#include "gdkwindow-x11.h"
+#include "gdksurface-x11.h"
 
 
 typedef struct _GdkSurfaceQueueItem GdkSurfaceQueueItem;
index 682df01b39143c2557bf61674437fbb10affa169..0405d0588a6635cdcaf87c0fec5b523de2ba11ef 100644 (file)
@@ -28,7 +28,7 @@
 #include "gdkx11display.h"
 #include "gdkx11glcontext.h"
 #include "gdkx11screen.h"
-#include "gdkx11window.h"
+#include "gdkx11surface.h"
 #include "gdkvisual-x11.h"
 #include "gdkx11property.h"
 #include <X11/Xatom.h>
index 61dbadef1fb90739c0b8dd329fcea862df6466ec..89d1131fcce9d48c83153cd39ead55d731d5583e 100644 (file)
@@ -30,7 +30,7 @@
 #include "gdkglcontextprivate.h"
 #include "gdkdisplayprivate.h"
 #include "gdkvisual-x11.h"
-#include "gdkwindow.h"
+#include "gdksurface.h"
 #include "gdkinternals.h"
 
 G_BEGIN_DECLS
index 90d6ecaafe81349ceb9994e1a2a3717f8f436722..e784b1f1b760c6888cc61651979ee5ab27bb3bd2 100644 (file)
@@ -32,7 +32,7 @@
 #include "gdkcursor.h"
 #include "gdkinternals.h"
 #include "gdkx.h"
-#include "gdkwindow-x11.h"
+#include "gdksurface-x11.h"
 #include "gdkscreen-x11.h"
 
 #include <X11/Xlib.h>
index c3ae89534457c56edbe644a5f8829d80093bb105..55f83b497564ddd827f1275a6551d718c455b352 100644 (file)
@@ -27,7 +27,7 @@
 #include "gdkintl.h"
 #include "gdkx11display.h"
 #include "gdkx11property.h"
-#include "gdkx11window.h"
+#include "gdkx11surface.h"
 
 typedef struct GdkX11SelectionInputStreamPrivate  GdkX11SelectionInputStreamPrivate;
 
index 106c6b780c3332136b4161457d29ba94097b04f0..5f35cdf6be055fb5abb530db1926db174fdd6ecc 100644 (file)
@@ -29,7 +29,7 @@
 #include "gdktextlistconverter-x11.h"
 #include "gdkx11display.h"
 #include "gdkx11property.h"
-#include "gdkx11window.h"
+#include "gdkx11surface.h"
 
 typedef struct _GdkX11PendingSelectionNotify GdkX11PendingSelectionNotify;
 typedef struct _GdkX11SelectionOutputStreamPrivate  GdkX11SelectionOutputStreamPrivate;
diff --git a/gdk/x11/gdksurface-x11.c b/gdk/x11/gdksurface-x11.c
new file mode 100644 (file)
index 0000000..21f1d14
--- /dev/null
@@ -0,0 +1,4948 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
+ * Josh MacDonald, Ryan Lortie
+ *
+ * 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include "config.h"
+
+#include "gdksurface-x11.h"
+
+#include "gdksurface.h"
+#include "gdksurfaceimpl.h"
+#include "gdkvisual-x11.h"
+#include "gdkinternals.h"
+#include "gdkdeviceprivate.h"
+#include "gdkframeclockprivate.h"
+#include "gdkasync.h"
+#include "gdkeventsource.h"
+#include "gdkdisplay-x11.h"
+#include "gdkglcontext-x11.h"
+#include "gdkprivate-x11.h"
+#include "gdktextureprivate.h"
+#include "gdk-private.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+#include <cairo-xlib.h>
+
+#include "MwmUtil.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+#include <X11/extensions/shape.h>
+
+#ifdef HAVE_XKB
+#include <X11/XKBlib.h>
+#endif
+
+#ifdef HAVE_XCOMPOSITE
+#include <X11/extensions/Xcomposite.h>
+#endif
+
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+
+#ifdef HAVE_XDAMAGE
+#include <X11/extensions/Xdamage.h>
+#endif
+
+const int _gdk_x11_event_mask_table[21] =
+{
+  ExposureMask,
+  PointerMotionMask,
+  PointerMotionHintMask,
+  ButtonMotionMask,
+  Button1MotionMask,
+  Button2MotionMask,
+  Button3MotionMask,
+  ButtonPressMask,
+  ButtonReleaseMask,
+  KeyPressMask,
+  KeyReleaseMask,
+  EnterWindowMask,
+  LeaveWindowMask,
+  FocusChangeMask,
+  StructureNotifyMask,
+  PropertyChangeMask,
+  VisibilityChangeMask,
+  0,                    /* PROXIMITY_IN */
+  0,                    /* PROXIMTY_OUT */
+  SubstructureNotifyMask,
+  ButtonPressMask      /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
+};
+
+const gint _gdk_x11_event_mask_table_size = G_N_ELEMENTS (_gdk_x11_event_mask_table);
+
+/* Forward declarations */
+static void     gdk_x11_surface_apply_fullscreen_mode (GdkSurface  *window);
+static gboolean gdk_surface_icon_name_set          (GdkSurface  *window);
+static void     set_wm_name                       (GdkDisplay  *display,
+                                                  Window       xwindow,
+                                                  const gchar *name);
+static void     move_to_current_desktop           (GdkSurface *window);
+
+static void        gdk_surface_impl_x11_finalize   (GObject            *object);
+
+#define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window)           \
+  (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL ||   \
+   GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP ||       \
+   GDK_SURFACE_TYPE (window) == GDK_SURFACE_FOREIGN)
+
+#define WINDOW_IS_TOPLEVEL(window)                      \
+  (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL ||   \
+   GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP)
+
+/* Return whether time1 is considered later than time2 as far as xserver
+ * time is concerned.  Accounts for wraparound.
+ */
+#define XSERVER_TIME_IS_LATER(time1, time2)                        \
+  ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
+    (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
+  )
+
+struct _GdkX11Surface {
+  GdkSurface parent;
+};
+
+struct _GdkX11SurfaceClass {
+  GdkSurfaceClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkX11Surface, gdk_x11_surface, GDK_TYPE_SURFACE)
+
+static void
+gdk_x11_surface_class_init (GdkX11SurfaceClass *x11_surface_class)
+{
+}
+
+static void
+gdk_x11_surface_init (GdkX11Surface *x11_surface)
+{
+}
+
+
+G_DEFINE_TYPE (GdkSurfaceImplX11, gdk_surface_impl_x11, GDK_TYPE_SURFACE_IMPL)
+
+static void
+gdk_surface_impl_x11_init (GdkSurfaceImplX11 *impl)
+{  
+  impl->window_scale = 1;
+  impl->frame_sync_enabled = TRUE;
+}
+
+GdkToplevelX11 *
+_gdk_x11_surface_get_toplevel (GdkSurface *window)
+{
+  GdkSurfaceImplX11 *impl;
+  
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return NULL;
+
+  impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (!impl->toplevel)
+    {
+      impl->toplevel = g_new0 (GdkToplevelX11, 1);
+      impl->toplevel->have_focused = FALSE;
+    }
+
+  return impl->toplevel;
+}
+
+/**
+ * _gdk_x11_surface_update_size:
+ * @impl: a #GdkSurfaceImplX11.
+ * 
+ * Updates the state of the window (in particular the drawable's
+ * cairo surface) when its size has changed.
+ **/
+void
+_gdk_x11_surface_update_size (GdkSurfaceImplX11 *impl)
+{
+  if (impl->cairo_surface)
+    {
+      cairo_xlib_surface_set_size (impl->cairo_surface,
+                                   impl->unscaled_width, impl->unscaled_height);
+    }
+}
+
+static void
+gdk_x11_surface_get_unscaled_size (GdkSurface *window,
+                                  int *unscaled_width,
+                                  int *unscaled_height)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (unscaled_width)
+    *unscaled_width = impl->unscaled_width;
+
+  if (unscaled_height)
+    *unscaled_height = impl->unscaled_height;
+}
+
+static gboolean
+gdk_x11_surface_supports_edge_constraints (GdkSurface *window)
+{
+  return gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
+                                              g_intern_static_string ("_GTK_EDGE_CONSTRAINTS"));
+}
+
+static void
+set_sync_counter(Display     *display,
+                XSyncCounter counter,
+                 gint64       value)
+{
+    XSyncValue sync_value;
+
+    XSyncIntsToValue (&sync_value,
+                      value & G_GINT64_CONSTANT(0xFFFFFFFF),
+                      value >> 32);
+    XSyncSetCounter (display, counter, sync_value);
+}
+
+static void
+window_pre_damage (GdkSurface *window)
+{
+  GdkSurface *toplevel_window = gdk_surface_get_toplevel (window);
+  GdkSurfaceImplX11 *impl;
+
+  if (!toplevel_window || !WINDOW_IS_TOPLEVEL (toplevel_window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_X11 (toplevel_window->impl);
+
+  if (impl->toplevel->in_frame &&
+      impl->toplevel->current_counter_value % 2 == 0)
+    {
+      impl->toplevel->current_counter_value += 1;
+      set_sync_counter (GDK_SURFACE_XDISPLAY (impl->wrapper),
+                       impl->toplevel->extended_update_counter,
+                        impl->toplevel->current_counter_value);
+    }
+}
+
+static void
+on_surface_changed (void *data)
+{
+  GdkSurface *window = data;
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (impl->tracking_damage)
+    window_pre_damage (window);
+}
+
+/* We want to know when cairo drawing causes damage to the window,
+ * so we engage in the _NET_WM_FRAME_DRAWN protocol with the
+ * window only when there actually is drawing. To do that we use
+ * a technique (hack) suggested by Uli Schlachter - if we set
+ * a dummy "mime data" on the cairo surface (this facility is
+ * used to attach JPEG data to an imager), then cairo wil flush
+ * and remove the mime data before making any changes to the window.
+ */
+
+static void
+hook_surface_changed (GdkSurface *window)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (impl->cairo_surface)
+    {
+      cairo_surface_set_mime_data (impl->cairo_surface,
+                                   "x-gdk/change-notify",
+                                   (unsigned char *)"X",
+                                   1,
+                                   on_surface_changed,
+                                   window);
+      impl->tracking_damage = 1;
+    }
+}
+
+static void
+unhook_surface_changed (GdkSurface *window)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (impl->cairo_surface)
+    {
+      impl->tracking_damage = 0;
+      cairo_surface_set_mime_data (impl->cairo_surface,
+                                   "x-gdk/change-notify",
+                                   NULL, 0,
+                                   NULL, NULL);
+    }
+}
+
+static void
+gdk_x11_surface_predict_presentation_time (GdkSurface *window)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+  GdkFrameClock *clock;
+  GdkFrameTimings *timings;
+  gint64 presentation_time;
+  gint64 refresh_interval;
+
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  clock = gdk_surface_get_frame_clock (window);
+
+  timings = gdk_frame_clock_get_current_timings (clock);
+
+  gdk_frame_clock_get_refresh_info (clock,
+                                    timings->frame_time,
+                                    &refresh_interval, &presentation_time);
+
+  if (presentation_time != 0)
+    {
+      if (timings->slept_before)
+        {
+          presentation_time += refresh_interval;
+        }
+      else
+        {
+          if (presentation_time < timings->frame_time + refresh_interval / 2)
+            presentation_time += refresh_interval;
+        }
+    }
+  else
+    {
+      if (timings->slept_before)
+        presentation_time = timings->frame_time + refresh_interval + refresh_interval / 2;
+      else
+        presentation_time = timings->frame_time + refresh_interval;
+    }
+
+  if (presentation_time < impl->toplevel->throttled_presentation_time)
+    presentation_time = impl->toplevel->throttled_presentation_time;
+
+  timings->predicted_presentation_time = presentation_time;
+}
+
+static void
+gdk_x11_surface_begin_frame (GdkSurface *window,
+                            gboolean   force_frame)
+{
+  GdkSurfaceImplX11 *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (!WINDOW_IS_TOPLEVEL (window) ||
+      impl->toplevel->extended_update_counter == None)
+    return;
+
+  impl->toplevel->in_frame = TRUE;
+
+  if (impl->toplevel->configure_counter_value != 0 &&
+      impl->toplevel->configure_counter_value_is_extended)
+    {
+      impl->toplevel->current_counter_value = impl->toplevel->configure_counter_value;
+      if ((impl->toplevel->current_counter_value % 2) == 1)
+        impl->toplevel->current_counter_value += 1;
+
+      impl->toplevel->configure_counter_value = 0;
+
+      window_pre_damage (window);
+    }
+  else if (force_frame)
+    {
+      /* When mapping the window, we really want to freeze the
+         rendering of the window by the compositor until we've
+         actually painted something into the window's buffer. */
+      window_pre_damage (window);
+    }
+  else
+    {
+      hook_surface_changed (window);
+    }
+}
+
+static void
+gdk_x11_surface_end_frame (GdkSurface *window)
+{
+  GdkFrameClock *clock;
+  GdkFrameTimings *timings;
+  GdkSurfaceImplX11 *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (!WINDOW_IS_TOPLEVEL (window) ||
+      impl->toplevel->extended_update_counter == None ||
+      !impl->toplevel->in_frame)
+    return;
+
+  clock = gdk_surface_get_frame_clock (window);
+  timings = gdk_frame_clock_get_current_timings (clock);
+
+  impl->toplevel->in_frame = FALSE;
+
+  if (impl->toplevel->current_counter_value % 2 == 1)
+    {
+      if (GDK_DISPLAY_DEBUG_CHECK (gdk_surface_get_display (window), FRAMES))
+        {
+          XImage *image = XGetImage (GDK_SURFACE_XDISPLAY (window),
+                                     GDK_SURFACE_XID (window),
+                                     0, 0, 1, 1,
+                                     (1 << 24) - 1,
+                                     ZPixmap);
+          XDestroyImage (image);
+        }
+
+      /* An increment of 3 means that the frame was not drawn as fast as possible,
+       * but rather at a particular time. This can trigger different handling from
+       * the compositor.
+       */
+      if (timings->slept_before)
+        impl->toplevel->current_counter_value += 3;
+      else
+        impl->toplevel->current_counter_value += 1;
+
+      set_sync_counter(GDK_SURFACE_XDISPLAY (impl->wrapper),
+                      impl->toplevel->extended_update_counter,
+                      impl->toplevel->current_counter_value);
+
+      if (impl->frame_sync_enabled &&
+          gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
+                                              g_intern_static_string ("_NET_WM_FRAME_DRAWN")))
+        {
+          impl->toplevel->frame_pending = TRUE;
+          _gdk_frame_clock_freeze (gdk_surface_get_frame_clock (window));
+          timings->cookie = impl->toplevel->current_counter_value;
+        }
+    }
+
+  unhook_surface_changed (window);
+
+  if (impl->toplevel->configure_counter_value != 0 &&
+      !impl->toplevel->configure_counter_value_is_extended)
+    {
+      set_sync_counter (GDK_SURFACE_XDISPLAY (window),
+                        impl->toplevel->update_counter,
+                        impl->toplevel->configure_counter_value);
+
+      impl->toplevel->configure_counter_value = 0;
+    }
+
+  if (!impl->toplevel->frame_pending)
+    timings->complete = TRUE;
+}
+
+/*****************************************************
+ * X11 specific implementations of generic functions *
+ *****************************************************/
+
+static cairo_surface_t *
+gdk_x11_create_cairo_surface (GdkSurfaceImplX11 *impl,
+                             int width,
+                             int height)
+{
+  Visual *visual;
+    
+  visual = gdk_x11_display_get_window_visual (GDK_X11_DISPLAY (gdk_surface_get_display (impl->wrapper)));
+  return cairo_xlib_surface_create (GDK_SURFACE_XDISPLAY (impl->wrapper),
+                                    GDK_SURFACE_IMPL_X11 (impl)->xid,
+                                    visual,
+                                    width, height);
+}
+
+static cairo_surface_t *
+gdk_x11_ref_cairo_surface (GdkSurface *window)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return NULL;
+
+  if (!impl->cairo_surface)
+    {
+      impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
+                                                          gdk_surface_get_width (window) * impl->window_scale,
+                                                          gdk_surface_get_height (window) * impl->window_scale);
+      cairo_surface_set_device_scale (impl->cairo_surface, impl->window_scale, impl->window_scale);
+
+      if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel->in_frame)
+        hook_surface_changed (window);
+    }
+
+  cairo_surface_reference (impl->cairo_surface);
+
+  return impl->cairo_surface;
+}
+
+static void
+gdk_surface_impl_x11_finalize (GObject *object)
+{
+  GdkSurface *wrapper;
+  GdkSurfaceImplX11 *impl;
+
+  g_return_if_fail (GDK_IS_SURFACE_IMPL_X11 (object));
+
+  impl = GDK_SURFACE_IMPL_X11 (object);
+
+  wrapper = impl->wrapper;
+
+  if (WINDOW_IS_TOPLEVEL (wrapper) && impl->toplevel->in_frame)
+    unhook_surface_changed (wrapper);
+
+  _gdk_x11_surface_grab_check_destroy (wrapper);
+
+  if (!GDK_SURFACE_DESTROYED (wrapper))
+    {
+      GdkDisplay *display = GDK_SURFACE_DISPLAY (wrapper);
+
+      _gdk_x11_display_remove_window (display, impl->xid);
+      if (impl->toplevel && impl->toplevel->focus_window)
+        _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
+    }
+
+  g_free (impl->toplevel);
+
+  if (impl->cursor)
+    g_object_unref (impl->cursor);
+
+  G_OBJECT_CLASS (gdk_surface_impl_x11_parent_class)->finalize (object);
+}
+
+typedef struct {
+  GdkDisplay *display;
+  Pixmap pixmap;
+} FreePixmapData;
+
+static void
+free_pixmap (gpointer datap)
+{
+  FreePixmapData *data = datap;
+
+  if (!gdk_display_is_closed (data->display))
+    {
+      XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display),
+                   data->pixmap);
+    }
+
+  g_object_unref (data->display);
+  g_slice_free (FreePixmapData, data);
+}
+
+static void
+attach_free_pixmap_handler (cairo_surface_t *surface,
+                            GdkDisplay      *display,
+                            Pixmap           pixmap)
+{
+  static const cairo_user_data_key_t key;
+  FreePixmapData *data;
+  
+  data = g_slice_new (FreePixmapData);
+  data->display = g_object_ref (display);
+  data->pixmap = pixmap;
+
+  cairo_surface_set_user_data (surface, &key, data, free_pixmap);
+}
+
+/* Cairo does not guarantee we get an xlib surface if we call
+ * cairo_surface_create_similar(). In some cases however, we must use a
+ * pixmap or bitmap in the X11 API.
+ * These functions ensure an Xlib surface.
+ */
+cairo_surface_t *
+_gdk_x11_display_create_bitmap_surface (GdkDisplay *display,
+                                        int         width,
+                                        int         height)
+{
+  cairo_surface_t *surface;
+  Pixmap pixmap;
+
+  pixmap = XCreatePixmap (GDK_DISPLAY_XDISPLAY (display),
+                          GDK_SCREEN_XROOTWIN (GDK_X11_DISPLAY (display)->screen),
+                          width, height, 1);
+  surface = cairo_xlib_surface_create_for_bitmap (GDK_DISPLAY_XDISPLAY (display),
+                                                  pixmap,
+                                                  GDK_X11_SCREEN (GDK_X11_DISPLAY (display)->screen)->xscreen,
+                                                  width, height);
+  attach_free_pixmap_handler (surface, display, pixmap);
+
+  return surface;
+}
+
+/* Create a surface backed with a pixmap without alpha on the same screen as window */
+static cairo_surface_t *
+gdk_x11_surface_create_pixmap_surface (GdkSurface *window,
+                                      int        width,
+                                      int        height)
+{
+  GdkDisplay *display;
+  Display *dpy;
+  cairo_surface_t *surface;
+  Pixmap pixmap;
+
+  display = gdk_surface_get_display (window);
+  dpy = GDK_DISPLAY_XDISPLAY (display);
+
+  pixmap = XCreatePixmap (dpy,
+                          GDK_SURFACE_XID (window),
+                          width, height,
+                          DefaultDepth (dpy, DefaultScreen (dpy)));
+  surface = cairo_xlib_surface_create (dpy,
+                                       pixmap,
+                                       DefaultVisual (dpy, DefaultScreen (dpy)),
+                                       width, height);
+  attach_free_pixmap_handler (surface, display, pixmap);
+
+  return surface;
+}
+
+static void
+set_wm_protocols (GdkSurface *window)
+{
+  GdkDisplay *display = gdk_surface_get_display (window);
+  Atom protocols[4];
+  int n = 0;
+  
+  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
+  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
+  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
+
+#ifdef HAVE_XSYNC
+  if (GDK_X11_DISPLAY (display)->use_sync)
+    protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
+#endif
+  
+  XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window), protocols, n);
+}
+
+static const gchar *
+get_default_title (void)
+{
+  const char *title;
+
+  title = g_get_application_name ();
+  if (!title)
+    title = g_get_prgname ();
+  if (!title)
+    title = "";
+
+  return title;
+}
+
+static void
+check_leader_window_title (GdkDisplay *display)
+{
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
+
+  if (display_x11->leader_window && !display_x11->leader_window_title_set)
+    {
+      set_wm_name (display,
+                  display_x11->leader_window,
+                  get_default_title ());
+      
+      display_x11->leader_window_title_set = TRUE;
+    }
+}
+
+static Window
+create_focus_window (GdkDisplay *display,
+                    XID         parent)
+{
+  GdkX11Display *display_x11;
+  GdkEventMask event_mask;
+  Display *xdisplay;
+  Window focus_window;
+  XSetWindowAttributes attrs;
+
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  display_x11 = GDK_X11_DISPLAY (display);
+
+  focus_window = XCreateWindow (xdisplay, parent,
+                                -1, -1, 1, 1, 0,
+                                0, /* depth */
+                                InputOnly,
+                                CopyFromParent,
+                                0, &attrs);
+
+  event_mask = (GDK_KEY_PRESS_MASK |
+                GDK_KEY_RELEASE_MASK |
+                GDK_FOCUS_CHANGE_MASK);
+
+  gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
+                                      focus_window,
+                                      event_mask, 0);
+
+  XMapWindow (xdisplay, focus_window);
+
+  return focus_window;
+}
+
+static void
+ensure_sync_counter (GdkSurface *window)
+{
+#ifdef HAVE_XSYNC
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
+      GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (window);
+
+      if (toplevel &&
+         toplevel->update_counter == None &&
+         GDK_X11_DISPLAY (display)->use_sync)
+       {
+         Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+         XSyncValue value;
+         Atom atom;
+         XID counters[2];
+
+         XSyncIntToValue (&value, 0);
+         
+         toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
+         toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
+         
+         atom = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_SYNC_REQUEST_COUNTER");
+
+         counters[0] = toplevel->update_counter;
+         counters[1] = toplevel->extended_update_counter;
+         XChangeProperty (xdisplay, GDK_SURFACE_XID (window),
+                          atom, XA_CARDINAL,
+                          32, PropModeReplace,
+                          (guchar *)counters, 2);
+         
+         toplevel->current_counter_value = 0;
+       }
+    }
+#endif
+}
+
+static void
+setup_toplevel_window (GdkSurface    *window,
+                      GdkX11Screen *x11_screen)
+{
+  GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (window);
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+  GdkDisplay *display = gdk_surface_get_display (window);
+  Display *xdisplay = GDK_SURFACE_XDISPLAY (window);
+  XID xid = GDK_SURFACE_XID (window);
+  XSizeHints size_hints;
+  long pid;
+  Window leader_window;
+
+  set_wm_protocols (window);
+
+  if (!window->input_only)
+    {
+      /* The focus window is off the visible area, and serves to receive key
+       * press events so they don't get sent to child windows.
+       */
+      toplevel->focus_window = create_focus_window (display, xid);
+      _gdk_x11_display_add_window (x11_screen->display,
+                                   &toplevel->focus_window,
+                                   window);
+    }
+
+  check_leader_window_title (x11_screen->display);
+
+  /* FIXME: Is there any point in doing this? Do any WM's pay
+   * attention to PSize, and even if they do, is this the
+   * correct value???
+   */
+  size_hints.flags = PSize;
+  size_hints.width = window->width * impl->window_scale;
+  size_hints.height = window->height * impl->window_scale;
+  
+  XSetWMNormalHints (xdisplay, xid, &size_hints);
+  
+  /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
+  XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
+  
+  pid = getpid ();
+  XChangeProperty (xdisplay, xid,
+                  gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
+                  XA_CARDINAL, 32,
+                  PropModeReplace,
+                  (guchar *)&pid, 1);
+
+  leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
+  if (!leader_window)
+    leader_window = xid;
+  XChangeProperty (xdisplay, xid, 
+                  gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
+                  XA_WINDOW, 32, PropModeReplace,
+                  (guchar *) &leader_window, 1);
+
+  if (toplevel->focus_window != None)
+    XChangeProperty (xdisplay, xid, 
+                     gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
+                     XA_WINDOW, 32, PropModeReplace,
+                     (guchar *) &toplevel->focus_window, 1);
+
+  if (!window->focus_on_map)
+    gdk_x11_surface_set_user_time (window, 0);
+  else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
+    gdk_x11_surface_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
+
+  ensure_sync_counter (window);
+
+  /* Start off in a frozen state - we'll finish this when we first paint */
+  gdk_x11_surface_begin_frame (window, TRUE);
+}
+
+static void
+on_frame_clock_before_paint (GdkFrameClock *clock,
+                             GdkSurface     *window)
+{
+  gdk_x11_surface_predict_presentation_time (window);
+  gdk_x11_surface_begin_frame (window, FALSE);
+}
+
+static void
+on_frame_clock_after_paint (GdkFrameClock *clock,
+                            GdkSurface     *window)
+{
+  gdk_x11_surface_end_frame (window);
+
+}
+
+static void
+connect_frame_clock (GdkSurface *window)
+{
+  GdkSurfaceImplX11 *impl;
+
+  impl = GDK_SURFACE_IMPL_X11 (window->impl);
+  if (WINDOW_IS_TOPLEVEL (window) && !impl->frame_clock_connected)
+    {
+      GdkFrameClock *frame_clock = gdk_surface_get_frame_clock (window);
+
+      g_signal_connect (frame_clock, "before-paint",
+                        G_CALLBACK (on_frame_clock_before_paint), window);
+      g_signal_connect (frame_clock, "after-paint",
+                        G_CALLBACK (on_frame_clock_after_paint), window);
+
+      impl->frame_clock_connected = TRUE;
+    }
+}
+
+void
+_gdk_x11_display_create_window_impl (GdkDisplay    *display,
+                                     GdkSurface     *window,
+                                     GdkSurface     *real_parent,
+                                     GdkEventMask   event_mask,
+                                     GdkSurfaceAttr *attributes)
+{
+  GdkSurfaceImplX11 *impl;
+  GdkX11Screen *x11_screen;
+  GdkX11Display *display_x11;
+
+  Window xparent;
+  Visual *xvisual;
+  Display *xdisplay;
+
+  XSetWindowAttributes xattributes;
+  long xattributes_mask;
+  XClassHint *class_hint;
+
+  unsigned int class;
+  int depth;
+
+  int abs_x;
+  int abs_y;
+
+  display_x11 = GDK_X11_DISPLAY (display);
+  x11_screen = GDK_X11_SCREEN (display_x11->screen);
+  if (real_parent)
+    xparent = GDK_SURFACE_XID (real_parent);
+  else
+    xparent = GDK_SCREEN_XROOTWIN (x11_screen);
+
+  impl = g_object_new (GDK_TYPE_SURFACE_IMPL_X11, NULL);
+  window->impl = GDK_SURFACE_IMPL (impl);
+  impl->wrapper = GDK_SURFACE (window);
+  impl->window_scale = x11_screen->window_scale;
+
+  xdisplay = x11_screen->xdisplay;
+
+  xattributes_mask = 0;
+
+  xvisual = gdk_x11_display_get_window_visual (display_x11);
+
+  impl->override_redirect = FALSE;
+
+  /* Sanity checks */
+  switch (window->window_type)
+    {
+    case GDK_SURFACE_TOPLEVEL:
+    case GDK_SURFACE_TEMP:
+      if (window->parent)
+        {
+          /* The common code warns for this case */
+          xparent = GDK_SCREEN_XROOTWIN (x11_screen);
+        }
+      break;
+
+    case GDK_SURFACE_CHILD:
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  if (!window->input_only)
+    {
+      class = InputOutput;
+
+      xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
+
+      xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
+      xattributes_mask |= CWBorderPixel | CWBackPixel;
+
+      xattributes.bit_gravity = NorthWestGravity;
+      xattributes_mask |= CWBitGravity;
+
+      xattributes.colormap = gdk_x11_display_get_window_colormap (display_x11);
+      xattributes_mask |= CWColormap;
+
+      if (window->window_type == GDK_SURFACE_TEMP)
+        {
+          xattributes.save_under = True;
+          xattributes.override_redirect = True;
+          xattributes.cursor = None;
+          xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
+
+          impl->override_redirect = TRUE;
+        }
+
+      depth = gdk_x11_display_get_window_depth (display_x11);
+    }
+  else
+    {
+      class = InputOnly;
+
+      if (window->window_type == GDK_SURFACE_TEMP)
+        {
+          xattributes.override_redirect = True;
+          xattributes_mask |= CWOverrideRedirect;
+
+          impl->override_redirect = TRUE;
+        }
+
+      depth = 0;
+    }
+
+  if (window->width * impl->window_scale > 32767 ||
+      window->height * impl->window_scale > 32767)
+    {
+      g_warning ("Native Windows wider or taller than 32767 pixels are not supported");
+
+      if (window->width * impl->window_scale > 32767)
+        window->width = 32767 / impl->window_scale;
+      if (window->height  * impl->window_scale > 32767)
+        window->height = 32767 /  impl->window_scale;
+    }
+
+  impl->unscaled_width = window->width * impl->window_scale;
+  impl->unscaled_height = window->height * impl->window_scale;
+
+  if (window->parent)
+    {
+      abs_x = window->parent->abs_x;
+      abs_y = window->parent->abs_y;
+    }
+  else
+    {
+      abs_x = 0;
+      abs_y = 0;
+    }
+
+  impl->xid = XCreateWindow (xdisplay, xparent,
+                             (window->x + abs_x) * impl->window_scale,
+                             (window->y + abs_y) * impl->window_scale,
+                             window->width * impl->window_scale, window->height * impl->window_scale,
+                             0, depth, class, xvisual,
+                             xattributes_mask, &xattributes);
+
+  g_object_ref (window);
+  _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
+
+  switch (GDK_SURFACE_TYPE (window))
+    {
+    case GDK_SURFACE_TOPLEVEL:
+    case GDK_SURFACE_TEMP:
+      gdk_surface_set_title (window, get_default_title ());
+
+      class_hint = XAllocClassHint ();
+      class_hint->res_name = (char *) g_get_prgname ();
+      class_hint->res_class = (char *) display_x11->program_class;
+      XSetClassHint (xdisplay, impl->xid, class_hint);
+      XFree (class_hint);
+
+      setup_toplevel_window (window, x11_screen);
+      break;
+
+    case GDK_SURFACE_CHILD:
+    default:
+      break;
+    }
+
+  gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
+                                      GDK_SURFACE_XID (window), event_mask,
+                                      StructureNotifyMask | PropertyChangeMask);
+
+  connect_frame_clock (window);
+
+  gdk_surface_freeze_toplevel_updates (window);
+}
+
+static GdkEventMask
+x_event_mask_to_gdk_event_mask (long mask)
+{
+  GdkEventMask event_mask = 0;
+  int i;
+
+  for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
+    {
+      if (mask & _gdk_x11_event_mask_table[i])
+       event_mask |= 1 << (i + 1);
+    }
+
+  return event_mask;
+}
+
+/**
+ * gdk_x11_surface_foreign_new_for_display:
+ * @display: (type GdkX11Display): the #GdkDisplay where the window handle comes from.
+ * @window: an Xlib Window
+ *
+ * Wraps a native window in a #GdkSurface. The function will try to
+ * look up the window using gdk_x11_surface_lookup_for_display() first.
+ * If it does not find it there, it will create a new window.
+ *
+ * This may fail if the window has been destroyed. If the window
+ * was already known to GDK, a new reference to the existing
+ * #GdkSurface is returned.
+ *
+ * Returns: (transfer full): a #GdkSurface wrapper for the native
+ *   window, or %NULL if the window has been destroyed. The wrapper
+ *   will be newly created, if one doesn’t exist already.
+ */
+GdkSurface *
+gdk_x11_surface_foreign_new_for_display (GdkDisplay *display,
+                                        Window      window)
+{
+  GdkX11Screen *screen;
+  GdkSurface *win;
+  GdkSurfaceImplX11 *impl;
+  GdkX11Display *display_x11;
+  XWindowAttributes attrs;
+  Window root, parent;
+  Window *children = NULL;
+  guint nchildren;
+  gboolean result;
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  display_x11 = GDK_X11_DISPLAY (display);
+
+  if ((win = gdk_x11_surface_lookup_for_display (display, window)) != NULL)
+    return g_object_ref (win);
+
+  gdk_x11_display_error_trap_push (display);
+  result = XGetWindowAttributes (display_x11->xdisplay, window, &attrs);
+  if (gdk_x11_display_error_trap_pop (display) || !result)
+    return NULL;
+
+  /* FIXME: This is pretty expensive.
+   * Maybe the caller should supply the parent
+   */
+  gdk_x11_display_error_trap_push (display);
+  result = XQueryTree (display_x11->xdisplay, window, &root, &parent, &children, &nchildren);
+  if (gdk_x11_display_error_trap_pop (display) || !result)
+    return NULL;
+
+  if (children)
+    XFree (children);
+
+  screen = _gdk_x11_display_screen_for_xrootwin (display, root);
+  if (screen == NULL)
+    return NULL;
+
+  win = _gdk_display_create_window (display);
+  win->impl = g_object_new (GDK_TYPE_SURFACE_IMPL_X11, NULL);
+  win->impl_window = win;
+
+  impl = GDK_SURFACE_IMPL_X11 (win->impl);
+  impl->wrapper = win;
+  impl->window_scale = GDK_X11_SCREEN (screen)->window_scale;
+
+  /* Always treat foreigns as toplevels */
+  win->parent = NULL;
+
+  impl->xid = window;
+
+  win->x = attrs.x / impl->window_scale;
+  win->y = attrs.y / impl->window_scale;
+  impl->unscaled_width = attrs.width;
+  impl->unscaled_height = attrs.height;
+  win->width = attrs.width / impl->window_scale;
+  win->height = attrs.height  / impl->window_scale;
+  win->window_type = GDK_SURFACE_FOREIGN;
+  win->destroyed = FALSE;
+
+  win->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
+
+  if (attrs.map_state == IsUnmapped)
+    win->state = GDK_SURFACE_STATE_WITHDRAWN;
+  else
+    win->state = 0;
+  win->viewable = TRUE;
+
+  g_object_ref (win);
+  _gdk_x11_display_add_window (display, &GDK_SURFACE_XID (win), win);
+
+  /* Update the clip region, etc */
+  _gdk_surface_update_size (win);
+
+  return win;
+}
+
+static void
+gdk_toplevel_x11_free_contents (GdkDisplay *display,
+                               GdkToplevelX11 *toplevel)
+{
+  if (toplevel->icon_pixmap)
+    {
+      cairo_surface_destroy (toplevel->icon_pixmap);
+      toplevel->icon_pixmap = NULL;
+    }
+  if (toplevel->icon_mask)
+    {
+      cairo_surface_destroy (toplevel->icon_mask);
+      toplevel->icon_mask = NULL;
+    }
+  if (toplevel->group_leader)
+    {
+      g_object_unref (toplevel->group_leader);
+      toplevel->group_leader = NULL;
+    }
+#ifdef HAVE_XSYNC
+  if (toplevel->update_counter != None)
+    {
+      XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display), 
+                          toplevel->update_counter);
+      XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display),
+                           toplevel->extended_update_counter);
+      toplevel->update_counter = None;
+      toplevel->extended_update_counter = None;
+
+      toplevel->current_counter_value = 0;
+    }
+#endif
+}
+
+static void
+gdk_x11_surface_destroy (GdkSurface *window,
+                        gboolean   recursing,
+                        gboolean   foreign_destroy)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+  GdkToplevelX11 *toplevel;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+  if (toplevel)
+    gdk_toplevel_x11_free_contents (GDK_SURFACE_DISPLAY (window), toplevel);
+
+  unhook_surface_changed (window);
+
+  if (impl->cairo_surface)
+    {
+      cairo_surface_finish (impl->cairo_surface);
+      cairo_surface_destroy (impl->cairo_surface);
+      impl->cairo_surface = NULL;
+    }
+
+  if (!recursing && !foreign_destroy)
+    XDestroyWindow (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XID (window));
+}
+
+/* This function is called when the XWindow is really gone.
+ */
+static void
+gdk_x11_surface_destroy_notify (GdkSurface *window)
+{
+  GdkSurfaceImplX11 *window_impl;
+
+  window_impl = GDK_SURFACE_IMPL_X11 ((window)->impl);
+
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      if (GDK_SURFACE_TYPE(window) != GDK_SURFACE_FOREIGN)
+       g_warning ("GdkSurface %#lx unexpectedly destroyed", GDK_SURFACE_XID (window));
+
+      _gdk_surface_destroy (window, TRUE);
+    }
+
+  _gdk_x11_display_remove_window (GDK_SURFACE_DISPLAY (window), GDK_SURFACE_XID (window));
+  if (window_impl->toplevel && window_impl->toplevel->focus_window)
+    _gdk_x11_display_remove_window (GDK_SURFACE_DISPLAY (window), window_impl->toplevel->focus_window);
+
+  _gdk_x11_surface_grab_check_destroy (window);
+
+  g_object_unref (window);
+}
+
+static void
+update_wm_hints (GdkSurface *window,
+                gboolean   force)
+{
+  GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (window);
+  GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
+  XWMHints wm_hints;
+
+  if (!force &&
+      !toplevel->is_leader &&
+      window->state & GDK_SURFACE_STATE_WITHDRAWN)
+    return;
+
+  wm_hints.flags = StateHint | InputHint;
+  wm_hints.input = window->accept_focus ? True : False;
+  wm_hints.initial_state = NormalState;
+  
+  if (window->state & GDK_SURFACE_STATE_ICONIFIED)
+    {
+      wm_hints.flags |= StateHint;
+      wm_hints.initial_state = IconicState;
+    }
+
+  if (toplevel->icon_pixmap)
+    {
+      wm_hints.flags |= IconPixmapHint;
+      wm_hints.icon_pixmap = cairo_xlib_surface_get_drawable (toplevel->icon_pixmap);
+    }
+
+  if (toplevel->icon_mask)
+    {
+      wm_hints.flags |= IconMaskHint;
+      wm_hints.icon_mask = cairo_xlib_surface_get_drawable (toplevel->icon_mask);
+    }
+  
+  wm_hints.flags |= WindowGroupHint;
+  if (toplevel->group_leader && !GDK_SURFACE_DESTROYED (toplevel->group_leader))
+    {
+      wm_hints.flags |= WindowGroupHint;
+      wm_hints.window_group = GDK_SURFACE_XID (toplevel->group_leader);
+    }
+  else
+    wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
+
+  if (toplevel->urgency_hint)
+    wm_hints.flags |= XUrgencyHint;
+  
+  XSetWMHints (GDK_SURFACE_XDISPLAY (window),
+              GDK_SURFACE_XID (window),
+              &wm_hints);
+}
+
+static void
+set_initial_hints (GdkSurface *window)
+{
+  GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
+  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  Window xwindow = GDK_SURFACE_XID (window);  
+  GdkToplevelX11 *toplevel;
+  Atom atoms[9];
+  gint i;
+
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+
+  if (!toplevel)
+    return;
+
+  update_wm_hints (window, TRUE);
+  
+  /* We set the spec hints regardless of whether the spec is supported,
+   * since it can't hurt and it's kind of expensive to check whether
+   * it's supported.
+   */
+  
+  i = 0;
+
+  if (window->state & GDK_SURFACE_STATE_MAXIMIZED)
+    {
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_STATE_MAXIMIZED_VERT");
+      ++i;
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_STATE_MAXIMIZED_HORZ");
+      ++i;
+      toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
+    }
+
+  if (window->state & GDK_SURFACE_STATE_ABOVE)
+    {
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_STATE_ABOVE");
+      ++i;
+    }
+  
+  if (window->state & GDK_SURFACE_STATE_BELOW)
+    {
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_STATE_BELOW");
+      ++i;
+    }
+  
+  if (window->state & GDK_SURFACE_STATE_STICKY)
+    {
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_STATE_STICKY");
+      ++i;
+      toplevel->have_sticky = TRUE;
+    }
+
+  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
+    {
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_STATE_FULLSCREEN");
+      ++i;
+      toplevel->have_fullscreen = TRUE;
+    }
+
+  if (window->modal_hint)
+    {
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_STATE_MODAL");
+      ++i;
+    }
+
+  if (toplevel->skip_taskbar_hint)
+    {
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_STATE_SKIP_TASKBAR");
+      ++i;
+    }
+
+  if (toplevel->skip_pager_hint)
+    {
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_STATE_SKIP_PAGER");
+      ++i;
+    }
+
+  if (window->state & GDK_SURFACE_STATE_ICONIFIED)
+    {
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_STATE_HIDDEN");
+      ++i;
+      toplevel->have_hidden = TRUE;
+    }
+
+  if (i > 0)
+    {
+      XChangeProperty (xdisplay,
+                       xwindow,
+                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
+                       XA_ATOM, 32, PropModeReplace,
+                       (guchar*) atoms, i);
+    }
+  else 
+    {
+      XDeleteProperty (xdisplay,
+                       xwindow,
+                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
+    }
+
+  if (window->state & GDK_SURFACE_STATE_STICKY)
+    {
+      atoms[0] = 0xFFFFFFFF;
+      XChangeProperty (xdisplay,
+                       xwindow,
+                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
+                       XA_CARDINAL, 32, PropModeReplace,
+                       (guchar*) atoms, 1);
+      toplevel->on_all_desktops = TRUE;
+    }
+  else
+    {
+      XDeleteProperty (xdisplay,
+                       xwindow,
+                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
+    }
+
+  toplevel->map_serial = NextRequest (xdisplay);
+}
+
+static void
+gdk_surface_x11_show (GdkSurface *window, gboolean already_mapped)
+{
+  GdkDisplay *display;
+  GdkX11Display *display_x11;
+  GdkToplevelX11 *toplevel;
+  Display *xdisplay = GDK_SURFACE_XDISPLAY (window);
+  Window xwindow = GDK_SURFACE_XID (window);
+
+  if (!already_mapped)
+    set_initial_hints (window);
+      
+  if (WINDOW_IS_TOPLEVEL (window))
+    {
+      display = gdk_surface_get_display (window);
+      display_x11 = GDK_X11_DISPLAY (display);
+      toplevel = _gdk_x11_surface_get_toplevel (window);
+      
+      if (toplevel->user_time != 0 &&
+             display_x11->user_time != 0 &&
+         XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
+       gdk_x11_surface_set_user_time (window, display_x11->user_time);
+    }
+  
+  XMapWindow (xdisplay, xwindow);
+  
+  /* Fullscreen on current monitor is the default, no need to apply this mode
+   * when mapping a window. This also ensures that the default behavior remains
+   * consistent with pre-fullscreen mode implementation.
+   */
+  if (window->fullscreen_mode != GDK_FULLSCREEN_ON_CURRENT_MONITOR)
+    gdk_x11_surface_apply_fullscreen_mode (window);
+}
+
+static void
+gdk_surface_x11_hide (GdkSurface *window)
+{
+  /* We'll get the unmap notify eventually, and handle it then,
+   * but checking here makes things more consistent if we are
+   * just doing stuff ourself.
+   */
+  _gdk_x11_surface_grab_check_unmap (window,
+                                    NextRequest (GDK_SURFACE_XDISPLAY (window)));
+
+  /* You can't simply unmap toplevel windows. */
+  switch (window->window_type)
+    {
+    case GDK_SURFACE_TOPLEVEL:
+    case GDK_SURFACE_TEMP: /* ? */
+      gdk_surface_withdraw (window);
+      return;
+      
+    case GDK_SURFACE_FOREIGN:
+    case GDK_SURFACE_CHILD:
+    default:
+      break;
+    }
+  
+  _gdk_surface_clear_update_area (window);
+  
+  XUnmapWindow (GDK_SURFACE_XDISPLAY (window),
+               GDK_SURFACE_XID (window));
+}
+
+static void
+gdk_surface_x11_withdraw (GdkSurface *window)
+{
+  if (!window->destroyed)
+    {
+      if (GDK_SURFACE_IS_MAPPED (window))
+        gdk_synthesize_window_state (window,
+                                     0,
+                                     GDK_SURFACE_STATE_WITHDRAWN);
+
+      g_assert (!GDK_SURFACE_IS_MAPPED (window));
+
+      XWithdrawWindow (GDK_SURFACE_XDISPLAY (window),
+                       GDK_SURFACE_XID (window), 0);
+    }
+}
+
+static inline void
+window_x11_move (GdkSurface *window,
+                 gint       x,
+                 gint       y)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  XMoveWindow (GDK_SURFACE_XDISPLAY (window),
+               GDK_SURFACE_XID (window),
+               x * impl->window_scale, y * impl->window_scale);
+
+  if (impl->override_redirect)
+    {
+      window->x = x;
+      window->y = y;
+    }
+}
+
+static inline void
+window_x11_resize (GdkSurface *window,
+                   gint       width,
+                   gint       height)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (width < 1)
+    width = 1;
+
+  if (height < 1)
+    height = 1;
+
+  window_pre_damage (window);
+
+  XResizeWindow (GDK_SURFACE_XDISPLAY (window),
+                 GDK_SURFACE_XID (window),
+                 width * impl->window_scale, height * impl->window_scale);
+
+  if (impl->override_redirect)
+    {
+      impl->unscaled_width = width * impl->window_scale;
+      impl->unscaled_height = height * impl->window_scale;
+      window->width = width;
+      window->height = height;
+      _gdk_x11_surface_update_size (GDK_SURFACE_IMPL_X11 (window->impl));
+    }
+  else
+    {
+      if (width * impl->window_scale != impl->unscaled_width || height * impl->window_scale != impl->unscaled_height)
+        window->resize_count += 1;
+    }
+}
+
+static inline void
+window_x11_move_resize (GdkSurface *window,
+                        gint       x,
+                        gint       y,
+                        gint       width,
+                        gint       height)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (width < 1)
+    width = 1;
+
+  if (height < 1)
+    height = 1;
+
+  window_pre_damage (window);
+
+  XMoveResizeWindow (GDK_SURFACE_XDISPLAY (window),
+                     GDK_SURFACE_XID (window),
+                     x * impl->window_scale, y * impl->window_scale,
+                     width * impl->window_scale, height * impl->window_scale);
+
+  if (impl->override_redirect)
+    {
+      window->x = x;
+      window->y = y;
+
+      impl->unscaled_width = width * impl->window_scale;
+      impl->unscaled_height = height * impl->window_scale;
+      window->width = width;
+      window->height = height;
+
+      _gdk_x11_surface_update_size (GDK_SURFACE_IMPL_X11 (window->impl));
+    }
+  else
+    {
+      if (width * impl->window_scale != impl->unscaled_width || height * impl->window_scale != impl->unscaled_height)
+        window->resize_count += 1;
+    }
+}
+
+static void
+gdk_surface_x11_move_resize (GdkSurface *window,
+                            gboolean   with_move,
+                            gint       x,
+                            gint       y,
+                            gint       width,
+                            gint       height)
+{
+  if (with_move && (width < 0 && height < 0))
+    window_x11_move (window, x, y);
+  else
+    {
+      if (with_move)
+        window_x11_move_resize (window, x, y, width, height);
+      else
+        window_x11_resize (window, width, height);
+    }
+}
+
+void
+_gdk_x11_surface_set_window_scale (GdkSurface *window,
+                                 int scale)
+{
+  GdkSurfaceImplX11 *impl;
+  GdkToplevelX11 *toplevel;
+  GdkSurfaceHints geom_mask;
+
+  impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  impl->window_scale = scale;
+  if (impl->cairo_surface)
+    cairo_surface_set_device_scale (impl->cairo_surface, impl->window_scale, impl->window_scale);
+  _gdk_surface_update_size (window);
+
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+  if (toplevel && window->window_type != GDK_SURFACE_FOREIGN)
+    {
+      /* These are affected by window scale: */
+      geom_mask = toplevel->last_geometry_hints_mask &
+        (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE | GDK_HINT_BASE_SIZE | GDK_HINT_RESIZE_INC);
+      if (geom_mask)
+        gdk_surface_set_geometry_hints (window,
+                                       &toplevel->last_geometry_hints,
+                                       geom_mask);
+    }
+
+  if (window->window_type == GDK_SURFACE_FOREIGN)
+    XMoveWindow (GDK_SURFACE_XDISPLAY (window),
+                 GDK_SURFACE_XID (window),
+                 window->x * impl->window_scale,
+                 window->y * impl->window_scale);
+  else
+    {
+      if (impl->override_redirect)
+        {
+          impl->unscaled_width = window->width * impl->window_scale;
+          impl->unscaled_height = window->height * impl->window_scale;
+        }
+
+      XResizeWindow (GDK_SURFACE_XDISPLAY (window),
+                     GDK_SURFACE_XID (window),
+                     window->width * impl->window_scale,
+                     window->height * impl->window_scale);
+    }
+
+  gdk_surface_invalidate_rect (window, NULL, TRUE);
+}
+
+static void
+gdk_surface_x11_raise (GdkSurface *window)
+{
+  XRaiseWindow (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XID (window));
+}
+
+static void
+gdk_surface_x11_restack_toplevel (GdkSurface *window,
+                                GdkSurface *sibling,
+                                gboolean   above)
+{
+  XWindowChanges changes;
+
+  changes.sibling = GDK_SURFACE_XID (sibling);
+  changes.stack_mode = above ? Above : Below;
+  XReconfigureWMWindow (GDK_SURFACE_XDISPLAY (window),
+                       GDK_SURFACE_XID (window),
+                       gdk_x11_screen_get_screen_number (GDK_SURFACE_SCREEN (window)),
+                       CWStackMode | CWSibling, &changes);
+}
+
+static void
+gdk_surface_x11_lower (GdkSurface *window)
+{
+  XLowerWindow (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XID (window));
+}
+
+/**
+ * gdk_x11_surface_move_to_current_desktop:
+ * @window: (type GdkX11Surface): a #GdkSurface
+ * 
+ * Moves the window to the correct workspace when running under a 
+ * window manager that supports multiple workspaces, as described
+ * in the [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec) specification.
+ * Will not do anything if the window is already on all workspaces.
+ */
+void
+gdk_x11_surface_move_to_current_desktop (GdkSurface *window)
+{
+  GdkToplevelX11 *toplevel;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD);
+
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+
+  if (toplevel->on_all_desktops)
+    return;
+  
+  move_to_current_desktop (window);
+}
+
+static void
+move_to_current_desktop (GdkSurface *window)
+{
+  guint32 desktop;
+
+  desktop = gdk_x11_screen_get_current_desktop (GDK_SURFACE_SCREEN (window));
+  gdk_x11_surface_move_to_desktop (window, desktop);
+}
+
+static guint32
+get_netwm_cardinal_property (GdkSurface   *window,
+                             const gchar *name)
+{
+  GdkX11Screen *x11_screen = GDK_SURFACE_SCREEN (window);
+  GdkAtom atom;
+  guint32 prop = 0;
+  Atom type;
+  gint format;
+  gulong nitems;
+  gulong bytes_after;
+  guchar *data;
+
+  atom = g_intern_static_string (name);
+
+  if (!gdk_x11_screen_supports_net_wm_hint (x11_screen, atom))
+    return 0;
+
+  XGetWindowProperty (x11_screen->xdisplay,
+                      GDK_SURFACE_XID (window),
+                      gdk_x11_get_xatom_by_name_for_display (GDK_SURFACE_DISPLAY (window), name),
+                      0, G_MAXLONG,
+                      False, XA_CARDINAL, &type, &format, &nitems,
+                      &bytes_after, &data);
+  if (type == XA_CARDINAL)
+    {
+      prop = *(gulong *)data;
+      XFree (data);
+    }
+
+  return prop;
+}
+
+/**
+ * gdk_x11_surface_get_desktop:
+ * @window: (type GdkX11Surface): a #GdkSurface
+ *
+ * Gets the number of the workspace @window is on.
+ *
+ * Returns: the current workspace of @window
+ */
+guint32
+gdk_x11_surface_get_desktop (GdkSurface *window)
+{
+  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
+
+  return get_netwm_cardinal_property (window, "_NET_WM_DESKTOP");
+}
+
+/**
+ * gdk_x11_surface_move_to_desktop:
+ * @window: (type GdkX11Surface): a #GdkSurface
+ * @desktop: the number of the workspace to move the window to
+ *
+ * Moves the window to the given workspace when running unde a
+ * window manager that supports multiple workspaces, as described
+ * in the [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec) specification.
+ */
+void
+gdk_x11_surface_move_to_desktop (GdkSurface *window,
+                                guint32    desktop)
+{
+  GdkAtom atom;
+  XClientMessageEvent xclient;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  atom = g_intern_static_string ("_NET_WM_DESKTOP");
+  if (!gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window), atom))
+    return;
+
+  memset (&xclient, 0, sizeof (xclient));
+  xclient.type = ClientMessage;
+  xclient.serial = 0;
+  xclient.send_event = True;
+  xclient.window = GDK_SURFACE_XID (window);
+  xclient.message_type = gdk_x11_atom_to_xatom_for_display (GDK_SURFACE_DISPLAY (window), atom);
+  xclient.format = 32;
+
+  xclient.data.l[0] = desktop;
+  xclient.data.l[1] = 1; /* source indication */
+  xclient.data.l[2] = 0;
+  xclient.data.l[3] = 0;
+  xclient.data.l[4] = 0;
+
+  XSendEvent (GDK_SURFACE_XDISPLAY (window),
+              GDK_SURFACE_XROOTWIN (window),
+              False,
+              SubstructureRedirectMask | SubstructureNotifyMask,
+              (XEvent *)&xclient);
+}
+
+static void
+gdk_x11_surface_focus (GdkSurface *window,
+                     guint32    timestamp)
+{
+  GdkDisplay *display;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  display = GDK_SURFACE_DISPLAY (window);
+
+  if (gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
+                                          g_intern_static_string ("_NET_ACTIVE_WINDOW")))
+    {
+      XClientMessageEvent xclient;
+
+      memset (&xclient, 0, sizeof (xclient));
+      xclient.type = ClientMessage;
+      xclient.window = GDK_SURFACE_XID (window);
+      xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
+                                                                    "_NET_ACTIVE_WINDOW");
+      xclient.format = 32;
+      xclient.data.l[0] = 1; /* requestor type; we're an app */
+      xclient.data.l[1] = timestamp;
+      xclient.data.l[2] = None; /* currently active window */
+      xclient.data.l[3] = 0;
+      xclient.data.l[4] = 0;
+      
+      XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XROOTWIN (window), False,
+                  SubstructureRedirectMask | SubstructureNotifyMask,
+                  (XEvent *)&xclient);
+    }
+  else
+    {
+      XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window));
+
+      /* There is no way of knowing reliably whether we are viewable;
+       * so trap errors asynchronously around the XSetInputFocus call
+       */
+      gdk_x11_display_error_trap_push (display);
+      XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
+                      GDK_SURFACE_XID (window),
+                      RevertToParent,
+                      timestamp);
+      gdk_x11_display_error_trap_pop_ignored (display);
+    }
+}
+
+static void
+gdk_x11_surface_set_type_hint (GdkSurface        *window,
+                             GdkSurfaceTypeHint hint)
+{
+  GdkDisplay *display;
+  Atom atom;
+  
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  display = gdk_surface_get_display (window);
+
+  switch (hint)
+    {
+    case GDK_SURFACE_TYPE_HINT_DIALOG:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
+      break;
+    case GDK_SURFACE_TYPE_HINT_MENU:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
+      break;
+    case GDK_SURFACE_TYPE_HINT_TOOLBAR:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
+      break;
+    case GDK_SURFACE_TYPE_HINT_UTILITY:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
+      break;
+    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
+      break;
+    case GDK_SURFACE_TYPE_HINT_DOCK:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
+      break;
+    case GDK_SURFACE_TYPE_HINT_DESKTOP:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
+      break;
+    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
+      break;
+    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
+      break;
+    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
+      break;
+    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
+      break;
+    case GDK_SURFACE_TYPE_HINT_COMBO:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
+      break;
+    case GDK_SURFACE_TYPE_HINT_DND:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
+      break;
+    default:
+      g_warning ("Unknown hint %d passed to gdk_surface_set_type_hint", hint);
+      /* Fall thru */
+    case GDK_SURFACE_TYPE_HINT_NORMAL:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
+      break;
+    }
+
+  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
+                  gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
+                  XA_ATOM, 32, PropModeReplace,
+                  (guchar *)&atom, 1);
+}
+
+static GdkSurfaceTypeHint
+gdk_x11_surface_get_type_hint (GdkSurface *window)
+{
+  GdkDisplay *display;
+  GdkSurfaceTypeHint type;
+  Atom type_return;
+  gint format_return;
+  gulong nitems_return;
+  gulong bytes_after_return;
+  guchar *data = NULL;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), GDK_SURFACE_TYPE_HINT_NORMAL);
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return GDK_SURFACE_TYPE_HINT_NORMAL;
+
+  type = GDK_SURFACE_TYPE_HINT_NORMAL;
+
+  display = gdk_surface_get_display (window);
+
+  if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
+                          gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
+                          0, G_MAXLONG, False, XA_ATOM, &type_return,
+                          &format_return, &nitems_return, &bytes_after_return,
+                          &data) == Success)
+    {
+      if ((type_return == XA_ATOM) && (format_return == 32) &&
+          (data) && (nitems_return == 1))
+        {
+          Atom atom = *(Atom*)data;
+
+          if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
+            type = GDK_SURFACE_TYPE_HINT_DIALOG;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
+            type = GDK_SURFACE_TYPE_HINT_MENU;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
+            type = GDK_SURFACE_TYPE_HINT_TOOLBAR;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
+            type = GDK_SURFACE_TYPE_HINT_UTILITY;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
+            type = GDK_SURFACE_TYPE_HINT_SPLASHSCREEN;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
+            type = GDK_SURFACE_TYPE_HINT_DOCK;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
+            type = GDK_SURFACE_TYPE_HINT_DESKTOP;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
+           type = GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
+           type = GDK_SURFACE_TYPE_HINT_POPUP_MENU;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
+           type = GDK_SURFACE_TYPE_HINT_TOOLTIP;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
+           type = GDK_SURFACE_TYPE_HINT_NOTIFICATION;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
+           type = GDK_SURFACE_TYPE_HINT_COMBO;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
+           type = GDK_SURFACE_TYPE_HINT_DND;
+        }
+
+      if (type_return != None && data != NULL)
+        XFree (data);
+    }
+
+  return type;
+}
+
+static void
+gdk_wmspec_change_state (gboolean   add,
+                        GdkSurface *window,
+                        GdkAtom    state1,
+                        GdkAtom    state2)
+{
+  GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
+  XClientMessageEvent xclient;
+  
+#define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
+#define _NET_WM_STATE_ADD           1    /* add/set property */
+#define _NET_WM_STATE_TOGGLE        2    /* toggle property  */  
+  
+  memset (&xclient, 0, sizeof (xclient));
+  xclient.type = ClientMessage;
+  xclient.window = GDK_SURFACE_XID (window);
+  xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
+  xclient.format = 32;
+  xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+  xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
+  xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
+  xclient.data.l[3] = 1; /* source indication */
+  xclient.data.l[4] = 0;
+  
+  XSendEvent (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XROOTWIN (window), False,
+             SubstructureRedirectMask | SubstructureNotifyMask,
+             (XEvent *)&xclient);
+}
+
+static void
+gdk_x11_surface_set_modal_hint (GdkSurface *window,
+                              gboolean   modal)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  window->modal_hint = modal;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    gdk_wmspec_change_state (modal, window,
+                            g_intern_static_string ("_NET_WM_STATE_MODAL"), 
+                            NULL);
+}
+
+static void
+gdk_x11_surface_set_skip_taskbar_hint (GdkSurface *window,
+                                     gboolean   skips_taskbar)
+{
+  GdkToplevelX11 *toplevel;
+  
+  g_return_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD);
+  
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+  toplevel->skip_taskbar_hint = skips_taskbar;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    gdk_wmspec_change_state (skips_taskbar, window,
+                            g_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
+                            NULL);
+}
+
+static void
+gdk_x11_surface_set_skip_pager_hint (GdkSurface *window,
+                                   gboolean   skips_pager)
+{
+  GdkToplevelX11 *toplevel;
+    
+  g_return_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD);
+  
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+  toplevel->skip_pager_hint = skips_pager;
+  
+  if (GDK_SURFACE_IS_MAPPED (window))
+    gdk_wmspec_change_state (skips_pager, window,
+                            g_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"), 
+                            NULL);
+}
+
+static void
+gdk_x11_surface_set_urgency_hint (GdkSurface *window,
+                            gboolean   urgent)
+{
+  GdkToplevelX11 *toplevel;
+    
+  g_return_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD);
+  
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+  toplevel->urgency_hint = urgent;
+  
+  update_wm_hints (window, FALSE);
+}
+
+static void
+gdk_x11_surface_set_geometry_hints (GdkSurface         *window,
+                                  const GdkGeometry *geometry,
+                                  GdkSurfaceHints     geom_mask)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+  XSizeHints size_hints;
+  GdkToplevelX11 *toplevel;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+  if (toplevel)
+    {
+      if (geometry)
+        toplevel->last_geometry_hints = *geometry;
+      toplevel->last_geometry_hints_mask = geom_mask;
+    }
+  
+  size_hints.flags = 0;
+  
+  if (geom_mask & GDK_HINT_POS)
+    {
+      size_hints.flags |= PPosition;
+      /* We need to initialize the following obsolete fields because KWM 
+       * apparently uses these fields if they are non-zero.
+       * #@#!#!$!.
+       */
+      size_hints.x = 0;
+      size_hints.y = 0;
+    }
+
+  if (geom_mask & GDK_HINT_USER_POS)
+    {
+      size_hints.flags |= USPosition;
+    }
+
+  if (geom_mask & GDK_HINT_USER_SIZE)
+    {
+      size_hints.flags |= USSize;
+    }
+  
+  if (geom_mask & GDK_HINT_MIN_SIZE)
+    {
+      size_hints.flags |= PMinSize;
+      size_hints.min_width = geometry->min_width * impl->window_scale;
+      size_hints.min_height = geometry->min_height * impl->window_scale;
+    }
+  
+  if (geom_mask & GDK_HINT_MAX_SIZE)
+    {
+      size_hints.flags |= PMaxSize;
+      size_hints.max_width = MAX (geometry->max_width, 1) * impl->window_scale;
+      size_hints.max_height = MAX (geometry->max_height, 1) * impl->window_scale;
+    }
+  
+  if (geom_mask & GDK_HINT_BASE_SIZE)
+    {
+      size_hints.flags |= PBaseSize;
+      size_hints.base_width = geometry->base_width * impl->window_scale;
+      size_hints.base_height = geometry->base_height * impl->window_scale;
+    }
+  
+  if (geom_mask & GDK_HINT_RESIZE_INC)
+    {
+      size_hints.flags |= PResizeInc;
+      size_hints.width_inc = geometry->width_inc * impl->window_scale;
+      size_hints.height_inc = geometry->height_inc * impl->window_scale;
+    }
+  else if (impl->window_scale > 1)
+    {
+      size_hints.flags |= PResizeInc;
+      size_hints.width_inc = impl->window_scale;
+      size_hints.height_inc = impl->window_scale;
+    }
+
+  if (geom_mask & GDK_HINT_ASPECT)
+    {
+      size_hints.flags |= PAspect;
+      if (geometry->min_aspect <= 1)
+       {
+         size_hints.min_aspect.x = 65536 * geometry->min_aspect;
+         size_hints.min_aspect.y = 65536;
+       }
+      else
+       {
+         size_hints.min_aspect.x = 65536;
+         size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
+       }
+      if (geometry->max_aspect <= 1)
+       {
+         size_hints.max_aspect.x = 65536 * geometry->max_aspect;
+         size_hints.max_aspect.y = 65536;
+       }
+      else
+       {
+         size_hints.max_aspect.x = 65536;
+         size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
+       }
+    }
+
+  if (geom_mask & GDK_HINT_WIN_GRAVITY)
+    {
+      size_hints.flags |= PWinGravity;
+      size_hints.win_gravity = geometry->win_gravity;
+    }
+  
+  /* FIXME: Would it be better to delete this property if
+   *        geom_mask == 0? It would save space on the server
+   */
+  XSetWMNormalHints (GDK_SURFACE_XDISPLAY (window),
+                    GDK_SURFACE_XID (window),
+                    &size_hints);
+}
+
+static void
+gdk_surface_get_geometry_hints (GdkSurface      *window,
+                               GdkGeometry    *geometry,
+                               GdkSurfaceHints *geom_mask)
+{
+  GdkSurfaceImplX11 *impl;
+  XSizeHints *size_hints;  
+  glong junk_supplied_mask = 0;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (geometry != NULL);
+  g_return_if_fail (geom_mask != NULL);
+
+  *geom_mask = 0;
+  
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  size_hints = XAllocSizeHints ();
+  if (!size_hints)
+    return;
+  
+  if (!XGetWMNormalHints (GDK_SURFACE_XDISPLAY (window),
+                          GDK_SURFACE_XID (window),
+                          size_hints,
+                          &junk_supplied_mask))
+    size_hints->flags = 0;
+
+  if (size_hints->flags & PMinSize)
+    {
+      *geom_mask |= GDK_HINT_MIN_SIZE;
+      geometry->min_width = size_hints->min_width / impl->window_scale;
+      geometry->min_height = size_hints->min_height / impl->window_scale;
+    }
+
+  if (size_hints->flags & PMaxSize)
+    {
+      *geom_mask |= GDK_HINT_MAX_SIZE;
+      geometry->max_width = MAX (size_hints->max_width, 1) / impl->window_scale;
+      geometry->max_height = MAX (size_hints->max_height, 1) / impl->window_scale;
+    }
+
+  if (size_hints->flags & PResizeInc)
+    {
+      *geom_mask |= GDK_HINT_RESIZE_INC;
+      geometry->width_inc = size_hints->width_inc / impl->window_scale;
+      geometry->height_inc = size_hints->height_inc / impl->window_scale;
+    }
+
+  if (size_hints->flags & PAspect)
+    {
+      *geom_mask |= GDK_HINT_ASPECT;
+
+      geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
+      geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
+    }
+
+  if (size_hints->flags & PWinGravity)
+    {
+      *geom_mask |= GDK_HINT_WIN_GRAVITY;
+      geometry->win_gravity = size_hints->win_gravity;
+    }
+
+  XFree (size_hints);
+}
+
+static gboolean
+utf8_is_latin1 (const gchar *str)
+{
+  const char *p = str;
+
+  while (*p)
+    {
+      gunichar ch = g_utf8_get_char (p);
+
+      if (ch > 0xff)
+       return FALSE;
+      
+      p = g_utf8_next_char (p);
+    }
+
+  return TRUE;
+}
+
+/* Set the property to @utf8_str as STRING if the @utf8_str is fully
+ * convertable to STRING, otherwise, set it as compound text
+ */
+static void
+set_text_property (GdkDisplay  *display,
+                  Window       xwindow,
+                  Atom         property,
+                  const gchar *utf8_str)
+{
+  gchar *prop_text = NULL;
+  Atom prop_type;
+  gint prop_length;
+  gint prop_format;
+  gboolean is_compound_text;
+  
+  if (utf8_is_latin1 (utf8_str))
+    {
+      prop_type = XA_STRING;
+      prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
+      prop_length = prop_text ? strlen (prop_text) : 0;
+      prop_format = 8;
+      is_compound_text = FALSE;
+    }
+  else
+    {
+      GdkAtom gdk_type;
+
+      gdk_x11_display_utf8_to_compound_text (display,
+                                             utf8_str, &gdk_type, &prop_format,
+                                             (guchar **)&prop_text, &prop_length);
+      prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
+      is_compound_text = TRUE;
+    }
+
+  if (prop_text)
+    {
+      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                      xwindow,
+                      property,
+                      prop_type, prop_format,
+                      PropModeReplace, (guchar *)prop_text,
+                      prop_length);
+
+      if (is_compound_text)
+       gdk_x11_free_compound_text ((guchar *)prop_text);
+      else
+       g_free (prop_text);
+    }
+}
+
+/* Set WM_NAME and _NET_WM_NAME
+ */
+static void
+set_wm_name (GdkDisplay  *display,
+            Window       xwindow,
+            const gchar *name)
+{
+  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
+                  gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
+                  gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
+                  PropModeReplace, (guchar *)name, strlen (name));
+  
+  set_text_property (display, xwindow,
+                    gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
+                    name);
+}
+
+static void
+gdk_x11_surface_set_title (GdkSurface   *window,
+                         const gchar *title)
+{
+  GdkDisplay *display;
+  Display *xdisplay;
+  Window xwindow;
+  
+  g_return_if_fail (title != NULL);
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+  
+  display = gdk_surface_get_display (window);
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  xwindow = GDK_SURFACE_XID (window);
+
+  set_wm_name (display, xwindow, title);
+  
+  if (!gdk_surface_icon_name_set (window))
+    {
+      XChangeProperty (xdisplay, xwindow,
+                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
+                      gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
+                      PropModeReplace, (guchar *)title, strlen (title));
+      
+      set_text_property (display, xwindow,
+                        gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
+                        title);
+    }
+}
+
+static void
+gdk_x11_surface_set_role (GdkSurface   *window,
+                        const gchar *role)
+{
+  GdkDisplay *display;
+
+  display = gdk_surface_get_display (window);
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (role)
+    XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
+                     gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
+                     XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
+  else
+    XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
+                     gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
+}
+
+static void
+gdk_x11_surface_set_startup_id (GdkSurface   *window,
+                              const gchar *startup_id)
+{
+  GdkDisplay *display;
+
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  display = gdk_surface_get_display (window);
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (startup_id)
+    XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
+                     gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"), 
+                     gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
+                     PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
+  else
+    XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
+                     gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
+}
+
+static void
+gdk_x11_surface_set_transient_for (GdkSurface *window,
+                                 GdkSurface *parent)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  /* XSetTransientForHint() doesn't allow unsetting, so do it manually */
+  if (parent && !GDK_SURFACE_DESTROYED (parent))
+    XSetTransientForHint (GDK_SURFACE_XDISPLAY (window), 
+                         GDK_SURFACE_XID (window),
+                         GDK_SURFACE_XID (parent));
+  else
+    XDeleteProperty (GDK_SURFACE_XDISPLAY (window),
+                     GDK_SURFACE_XID (window),
+                     gdk_x11_get_xatom_by_name_for_display (GDK_SURFACE_DISPLAY (window), "WM_TRANSIENT_FOR"));
+}
+
+GdkCursor *
+_gdk_x11_surface_get_cursor (GdkSurface *window)
+{
+  GdkSurfaceImplX11 *impl;
+  
+  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
+    
+  impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  return impl->cursor;
+}
+
+static void
+gdk_surface_x11_get_geometry (GdkSurface *window,
+                             gint      *x,
+                             gint      *y,
+                             gint      *width,
+                             gint      *height)
+{
+  GdkSurfaceImplX11 *impl;
+  Window root;
+  gint tx;
+  gint ty;
+  guint twidth;
+  guint theight;
+  guint tborder_width;
+  guint tdepth;
+  
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+      XGetGeometry (GDK_SURFACE_XDISPLAY (window),
+                   GDK_SURFACE_XID (window),
+                   &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
+      
+      if (x)
+       *x = tx / impl->window_scale;
+      if (y)
+       *y = ty / impl->window_scale;
+      if (width)
+       *width = twidth / impl->window_scale;
+      if (height)
+       *height = theight / impl->window_scale;
+    }
+}
+
+static void
+gdk_surface_x11_get_root_coords (GdkSurface *window,
+                               gint       x,
+                               gint       y,
+                               gint      *root_x,
+                               gint      *root_y)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+  Window child;
+  gint tx;
+  gint ty;
+  
+  XTranslateCoordinates (GDK_SURFACE_XDISPLAY (window),
+                         GDK_SURFACE_XID (window),
+                         GDK_SURFACE_XROOTWIN (window),
+                         x * impl->window_scale, y * impl->window_scale, &tx, &ty,
+                         &child);
+
+  if (root_x)
+    *root_x = tx / impl->window_scale;
+  if (root_y)
+    *root_y = ty / impl->window_scale;
+}
+
+static void
+gdk_x11_surface_get_frame_extents (GdkSurface    *window,
+                                  GdkRectangle *rect)
+{
+  GdkDisplay *display;
+  GdkSurfaceImplX11 *impl;
+  Window xwindow;
+  Window xparent;
+  Window root;
+  Window child;
+  Window *children;
+  guchar *data;
+  Window *vroots;
+  Atom type_return;
+  guint nchildren;
+  guint nvroots;
+  gulong nitems_return;
+  gulong bytes_after_return;
+  gint format_return;
+  gint i;
+  guint ww, wh, wb, wd;
+  gint wx, wy;
+  gboolean got_frame_extents = FALSE;
+
+  g_return_if_fail (rect != NULL);
+
+  rect->x = 0;
+  rect->y = 0;
+  rect->width = 1;
+  rect->height = 1;
+
+  while (window->parent && (window->parent)->parent)
+    window = window->parent;
+
+  impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  /* Refine our fallback answer a bit using local information */
+  rect->x = window->x * impl->window_scale;
+  rect->y = window->y * impl->window_scale;
+  rect->width = window->width * impl->window_scale;
+  rect->height = window->height * impl->window_scale;
+
+  if (GDK_SURFACE_DESTROYED (window) || impl->override_redirect)
+    return;
+
+  nvroots = 0;
+  vroots = NULL;
+
+  display = gdk_surface_get_display (window);
+
+  gdk_x11_display_error_trap_push (display);
+
+  xwindow = GDK_SURFACE_XID (window);
+
+  /* first try: use _NET_FRAME_EXTENTS */
+  if (gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
+                                           g_intern_static_string ("_NET_FRAME_EXTENTS")) &&
+      XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
+                          gdk_x11_get_xatom_by_name_for_display (display,
+                                                                  "_NET_FRAME_EXTENTS"),
+                          0, G_MAXLONG, False, XA_CARDINAL, &type_return,
+                          &format_return, &nitems_return, &bytes_after_return,
+                          &data)
+      == Success)
+    {
+      if ((type_return == XA_CARDINAL) && (format_return == 32) &&
+         (nitems_return == 4) && (data))
+        {
+         gulong *ldata = (gulong *) data;
+         got_frame_extents = TRUE;
+
+         /* try to get the real client window geometry */
+         if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
+                           &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
+              XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
+                                    xwindow, root, 0, 0, &wx, &wy, &child))
+            {
+             rect->x = wx;
+             rect->y = wy;
+             rect->width = ww;
+             rect->height = wh;
+           }
+
+         /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
+         rect->x -= ldata[0];
+         rect->y -= ldata[2];
+         rect->width += ldata[0] + ldata[1];
+         rect->height += ldata[2] + ldata[3];
+       }
+
+      if (data)
+       XFree (data);
+    }
+
+  if (got_frame_extents)
+    goto out;
+
+  /* no frame extents property available, which means we either have a WM that
+     is not EWMH compliant or is broken - try fallback and walk up the window
+     tree to get our window's parent which hopefully is the window frame */
+
+  /* use NETWM_VIRTUAL_ROOTS if available */
+  root = GDK_SURFACE_XROOTWIN (window);
+
+  if (gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
+                                           g_intern_static_string ("_NET_VIRTUAL_ROOTS")) &&
+      XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
+                         gdk_x11_get_xatom_by_name_for_display (display, 
+                                                                "_NET_VIRTUAL_ROOTS"),
+                         0, G_MAXLONG, False, XA_WINDOW, &type_return,
+                         &format_return, &nitems_return, &bytes_after_return,
+                         &data)
+      == Success)
+    {
+      if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
+       {
+         nvroots = nitems_return;
+         vroots = (Window *)data;
+       }
+    }
+
+  xparent = GDK_SURFACE_XID (window);
+
+  do
+    {
+      xwindow = xparent;
+
+      if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
+                      &root, &xparent,
+                      &children, &nchildren))
+       goto out;
+      
+      if (children)
+       XFree (children);
+
+      /* check virtual roots */
+      for (i = 0; i < nvroots; i++)
+       {
+         if (xparent == vroots[i])
+           {
+             root = xparent;
+             break;
+           }
+       }
+    }
+  while (xparent != root);
+
+  if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
+                   &root, &wx, &wy, &ww, &wh, &wb, &wd))
+    {
+      rect->x = wx;
+      rect->y = wy;
+      rect->width = ww;
+      rect->height = wh;
+    }
+
+ out:
+  if (vroots)
+    XFree (vroots);
+
+  /* Here we extend the size to include the extra pixels if we round x/y down
+     as well as round the size up when we divide by scale so that the returned
+     size is guaranteed to cover the real pixels, but it may overshoot a bit
+     in case the window is not positioned/sized according to the scale */
+  rect->width = (rect->width + rect->x % impl->window_scale + impl->window_scale - 1) / impl->window_scale;
+  rect->height = (rect->height + rect->y % impl->window_scale + impl->window_scale - 1) / impl->window_scale;
+  rect->x = rect->x / impl->window_scale;
+  rect->y = rect->y / impl->window_scale;
+  gdk_x11_display_error_trap_pop_ignored (display);
+}
+
+static gboolean
+gdk_surface_x11_get_device_state (GdkSurface       *window,
+                                 GdkDevice       *device,
+                                 gdouble         *x,
+                                 gdouble         *y,
+                                 GdkModifierType *mask)
+{
+  GdkSurface *child;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return FALSE;
+
+  /*HIDPI: handle coords here?*/
+  GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
+                                              &child,
+                                              NULL, NULL,
+                                              x, y, mask);
+  return child != NULL;
+}
+
+static GdkEventMask
+gdk_surface_x11_get_events (GdkSurface *window)
+{
+  XWindowAttributes attrs;
+  GdkEventMask event_mask;
+  GdkEventMask filtered;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return 0;
+  else
+    {
+      XGetWindowAttributes (GDK_SURFACE_XDISPLAY (window),
+                           GDK_SURFACE_XID (window),
+                           &attrs);
+      event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
+      /* if property change was filtered out before, keep it filtered out */
+      filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
+      window->event_mask = event_mask & ((window->event_mask & filtered) | ~filtered);
+
+      return event_mask;
+    }
+}
+static void
+gdk_surface_x11_set_events (GdkSurface    *window,
+                           GdkEventMask  event_mask)
+{
+  long xevent_mask = 0;
+  
+  if (!GDK_SURFACE_DESTROYED (window))
+    {
+      GdkX11Display *display_x11;
+
+      if (GDK_SURFACE_XID (window) != GDK_SURFACE_XROOTWIN (window))
+        xevent_mask = StructureNotifyMask | PropertyChangeMask;
+
+      display_x11 = GDK_X11_DISPLAY (gdk_surface_get_display (window));
+      gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
+                                          GDK_SURFACE_XID (window), event_mask,
+                                          xevent_mask);
+    }
+}
+
+static inline void
+do_shape_combine_region (GdkSurface       *window,
+                        const cairo_region_t *shape_region,
+                        gint             offset_x,
+                        gint             offset_y,
+                        gint             shape)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (shape_region == NULL)
+    {
+      /* Use NULL mask to unset the shape */
+      if (shape == ShapeBounding
+         ? gdk_display_supports_shapes (GDK_SURFACE_DISPLAY (window))
+         : gdk_display_supports_input_shapes (GDK_SURFACE_DISPLAY (window)))
+       {
+         XShapeCombineMask (GDK_SURFACE_XDISPLAY (window),
+                            GDK_SURFACE_XID (window),
+                            shape,
+                            0, 0,
+                            None,
+                            ShapeSet);
+       }
+      return;
+    }
+  
+  if (shape == ShapeBounding
+      ? gdk_display_supports_shapes (GDK_SURFACE_DISPLAY (window))
+      : gdk_display_supports_input_shapes (GDK_SURFACE_DISPLAY (window)))
+    {
+      gint n_rects = 0;
+      XRectangle *xrects = NULL;
+
+      _gdk_x11_region_get_xrectangles (shape_region,
+                                       0, 0, impl->window_scale,
+                                       &xrects, &n_rects);
+      
+      XShapeCombineRectangles (GDK_SURFACE_XDISPLAY (window),
+                               GDK_SURFACE_XID (window),
+                               shape,
+                               offset_x * impl->window_scale,
+                               offset_y * impl->window_scale,
+                               xrects, n_rects,
+                               ShapeSet,
+                               YXBanded);
+      
+      g_free (xrects);
+    }
+}
+
+static void
+gdk_surface_x11_shape_combine_region (GdkSurface       *window,
+                                     const cairo_region_t *shape_region,
+                                     gint             offset_x,
+                                     gint             offset_y)
+{
+  do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
+}
+
+static void 
+gdk_surface_x11_input_shape_combine_region (GdkSurface       *window,
+                                          const cairo_region_t *shape_region,
+                                          gint             offset_x,
+                                          gint             offset_y)
+{
+#ifdef ShapeInput
+  do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
+#endif
+}
+
+static void
+gdk_x11_surface_set_accept_focus (GdkSurface *window,
+                                gboolean accept_focus)
+{
+  accept_focus = accept_focus != FALSE;
+
+  if (window->accept_focus != accept_focus)
+    {
+      window->accept_focus = accept_focus;
+
+      if (!GDK_SURFACE_DESTROYED (window) &&
+         WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+       update_wm_hints (window, FALSE);
+    }
+}
+
+static void
+gdk_x11_surface_set_focus_on_map (GdkSurface *window,
+                                gboolean focus_on_map)
+{
+  focus_on_map = focus_on_map != FALSE;
+
+  if (window->focus_on_map != focus_on_map)
+    {
+      window->focus_on_map = focus_on_map;
+      
+      if ((!GDK_SURFACE_DESTROYED (window)) &&
+         (!window->focus_on_map) &&
+         WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+       gdk_x11_surface_set_user_time (window, 0);
+    }
+}
+
+/**
+ * gdk_x11_surface_set_user_time:
+ * @window: (type GdkX11Surface): A toplevel #GdkSurface
+ * @timestamp: An XServer timestamp to which the property should be set
+ *
+ * The application can use this call to update the _NET_WM_USER_TIME
+ * property on a toplevel window.  This property stores an Xserver
+ * time which represents the time of the last user input event
+ * received for this window.  This property may be used by the window
+ * manager to alter the focus, stacking, and/or placement behavior of
+ * windows when they are mapped depending on whether the new window
+ * was created by a user action or is a "pop-up" window activated by a
+ * timer or some other event.
+ *
+ * Note that this property is automatically updated by GDK, so this
+ * function should only be used by applications which handle input
+ * events bypassing GDK.
+ **/
+void
+gdk_x11_surface_set_user_time (GdkSurface *window,
+                              guint32    timestamp)
+{
+  GdkDisplay *display;
+  GdkX11Display *display_x11;
+  GdkToplevelX11 *toplevel;
+  glong timestamp_long = (glong)timestamp;
+  Window xid;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  display = gdk_surface_get_display (window);
+  display_x11 = GDK_X11_DISPLAY (display);
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+
+  if (!toplevel)
+    {
+      g_warning ("gdk_surface_set_user_time called on non-toplevel\n");
+      return;
+    }
+
+  if (toplevel->focus_window != None &&
+      gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
+                                           g_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
+    xid = toplevel->focus_window;
+  else
+    xid = GDK_SURFACE_XID (window);
+
+  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
+                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
+                   XA_CARDINAL, 32, PropModeReplace,
+                   (guchar *)&timestamp_long, 1);
+
+  if (timestamp_long != GDK_CURRENT_TIME &&
+      (display_x11->user_time == GDK_CURRENT_TIME ||
+       XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
+    display_x11->user_time = timestamp_long;
+
+  if (toplevel)
+    toplevel->user_time = timestamp_long;
+}
+
+/**
+ * gdk_x11_surface_set_utf8_property:
+ * @window: (type GdkX11Surface): a #GdkSurface
+ * @name: Property name, will be interned as an X atom
+ * @value: (allow-none): Property value, or %NULL to delete
+ *
+ * This function modifies or removes an arbitrary X11 window
+ * property of type UTF8_STRING.  If the given @window is
+ * not a toplevel window, it is ignored.
+ */
+void
+gdk_x11_surface_set_utf8_property  (GdkSurface *window,
+                                  const gchar *name,
+                                  const gchar *value)
+{
+  GdkDisplay *display;
+
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  display = gdk_surface_get_display (window);
+
+  if (value != NULL)
+    {
+      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_SURFACE_XID (window),
+                       gdk_x11_get_xatom_by_name_for_display (display, name),
+                       gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
+                       PropModeReplace, (guchar *)value, strlen (value));
+    }
+  else
+    {
+      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_SURFACE_XID (window),
+                       gdk_x11_get_xatom_by_name_for_display (display, name));
+    }
+}
+
+static void
+gdk_x11_surface_set_shadow_width (GdkSurface *window,
+                                 int        left,
+                                 int        right,
+                                 int        top,
+                                 int        bottom)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+  Atom frame_extents;
+  gulong data[4] = {
+    left * impl->window_scale,
+    right * impl->window_scale,
+    top * impl->window_scale,
+    bottom * impl->window_scale
+  };
+
+  frame_extents = gdk_x11_get_xatom_by_name_for_display (gdk_surface_get_display (window),
+                                                         "_GTK_FRAME_EXTENTS");
+  XChangeProperty (GDK_SURFACE_XDISPLAY (window),
+                   GDK_SURFACE_XID (window),
+                   frame_extents, XA_CARDINAL,
+                   32, PropModeReplace,
+                   (guchar *) &data, 4);
+}
+
+/**
+ * gdk_x11_surface_set_theme_variant:
+ * @window: (type GdkX11Surface): a #GdkSurface
+ * @variant: the theme variant to export
+ *
+ * GTK+ applications can request a dark theme variant. In order to
+ * make other applications - namely window managers using GTK+ for
+ * themeing - aware of this choice, GTK+ uses this function to
+ * export the requested theme variant as _GTK_THEME_VARIANT property
+ * on toplevel windows.
+ *
+ * Note that this property is automatically updated by GTK+, so this
+ * function should only be used by applications which do not use GTK+
+ * to create toplevel windows.
+ */
+void
+gdk_x11_surface_set_theme_variant (GdkSurface  *window,
+                                  const char *variant)
+{
+  gdk_x11_surface_set_utf8_property (window, "_GTK_THEME_VARIANT",
+                                    variant ? variant : "");
+}
+
+#define GDK_SELECTION_MAX_SIZE(display)                                 \
+  MIN(262144,                                                           \
+      XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0     \
+       ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100         \
+       : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
+
+static void
+gdk_surface_update_icon (GdkSurface *window,
+                        GList     *icon_list)
+{
+  GdkToplevelX11 *toplevel;
+  GdkTexture *best_icon;
+  GList *tmp_list;
+  int best_size;
+
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+
+  if (toplevel->icon_pixmap != NULL)
+    {
+      cairo_surface_destroy (toplevel->icon_pixmap);
+      toplevel->icon_pixmap = NULL;
+    }
+
+  if (toplevel->icon_mask != NULL)
+    {
+      cairo_surface_destroy (toplevel->icon_mask);
+      toplevel->icon_mask = NULL;
+    }
+
+#define IDEAL_SIZE 48
+
+  best_size = G_MAXINT;
+  best_icon = NULL;
+  for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
+    {
+      GdkTexture *texture = tmp_list->data;
+      int this;
+
+      /* average width and height - if someone passes in a rectangular
+       * icon they deserve what they get.
+       */
+      this = gdk_texture_get_width (texture) + gdk_texture_get_height (texture);
+      this /= 2;
+
+      if (best_icon == NULL)
+        {
+          best_icon = texture;
+          best_size = this;
+        }
+      else
+        {
+          /* icon is better if it's 32 pixels or larger, and closer to
+           * the ideal size than the current best.
+           */
+          if (this >= 32 &&
+              (ABS (best_size - IDEAL_SIZE) <
+               ABS (this - IDEAL_SIZE)))
+            {
+              best_icon = texture;
+              best_size = this;
+            }
+        }
+    }
+
+  if (best_icon)
+    {
+      int width = gdk_texture_get_width (best_icon);
+      int height = gdk_texture_get_height (best_icon);
+      cairo_surface_t *surface;
+      cairo_t *cr;
+
+      toplevel->icon_pixmap = gdk_x11_surface_create_pixmap_surface (window, width, height);
+
+      surface = gdk_texture_download_surface (best_icon);
+
+      cr = cairo_create (toplevel->icon_pixmap);
+      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+      cairo_set_source_surface (cr, surface, 0, 0);
+      if (cairo_surface_get_content (surface) == CAIRO_CONTENT_COLOR_ALPHA)
+        {
+          /* Saturate the image, so it has bilevel alpha */
+          cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
+          cairo_paint (cr);
+          cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
+          cairo_paint (cr);
+          cairo_pop_group_to_source (cr);
+        }
+      cairo_paint (cr);
+      cairo_destroy (cr);
+
+      if (cairo_surface_get_content (surface) == CAIRO_CONTENT_COLOR_ALPHA)
+        {
+          GdkDisplay *display = gdk_surface_get_display (window);
+
+          toplevel->icon_mask = _gdk_x11_display_create_bitmap_surface (display, width, height);
+
+          cr = cairo_create (toplevel->icon_mask);
+          cairo_set_source_surface (cr, surface, 0, 0);
+          cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+          cairo_paint (cr);
+          cairo_destroy (cr);
+        }
+
+      cairo_surface_destroy (surface);
+    }
+
+  update_wm_hints (window, FALSE);
+}
+
+static void
+gdk_x11_surface_set_icon_list (GdkSurface *window,
+                             GList     *textures)
+{
+  gulong *data;
+  gulong *p;
+  gint size;
+  GList *l;
+  gint width, height;
+  GdkTexture *texture;
+  GdkDisplay *display;
+  gint i, n;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  display = gdk_surface_get_display (window);
+
+  size = 0;
+  n = 0;
+  for (l = textures; l != NULL; l = l->next)
+    {
+      texture = l->data;
+
+      width = gdk_texture_get_width (texture);
+      height = gdk_texture_get_height (texture);
+
+      /* silently ignore overlarge icons */
+      if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
+        break;
+
+      n++;
+      size += 2 + width * height;
+    }
+
+  data = g_malloc (size * sizeof (gulong));
+
+  p = data;
+  for (l = textures; l != NULL && n > 0; l = l->next)
+    {
+      texture = l->data;
+
+      width = gdk_texture_get_width (texture);
+      height = gdk_texture_get_height (texture);
+
+      *p++ = width;
+      *p++ = height;
+
+      gdk_texture_download (texture, (guchar *) p, width * 4);
+      if (sizeof (gulong) > 4)
+        {
+          i = width * height;
+          while (i-- > 0)
+            p[i] = ((guint32 *) p)[i];
+        }
+
+      p += width * height;
+      n--;
+    }
+
+  if (size > 0)
+    {
+      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_SURFACE_XID (window),
+                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
+                       XA_CARDINAL, 32,
+                       PropModeReplace,
+                       (guchar*) data, size);
+    }
+  else
+    {
+      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_SURFACE_XID (window),
+                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
+    }
+  
+  g_free (data);
+
+  gdk_surface_update_icon (window, textures);
+}
+
+static gboolean
+gdk_surface_icon_name_set (GdkSurface *window)
+{
+  return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
+                                              g_quark_from_static_string ("gdk-icon-name-set")));
+}
+
+static void
+gdk_x11_surface_set_icon_name (GdkSurface   *window,
+                             const gchar *name)
+{
+  GdkDisplay *display;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  display = gdk_surface_get_display (window);
+
+  g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
+                      GUINT_TO_POINTER (name != NULL));
+
+  if (name != NULL)
+    {
+      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_SURFACE_XID (window),
+                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
+                       gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
+                       PropModeReplace, (guchar *)name, strlen (name));
+
+      set_text_property (display, GDK_SURFACE_XID (window),
+                         gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
+                         name);
+    }
+  else
+    {
+      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_SURFACE_XID (window),
+                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
+      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_SURFACE_XID (window),
+                       gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
+    }
+}
+
+static void
+gdk_x11_surface_iconify (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {  
+      XIconifyWindow (GDK_SURFACE_XDISPLAY (window),
+                     GDK_SURFACE_XID (window),
+                     gdk_x11_screen_get_screen_number (GDK_SURFACE_SCREEN (window)));
+    }
+  else
+    {
+      /* Flip our client side flag, the real work happens on map. */
+      gdk_synthesize_window_state (window,
+                                   0,
+                                   GDK_SURFACE_STATE_ICONIFIED);
+      gdk_wmspec_change_state (TRUE, window,
+                               g_intern_static_string ("_NET_WM_STATE_HIDDEN"),
+                               NULL);
+    }
+}
+
+static void
+gdk_x11_surface_deiconify (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {  
+      gdk_surface_show (window);
+      gdk_wmspec_change_state (FALSE, window,
+                               g_intern_static_string ("_NET_WM_STATE_HIDDEN"),
+                               NULL);
+    }
+  else
+    {
+      /* Flip our client side flag, the real work happens on map. */
+      gdk_synthesize_window_state (window,
+                                   GDK_SURFACE_STATE_ICONIFIED,
+                                   0);
+      gdk_wmspec_change_state (FALSE, window,
+                               g_intern_static_string ("_NET_WM_STATE_HIDDEN"),
+                               NULL);
+    }
+}
+
+static void
+gdk_x11_surface_stick (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      /* "stick" means stick to all desktops _and_ do not scroll with the
+       * viewport. i.e. glue to the monitor glass in all cases.
+       */
+      
+      XClientMessageEvent xclient;
+
+      /* Request stick during viewport scroll */
+      gdk_wmspec_change_state (TRUE, window,
+                              g_intern_static_string ("_NET_WM_STATE_STICKY"),
+                              NULL);
+
+      /* Request desktop 0xFFFFFFFF */
+      memset (&xclient, 0, sizeof (xclient));
+      xclient.type = ClientMessage;
+      xclient.window = GDK_SURFACE_XID (window);
+      xclient.display = GDK_SURFACE_XDISPLAY (window);
+      xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_SURFACE_DISPLAY (window), 
+                                                                       "_NET_WM_DESKTOP");
+      xclient.format = 32;
+
+      xclient.data.l[0] = 0xFFFFFFFF;
+      xclient.data.l[1] = 0;
+      xclient.data.l[2] = 0;
+      xclient.data.l[3] = 0;
+      xclient.data.l[4] = 0;
+
+      XSendEvent (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XROOTWIN (window), False,
+                  SubstructureRedirectMask | SubstructureNotifyMask,
+                  (XEvent *)&xclient);
+    }
+  else
+    {
+      /* Flip our client side flag, the real work happens on map. */
+      gdk_synthesize_window_state (window,
+                                   0,
+                                   GDK_SURFACE_STATE_STICKY);
+    }
+}
+
+static void
+gdk_x11_surface_unstick (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      /* Request unstick from viewport */
+      gdk_wmspec_change_state (FALSE, window,
+                              g_intern_static_string ("_NET_WM_STATE_STICKY"),
+                              NULL);
+
+      move_to_current_desktop (window);
+    }
+  else
+    {
+      /* Flip our client side flag, the real work happens on map. */
+      gdk_synthesize_window_state (window,
+                                   GDK_SURFACE_STATE_STICKY,
+                                   0);
+
+    }
+}
+
+static void
+gdk_x11_surface_maximize (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    gdk_wmspec_change_state (TRUE, window,
+                            g_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
+                            g_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
+  else
+    gdk_synthesize_window_state (window,
+                                0,
+                                GDK_SURFACE_STATE_MAXIMIZED);
+}
+
+static void
+gdk_x11_surface_unmaximize (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    gdk_wmspec_change_state (FALSE, window,
+                            g_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
+                            g_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
+  else
+    gdk_synthesize_window_state (window,
+                                GDK_SURFACE_STATE_MAXIMIZED,
+                                0);
+}
+
+static void
+gdk_x11_surface_apply_fullscreen_mode (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  /* _NET_WM_FULLSCREEN_MONITORS gives an indication to the window manager as
+   * to which monitors so span across when the window is fullscreen, but it's
+   * not a state in itself so this would have no effect if the window is not
+   * mapped.
+   */
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      XClientMessageEvent xclient;
+      gint                monitors[4];
+      gint                i;
+
+      memset (&xclient, 0, sizeof (xclient));
+      xclient.type = ClientMessage;
+      xclient.window = GDK_SURFACE_XID (window);
+      xclient.display = GDK_SURFACE_XDISPLAY (window);
+      xclient.format = 32;
+
+      switch (window->fullscreen_mode)
+       {
+       case GDK_FULLSCREEN_ON_CURRENT_MONITOR:
+
+         /* FIXME: This is not part of the EWMH spec!
+          *
+          * There is no documented mechanism to remove the property
+          * _NET_WM_FULLSCREEN_MONITORS once set, so we use use a set of
+          * invalid, largest possible value.
+          *
+          * When given values larger than actual possible monitor values, most
+          * window managers who support the _NET_WM_FULLSCREEN_MONITORS spec
+          * will simply unset _NET_WM_FULLSCREEN_MONITORS and revert to their
+          * default behavior.
+          *
+          * Successfully tested on mutter/metacity, kwin, compiz and xfwm4.
+          *
+          * Note, this (non documented) mechanism is unlikely to be an issue
+          * as it's used only for transitionning back from "all monitors" to
+          * "current monitor" mode.
+          *
+          * Applications who don't change the default mode won't trigger this
+          * mechanism.
+          */
+         for (i = 0; i < 4; ++i)
+           xclient.data.l[i] = G_MAXLONG;
+
+         break;
+
+       case GDK_FULLSCREEN_ON_ALL_MONITORS:
+
+         _gdk_x11_screen_get_edge_monitors (GDK_SURFACE_SCREEN (window),
+                                            &monitors[0],
+                                            &monitors[1],
+                                            &monitors[2],
+                                            &monitors[3]);
+         /* Translate all 4 monitors from the GDK set into XINERAMA indices */
+         for (i = 0; i < 4; ++i)
+           {
+             xclient.data.l[i] = monitors[i];
+             /* Sanity check, if XINERAMA is not available, we could have invalid
+              * negative values for the XINERAMA indices.
+              */
+             if (xclient.data.l[i] < 0)
+               {
+                 g_warning ("gdk_x11_surface_apply_fullscreen_mode: Invalid XINERAMA monitor index");
+                 return;
+               }
+           }
+         break;
+
+       default:
+         g_warning ("gdk_x11_surface_apply_fullscreen_mode: Unhandled fullscreen mode %d",
+                    window->fullscreen_mode);
+         return;
+       }
+
+      /* Send fullscreen monitors client message */
+      xclient.data.l[4] = 1; /* source indication */
+      xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_SURFACE_DISPLAY (window),
+                                                                   "_NET_WM_FULLSCREEN_MONITORS");
+      XSendEvent (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XROOTWIN (window), False,
+                  SubstructureRedirectMask | SubstructureNotifyMask,
+                  (XEvent *)&xclient);
+    }
+}
+
+static void
+gdk_x11_surface_fullscreen (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      gdk_wmspec_change_state (TRUE, window,
+                              g_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
+                               NULL);
+      /* Actual XRandR layout may have change since we computed the fullscreen
+       * monitors in GDK_FULLSCREEN_ON_ALL_MONITORS mode.
+       */
+      if (window->fullscreen_mode == GDK_FULLSCREEN_ON_ALL_MONITORS)
+       gdk_x11_surface_apply_fullscreen_mode (window);
+    }
+  else
+    gdk_synthesize_window_state (window,
+                                 0,
+                                 GDK_SURFACE_STATE_FULLSCREEN);
+}
+
+static void
+gdk_x11_surface_fullscreen_on_monitor (GdkSurface  *window,
+                                      GdkMonitor *monitor)
+{
+  GdkRectangle geom;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  gdk_monitor_get_geometry (monitor, &geom);
+  gdk_surface_move (window, geom.x, geom.y);
+
+  gdk_surface_set_fullscreen_mode (window, GDK_FULLSCREEN_ON_CURRENT_MONITOR);
+  gdk_x11_surface_fullscreen (window);
+}
+
+static void
+gdk_x11_surface_unfullscreen (GdkSurface *window)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    gdk_wmspec_change_state (FALSE, window,
+                            g_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
+                             NULL);
+
+  else
+    gdk_synthesize_window_state (window,
+                                GDK_SURFACE_STATE_FULLSCREEN,
+                                0);
+}
+
+static void
+gdk_x11_surface_set_keep_above (GdkSurface *window,
+                              gboolean   setting)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      if (setting)
+       gdk_wmspec_change_state (FALSE, window,
+                                g_intern_static_string ("_NET_WM_STATE_BELOW"),
+                                NULL);
+      gdk_wmspec_change_state (setting, window,
+                              g_intern_static_string ("_NET_WM_STATE_ABOVE"),
+                              NULL);
+    }
+  else
+    gdk_synthesize_window_state (window,
+                                setting ? GDK_SURFACE_STATE_BELOW : GDK_SURFACE_STATE_ABOVE,
+                                setting ? GDK_SURFACE_STATE_ABOVE : 0);
+}
+
+static void
+gdk_x11_surface_set_keep_below (GdkSurface *window, gboolean setting)
+{
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  if (GDK_SURFACE_IS_MAPPED (window))
+    {
+      if (setting)
+       gdk_wmspec_change_state (FALSE, window,
+                                g_intern_static_string ("_NET_WM_STATE_ABOVE"),
+                                NULL);
+      gdk_wmspec_change_state (setting, window,
+                              g_intern_static_string ("_NET_WM_STATE_BELOW"),
+                              NULL);
+    }
+  else
+    gdk_synthesize_window_state (window,
+                                setting ? GDK_SURFACE_STATE_ABOVE : GDK_SURFACE_STATE_BELOW,
+                                setting ? GDK_SURFACE_STATE_BELOW : 0);
+}
+
+static GdkSurface *
+gdk_x11_surface_get_group (GdkSurface *window)
+{
+  GdkToplevelX11 *toplevel;
+  
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return NULL;
+  
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+
+  return toplevel->group_leader;
+}
+
+static void
+gdk_x11_surface_set_group (GdkSurface *window,
+                         GdkSurface *leader)
+{
+  GdkToplevelX11 *toplevel;
+  
+  g_return_if_fail (GDK_IS_SURFACE (window));
+  g_return_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD);
+  g_return_if_fail (leader == NULL || GDK_IS_SURFACE (leader));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      (leader != NULL && GDK_SURFACE_DESTROYED (leader)) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  toplevel = _gdk_x11_surface_get_toplevel (window);
+
+  if (leader == NULL)
+    leader = gdk_display_get_default_group (gdk_surface_get_display (window));
+  
+  if (toplevel->group_leader != leader)
+    {
+      if (toplevel->group_leader)
+       g_object_unref (toplevel->group_leader);
+      toplevel->group_leader = g_object_ref (leader);
+      (_gdk_x11_surface_get_toplevel (leader))->is_leader = TRUE;      
+    }
+
+  update_wm_hints (window, FALSE);
+}
+
+static MotifWmHints *
+gdk_surface_get_mwm_hints (GdkSurface *window)
+{
+  GdkDisplay *display;
+  Atom hints_atom = None;
+  guchar *data;
+  Atom type;
+  gint format;
+  gulong nitems;
+  gulong bytes_after;
+  
+  if (GDK_SURFACE_DESTROYED (window))
+    return NULL;
+
+  display = gdk_surface_get_display (window);
+  
+  hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
+
+  XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
+                     hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
+                     False, AnyPropertyType, &type, &format, &nitems,
+                     &bytes_after, &data);
+
+  if (type == None)
+    return NULL;
+  
+  return (MotifWmHints *)data;
+}
+
+static void
+gdk_surface_set_mwm_hints (GdkSurface *window,
+                         MotifWmHints *new_hints)
+{
+  GdkDisplay *display;
+  Atom hints_atom = None;
+  guchar *data;
+  MotifWmHints *hints;
+  Atom type;
+  gint format;
+  gulong nitems;
+  gulong bytes_after;
+  
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+  
+  display = gdk_surface_get_display (window);
+  
+  hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
+
+  XGetWindowProperty (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XID (window),
+                     hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
+                     False, AnyPropertyType, &type, &format, &nitems,
+                     &bytes_after, &data);
+  
+  if (type == None)
+    hints = new_hints;
+  else
+    {
+      hints = (MotifWmHints *)data;
+       
+      if (new_hints->flags & MWM_HINTS_FUNCTIONS)
+       {
+         hints->flags |= MWM_HINTS_FUNCTIONS;
+         hints->functions = new_hints->functions;
+       }
+      if (new_hints->flags & MWM_HINTS_DECORATIONS)
+       {
+         hints->flags |= MWM_HINTS_DECORATIONS;
+         hints->decorations = new_hints->decorations;
+       }
+    }
+  
+  XChangeProperty (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XID (window),
+                  hints_atom, hints_atom, 32, PropModeReplace,
+                  (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
+  
+  if (hints != new_hints)
+    XFree (hints);
+}
+
+static void
+gdk_x11_surface_set_decorations (GdkSurface      *window,
+                               GdkWMDecoration decorations)
+{
+  MotifWmHints hints;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+  
+  /* initialize to zero to avoid writing uninitialized data to socket */
+  memset(&hints, 0, sizeof(hints));
+  hints.flags = MWM_HINTS_DECORATIONS;
+  hints.decorations = decorations;
+  
+  gdk_surface_set_mwm_hints (window, &hints);
+}
+
+static gboolean
+gdk_x11_surface_get_decorations(GdkSurface       *window,
+                              GdkWMDecoration *decorations)
+{
+  MotifWmHints *hints;
+  gboolean result = FALSE;
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return FALSE;
+  
+  hints = gdk_surface_get_mwm_hints (window);
+  
+  if (hints)
+    {
+      if (hints->flags & MWM_HINTS_DECORATIONS)
+       {
+         if (decorations)
+           *decorations = hints->decorations;
+         result = TRUE;
+       }
+      
+      XFree (hints);
+    }
+
+  return result;
+}
+
+static void
+gdk_x11_surface_set_functions (GdkSurface    *window,
+                              GdkWMFunction functions)
+{
+  MotifWmHints hints;
+  
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+  
+  /* initialize to zero to avoid writing uninitialized data to socket */
+  memset(&hints, 0, sizeof(hints));
+  hints.flags = MWM_HINTS_FUNCTIONS;
+  hints.functions = functions;
+  
+  gdk_surface_set_mwm_hints (window, &hints);
+}
+
+cairo_region_t *
+_gdk_x11_xwindow_get_shape (Display *xdisplay,
+                            Window   window,
+                            gint     scale,
+                            gint     shape_type)
+{
+  cairo_region_t *shape;
+  GdkRectangle *rl;
+  XRectangle *xrl;
+  gint rn, ord, i;
+
+  shape = NULL;
+  rn = 0;
+
+  /* Note that XShapeGetRectangles returns NULL in two situations:
+   * - the server doesn't support the SHAPE extension
+   * - the shape is empty
+   *
+   * Since we can't discriminate these here, we always return
+   * an empty shape. It is the callers responsibility to check
+   * whether the server supports the SHAPE extensions beforehand.
+   */
+  xrl = XShapeGetRectangles (xdisplay, window, shape_type, &rn, &ord);
+
+  if (rn == 0)
+    return cairo_region_create (); /* Empty */
+
+  if (ord != YXBanded)
+    {
+      /* This really shouldn't happen with any xserver, as they
+       * generally convert regions to YXBanded internally
+       */
+      g_warning ("non YXBanded shape masks not supported");
+      XFree (xrl);
+      return NULL;
+    }
+
+  /* NOTE: The scale divisions here may lose some precision if someone
+     else set the shape to be non-scale precision */
+  rl = g_new (GdkRectangle, rn);
+  for (i = 0; i < rn; i++)
+    {
+      rl[i].x = xrl[i].x / scale;
+      rl[i].y = xrl[i].y / scale;
+      rl[i].width = xrl[i].width / scale;
+      rl[i].height = xrl[i].height / scale;
+    }
+  XFree (xrl);
+
+  shape = cairo_region_create_rectangles (rl, rn);
+  g_free (rl);
+
+  return shape;
+}
+
+/* From the WM spec */
+#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT      0
+#define _NET_WM_MOVERESIZE_SIZE_TOP          1
+#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT     2
+#define _NET_WM_MOVERESIZE_SIZE_RIGHT        3
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT  4
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOM       5
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT   6
+#define _NET_WM_MOVERESIZE_SIZE_LEFT         7
+#define _NET_WM_MOVERESIZE_MOVE              8   /* movement only */
+#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD     9   /* size via keyboard */
+#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD    10   /* move via keyboard */
+#define _NET_WM_MOVERESIZE_CANCEL           11   /* cancel operation */
+
+static void
+wmspec_send_message (GdkDisplay *display,
+                     GdkSurface  *window,
+                     gint        root_x,
+                     gint        root_y,
+                     gint        action,
+                     gint        button)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+  XClientMessageEvent xclient;
+
+  memset (&xclient, 0, sizeof (xclient));
+  xclient.type = ClientMessage;
+  xclient.window = GDK_SURFACE_XID (window);
+  xclient.message_type =
+    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
+  xclient.format = 32;
+  xclient.data.l[0] = root_x * impl->window_scale;
+  xclient.data.l[1] = root_y * impl->window_scale;
+  xclient.data.l[2] = action;
+  xclient.data.l[3] = button;
+  xclient.data.l[4] = 1;  /* source indication */
+
+  XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XROOTWIN (window), False,
+              SubstructureRedirectMask | SubstructureNotifyMask,
+              (XEvent *)&xclient);
+}
+
+static void
+handle_wmspec_button_release (GdkDisplay   *display,
+                              const XEvent *xevent)
+{
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
+  GdkSurface *window;
+
+#if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
+  XIEvent *xiev = (XIEvent *) xevent->xcookie.data;
+  XIDeviceEvent *xidev = (XIDeviceEvent *) xiev;
+
+  if (xevent->xany.type == GenericEvent)
+    window = gdk_x11_surface_lookup_for_display (display, xidev->event);
+  else
+#endif
+    window = gdk_x11_surface_lookup_for_display (display, xevent->xany.window);
+
+  if (display_x11->wm_moveresize_button != 0 && window != NULL)
+    {
+      if ((xevent->xany.type == ButtonRelease &&
+           xevent->xbutton.button == display_x11->wm_moveresize_button)
+#if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
+          ||
+          (xevent->xany.type == GenericEvent &&
+           xiev->evtype == XI_ButtonRelease &&
+           xidev->detail == display_x11->wm_moveresize_button)
+#endif
+          )
+        {
+          display_x11->wm_moveresize_button = 0;
+          wmspec_send_message (display, window, 0, 0, _NET_WM_MOVERESIZE_CANCEL, 0);
+        }
+    }
+}
+
+static void
+wmspec_moveresize (GdkSurface *window,
+                   gint       direction,
+                   GdkDevice *device,
+                   gint       button,
+                   gint       root_x,
+                   gint       root_y,
+                   guint32    timestamp)
+{
+  GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
+
+  if (button != 0)
+    gdk_seat_ungrab (gdk_device_get_seat (device)); /* Release passive grab */
+  GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
+
+  wmspec_send_message (display, window, root_x, root_y, direction, button);
+}
+
+static void
+wmspec_resize_drag (GdkSurface     *window,
+                    GdkSurfaceEdge  edge,
+                    GdkDevice     *device,
+                    gint           button,
+                    gint           root_x,
+                    gint           root_y,
+                    guint32        timestamp)
+{
+  gint direction;
+  
+  if (button == 0)
+    direction = _NET_WM_MOVERESIZE_SIZE_KEYBOARD;
+  else
+    switch (edge)
+      {
+      /* Let the compiler turn a switch into a table, instead
+       * of doing the table manually, this way is easier to verify.
+       */
+      case GDK_SURFACE_EDGE_NORTH_WEST:
+        direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
+        break;
+
+      case GDK_SURFACE_EDGE_NORTH:
+        direction = _NET_WM_MOVERESIZE_SIZE_TOP;
+        break;
+
+      case GDK_SURFACE_EDGE_NORTH_EAST:
+        direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
+        break;
+
+      case GDK_SURFACE_EDGE_WEST:
+        direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
+        break;
+
+      case GDK_SURFACE_EDGE_EAST:
+        direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
+        break;
+
+      case GDK_SURFACE_EDGE_SOUTH_WEST:
+        direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
+        break;
+
+      case GDK_SURFACE_EDGE_SOUTH:
+        direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
+        break;
+
+      case GDK_SURFACE_EDGE_SOUTH_EAST:
+        direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
+        break;
+
+      default:
+        g_warning ("gdk_surface_begin_resize_drag: bad resize edge %d!",
+                   edge);
+        return;
+      }
+  
+  wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
+}
+
+typedef struct _MoveResizeData MoveResizeData;
+
+struct _MoveResizeData
+{
+  GdkDisplay *display;
+
+  GdkSurface *moveresize_window;
+  GdkSurface *moveresize_emulation_window;
+  gboolean is_resize;
+  GdkSurfaceEdge resize_edge;
+  GdkDevice *device;
+  gint moveresize_button;
+  gint moveresize_x;
+  gint moveresize_y;
+  gint moveresize_orig_x;
+  gint moveresize_orig_y;
+  gint moveresize_orig_width;
+  gint moveresize_orig_height;
+  GdkSurfaceHints moveresize_geom_mask;
+  GdkGeometry moveresize_geometry;
+  Time moveresize_process_time;
+  XEvent *moveresize_pending_event;
+};
+
+static MoveResizeData *
+get_move_resize_data (GdkDisplay *display,
+                     gboolean    create)
+{
+  MoveResizeData *mv_resize;
+  static GQuark move_resize_quark = 0;
+
+  if (!move_resize_quark)
+    move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
+  
+  mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
+
+  if (!mv_resize && create)
+    {
+      mv_resize = g_new0 (MoveResizeData, 1);
+      mv_resize->display = display;
+      
+      g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
+    }
+
+  return mv_resize;
+}
+
+static void
+check_maximize (MoveResizeData *mv_resize,
+                gdouble         x_root,
+                gdouble         y_root)
+{
+  GdkSurfaceState state;
+  gint y;
+
+  if (mv_resize->is_resize)
+    return;
+
+  state = gdk_surface_get_state (mv_resize->moveresize_window);
+
+  if (state & GDK_SURFACE_STATE_MAXIMIZED)
+    return;
+
+  y = mv_resize->moveresize_orig_y + (y_root - mv_resize->moveresize_y);
+
+  if (y < 10)
+    gdk_surface_maximize (mv_resize->moveresize_window);
+}
+
+static void
+check_unmaximize (MoveResizeData *mv_resize,
+                  gdouble         x_root,
+                  gdouble         y_root)
+{
+  GdkSurfaceState state;
+  gint dx, dy;
+
+  if (mv_resize->is_resize)
+    return;
+
+  state = gdk_surface_get_state (mv_resize->moveresize_window);
+
+  if ((state & (GDK_SURFACE_STATE_MAXIMIZED | GDK_SURFACE_STATE_TILED)) == 0)
+    return;
+
+  dx = x_root - mv_resize->moveresize_x;
+  dy = y_root - mv_resize->moveresize_y;
+
+  if (ABS (dx) > 20 || ABS (dy) > 20)
+    gdk_surface_unmaximize (mv_resize->moveresize_window);
+}
+
+static void
+update_pos (MoveResizeData *mv_resize,
+           gint            new_root_x,
+           gint            new_root_y)
+{
+  gint dx, dy;
+
+  check_unmaximize (mv_resize, new_root_x, new_root_y);
+  dx = new_root_x - mv_resize->moveresize_x;
+  dy = new_root_y - mv_resize->moveresize_y;
+
+  if (mv_resize->is_resize)
+    {
+      gint x, y, w, h;
+
+      x = mv_resize->moveresize_orig_x;
+      y = mv_resize->moveresize_orig_y;
+
+      w = mv_resize->moveresize_orig_width;
+      h = mv_resize->moveresize_orig_height;
+
+      switch (mv_resize->resize_edge)
+       {
+       case GDK_SURFACE_EDGE_NORTH_WEST:
+         x += dx;
+         y += dy;
+         w -= dx;
+         h -= dy;
+         break;
+       case GDK_SURFACE_EDGE_NORTH:
+         y += dy;
+         h -= dy;
+         break;
+       case GDK_SURFACE_EDGE_NORTH_EAST:
+         y += dy;
+         h -= dy;
+         w += dx;
+         break;
+       case GDK_SURFACE_EDGE_SOUTH_WEST:
+         h += dy;
+         x += dx;
+         w -= dx;
+         break;
+       case GDK_SURFACE_EDGE_SOUTH_EAST:
+         w += dx;
+         h += dy;
+         break;
+       case GDK_SURFACE_EDGE_SOUTH:
+         h += dy;
+         break;
+       case GDK_SURFACE_EDGE_EAST:
+         w += dx;
+         break;
+       case GDK_SURFACE_EDGE_WEST:
+         x += dx;
+         w -= dx;
+         break;
+        default:
+          break;
+       }
+
+      x = MAX (x, 0);
+      y = MAX (y, 0);
+      w = MAX (w, 1);
+      h = MAX (h, 1);
+
+      if (mv_resize->moveresize_geom_mask)
+       {
+         gdk_surface_constrain_size (&mv_resize->moveresize_geometry,
+                                    mv_resize->moveresize_geom_mask,
+                                    w, h, &w, &h);
+       }
+
+      gdk_surface_move_resize (mv_resize->moveresize_window, x, y, w, h);
+    }
+  else
+    {
+      gint x, y;
+
+      x = mv_resize->moveresize_orig_x + dx;
+      y = mv_resize->moveresize_orig_y + dy;
+
+      gdk_surface_move (mv_resize->moveresize_window, x, y);
+    }
+}
+
+static void
+finish_drag (MoveResizeData *mv_resize)
+{
+  gdk_surface_destroy (mv_resize->moveresize_emulation_window);
+  mv_resize->moveresize_emulation_window = NULL;
+  g_clear_object (&mv_resize->moveresize_window);
+  g_clear_pointer (&mv_resize->moveresize_pending_event, g_free);
+}
+
+static int
+lookahead_motion_predicate (Display *xdisplay,
+                           XEvent  *event,
+                           XPointer arg)
+{
+  gboolean *seen_release = (gboolean *)arg;
+  GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
+  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
+
+  if (*seen_release)
+    return False;
+
+  switch (event->xany.type)
+    {
+    case ButtonRelease:
+      *seen_release = TRUE;
+      break;
+    case MotionNotify:
+      mv_resize->moveresize_process_time = event->xmotion.time;
+      break;
+    default:
+      break;
+    }
+
+  return False;
+}
+
+static gboolean
+moveresize_lookahead (MoveResizeData *mv_resize,
+                     const XEvent   *event)
+{
+  XEvent tmp_event;
+  gboolean seen_release = FALSE;
+
+  if (mv_resize->moveresize_process_time)
+    {
+      if (event->xmotion.time == mv_resize->moveresize_process_time)
+        {
+          mv_resize->moveresize_process_time = 0;
+          return TRUE;
+        }
+      else
+        return FALSE;
+    }
+
+  XCheckIfEvent (event->xany.display, &tmp_event,
+                 lookahead_motion_predicate, (XPointer) & seen_release);
+
+  return mv_resize->moveresize_process_time == 0;
+}
+
+gboolean
+_gdk_x11_moveresize_handle_event (const XEvent *event)
+{
+  guint button_mask = 0;
+  GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
+  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
+  GdkSurfaceImplX11 *impl;
+
+  if (!mv_resize || !mv_resize->moveresize_window)
+    {
+      handle_wmspec_button_release (display, event);
+      return FALSE;
+    }
+
+  impl = GDK_SURFACE_IMPL_X11 (mv_resize->moveresize_window->impl);
+
+  if (mv_resize->moveresize_button != 0)
+    button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
+
+  switch (event->xany.type)
+    {
+    case MotionNotify:
+      if (mv_resize->moveresize_window->resize_count > 0)
+        {
+          if (mv_resize->moveresize_pending_event)
+            *mv_resize->moveresize_pending_event = *event;
+          else
+            mv_resize->moveresize_pending_event =
+              g_memdup (event, sizeof (XEvent));
+
+          break;
+        }
+      if (!moveresize_lookahead (mv_resize, event))
+        break;
+
+      update_pos (mv_resize,
+                  event->xmotion.x_root / impl->window_scale,
+                  event->xmotion.y_root / impl->window_scale);
+
+      /* This should never be triggered in normal cases, but in the
+       * case where the drag started without an implicit grab being
+       * in effect, we could miss the release if it occurs before
+       * we grab the pointer; this ensures that we will never
+       * get a permanently stuck grab.
+       */
+      if ((event->xmotion.state & button_mask) == 0)
+        {
+          check_maximize (mv_resize,
+                          event->xmotion.x_root / impl->window_scale,
+                          event->xmotion.y_root / impl->window_scale);
+          finish_drag (mv_resize);
+        }
+      break;
+
+    case ButtonRelease:
+      update_pos (mv_resize,
+                  event->xbutton.x_root / impl->window_scale,
+                  event->xbutton.y_root / impl->window_scale);
+
+      if (event->xbutton.button == mv_resize->moveresize_button)
+        {
+          check_maximize (mv_resize,
+                          event->xmotion.x_root / impl->window_scale,
+                          event->xmotion.y_root / impl->window_scale);
+          finish_drag (mv_resize);
+        }
+      break;
+
+#if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
+    case GenericEvent:
+      {
+        /* we just assume this is an XI2 event */
+        XIEvent *ev = (XIEvent *) event->xcookie.data;
+        XIDeviceEvent *xev = (XIDeviceEvent *)ev;
+        gint state;
+        switch (ev->evtype)
+          {
+          case XI_Motion:
+            update_pos (mv_resize, xev->root_x / impl->window_scale, xev->root_y / impl->window_scale);
+            state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+            if ((state & button_mask) == 0)
+              {
+                check_maximize (mv_resize,
+                                xev->root_x / impl->window_scale,
+                                xev->root_y / impl->window_scale);
+                finish_drag (mv_resize);
+              }
+            break;
+
+          case XI_ButtonRelease:
+            update_pos (mv_resize, xev->root_x / impl->window_scale, xev->root_y / impl->window_scale);
+            if (xev->detail == mv_resize->moveresize_button)
+              {
+                check_maximize (mv_resize,
+                                xev->root_x / impl->window_scale,
+                                xev->root_y / impl->window_scale);
+                finish_drag (mv_resize);
+              }
+            break;
+          default:
+            break;
+          }
+      }
+      break;
+#endif
+
+    default:
+      break;
+
+    }
+  return TRUE;
+}
+
+gboolean
+_gdk_x11_moveresize_configure_done (GdkDisplay *display,
+                                    GdkSurface  *window)
+{
+  XEvent *tmp_event;
+  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
+
+  if (!mv_resize || window != mv_resize->moveresize_window)
+    return FALSE;
+
+  if (mv_resize->moveresize_pending_event)
+    {
+      tmp_event = mv_resize->moveresize_pending_event;
+      mv_resize->moveresize_pending_event = NULL;
+      _gdk_x11_moveresize_handle_event (tmp_event);
+      g_free (tmp_event);
+    }
+
+  return TRUE;
+}
+
+static void
+create_moveresize_window (MoveResizeData *mv_resize,
+                          guint32         timestamp)
+{
+  GdkGrabStatus status;
+
+  g_assert (mv_resize->moveresize_emulation_window == NULL);
+
+  mv_resize->moveresize_emulation_window = gdk_surface_new_temp (mv_resize->display);
+  gdk_surface_show (mv_resize->moveresize_emulation_window);
+
+  status = gdk_seat_grab (gdk_device_get_seat (mv_resize->device),
+                          mv_resize->moveresize_emulation_window,
+                          GDK_SEAT_CAPABILITY_POINTER, FALSE,
+                          NULL, NULL, NULL, NULL);
+
+  if (status != GDK_GRAB_SUCCESS)
+    {
+      /* If this fails, some other client has grabbed the window
+       * already.
+       */
+      finish_drag (mv_resize);
+    }
+
+  mv_resize->moveresize_process_time = 0;
+}
+
+/* 
+   Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
+   so that calling XMoveWindow with these coordinates will not move the 
+   window.
+   Note that this depends on the WM to implement ICCCM-compliant reference
+   point handling.
+*/
+static void 
+calculate_unmoving_origin (MoveResizeData *mv_resize)
+{
+  GdkRectangle rect;
+  gint width, height;
+
+  if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
+      mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
+    {
+      gdk_surface_get_origin (mv_resize->moveresize_window,
+                            &mv_resize->moveresize_orig_x,
+                            &mv_resize->moveresize_orig_y);
+    }
+  else
+    {
+      gdk_surface_get_frame_extents (mv_resize->moveresize_window, &rect);
+      gdk_surface_get_geometry (mv_resize->moveresize_window, 
+                              NULL, NULL, &width, &height);
+      
+      switch (mv_resize->moveresize_geometry.win_gravity) 
+       {
+       case GDK_GRAVITY_NORTH_WEST:
+         mv_resize->moveresize_orig_x = rect.x;
+         mv_resize->moveresize_orig_y = rect.y;
+         break;
+       case GDK_GRAVITY_NORTH:
+         mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
+         mv_resize->moveresize_orig_y = rect.y;
+         break;          
+       case GDK_GRAVITY_NORTH_EAST:
+         mv_resize->moveresize_orig_x = rect.x + rect.width - width;
+         mv_resize->moveresize_orig_y = rect.y;
+         break;
+       case GDK_GRAVITY_WEST:
+         mv_resize->moveresize_orig_x = rect.x;
+         mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
+         break;
+       case GDK_GRAVITY_CENTER:
+         mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
+         mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
+         break;
+       case GDK_GRAVITY_EAST:
+         mv_resize->moveresize_orig_x = rect.x + rect.width - width;
+         mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
+         break;
+       case GDK_GRAVITY_SOUTH_WEST:
+         mv_resize->moveresize_orig_x = rect.x;
+         mv_resize->moveresize_orig_y = rect.y + rect.height - height;
+         break;
+       case GDK_GRAVITY_SOUTH:
+         mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
+         mv_resize->moveresize_orig_y = rect.y + rect.height - height;
+         break;
+       case GDK_GRAVITY_SOUTH_EAST:
+         mv_resize->moveresize_orig_x = rect.x + rect.width - width;
+         mv_resize->moveresize_orig_y = rect.y + rect.height - height;
+         break;
+       case GDK_GRAVITY_STATIC:
+       default:
+         mv_resize->moveresize_orig_x = rect.x;
+         mv_resize->moveresize_orig_y = rect.y;
+         break; 
+       }
+    }  
+}
+
+static void
+emulate_resize_drag (GdkSurface     *window,
+                     GdkSurfaceEdge  edge,
+                     GdkDevice     *device,
+                     gint           button,
+                     gint           root_x,
+                     gint           root_y,
+                     guint32        timestamp)
+{
+  MoveResizeData *mv_resize = get_move_resize_data (GDK_SURFACE_DISPLAY (window), TRUE);
+
+  if (mv_resize->moveresize_window != NULL)
+    return; /* already a drag operation in progress */
+
+  mv_resize->is_resize = TRUE;
+  mv_resize->moveresize_button = button;
+  mv_resize->resize_edge = edge;
+  mv_resize->device = device;
+  mv_resize->moveresize_x = root_x;
+  mv_resize->moveresize_y = root_y;
+  mv_resize->moveresize_window = g_object_ref (window);
+
+  mv_resize->moveresize_orig_width = gdk_surface_get_width (window);
+  mv_resize->moveresize_orig_height = gdk_surface_get_height (window);
+
+  mv_resize->moveresize_geom_mask = 0;
+  gdk_surface_get_geometry_hints (window,
+                                &mv_resize->moveresize_geometry,
+                                &mv_resize->moveresize_geom_mask);
+
+  calculate_unmoving_origin (mv_resize);
+
+  create_moveresize_window (mv_resize, timestamp);
+}
+
+static void
+emulate_move_drag (GdkSurface     *window,
+                   GdkDevice     *device,
+                   gint           button,
+                   gint           root_x,
+                   gint           root_y,
+                   guint32        timestamp)
+{
+  MoveResizeData *mv_resize = get_move_resize_data (GDK_SURFACE_DISPLAY (window), TRUE);
+
+  if (mv_resize->moveresize_window != NULL)
+    return; /* already a drag operation in progress */
+
+  mv_resize->is_resize = FALSE;
+  mv_resize->device = device;
+  mv_resize->moveresize_button = button;
+  mv_resize->moveresize_x = root_x;
+  mv_resize->moveresize_y = root_y;
+
+  mv_resize->moveresize_window = g_object_ref (window);
+
+  calculate_unmoving_origin (mv_resize);
+
+  create_moveresize_window (mv_resize, timestamp);
+}
+
+static gboolean
+_should_perform_ewmh_drag (GdkSurface *window,
+                           GdkDevice *device)
+{
+  GdkPointerSurfaceInfo *info;
+  GdkDisplay *display;
+
+  display = gdk_surface_get_display (window);
+  info = _gdk_display_get_pointer_info (display, device);
+
+  if ((!info->last_slave || gdk_device_get_source (info->last_slave) != GDK_SOURCE_TOUCHSCREEN) &&
+      gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
+                                           g_intern_static_string ("_NET_WM_MOVERESIZE")))
+    return TRUE;
+
+  return FALSE;
+}
+
+static void
+gdk_x11_surface_begin_resize_drag (GdkSurface     *window,
+                                  GdkSurfaceEdge  edge,
+                                  GdkDevice     *device,
+                                  gint           button,
+                                  gint           root_x,
+                                  gint           root_y,
+                                  guint32        timestamp)
+{
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+    return;
+
+  /* Avoid EWMH for touch devices */
+  if (_should_perform_ewmh_drag (window, device))
+    wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
+  else
+    emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
+}
+
+static void
+gdk_x11_surface_begin_move_drag (GdkSurface *window,
+                                GdkDevice *device,
+                               gint       button,
+                               gint       root_x,
+                               gint       root_y,
+                               guint32    timestamp)
+{
+  gint direction;
+
+  if (GDK_SURFACE_DESTROYED (window) || !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  if (button == 0)
+    direction = _NET_WM_MOVERESIZE_MOVE_KEYBOARD;
+  else
+    direction = _NET_WM_MOVERESIZE_MOVE;
+
+  /* Avoid EWMH for touch devices */
+  if (_should_perform_ewmh_drag (window, device))
+    wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
+  else
+    emulate_move_drag (window, device, button, root_x, root_y, timestamp);
+}
+
+static gboolean
+gdk_x11_surface_beep (GdkSurface *window)
+{
+  GdkDisplay *display;
+
+  display = GDK_SURFACE_DISPLAY (window);
+
+#ifdef HAVE_XKB
+  if (GDK_X11_DISPLAY (display)->use_xkb)
+    {
+      XkbBell (GDK_DISPLAY_XDISPLAY (display),
+               GDK_SURFACE_XID (window),
+               0,
+               None);
+      return TRUE;
+    }
+#endif
+
+  return FALSE;
+}
+
+static void
+gdk_x11_surface_set_opacity (GdkSurface *window,
+                           gdouble    opacity)
+{
+  GdkDisplay *display;
+  gulong cardinal;
+  
+  g_return_if_fail (GDK_IS_SURFACE (window));
+
+  if (GDK_SURFACE_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  display = gdk_surface_get_display (window);
+
+  if (opacity < 0)
+    opacity = 0;
+  else if (opacity > 1)
+    opacity = 1;
+
+  cardinal = opacity * 0xffffffff;
+
+  if (cardinal == 0xffffffff)
+    XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
+                    GDK_SURFACE_XID (window),
+                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
+  else
+    XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                    GDK_SURFACE_XID (window),
+                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
+                    XA_CARDINAL, 32,
+                    PropModeReplace,
+                    (guchar *) &cardinal, 1);
+}
+
+static Bool
+timestamp_predicate (Display *display,
+                    XEvent  *xevent,
+                    XPointer arg)
+{
+  Window xwindow = GPOINTER_TO_UINT (arg);
+  GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
+
+  if (xevent->type == PropertyNotify &&
+      xevent->xproperty.window == xwindow &&
+      xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
+                                                                      "GDK_TIMESTAMP_PROP"))
+    return True;
+
+  return False;
+}
+
+/**
+ * gdk_x11_get_server_time:
+ * @window: (type GdkX11Surface): a #GdkSurface, used for communication
+ *          with the server.  The window must have
+ *          GDK_PROPERTY_CHANGE_MASK in its events mask or a hang will
+ *          result.
+ *
+ * Routine to get the current X server time stamp.
+ *
+ * Returns: the time stamp.
+ **/
+guint32
+gdk_x11_get_server_time (GdkSurface *window)
+{
+  Display *xdisplay;
+  Window   xwindow;
+  guchar c = 'a';
+  XEvent xevent;
+  Atom timestamp_prop_atom;
+
+  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
+  g_return_val_if_fail (!GDK_SURFACE_DESTROYED (window), 0);
+
+  xdisplay = GDK_SURFACE_XDISPLAY (window);
+  xwindow = GDK_SURFACE_XID (window);
+  timestamp_prop_atom =
+    gdk_x11_get_xatom_by_name_for_display (GDK_SURFACE_DISPLAY (window),
+                                          "GDK_TIMESTAMP_PROP");
+
+  XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
+                  timestamp_prop_atom,
+                  8, PropModeReplace, &c, 1);
+
+  XIfEvent (xdisplay, &xevent,
+           timestamp_predicate, GUINT_TO_POINTER(xwindow));
+
+  return xevent.xproperty.time;
+}
+
+/**
+ * gdk_x11_surface_get_xid:
+ * @window: (type GdkX11Surface): a native #GdkSurface.
+ * 
+ * Returns the X resource (window) belonging to a #GdkSurface.
+ * 
+ * Returns: the ID of @drawable’s X resource.
+ **/
+XID
+gdk_x11_surface_get_xid (GdkSurface *window)
+{
+  if (!GDK_SURFACE_IS_X11 (window) ||
+      !_gdk_surface_has_impl (window))
+    {
+      g_warning (G_STRLOC " drawable is not a native X11 window");
+      return None;
+    }
+  
+  return GDK_SURFACE_IMPL_X11 (window->impl)->xid;
+}
+
+static gint
+gdk_x11_surface_get_scale_factor (GdkSurface *window)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return 1;
+
+  return impl->window_scale;
+}
+
+/**
+ * gdk_x11_surface_set_frame_sync_enabled:
+ * @window: (type GdkX11Surface): a native #GdkSurface
+ * @frame_sync_enabled: whether frame-synchronization should be enabled
+ *
+ * This function can be used to disable frame synchronization for a window.
+ * Normally frame synchronziation will be enabled or disabled based on whether
+ * the system has a compositor that supports frame synchronization, but if
+ * the window is not directly managed by the window manager, then frame
+ * synchronziation may need to be disabled. This is the case for a window
+ * embedded via the XEMBED protocol.
+ */
+void
+gdk_x11_surface_set_frame_sync_enabled (GdkSurface *window,
+                                       gboolean   frame_sync_enabled)
+{
+  if (!GDK_SURFACE_IS_X11 (window) ||
+      !_gdk_surface_has_impl (window))
+    {
+      g_warning (G_STRLOC " drawable is not a native X11 window");
+      return;
+    }
+
+  GDK_SURFACE_IMPL_X11 (window->impl)->frame_sync_enabled = FALSE;
+}
+
+static void
+gdk_x11_surface_set_opaque_region (GdkSurface      *window,
+                                  cairo_region_t *region)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+  GdkDisplay *display;
+  int nitems;
+  gulong *data;
+
+  if (GDK_SURFACE_DESTROYED (window))
+    return;
+
+  if (region != NULL)
+    {
+      int i, nrects;
+
+      nrects = cairo_region_num_rectangles (region);
+      nitems = nrects * 4;
+      data = g_new (gulong, nitems);
+
+      for (i = 0; i < nrects; i++)
+        {
+          cairo_rectangle_int_t rect;
+          cairo_region_get_rectangle (region, i, &rect);
+          data[i*4+0] = rect.x * impl->window_scale;
+          data[i*4+1] = rect.y * impl->window_scale;
+          data[i*4+2] = rect.width * impl->window_scale;
+          data[i*4+3] = rect.height * impl->window_scale;
+        }
+    }
+  else
+    {
+      nitems = 0;
+      data = NULL;
+    }
+
+  display = gdk_surface_get_display (window);
+
+  XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                   GDK_SURFACE_XID (window),
+                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_OPAQUE_REGION"),
+                   XA_CARDINAL, 32, PropModeReplace,
+                   (guchar *) data, nitems);
+
+  g_free (data);
+}
+
+static gboolean
+gdk_x11_surface_show_window_menu (GdkSurface *window,
+                                 GdkEvent  *event)
+{
+  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
+  GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
+  GdkDevice *device;
+  int device_id;
+  double x_root, y_root;
+  XClientMessageEvent xclient = { 0 };
+
+  switch ((guint) event->any.type)
+    {
+    case GDK_BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+      break;
+    default:
+      return FALSE;
+    }
+
+  if (!gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
+                                            g_intern_static_string ("_GTK_SHOW_WINDOW_MENU")))
+    return FALSE;
+
+  gdk_event_get_root_coords (event, &x_root, &y_root);
+  device = gdk_event_get_device (event);
+  g_object_get (G_OBJECT (device),
+                "device-id", &device_id,
+                NULL);
+
+  /* Ungrab the implicit grab */
+  gdk_seat_ungrab (gdk_device_get_seat (device));
+
+  xclient.type = ClientMessage;
+  xclient.window = GDK_SURFACE_XID (window);
+  xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_GTK_SHOW_WINDOW_MENU");
+  xclient.data.l[0] = device_id;
+  xclient.data.l[1] = x_root * impl->window_scale;
+  xclient.data.l[2] = y_root * impl->window_scale;
+  xclient.format = 32;
+
+  XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XROOTWIN (window), False,
+              SubstructureRedirectMask | SubstructureNotifyMask,
+              (XEvent *)&xclient);
+
+  return TRUE;
+}
+
+static void
+gdk_surface_impl_x11_class_init (GdkSurfaceImplX11Class *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_CLASS (klass);
+  
+  object_class->finalize = gdk_surface_impl_x11_finalize;
+  
+  impl_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
+  impl_class->show = gdk_surface_x11_show;
+  impl_class->hide = gdk_surface_x11_hide;
+  impl_class->withdraw = gdk_surface_x11_withdraw;
+  impl_class->set_events = gdk_surface_x11_set_events;
+  impl_class->get_events = gdk_surface_x11_get_events;
+  impl_class->raise = gdk_surface_x11_raise;
+  impl_class->lower = gdk_surface_x11_lower;
+  impl_class->restack_toplevel = gdk_surface_x11_restack_toplevel;
+  impl_class->move_resize = gdk_surface_x11_move_resize;
+  impl_class->get_geometry = gdk_surface_x11_get_geometry;
+  impl_class->get_root_coords = gdk_surface_x11_get_root_coords;
+  impl_class->get_device_state = gdk_surface_x11_get_device_state;
+  impl_class->shape_combine_region = gdk_surface_x11_shape_combine_region;
+  impl_class->input_shape_combine_region = gdk_surface_x11_input_shape_combine_region;
+  impl_class->queue_antiexpose = _gdk_x11_surface_queue_antiexpose;
+  impl_class->destroy = gdk_x11_surface_destroy;
+  impl_class->beep = gdk_x11_surface_beep;
+
+  impl_class->focus = gdk_x11_surface_focus;
+  impl_class->set_type_hint = gdk_x11_surface_set_type_hint;
+  impl_class->get_type_hint = gdk_x11_surface_get_type_hint;
+  impl_class->set_modal_hint = gdk_x11_surface_set_modal_hint;
+  impl_class->set_skip_taskbar_hint = gdk_x11_surface_set_skip_taskbar_hint;
+  impl_class->set_skip_pager_hint = gdk_x11_surface_set_skip_pager_hint;
+  impl_class->set_urgency_hint = gdk_x11_surface_set_urgency_hint;
+  impl_class->set_geometry_hints = gdk_x11_surface_set_geometry_hints;
+  impl_class->set_title = gdk_x11_surface_set_title;
+  impl_class->set_role = gdk_x11_surface_set_role;
+  impl_class->set_startup_id = gdk_x11_surface_set_startup_id;
+  impl_class->set_transient_for = gdk_x11_surface_set_transient_for;
+  impl_class->get_frame_extents = gdk_x11_surface_get_frame_extents;
+  impl_class->set_accept_focus = gdk_x11_surface_set_accept_focus;
+  impl_class->set_focus_on_map = gdk_x11_surface_set_focus_on_map;
+  impl_class->set_icon_list = gdk_x11_surface_set_icon_list;
+  impl_class->set_icon_name = gdk_x11_surface_set_icon_name;
+  impl_class->iconify = gdk_x11_surface_iconify;
+  impl_class->deiconify = gdk_x11_surface_deiconify;
+  impl_class->stick = gdk_x11_surface_stick;
+  impl_class->unstick = gdk_x11_surface_unstick;
+  impl_class->maximize = gdk_x11_surface_maximize;
+  impl_class->unmaximize = gdk_x11_surface_unmaximize;
+  impl_class->fullscreen = gdk_x11_surface_fullscreen;
+  impl_class->fullscreen_on_monitor = gdk_x11_surface_fullscreen_on_monitor;
+  impl_class->apply_fullscreen_mode = gdk_x11_surface_apply_fullscreen_mode;
+  impl_class->unfullscreen = gdk_x11_surface_unfullscreen;
+  impl_class->set_keep_above = gdk_x11_surface_set_keep_above;
+  impl_class->set_keep_below = gdk_x11_surface_set_keep_below;
+  impl_class->get_group = gdk_x11_surface_get_group;
+  impl_class->set_group = gdk_x11_surface_set_group;
+  impl_class->set_decorations = gdk_x11_surface_set_decorations;
+  impl_class->get_decorations = gdk_x11_surface_get_decorations;
+  impl_class->set_functions = gdk_x11_surface_set_functions;
+  impl_class->begin_resize_drag = gdk_x11_surface_begin_resize_drag;
+  impl_class->begin_move_drag = gdk_x11_surface_begin_move_drag;
+  impl_class->set_opacity = gdk_x11_surface_set_opacity;
+  impl_class->destroy_notify = gdk_x11_surface_destroy_notify;
+  impl_class->register_dnd = _gdk_x11_surface_register_dnd;
+  impl_class->drag_begin = _gdk_x11_surface_drag_begin;
+  impl_class->get_scale_factor = gdk_x11_surface_get_scale_factor;
+  impl_class->set_opaque_region = gdk_x11_surface_set_opaque_region;
+  impl_class->set_shadow_width = gdk_x11_surface_set_shadow_width;
+  impl_class->show_window_menu = gdk_x11_surface_show_window_menu;
+  impl_class->create_gl_context = gdk_x11_surface_create_gl_context;
+  impl_class->get_unscaled_size = gdk_x11_surface_get_unscaled_size;
+  impl_class->supports_edge_constraints = gdk_x11_surface_supports_edge_constraints;
+}
diff --git a/gdk/x11/gdksurface-x11.h b/gdk/x11/gdksurface-x11.h
new file mode 100644 (file)
index 0000000..15993af
--- /dev/null
@@ -0,0 +1,199 @@
+/* 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GDK_SURFACE_X11_H__
+#define __GDK_SURFACE_X11_H__
+
+#include "gdk/x11/gdkprivate-x11.h"
+#include "gdk/gdksurfaceimpl.h"
+
+#include <X11/Xlib.h>
+
+#ifdef HAVE_XDAMAGE
+#include <X11/extensions/Xdamage.h>
+#endif
+
+#ifdef HAVE_XSYNC
+#include <X11/Xlib.h>
+#include <X11/extensions/sync.h>
+#endif
+
+G_BEGIN_DECLS
+
+typedef struct _GdkToplevelX11 GdkToplevelX11;
+typedef struct _GdkSurfaceImplX11 GdkSurfaceImplX11;
+typedef struct _GdkSurfaceImplX11Class GdkSurfaceImplX11Class;
+typedef struct _GdkXPositionInfo GdkXPositionInfo;
+
+/* Window implementation for X11
+ */
+
+#define GDK_TYPE_SURFACE_IMPL_X11              (gdk_surface_impl_x11_get_type ())
+#define GDK_SURFACE_IMPL_X11(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_X11, GdkSurfaceImplX11))
+#define GDK_SURFACE_IMPL_X11_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_X11, GdkSurfaceImplX11Class))
+#define GDK_IS_SURFACE_IMPL_X11(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_X11))
+#define GDK_IS_SURFACE_IMPL_X11_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_X11))
+#define GDK_SURFACE_IMPL_X11_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_X11, GdkSurfaceImplX11Class))
+
+struct _GdkSurfaceImplX11
+{
+  GdkSurfaceImpl parent_instance;
+
+  GdkSurface *wrapper;
+
+  Window xid;
+
+  GdkToplevelX11 *toplevel;    /* Toplevel-specific information */
+  GdkCursor *cursor;
+
+  guint no_bg : 1;        /* Set when the window background is temporarily
+                           * unset during resizing and scaling */
+  guint override_redirect : 1;
+  guint frame_clock_connected : 1;
+  guint frame_sync_enabled : 1;
+  guint tracking_damage: 1;
+
+  gint window_scale;
+
+  /* Width and height not divided by window_scale - this matters in the
+   * corner-case where the window manager assigns us a size that isn't
+   * a multiple of window_scale - for example for a maximized window
+   * with an odd-sized title-bar.
+   */
+  gint unscaled_width;
+  gint unscaled_height;
+
+  cairo_surface_t *cairo_surface;
+
+#if defined (HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
+  Damage damage;
+#endif
+};
+struct _GdkSurfaceImplX11Class 
+{
+  GdkSurfaceImplClass parent_class;
+};
+
+struct _GdkToplevelX11
+{
+
+  /* Set if the window, or any descendent of it, is the server's focus window
+   */
+  guint has_focus_window : 1;
+
+  /* Set if window->has_focus_window and the focus isn't grabbed elsewhere.
+   */
+  guint has_focus : 1;
+
+  /* Set if the pointer is inside this window. (This is needed for
+   * for focus tracking)
+   */
+  guint has_pointer : 1;
+  
+  /* Set if the window is a descendent of the focus window and the pointer is
+   * inside it. (This is the case where the window will receive keystroke
+   * events even window->has_focus_window is FALSE)
+   */
+  guint has_pointer_focus : 1;
+
+  /* Set if we are requesting these hints */
+  guint skip_taskbar_hint : 1;
+  guint skip_pager_hint : 1;
+  guint urgency_hint : 1;
+
+  guint on_all_desktops : 1;   /* _NET_WM_STICKY == 0xFFFFFFFF */
+
+  guint have_sticky : 1;       /* _NET_WM_STATE_STICKY */
+  guint have_maxvert : 1;       /* _NET_WM_STATE_MAXIMIZED_VERT */
+  guint have_maxhorz : 1;       /* _NET_WM_STATE_MAXIMIZED_HORZ */
+  guint have_fullscreen : 1;    /* _NET_WM_STATE_FULLSCREEN */
+  guint have_hidden : 1;       /* _NET_WM_STATE_HIDDEN */
+
+  guint is_leader : 1;
+
+  /* Set if the WM is presenting us as focused, i.e. with active decorations
+   */
+  guint have_focused : 1;
+
+  guint in_frame : 1;
+
+  /* If we're expecting a response from the compositor after painting a frame */
+  guint frame_pending : 1;
+
+  /* Whether pending_counter_value/configure_counter_value are updates
+   * to the extended update counter */
+  guint pending_counter_value_is_extended : 1;
+  guint configure_counter_value_is_extended : 1;
+
+  gulong map_serial;   /* Serial of last transition from unmapped */
+  
+  cairo_surface_t *icon_pixmap;
+  cairo_surface_t *icon_mask;
+  GdkSurface *group_leader;
+
+  /* Time of most recent user interaction. */
+  gulong user_time;
+
+  /* We use an extra X window for toplevel windows that we XSetInputFocus()
+   * to in order to avoid getting keyboard events redirected to subwindows
+   * that might not even be part of this app
+   */
+  Window focus_window;
+
+  GdkSurfaceHints last_geometry_hints_mask;
+  GdkGeometry last_geometry_hints;
+  
+  /* Constrained edge information */
+  guint edge_constraints;
+
+#ifdef HAVE_XSYNC
+  XID update_counter;
+  XID extended_update_counter;
+  gint64 pending_counter_value; /* latest _NET_WM_SYNC_REQUEST value received */
+  gint64 configure_counter_value; /* Latest _NET_WM_SYNC_REQUEST value received
+                                * where we have also seen the corresponding
+                                * ConfigureNotify
+                                */
+  gint64 current_counter_value;
+
+  /* After a _NET_WM_FRAME_DRAWN message, this is the soonest that we think
+   * frame after will be presented */
+  gint64 throttled_presentation_time;
+#endif
+};
+
+GType gdk_surface_impl_x11_get_type (void);
+
+GdkToplevelX11 *_gdk_x11_surface_get_toplevel        (GdkSurface *window);
+
+GdkCursor      *_gdk_x11_surface_get_cursor          (GdkSurface *window);
+
+void            _gdk_x11_surface_update_size         (GdkSurfaceImplX11 *impl);
+void            _gdk_x11_surface_set_window_scale    (GdkSurface *window,
+                                                    int        scale);
+
+G_END_DECLS
+
+#endif /* __GDK_SURFACE_X11_H__ */
index 0e88ec6d63d7dcbaaec5ec5a968a8bdf8d124fb6..b27c407bd443b4144acfef362b918fed66cca11e 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "gdkinternals.h"
 #include "gdkdisplay-x11.h"
-#include "gdkwindow-x11.h"
+#include "gdksurface-x11.h"
 
 G_DEFINE_TYPE (GdkX11VulkanContext, gdk_x11_vulkan_context, GDK_TYPE_VULKAN_CONTEXT)
 
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
deleted file mode 100644 (file)
index c78c5c1..0000000
+++ /dev/null
@@ -1,4948 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
- * Josh MacDonald, Ryan Lortie
- *
- * 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-#include "config.h"
-
-#include "gdkwindow-x11.h"
-
-#include "gdkwindow.h"
-#include "gdkwindowimpl.h"
-#include "gdkvisual-x11.h"
-#include "gdkinternals.h"
-#include "gdkdeviceprivate.h"
-#include "gdkframeclockprivate.h"
-#include "gdkasync.h"
-#include "gdkeventsource.h"
-#include "gdkdisplay-x11.h"
-#include "gdkglcontext-x11.h"
-#include "gdkprivate-x11.h"
-#include "gdktextureprivate.h"
-#include "gdk-private.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <unistd.h>
-
-#include <cairo-xlib.h>
-
-#include "MwmUtil.h"
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-
-#include <X11/extensions/shape.h>
-
-#ifdef HAVE_XKB
-#include <X11/XKBlib.h>
-#endif
-
-#ifdef HAVE_XCOMPOSITE
-#include <X11/extensions/Xcomposite.h>
-#endif
-
-#ifdef HAVE_XFIXES
-#include <X11/extensions/Xfixes.h>
-#endif
-
-#ifdef HAVE_XDAMAGE
-#include <X11/extensions/Xdamage.h>
-#endif
-
-const int _gdk_x11_event_mask_table[21] =
-{
-  ExposureMask,
-  PointerMotionMask,
-  PointerMotionHintMask,
-  ButtonMotionMask,
-  Button1MotionMask,
-  Button2MotionMask,
-  Button3MotionMask,
-  ButtonPressMask,
-  ButtonReleaseMask,
-  KeyPressMask,
-  KeyReleaseMask,
-  EnterWindowMask,
-  LeaveWindowMask,
-  FocusChangeMask,
-  StructureNotifyMask,
-  PropertyChangeMask,
-  VisibilityChangeMask,
-  0,                    /* PROXIMITY_IN */
-  0,                    /* PROXIMTY_OUT */
-  SubstructureNotifyMask,
-  ButtonPressMask      /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
-};
-
-const gint _gdk_x11_event_mask_table_size = G_N_ELEMENTS (_gdk_x11_event_mask_table);
-
-/* Forward declarations */
-static void     gdk_x11_surface_apply_fullscreen_mode (GdkSurface  *window);
-static gboolean gdk_surface_icon_name_set          (GdkSurface  *window);
-static void     set_wm_name                       (GdkDisplay  *display,
-                                                  Window       xwindow,
-                                                  const gchar *name);
-static void     move_to_current_desktop           (GdkSurface *window);
-
-static void        gdk_surface_impl_x11_finalize   (GObject            *object);
-
-#define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window)           \
-  (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL ||   \
-   GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP ||       \
-   GDK_SURFACE_TYPE (window) == GDK_SURFACE_FOREIGN)
-
-#define WINDOW_IS_TOPLEVEL(window)                      \
-  (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TOPLEVEL ||   \
-   GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP)
-
-/* Return whether time1 is considered later than time2 as far as xserver
- * time is concerned.  Accounts for wraparound.
- */
-#define XSERVER_TIME_IS_LATER(time1, time2)                        \
-  ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
-    (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
-  )
-
-struct _GdkX11Surface {
-  GdkSurface parent;
-};
-
-struct _GdkX11SurfaceClass {
-  GdkSurfaceClass parent_class;
-};
-
-G_DEFINE_TYPE (GdkX11Surface, gdk_x11_surface, GDK_TYPE_SURFACE)
-
-static void
-gdk_x11_surface_class_init (GdkX11SurfaceClass *x11_surface_class)
-{
-}
-
-static void
-gdk_x11_surface_init (GdkX11Surface *x11_surface)
-{
-}
-
-
-G_DEFINE_TYPE (GdkSurfaceImplX11, gdk_surface_impl_x11, GDK_TYPE_SURFACE_IMPL)
-
-static void
-gdk_surface_impl_x11_init (GdkSurfaceImplX11 *impl)
-{  
-  impl->window_scale = 1;
-  impl->frame_sync_enabled = TRUE;
-}
-
-GdkToplevelX11 *
-_gdk_x11_surface_get_toplevel (GdkSurface *window)
-{
-  GdkSurfaceImplX11 *impl;
-  
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-
-  if (!WINDOW_IS_TOPLEVEL (window))
-    return NULL;
-
-  impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (!impl->toplevel)
-    {
-      impl->toplevel = g_new0 (GdkToplevelX11, 1);
-      impl->toplevel->have_focused = FALSE;
-    }
-
-  return impl->toplevel;
-}
-
-/**
- * _gdk_x11_surface_update_size:
- * @impl: a #GdkSurfaceImplX11.
- * 
- * Updates the state of the window (in particular the drawable's
- * cairo surface) when its size has changed.
- **/
-void
-_gdk_x11_surface_update_size (GdkSurfaceImplX11 *impl)
-{
-  if (impl->cairo_surface)
-    {
-      cairo_xlib_surface_set_size (impl->cairo_surface,
-                                   impl->unscaled_width, impl->unscaled_height);
-    }
-}
-
-static void
-gdk_x11_surface_get_unscaled_size (GdkSurface *window,
-                                  int *unscaled_width,
-                                  int *unscaled_height)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (unscaled_width)
-    *unscaled_width = impl->unscaled_width;
-
-  if (unscaled_height)
-    *unscaled_height = impl->unscaled_height;
-}
-
-static gboolean
-gdk_x11_surface_supports_edge_constraints (GdkSurface *window)
-{
-  return gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
-                                              g_intern_static_string ("_GTK_EDGE_CONSTRAINTS"));
-}
-
-static void
-set_sync_counter(Display     *display,
-                XSyncCounter counter,
-                 gint64       value)
-{
-    XSyncValue sync_value;
-
-    XSyncIntsToValue (&sync_value,
-                      value & G_GINT64_CONSTANT(0xFFFFFFFF),
-                      value >> 32);
-    XSyncSetCounter (display, counter, sync_value);
-}
-
-static void
-window_pre_damage (GdkSurface *window)
-{
-  GdkSurface *toplevel_window = gdk_surface_get_toplevel (window);
-  GdkSurfaceImplX11 *impl;
-
-  if (!toplevel_window || !WINDOW_IS_TOPLEVEL (toplevel_window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_X11 (toplevel_window->impl);
-
-  if (impl->toplevel->in_frame &&
-      impl->toplevel->current_counter_value % 2 == 0)
-    {
-      impl->toplevel->current_counter_value += 1;
-      set_sync_counter (GDK_SURFACE_XDISPLAY (impl->wrapper),
-                       impl->toplevel->extended_update_counter,
-                        impl->toplevel->current_counter_value);
-    }
-}
-
-static void
-on_surface_changed (void *data)
-{
-  GdkSurface *window = data;
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (impl->tracking_damage)
-    window_pre_damage (window);
-}
-
-/* We want to know when cairo drawing causes damage to the window,
- * so we engage in the _NET_WM_FRAME_DRAWN protocol with the
- * window only when there actually is drawing. To do that we use
- * a technique (hack) suggested by Uli Schlachter - if we set
- * a dummy "mime data" on the cairo surface (this facility is
- * used to attach JPEG data to an imager), then cairo wil flush
- * and remove the mime data before making any changes to the window.
- */
-
-static void
-hook_surface_changed (GdkSurface *window)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (impl->cairo_surface)
-    {
-      cairo_surface_set_mime_data (impl->cairo_surface,
-                                   "x-gdk/change-notify",
-                                   (unsigned char *)"X",
-                                   1,
-                                   on_surface_changed,
-                                   window);
-      impl->tracking_damage = 1;
-    }
-}
-
-static void
-unhook_surface_changed (GdkSurface *window)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (impl->cairo_surface)
-    {
-      impl->tracking_damage = 0;
-      cairo_surface_set_mime_data (impl->cairo_surface,
-                                   "x-gdk/change-notify",
-                                   NULL, 0,
-                                   NULL, NULL);
-    }
-}
-
-static void
-gdk_x11_surface_predict_presentation_time (GdkSurface *window)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-  GdkFrameClock *clock;
-  GdkFrameTimings *timings;
-  gint64 presentation_time;
-  gint64 refresh_interval;
-
-  if (!WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  clock = gdk_surface_get_frame_clock (window);
-
-  timings = gdk_frame_clock_get_current_timings (clock);
-
-  gdk_frame_clock_get_refresh_info (clock,
-                                    timings->frame_time,
-                                    &refresh_interval, &presentation_time);
-
-  if (presentation_time != 0)
-    {
-      if (timings->slept_before)
-        {
-          presentation_time += refresh_interval;
-        }
-      else
-        {
-          if (presentation_time < timings->frame_time + refresh_interval / 2)
-            presentation_time += refresh_interval;
-        }
-    }
-  else
-    {
-      if (timings->slept_before)
-        presentation_time = timings->frame_time + refresh_interval + refresh_interval / 2;
-      else
-        presentation_time = timings->frame_time + refresh_interval;
-    }
-
-  if (presentation_time < impl->toplevel->throttled_presentation_time)
-    presentation_time = impl->toplevel->throttled_presentation_time;
-
-  timings->predicted_presentation_time = presentation_time;
-}
-
-static void
-gdk_x11_surface_begin_frame (GdkSurface *window,
-                            gboolean   force_frame)
-{
-  GdkSurfaceImplX11 *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (!WINDOW_IS_TOPLEVEL (window) ||
-      impl->toplevel->extended_update_counter == None)
-    return;
-
-  impl->toplevel->in_frame = TRUE;
-
-  if (impl->toplevel->configure_counter_value != 0 &&
-      impl->toplevel->configure_counter_value_is_extended)
-    {
-      impl->toplevel->current_counter_value = impl->toplevel->configure_counter_value;
-      if ((impl->toplevel->current_counter_value % 2) == 1)
-        impl->toplevel->current_counter_value += 1;
-
-      impl->toplevel->configure_counter_value = 0;
-
-      window_pre_damage (window);
-    }
-  else if (force_frame)
-    {
-      /* When mapping the window, we really want to freeze the
-         rendering of the window by the compositor until we've
-         actually painted something into the window's buffer. */
-      window_pre_damage (window);
-    }
-  else
-    {
-      hook_surface_changed (window);
-    }
-}
-
-static void
-gdk_x11_surface_end_frame (GdkSurface *window)
-{
-  GdkFrameClock *clock;
-  GdkFrameTimings *timings;
-  GdkSurfaceImplX11 *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (!WINDOW_IS_TOPLEVEL (window) ||
-      impl->toplevel->extended_update_counter == None ||
-      !impl->toplevel->in_frame)
-    return;
-
-  clock = gdk_surface_get_frame_clock (window);
-  timings = gdk_frame_clock_get_current_timings (clock);
-
-  impl->toplevel->in_frame = FALSE;
-
-  if (impl->toplevel->current_counter_value % 2 == 1)
-    {
-      if (GDK_DISPLAY_DEBUG_CHECK (gdk_surface_get_display (window), FRAMES))
-        {
-          XImage *image = XGetImage (GDK_SURFACE_XDISPLAY (window),
-                                     GDK_SURFACE_XID (window),
-                                     0, 0, 1, 1,
-                                     (1 << 24) - 1,
-                                     ZPixmap);
-          XDestroyImage (image);
-        }
-
-      /* An increment of 3 means that the frame was not drawn as fast as possible,
-       * but rather at a particular time. This can trigger different handling from
-       * the compositor.
-       */
-      if (timings->slept_before)
-        impl->toplevel->current_counter_value += 3;
-      else
-        impl->toplevel->current_counter_value += 1;
-
-      set_sync_counter(GDK_SURFACE_XDISPLAY (impl->wrapper),
-                      impl->toplevel->extended_update_counter,
-                      impl->toplevel->current_counter_value);
-
-      if (impl->frame_sync_enabled &&
-          gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
-                                              g_intern_static_string ("_NET_WM_FRAME_DRAWN")))
-        {
-          impl->toplevel->frame_pending = TRUE;
-          _gdk_frame_clock_freeze (gdk_surface_get_frame_clock (window));
-          timings->cookie = impl->toplevel->current_counter_value;
-        }
-    }
-
-  unhook_surface_changed (window);
-
-  if (impl->toplevel->configure_counter_value != 0 &&
-      !impl->toplevel->configure_counter_value_is_extended)
-    {
-      set_sync_counter (GDK_SURFACE_XDISPLAY (window),
-                        impl->toplevel->update_counter,
-                        impl->toplevel->configure_counter_value);
-
-      impl->toplevel->configure_counter_value = 0;
-    }
-
-  if (!impl->toplevel->frame_pending)
-    timings->complete = TRUE;
-}
-
-/*****************************************************
- * X11 specific implementations of generic functions *
- *****************************************************/
-
-static cairo_surface_t *
-gdk_x11_create_cairo_surface (GdkSurfaceImplX11 *impl,
-                             int width,
-                             int height)
-{
-  Visual *visual;
-    
-  visual = gdk_x11_display_get_window_visual (GDK_X11_DISPLAY (gdk_surface_get_display (impl->wrapper)));
-  return cairo_xlib_surface_create (GDK_SURFACE_XDISPLAY (impl->wrapper),
-                                    GDK_SURFACE_IMPL_X11 (impl)->xid,
-                                    visual,
-                                    width, height);
-}
-
-static cairo_surface_t *
-gdk_x11_ref_cairo_surface (GdkSurface *window)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  if (!impl->cairo_surface)
-    {
-      impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
-                                                          gdk_surface_get_width (window) * impl->window_scale,
-                                                          gdk_surface_get_height (window) * impl->window_scale);
-      cairo_surface_set_device_scale (impl->cairo_surface, impl->window_scale, impl->window_scale);
-
-      if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel->in_frame)
-        hook_surface_changed (window);
-    }
-
-  cairo_surface_reference (impl->cairo_surface);
-
-  return impl->cairo_surface;
-}
-
-static void
-gdk_surface_impl_x11_finalize (GObject *object)
-{
-  GdkSurface *wrapper;
-  GdkSurfaceImplX11 *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE_IMPL_X11 (object));
-
-  impl = GDK_SURFACE_IMPL_X11 (object);
-
-  wrapper = impl->wrapper;
-
-  if (WINDOW_IS_TOPLEVEL (wrapper) && impl->toplevel->in_frame)
-    unhook_surface_changed (wrapper);
-
-  _gdk_x11_surface_grab_check_destroy (wrapper);
-
-  if (!GDK_SURFACE_DESTROYED (wrapper))
-    {
-      GdkDisplay *display = GDK_SURFACE_DISPLAY (wrapper);
-
-      _gdk_x11_display_remove_window (display, impl->xid);
-      if (impl->toplevel && impl->toplevel->focus_window)
-        _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
-    }
-
-  g_free (impl->toplevel);
-
-  if (impl->cursor)
-    g_object_unref (impl->cursor);
-
-  G_OBJECT_CLASS (gdk_surface_impl_x11_parent_class)->finalize (object);
-}
-
-typedef struct {
-  GdkDisplay *display;
-  Pixmap pixmap;
-} FreePixmapData;
-
-static void
-free_pixmap (gpointer datap)
-{
-  FreePixmapData *data = datap;
-
-  if (!gdk_display_is_closed (data->display))
-    {
-      XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display),
-                   data->pixmap);
-    }
-
-  g_object_unref (data->display);
-  g_slice_free (FreePixmapData, data);
-}
-
-static void
-attach_free_pixmap_handler (cairo_surface_t *surface,
-                            GdkDisplay      *display,
-                            Pixmap           pixmap)
-{
-  static const cairo_user_data_key_t key;
-  FreePixmapData *data;
-  
-  data = g_slice_new (FreePixmapData);
-  data->display = g_object_ref (display);
-  data->pixmap = pixmap;
-
-  cairo_surface_set_user_data (surface, &key, data, free_pixmap);
-}
-
-/* Cairo does not guarantee we get an xlib surface if we call
- * cairo_surface_create_similar(). In some cases however, we must use a
- * pixmap or bitmap in the X11 API.
- * These functions ensure an Xlib surface.
- */
-cairo_surface_t *
-_gdk_x11_display_create_bitmap_surface (GdkDisplay *display,
-                                        int         width,
-                                        int         height)
-{
-  cairo_surface_t *surface;
-  Pixmap pixmap;
-
-  pixmap = XCreatePixmap (GDK_DISPLAY_XDISPLAY (display),
-                          GDK_SCREEN_XROOTWIN (GDK_X11_DISPLAY (display)->screen),
-                          width, height, 1);
-  surface = cairo_xlib_surface_create_for_bitmap (GDK_DISPLAY_XDISPLAY (display),
-                                                  pixmap,
-                                                  GDK_X11_SCREEN (GDK_X11_DISPLAY (display)->screen)->xscreen,
-                                                  width, height);
-  attach_free_pixmap_handler (surface, display, pixmap);
-
-  return surface;
-}
-
-/* Create a surface backed with a pixmap without alpha on the same screen as window */
-static cairo_surface_t *
-gdk_x11_surface_create_pixmap_surface (GdkSurface *window,
-                                      int        width,
-                                      int        height)
-{
-  GdkDisplay *display;
-  Display *dpy;
-  cairo_surface_t *surface;
-  Pixmap pixmap;
-
-  display = gdk_surface_get_display (window);
-  dpy = GDK_DISPLAY_XDISPLAY (display);
-
-  pixmap = XCreatePixmap (dpy,
-                          GDK_SURFACE_XID (window),
-                          width, height,
-                          DefaultDepth (dpy, DefaultScreen (dpy)));
-  surface = cairo_xlib_surface_create (dpy,
-                                       pixmap,
-                                       DefaultVisual (dpy, DefaultScreen (dpy)),
-                                       width, height);
-  attach_free_pixmap_handler (surface, display, pixmap);
-
-  return surface;
-}
-
-static void
-set_wm_protocols (GdkSurface *window)
-{
-  GdkDisplay *display = gdk_surface_get_display (window);
-  Atom protocols[4];
-  int n = 0;
-  
-  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
-  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
-  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
-
-#ifdef HAVE_XSYNC
-  if (GDK_X11_DISPLAY (display)->use_sync)
-    protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
-#endif
-  
-  XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window), protocols, n);
-}
-
-static const gchar *
-get_default_title (void)
-{
-  const char *title;
-
-  title = g_get_application_name ();
-  if (!title)
-    title = g_get_prgname ();
-  if (!title)
-    title = "";
-
-  return title;
-}
-
-static void
-check_leader_window_title (GdkDisplay *display)
-{
-  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
-
-  if (display_x11->leader_window && !display_x11->leader_window_title_set)
-    {
-      set_wm_name (display,
-                  display_x11->leader_window,
-                  get_default_title ());
-      
-      display_x11->leader_window_title_set = TRUE;
-    }
-}
-
-static Window
-create_focus_window (GdkDisplay *display,
-                    XID         parent)
-{
-  GdkX11Display *display_x11;
-  GdkEventMask event_mask;
-  Display *xdisplay;
-  Window focus_window;
-  XSetWindowAttributes attrs;
-
-  xdisplay = GDK_DISPLAY_XDISPLAY (display);
-  display_x11 = GDK_X11_DISPLAY (display);
-
-  focus_window = XCreateWindow (xdisplay, parent,
-                                -1, -1, 1, 1, 0,
-                                0, /* depth */
-                                InputOnly,
-                                CopyFromParent,
-                                0, &attrs);
-
-  event_mask = (GDK_KEY_PRESS_MASK |
-                GDK_KEY_RELEASE_MASK |
-                GDK_FOCUS_CHANGE_MASK);
-
-  gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
-                                      focus_window,
-                                      event_mask, 0);
-
-  XMapWindow (xdisplay, focus_window);
-
-  return focus_window;
-}
-
-static void
-ensure_sync_counter (GdkSurface *window)
-{
-#ifdef HAVE_XSYNC
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
-      GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (window);
-
-      if (toplevel &&
-         toplevel->update_counter == None &&
-         GDK_X11_DISPLAY (display)->use_sync)
-       {
-         Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
-         XSyncValue value;
-         Atom atom;
-         XID counters[2];
-
-         XSyncIntToValue (&value, 0);
-         
-         toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
-         toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
-         
-         atom = gdk_x11_get_xatom_by_name_for_display (display,
-                                                       "_NET_WM_SYNC_REQUEST_COUNTER");
-
-         counters[0] = toplevel->update_counter;
-         counters[1] = toplevel->extended_update_counter;
-         XChangeProperty (xdisplay, GDK_SURFACE_XID (window),
-                          atom, XA_CARDINAL,
-                          32, PropModeReplace,
-                          (guchar *)counters, 2);
-         
-         toplevel->current_counter_value = 0;
-       }
-    }
-#endif
-}
-
-static void
-setup_toplevel_window (GdkSurface    *window,
-                      GdkX11Screen *x11_screen)
-{
-  GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (window);
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-  GdkDisplay *display = gdk_surface_get_display (window);
-  Display *xdisplay = GDK_SURFACE_XDISPLAY (window);
-  XID xid = GDK_SURFACE_XID (window);
-  XSizeHints size_hints;
-  long pid;
-  Window leader_window;
-
-  set_wm_protocols (window);
-
-  if (!window->input_only)
-    {
-      /* The focus window is off the visible area, and serves to receive key
-       * press events so they don't get sent to child windows.
-       */
-      toplevel->focus_window = create_focus_window (display, xid);
-      _gdk_x11_display_add_window (x11_screen->display,
-                                   &toplevel->focus_window,
-                                   window);
-    }
-
-  check_leader_window_title (x11_screen->display);
-
-  /* FIXME: Is there any point in doing this? Do any WM's pay
-   * attention to PSize, and even if they do, is this the
-   * correct value???
-   */
-  size_hints.flags = PSize;
-  size_hints.width = window->width * impl->window_scale;
-  size_hints.height = window->height * impl->window_scale;
-  
-  XSetWMNormalHints (xdisplay, xid, &size_hints);
-  
-  /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
-  XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
-  
-  pid = getpid ();
-  XChangeProperty (xdisplay, xid,
-                  gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
-                  XA_CARDINAL, 32,
-                  PropModeReplace,
-                  (guchar *)&pid, 1);
-
-  leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
-  if (!leader_window)
-    leader_window = xid;
-  XChangeProperty (xdisplay, xid, 
-                  gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
-                  XA_WINDOW, 32, PropModeReplace,
-                  (guchar *) &leader_window, 1);
-
-  if (toplevel->focus_window != None)
-    XChangeProperty (xdisplay, xid, 
-                     gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
-                     XA_WINDOW, 32, PropModeReplace,
-                     (guchar *) &toplevel->focus_window, 1);
-
-  if (!window->focus_on_map)
-    gdk_x11_surface_set_user_time (window, 0);
-  else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
-    gdk_x11_surface_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
-
-  ensure_sync_counter (window);
-
-  /* Start off in a frozen state - we'll finish this when we first paint */
-  gdk_x11_surface_begin_frame (window, TRUE);
-}
-
-static void
-on_frame_clock_before_paint (GdkFrameClock *clock,
-                             GdkSurface     *window)
-{
-  gdk_x11_surface_predict_presentation_time (window);
-  gdk_x11_surface_begin_frame (window, FALSE);
-}
-
-static void
-on_frame_clock_after_paint (GdkFrameClock *clock,
-                            GdkSurface     *window)
-{
-  gdk_x11_surface_end_frame (window);
-
-}
-
-static void
-connect_frame_clock (GdkSurface *window)
-{
-  GdkSurfaceImplX11 *impl;
-
-  impl = GDK_SURFACE_IMPL_X11 (window->impl);
-  if (WINDOW_IS_TOPLEVEL (window) && !impl->frame_clock_connected)
-    {
-      GdkFrameClock *frame_clock = gdk_surface_get_frame_clock (window);
-
-      g_signal_connect (frame_clock, "before-paint",
-                        G_CALLBACK (on_frame_clock_before_paint), window);
-      g_signal_connect (frame_clock, "after-paint",
-                        G_CALLBACK (on_frame_clock_after_paint), window);
-
-      impl->frame_clock_connected = TRUE;
-    }
-}
-
-void
-_gdk_x11_display_create_window_impl (GdkDisplay    *display,
-                                     GdkSurface     *window,
-                                     GdkSurface     *real_parent,
-                                     GdkEventMask   event_mask,
-                                     GdkSurfaceAttr *attributes)
-{
-  GdkSurfaceImplX11 *impl;
-  GdkX11Screen *x11_screen;
-  GdkX11Display *display_x11;
-
-  Window xparent;
-  Visual *xvisual;
-  Display *xdisplay;
-
-  XSetWindowAttributes xattributes;
-  long xattributes_mask;
-  XClassHint *class_hint;
-
-  unsigned int class;
-  int depth;
-
-  int abs_x;
-  int abs_y;
-
-  display_x11 = GDK_X11_DISPLAY (display);
-  x11_screen = GDK_X11_SCREEN (display_x11->screen);
-  if (real_parent)
-    xparent = GDK_SURFACE_XID (real_parent);
-  else
-    xparent = GDK_SCREEN_XROOTWIN (x11_screen);
-
-  impl = g_object_new (GDK_TYPE_SURFACE_IMPL_X11, NULL);
-  window->impl = GDK_SURFACE_IMPL (impl);
-  impl->wrapper = GDK_SURFACE (window);
-  impl->window_scale = x11_screen->window_scale;
-
-  xdisplay = x11_screen->xdisplay;
-
-  xattributes_mask = 0;
-
-  xvisual = gdk_x11_display_get_window_visual (display_x11);
-
-  impl->override_redirect = FALSE;
-
-  /* Sanity checks */
-  switch (window->window_type)
-    {
-    case GDK_SURFACE_TOPLEVEL:
-    case GDK_SURFACE_TEMP:
-      if (window->parent)
-        {
-          /* The common code warns for this case */
-          xparent = GDK_SCREEN_XROOTWIN (x11_screen);
-        }
-      break;
-
-    case GDK_SURFACE_CHILD:
-    default:
-      g_assert_not_reached ();
-      break;
-    }
-
-  if (!window->input_only)
-    {
-      class = InputOutput;
-
-      xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
-
-      xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
-      xattributes_mask |= CWBorderPixel | CWBackPixel;
-
-      xattributes.bit_gravity = NorthWestGravity;
-      xattributes_mask |= CWBitGravity;
-
-      xattributes.colormap = gdk_x11_display_get_window_colormap (display_x11);
-      xattributes_mask |= CWColormap;
-
-      if (window->window_type == GDK_SURFACE_TEMP)
-        {
-          xattributes.save_under = True;
-          xattributes.override_redirect = True;
-          xattributes.cursor = None;
-          xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
-
-          impl->override_redirect = TRUE;
-        }
-
-      depth = gdk_x11_display_get_window_depth (display_x11);
-    }
-  else
-    {
-      class = InputOnly;
-
-      if (window->window_type == GDK_SURFACE_TEMP)
-        {
-          xattributes.override_redirect = True;
-          xattributes_mask |= CWOverrideRedirect;
-
-          impl->override_redirect = TRUE;
-        }
-
-      depth = 0;
-    }
-
-  if (window->width * impl->window_scale > 32767 ||
-      window->height * impl->window_scale > 32767)
-    {
-      g_warning ("Native Windows wider or taller than 32767 pixels are not supported");
-
-      if (window->width * impl->window_scale > 32767)
-        window->width = 32767 / impl->window_scale;
-      if (window->height  * impl->window_scale > 32767)
-        window->height = 32767 /  impl->window_scale;
-    }
-
-  impl->unscaled_width = window->width * impl->window_scale;
-  impl->unscaled_height = window->height * impl->window_scale;
-
-  if (window->parent)
-    {
-      abs_x = window->parent->abs_x;
-      abs_y = window->parent->abs_y;
-    }
-  else
-    {
-      abs_x = 0;
-      abs_y = 0;
-    }
-
-  impl->xid = XCreateWindow (xdisplay, xparent,
-                             (window->x + abs_x) * impl->window_scale,
-                             (window->y + abs_y) * impl->window_scale,
-                             window->width * impl->window_scale, window->height * impl->window_scale,
-                             0, depth, class, xvisual,
-                             xattributes_mask, &xattributes);
-
-  g_object_ref (window);
-  _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
-
-  switch (GDK_SURFACE_TYPE (window))
-    {
-    case GDK_SURFACE_TOPLEVEL:
-    case GDK_SURFACE_TEMP:
-      gdk_surface_set_title (window, get_default_title ());
-
-      class_hint = XAllocClassHint ();
-      class_hint->res_name = (char *) g_get_prgname ();
-      class_hint->res_class = (char *) display_x11->program_class;
-      XSetClassHint (xdisplay, impl->xid, class_hint);
-      XFree (class_hint);
-
-      setup_toplevel_window (window, x11_screen);
-      break;
-
-    case GDK_SURFACE_CHILD:
-    default:
-      break;
-    }
-
-  gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
-                                      GDK_SURFACE_XID (window), event_mask,
-                                      StructureNotifyMask | PropertyChangeMask);
-
-  connect_frame_clock (window);
-
-  gdk_surface_freeze_toplevel_updates (window);
-}
-
-static GdkEventMask
-x_event_mask_to_gdk_event_mask (long mask)
-{
-  GdkEventMask event_mask = 0;
-  int i;
-
-  for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
-    {
-      if (mask & _gdk_x11_event_mask_table[i])
-       event_mask |= 1 << (i + 1);
-    }
-
-  return event_mask;
-}
-
-/**
- * gdk_x11_surface_foreign_new_for_display:
- * @display: (type GdkX11Display): the #GdkDisplay where the window handle comes from.
- * @window: an Xlib Window
- *
- * Wraps a native window in a #GdkSurface. The function will try to
- * look up the window using gdk_x11_surface_lookup_for_display() first.
- * If it does not find it there, it will create a new window.
- *
- * This may fail if the window has been destroyed. If the window
- * was already known to GDK, a new reference to the existing
- * #GdkSurface is returned.
- *
- * Returns: (transfer full): a #GdkSurface wrapper for the native
- *   window, or %NULL if the window has been destroyed. The wrapper
- *   will be newly created, if one doesn’t exist already.
- */
-GdkSurface *
-gdk_x11_surface_foreign_new_for_display (GdkDisplay *display,
-                                        Window      window)
-{
-  GdkX11Screen *screen;
-  GdkSurface *win;
-  GdkSurfaceImplX11 *impl;
-  GdkX11Display *display_x11;
-  XWindowAttributes attrs;
-  Window root, parent;
-  Window *children = NULL;
-  guint nchildren;
-  gboolean result;
-
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-
-  display_x11 = GDK_X11_DISPLAY (display);
-
-  if ((win = gdk_x11_surface_lookup_for_display (display, window)) != NULL)
-    return g_object_ref (win);
-
-  gdk_x11_display_error_trap_push (display);
-  result = XGetWindowAttributes (display_x11->xdisplay, window, &attrs);
-  if (gdk_x11_display_error_trap_pop (display) || !result)
-    return NULL;
-
-  /* FIXME: This is pretty expensive.
-   * Maybe the caller should supply the parent
-   */
-  gdk_x11_display_error_trap_push (display);
-  result = XQueryTree (display_x11->xdisplay, window, &root, &parent, &children, &nchildren);
-  if (gdk_x11_display_error_trap_pop (display) || !result)
-    return NULL;
-
-  if (children)
-    XFree (children);
-
-  screen = _gdk_x11_display_screen_for_xrootwin (display, root);
-  if (screen == NULL)
-    return NULL;
-
-  win = _gdk_display_create_window (display);
-  win->impl = g_object_new (GDK_TYPE_SURFACE_IMPL_X11, NULL);
-  win->impl_window = win;
-
-  impl = GDK_SURFACE_IMPL_X11 (win->impl);
-  impl->wrapper = win;
-  impl->window_scale = GDK_X11_SCREEN (screen)->window_scale;
-
-  /* Always treat foreigns as toplevels */
-  win->parent = NULL;
-
-  impl->xid = window;
-
-  win->x = attrs.x / impl->window_scale;
-  win->y = attrs.y / impl->window_scale;
-  impl->unscaled_width = attrs.width;
-  impl->unscaled_height = attrs.height;
-  win->width = attrs.width / impl->window_scale;
-  win->height = attrs.height  / impl->window_scale;
-  win->window_type = GDK_SURFACE_FOREIGN;
-  win->destroyed = FALSE;
-
-  win->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
-
-  if (attrs.map_state == IsUnmapped)
-    win->state = GDK_SURFACE_STATE_WITHDRAWN;
-  else
-    win->state = 0;
-  win->viewable = TRUE;
-
-  g_object_ref (win);
-  _gdk_x11_display_add_window (display, &GDK_SURFACE_XID (win), win);
-
-  /* Update the clip region, etc */
-  _gdk_surface_update_size (win);
-
-  return win;
-}
-
-static void
-gdk_toplevel_x11_free_contents (GdkDisplay *display,
-                               GdkToplevelX11 *toplevel)
-{
-  if (toplevel->icon_pixmap)
-    {
-      cairo_surface_destroy (toplevel->icon_pixmap);
-      toplevel->icon_pixmap = NULL;
-    }
-  if (toplevel->icon_mask)
-    {
-      cairo_surface_destroy (toplevel->icon_mask);
-      toplevel->icon_mask = NULL;
-    }
-  if (toplevel->group_leader)
-    {
-      g_object_unref (toplevel->group_leader);
-      toplevel->group_leader = NULL;
-    }
-#ifdef HAVE_XSYNC
-  if (toplevel->update_counter != None)
-    {
-      XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display), 
-                          toplevel->update_counter);
-      XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display),
-                           toplevel->extended_update_counter);
-      toplevel->update_counter = None;
-      toplevel->extended_update_counter = None;
-
-      toplevel->current_counter_value = 0;
-    }
-#endif
-}
-
-static void
-gdk_x11_surface_destroy (GdkSurface *window,
-                        gboolean   recursing,
-                        gboolean   foreign_destroy)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-  GdkToplevelX11 *toplevel;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-  if (toplevel)
-    gdk_toplevel_x11_free_contents (GDK_SURFACE_DISPLAY (window), toplevel);
-
-  unhook_surface_changed (window);
-
-  if (impl->cairo_surface)
-    {
-      cairo_surface_finish (impl->cairo_surface);
-      cairo_surface_destroy (impl->cairo_surface);
-      impl->cairo_surface = NULL;
-    }
-
-  if (!recursing && !foreign_destroy)
-    XDestroyWindow (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XID (window));
-}
-
-/* This function is called when the XWindow is really gone.
- */
-static void
-gdk_x11_surface_destroy_notify (GdkSurface *window)
-{
-  GdkSurfaceImplX11 *window_impl;
-
-  window_impl = GDK_SURFACE_IMPL_X11 ((window)->impl);
-
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      if (GDK_SURFACE_TYPE(window) != GDK_SURFACE_FOREIGN)
-       g_warning ("GdkSurface %#lx unexpectedly destroyed", GDK_SURFACE_XID (window));
-
-      _gdk_surface_destroy (window, TRUE);
-    }
-
-  _gdk_x11_display_remove_window (GDK_SURFACE_DISPLAY (window), GDK_SURFACE_XID (window));
-  if (window_impl->toplevel && window_impl->toplevel->focus_window)
-    _gdk_x11_display_remove_window (GDK_SURFACE_DISPLAY (window), window_impl->toplevel->focus_window);
-
-  _gdk_x11_surface_grab_check_destroy (window);
-
-  g_object_unref (window);
-}
-
-static void
-update_wm_hints (GdkSurface *window,
-                gboolean   force)
-{
-  GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (window);
-  GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
-  XWMHints wm_hints;
-
-  if (!force &&
-      !toplevel->is_leader &&
-      window->state & GDK_SURFACE_STATE_WITHDRAWN)
-    return;
-
-  wm_hints.flags = StateHint | InputHint;
-  wm_hints.input = window->accept_focus ? True : False;
-  wm_hints.initial_state = NormalState;
-  
-  if (window->state & GDK_SURFACE_STATE_ICONIFIED)
-    {
-      wm_hints.flags |= StateHint;
-      wm_hints.initial_state = IconicState;
-    }
-
-  if (toplevel->icon_pixmap)
-    {
-      wm_hints.flags |= IconPixmapHint;
-      wm_hints.icon_pixmap = cairo_xlib_surface_get_drawable (toplevel->icon_pixmap);
-    }
-
-  if (toplevel->icon_mask)
-    {
-      wm_hints.flags |= IconMaskHint;
-      wm_hints.icon_mask = cairo_xlib_surface_get_drawable (toplevel->icon_mask);
-    }
-  
-  wm_hints.flags |= WindowGroupHint;
-  if (toplevel->group_leader && !GDK_SURFACE_DESTROYED (toplevel->group_leader))
-    {
-      wm_hints.flags |= WindowGroupHint;
-      wm_hints.window_group = GDK_SURFACE_XID (toplevel->group_leader);
-    }
-  else
-    wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
-
-  if (toplevel->urgency_hint)
-    wm_hints.flags |= XUrgencyHint;
-  
-  XSetWMHints (GDK_SURFACE_XDISPLAY (window),
-              GDK_SURFACE_XID (window),
-              &wm_hints);
-}
-
-static void
-set_initial_hints (GdkSurface *window)
-{
-  GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
-  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
-  Window xwindow = GDK_SURFACE_XID (window);  
-  GdkToplevelX11 *toplevel;
-  Atom atoms[9];
-  gint i;
-
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-
-  if (!toplevel)
-    return;
-
-  update_wm_hints (window, TRUE);
-  
-  /* We set the spec hints regardless of whether the spec is supported,
-   * since it can't hurt and it's kind of expensive to check whether
-   * it's supported.
-   */
-  
-  i = 0;
-
-  if (window->state & GDK_SURFACE_STATE_MAXIMIZED)
-    {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
-                                                       "_NET_WM_STATE_MAXIMIZED_VERT");
-      ++i;
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
-                                                       "_NET_WM_STATE_MAXIMIZED_HORZ");
-      ++i;
-      toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
-    }
-
-  if (window->state & GDK_SURFACE_STATE_ABOVE)
-    {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
-                                                       "_NET_WM_STATE_ABOVE");
-      ++i;
-    }
-  
-  if (window->state & GDK_SURFACE_STATE_BELOW)
-    {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
-                                                       "_NET_WM_STATE_BELOW");
-      ++i;
-    }
-  
-  if (window->state & GDK_SURFACE_STATE_STICKY)
-    {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
-                                                       "_NET_WM_STATE_STICKY");
-      ++i;
-      toplevel->have_sticky = TRUE;
-    }
-
-  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
-    {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
-                                                       "_NET_WM_STATE_FULLSCREEN");
-      ++i;
-      toplevel->have_fullscreen = TRUE;
-    }
-
-  if (window->modal_hint)
-    {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
-                                                       "_NET_WM_STATE_MODAL");
-      ++i;
-    }
-
-  if (toplevel->skip_taskbar_hint)
-    {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
-                                                       "_NET_WM_STATE_SKIP_TASKBAR");
-      ++i;
-    }
-
-  if (toplevel->skip_pager_hint)
-    {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
-                                                       "_NET_WM_STATE_SKIP_PAGER");
-      ++i;
-    }
-
-  if (window->state & GDK_SURFACE_STATE_ICONIFIED)
-    {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
-                                                       "_NET_WM_STATE_HIDDEN");
-      ++i;
-      toplevel->have_hidden = TRUE;
-    }
-
-  if (i > 0)
-    {
-      XChangeProperty (xdisplay,
-                       xwindow,
-                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
-                       XA_ATOM, 32, PropModeReplace,
-                       (guchar*) atoms, i);
-    }
-  else 
-    {
-      XDeleteProperty (xdisplay,
-                       xwindow,
-                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
-    }
-
-  if (window->state & GDK_SURFACE_STATE_STICKY)
-    {
-      atoms[0] = 0xFFFFFFFF;
-      XChangeProperty (xdisplay,
-                       xwindow,
-                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
-                       XA_CARDINAL, 32, PropModeReplace,
-                       (guchar*) atoms, 1);
-      toplevel->on_all_desktops = TRUE;
-    }
-  else
-    {
-      XDeleteProperty (xdisplay,
-                       xwindow,
-                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
-    }
-
-  toplevel->map_serial = NextRequest (xdisplay);
-}
-
-static void
-gdk_surface_x11_show (GdkSurface *window, gboolean already_mapped)
-{
-  GdkDisplay *display;
-  GdkX11Display *display_x11;
-  GdkToplevelX11 *toplevel;
-  Display *xdisplay = GDK_SURFACE_XDISPLAY (window);
-  Window xwindow = GDK_SURFACE_XID (window);
-
-  if (!already_mapped)
-    set_initial_hints (window);
-      
-  if (WINDOW_IS_TOPLEVEL (window))
-    {
-      display = gdk_surface_get_display (window);
-      display_x11 = GDK_X11_DISPLAY (display);
-      toplevel = _gdk_x11_surface_get_toplevel (window);
-      
-      if (toplevel->user_time != 0 &&
-             display_x11->user_time != 0 &&
-         XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
-       gdk_x11_surface_set_user_time (window, display_x11->user_time);
-    }
-  
-  XMapWindow (xdisplay, xwindow);
-  
-  /* Fullscreen on current monitor is the default, no need to apply this mode
-   * when mapping a window. This also ensures that the default behavior remains
-   * consistent with pre-fullscreen mode implementation.
-   */
-  if (window->fullscreen_mode != GDK_FULLSCREEN_ON_CURRENT_MONITOR)
-    gdk_x11_surface_apply_fullscreen_mode (window);
-}
-
-static void
-gdk_surface_x11_hide (GdkSurface *window)
-{
-  /* We'll get the unmap notify eventually, and handle it then,
-   * but checking here makes things more consistent if we are
-   * just doing stuff ourself.
-   */
-  _gdk_x11_surface_grab_check_unmap (window,
-                                    NextRequest (GDK_SURFACE_XDISPLAY (window)));
-
-  /* You can't simply unmap toplevel windows. */
-  switch (window->window_type)
-    {
-    case GDK_SURFACE_TOPLEVEL:
-    case GDK_SURFACE_TEMP: /* ? */
-      gdk_surface_withdraw (window);
-      return;
-      
-    case GDK_SURFACE_FOREIGN:
-    case GDK_SURFACE_CHILD:
-    default:
-      break;
-    }
-  
-  _gdk_surface_clear_update_area (window);
-  
-  XUnmapWindow (GDK_SURFACE_XDISPLAY (window),
-               GDK_SURFACE_XID (window));
-}
-
-static void
-gdk_surface_x11_withdraw (GdkSurface *window)
-{
-  if (!window->destroyed)
-    {
-      if (GDK_SURFACE_IS_MAPPED (window))
-        gdk_synthesize_window_state (window,
-                                     0,
-                                     GDK_SURFACE_STATE_WITHDRAWN);
-
-      g_assert (!GDK_SURFACE_IS_MAPPED (window));
-
-      XWithdrawWindow (GDK_SURFACE_XDISPLAY (window),
-                       GDK_SURFACE_XID (window), 0);
-    }
-}
-
-static inline void
-window_x11_move (GdkSurface *window,
-                 gint       x,
-                 gint       y)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  XMoveWindow (GDK_SURFACE_XDISPLAY (window),
-               GDK_SURFACE_XID (window),
-               x * impl->window_scale, y * impl->window_scale);
-
-  if (impl->override_redirect)
-    {
-      window->x = x;
-      window->y = y;
-    }
-}
-
-static inline void
-window_x11_resize (GdkSurface *window,
-                   gint       width,
-                   gint       height)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (width < 1)
-    width = 1;
-
-  if (height < 1)
-    height = 1;
-
-  window_pre_damage (window);
-
-  XResizeWindow (GDK_SURFACE_XDISPLAY (window),
-                 GDK_SURFACE_XID (window),
-                 width * impl->window_scale, height * impl->window_scale);
-
-  if (impl->override_redirect)
-    {
-      impl->unscaled_width = width * impl->window_scale;
-      impl->unscaled_height = height * impl->window_scale;
-      window->width = width;
-      window->height = height;
-      _gdk_x11_surface_update_size (GDK_SURFACE_IMPL_X11 (window->impl));
-    }
-  else
-    {
-      if (width * impl->window_scale != impl->unscaled_width || height * impl->window_scale != impl->unscaled_height)
-        window->resize_count += 1;
-    }
-}
-
-static inline void
-window_x11_move_resize (GdkSurface *window,
-                        gint       x,
-                        gint       y,
-                        gint       width,
-                        gint       height)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (width < 1)
-    width = 1;
-
-  if (height < 1)
-    height = 1;
-
-  window_pre_damage (window);
-
-  XMoveResizeWindow (GDK_SURFACE_XDISPLAY (window),
-                     GDK_SURFACE_XID (window),
-                     x * impl->window_scale, y * impl->window_scale,
-                     width * impl->window_scale, height * impl->window_scale);
-
-  if (impl->override_redirect)
-    {
-      window->x = x;
-      window->y = y;
-
-      impl->unscaled_width = width * impl->window_scale;
-      impl->unscaled_height = height * impl->window_scale;
-      window->width = width;
-      window->height = height;
-
-      _gdk_x11_surface_update_size (GDK_SURFACE_IMPL_X11 (window->impl));
-    }
-  else
-    {
-      if (width * impl->window_scale != impl->unscaled_width || height * impl->window_scale != impl->unscaled_height)
-        window->resize_count += 1;
-    }
-}
-
-static void
-gdk_surface_x11_move_resize (GdkSurface *window,
-                            gboolean   with_move,
-                            gint       x,
-                            gint       y,
-                            gint       width,
-                            gint       height)
-{
-  if (with_move && (width < 0 && height < 0))
-    window_x11_move (window, x, y);
-  else
-    {
-      if (with_move)
-        window_x11_move_resize (window, x, y, width, height);
-      else
-        window_x11_resize (window, width, height);
-    }
-}
-
-void
-_gdk_x11_surface_set_window_scale (GdkSurface *window,
-                                 int scale)
-{
-  GdkSurfaceImplX11 *impl;
-  GdkToplevelX11 *toplevel;
-  GdkSurfaceHints geom_mask;
-
-  impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  impl->window_scale = scale;
-  if (impl->cairo_surface)
-    cairo_surface_set_device_scale (impl->cairo_surface, impl->window_scale, impl->window_scale);
-  _gdk_surface_update_size (window);
-
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-  if (toplevel && window->window_type != GDK_SURFACE_FOREIGN)
-    {
-      /* These are affected by window scale: */
-      geom_mask = toplevel->last_geometry_hints_mask &
-        (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE | GDK_HINT_BASE_SIZE | GDK_HINT_RESIZE_INC);
-      if (geom_mask)
-        gdk_surface_set_geometry_hints (window,
-                                       &toplevel->last_geometry_hints,
-                                       geom_mask);
-    }
-
-  if (window->window_type == GDK_SURFACE_FOREIGN)
-    XMoveWindow (GDK_SURFACE_XDISPLAY (window),
-                 GDK_SURFACE_XID (window),
-                 window->x * impl->window_scale,
-                 window->y * impl->window_scale);
-  else
-    {
-      if (impl->override_redirect)
-        {
-          impl->unscaled_width = window->width * impl->window_scale;
-          impl->unscaled_height = window->height * impl->window_scale;
-        }
-
-      XResizeWindow (GDK_SURFACE_XDISPLAY (window),
-                     GDK_SURFACE_XID (window),
-                     window->width * impl->window_scale,
-                     window->height * impl->window_scale);
-    }
-
-  gdk_surface_invalidate_rect (window, NULL, TRUE);
-}
-
-static void
-gdk_surface_x11_raise (GdkSurface *window)
-{
-  XRaiseWindow (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XID (window));
-}
-
-static void
-gdk_surface_x11_restack_toplevel (GdkSurface *window,
-                                GdkSurface *sibling,
-                                gboolean   above)
-{
-  XWindowChanges changes;
-
-  changes.sibling = GDK_SURFACE_XID (sibling);
-  changes.stack_mode = above ? Above : Below;
-  XReconfigureWMWindow (GDK_SURFACE_XDISPLAY (window),
-                       GDK_SURFACE_XID (window),
-                       gdk_x11_screen_get_screen_number (GDK_SURFACE_SCREEN (window)),
-                       CWStackMode | CWSibling, &changes);
-}
-
-static void
-gdk_surface_x11_lower (GdkSurface *window)
-{
-  XLowerWindow (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XID (window));
-}
-
-/**
- * gdk_x11_surface_move_to_current_desktop:
- * @window: (type GdkX11Surface): a #GdkSurface
- * 
- * Moves the window to the correct workspace when running under a 
- * window manager that supports multiple workspaces, as described
- * in the [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec) specification.
- * Will not do anything if the window is already on all workspaces.
- */
-void
-gdk_x11_surface_move_to_current_desktop (GdkSurface *window)
-{
-  GdkToplevelX11 *toplevel;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD);
-
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-
-  if (toplevel->on_all_desktops)
-    return;
-  
-  move_to_current_desktop (window);
-}
-
-static void
-move_to_current_desktop (GdkSurface *window)
-{
-  guint32 desktop;
-
-  desktop = gdk_x11_screen_get_current_desktop (GDK_SURFACE_SCREEN (window));
-  gdk_x11_surface_move_to_desktop (window, desktop);
-}
-
-static guint32
-get_netwm_cardinal_property (GdkSurface   *window,
-                             const gchar *name)
-{
-  GdkX11Screen *x11_screen = GDK_SURFACE_SCREEN (window);
-  GdkAtom atom;
-  guint32 prop = 0;
-  Atom type;
-  gint format;
-  gulong nitems;
-  gulong bytes_after;
-  guchar *data;
-
-  atom = g_intern_static_string (name);
-
-  if (!gdk_x11_screen_supports_net_wm_hint (x11_screen, atom))
-    return 0;
-
-  XGetWindowProperty (x11_screen->xdisplay,
-                      GDK_SURFACE_XID (window),
-                      gdk_x11_get_xatom_by_name_for_display (GDK_SURFACE_DISPLAY (window), name),
-                      0, G_MAXLONG,
-                      False, XA_CARDINAL, &type, &format, &nitems,
-                      &bytes_after, &data);
-  if (type == XA_CARDINAL)
-    {
-      prop = *(gulong *)data;
-      XFree (data);
-    }
-
-  return prop;
-}
-
-/**
- * gdk_x11_surface_get_desktop:
- * @window: (type GdkX11Surface): a #GdkSurface
- *
- * Gets the number of the workspace @window is on.
- *
- * Returns: the current workspace of @window
- */
-guint32
-gdk_x11_surface_get_desktop (GdkSurface *window)
-{
-  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
-
-  return get_netwm_cardinal_property (window, "_NET_WM_DESKTOP");
-}
-
-/**
- * gdk_x11_surface_move_to_desktop:
- * @window: (type GdkX11Surface): a #GdkSurface
- * @desktop: the number of the workspace to move the window to
- *
- * Moves the window to the given workspace when running unde a
- * window manager that supports multiple workspaces, as described
- * in the [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec) specification.
- */
-void
-gdk_x11_surface_move_to_desktop (GdkSurface *window,
-                                guint32    desktop)
-{
-  GdkAtom atom;
-  XClientMessageEvent xclient;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  atom = g_intern_static_string ("_NET_WM_DESKTOP");
-  if (!gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window), atom))
-    return;
-
-  memset (&xclient, 0, sizeof (xclient));
-  xclient.type = ClientMessage;
-  xclient.serial = 0;
-  xclient.send_event = True;
-  xclient.window = GDK_SURFACE_XID (window);
-  xclient.message_type = gdk_x11_atom_to_xatom_for_display (GDK_SURFACE_DISPLAY (window), atom);
-  xclient.format = 32;
-
-  xclient.data.l[0] = desktop;
-  xclient.data.l[1] = 1; /* source indication */
-  xclient.data.l[2] = 0;
-  xclient.data.l[3] = 0;
-  xclient.data.l[4] = 0;
-
-  XSendEvent (GDK_SURFACE_XDISPLAY (window),
-              GDK_SURFACE_XROOTWIN (window),
-              False,
-              SubstructureRedirectMask | SubstructureNotifyMask,
-              (XEvent *)&xclient);
-}
-
-static void
-gdk_x11_surface_focus (GdkSurface *window,
-                     guint32    timestamp)
-{
-  GdkDisplay *display;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  display = GDK_SURFACE_DISPLAY (window);
-
-  if (gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
-                                          g_intern_static_string ("_NET_ACTIVE_WINDOW")))
-    {
-      XClientMessageEvent xclient;
-
-      memset (&xclient, 0, sizeof (xclient));
-      xclient.type = ClientMessage;
-      xclient.window = GDK_SURFACE_XID (window);
-      xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
-                                                                    "_NET_ACTIVE_WINDOW");
-      xclient.format = 32;
-      xclient.data.l[0] = 1; /* requestor type; we're an app */
-      xclient.data.l[1] = timestamp;
-      xclient.data.l[2] = None; /* currently active window */
-      xclient.data.l[3] = 0;
-      xclient.data.l[4] = 0;
-      
-      XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XROOTWIN (window), False,
-                  SubstructureRedirectMask | SubstructureNotifyMask,
-                  (XEvent *)&xclient);
-    }
-  else
-    {
-      XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window));
-
-      /* There is no way of knowing reliably whether we are viewable;
-       * so trap errors asynchronously around the XSetInputFocus call
-       */
-      gdk_x11_display_error_trap_push (display);
-      XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
-                      GDK_SURFACE_XID (window),
-                      RevertToParent,
-                      timestamp);
-      gdk_x11_display_error_trap_pop_ignored (display);
-    }
-}
-
-static void
-gdk_x11_surface_set_type_hint (GdkSurface        *window,
-                             GdkSurfaceTypeHint hint)
-{
-  GdkDisplay *display;
-  Atom atom;
-  
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  display = gdk_surface_get_display (window);
-
-  switch (hint)
-    {
-    case GDK_SURFACE_TYPE_HINT_DIALOG:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
-      break;
-    case GDK_SURFACE_TYPE_HINT_MENU:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
-      break;
-    case GDK_SURFACE_TYPE_HINT_TOOLBAR:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
-      break;
-    case GDK_SURFACE_TYPE_HINT_UTILITY:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
-      break;
-    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
-      break;
-    case GDK_SURFACE_TYPE_HINT_DOCK:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
-      break;
-    case GDK_SURFACE_TYPE_HINT_DESKTOP:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
-      break;
-    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
-      break;
-    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
-      break;
-    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
-      break;
-    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
-      break;
-    case GDK_SURFACE_TYPE_HINT_COMBO:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
-      break;
-    case GDK_SURFACE_TYPE_HINT_DND:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
-      break;
-    default:
-      g_warning ("Unknown hint %d passed to gdk_surface_set_type_hint", hint);
-      /* Fall thru */
-    case GDK_SURFACE_TYPE_HINT_NORMAL:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
-      break;
-    }
-
-  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
-                  gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
-                  XA_ATOM, 32, PropModeReplace,
-                  (guchar *)&atom, 1);
-}
-
-static GdkSurfaceTypeHint
-gdk_x11_surface_get_type_hint (GdkSurface *window)
-{
-  GdkDisplay *display;
-  GdkSurfaceTypeHint type;
-  Atom type_return;
-  gint format_return;
-  gulong nitems_return;
-  gulong bytes_after_return;
-  guchar *data = NULL;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), GDK_SURFACE_TYPE_HINT_NORMAL);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return GDK_SURFACE_TYPE_HINT_NORMAL;
-
-  type = GDK_SURFACE_TYPE_HINT_NORMAL;
-
-  display = gdk_surface_get_display (window);
-
-  if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
-                          gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
-                          0, G_MAXLONG, False, XA_ATOM, &type_return,
-                          &format_return, &nitems_return, &bytes_after_return,
-                          &data) == Success)
-    {
-      if ((type_return == XA_ATOM) && (format_return == 32) &&
-          (data) && (nitems_return == 1))
-        {
-          Atom atom = *(Atom*)data;
-
-          if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
-            type = GDK_SURFACE_TYPE_HINT_DIALOG;
-          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
-            type = GDK_SURFACE_TYPE_HINT_MENU;
-          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
-            type = GDK_SURFACE_TYPE_HINT_TOOLBAR;
-          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
-            type = GDK_SURFACE_TYPE_HINT_UTILITY;
-          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
-            type = GDK_SURFACE_TYPE_HINT_SPLASHSCREEN;
-          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
-            type = GDK_SURFACE_TYPE_HINT_DOCK;
-          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
-            type = GDK_SURFACE_TYPE_HINT_DESKTOP;
-         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
-           type = GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU;
-         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
-           type = GDK_SURFACE_TYPE_HINT_POPUP_MENU;
-         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
-           type = GDK_SURFACE_TYPE_HINT_TOOLTIP;
-         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
-           type = GDK_SURFACE_TYPE_HINT_NOTIFICATION;
-         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
-           type = GDK_SURFACE_TYPE_HINT_COMBO;
-         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
-           type = GDK_SURFACE_TYPE_HINT_DND;
-        }
-
-      if (type_return != None && data != NULL)
-        XFree (data);
-    }
-
-  return type;
-}
-
-static void
-gdk_wmspec_change_state (gboolean   add,
-                        GdkSurface *window,
-                        GdkAtom    state1,
-                        GdkAtom    state2)
-{
-  GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
-  XClientMessageEvent xclient;
-  
-#define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
-#define _NET_WM_STATE_ADD           1    /* add/set property */
-#define _NET_WM_STATE_TOGGLE        2    /* toggle property  */  
-  
-  memset (&xclient, 0, sizeof (xclient));
-  xclient.type = ClientMessage;
-  xclient.window = GDK_SURFACE_XID (window);
-  xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
-  xclient.format = 32;
-  xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
-  xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
-  xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
-  xclient.data.l[3] = 1; /* source indication */
-  xclient.data.l[4] = 0;
-  
-  XSendEvent (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XROOTWIN (window), False,
-             SubstructureRedirectMask | SubstructureNotifyMask,
-             (XEvent *)&xclient);
-}
-
-static void
-gdk_x11_surface_set_modal_hint (GdkSurface *window,
-                              gboolean   modal)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  window->modal_hint = modal;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    gdk_wmspec_change_state (modal, window,
-                            g_intern_static_string ("_NET_WM_STATE_MODAL"), 
-                            NULL);
-}
-
-static void
-gdk_x11_surface_set_skip_taskbar_hint (GdkSurface *window,
-                                     gboolean   skips_taskbar)
-{
-  GdkToplevelX11 *toplevel;
-  
-  g_return_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD);
-  
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-  toplevel->skip_taskbar_hint = skips_taskbar;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    gdk_wmspec_change_state (skips_taskbar, window,
-                            g_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
-                            NULL);
-}
-
-static void
-gdk_x11_surface_set_skip_pager_hint (GdkSurface *window,
-                                   gboolean   skips_pager)
-{
-  GdkToplevelX11 *toplevel;
-    
-  g_return_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD);
-  
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-  toplevel->skip_pager_hint = skips_pager;
-  
-  if (GDK_SURFACE_IS_MAPPED (window))
-    gdk_wmspec_change_state (skips_pager, window,
-                            g_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"), 
-                            NULL);
-}
-
-static void
-gdk_x11_surface_set_urgency_hint (GdkSurface *window,
-                            gboolean   urgent)
-{
-  GdkToplevelX11 *toplevel;
-    
-  g_return_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD);
-  
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-  toplevel->urgency_hint = urgent;
-  
-  update_wm_hints (window, FALSE);
-}
-
-static void
-gdk_x11_surface_set_geometry_hints (GdkSurface         *window,
-                                  const GdkGeometry *geometry,
-                                  GdkSurfaceHints     geom_mask)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-  XSizeHints size_hints;
-  GdkToplevelX11 *toplevel;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-  if (toplevel)
-    {
-      if (geometry)
-        toplevel->last_geometry_hints = *geometry;
-      toplevel->last_geometry_hints_mask = geom_mask;
-    }
-  
-  size_hints.flags = 0;
-  
-  if (geom_mask & GDK_HINT_POS)
-    {
-      size_hints.flags |= PPosition;
-      /* We need to initialize the following obsolete fields because KWM 
-       * apparently uses these fields if they are non-zero.
-       * #@#!#!$!.
-       */
-      size_hints.x = 0;
-      size_hints.y = 0;
-    }
-
-  if (geom_mask & GDK_HINT_USER_POS)
-    {
-      size_hints.flags |= USPosition;
-    }
-
-  if (geom_mask & GDK_HINT_USER_SIZE)
-    {
-      size_hints.flags |= USSize;
-    }
-  
-  if (geom_mask & GDK_HINT_MIN_SIZE)
-    {
-      size_hints.flags |= PMinSize;
-      size_hints.min_width = geometry->min_width * impl->window_scale;
-      size_hints.min_height = geometry->min_height * impl->window_scale;
-    }
-  
-  if (geom_mask & GDK_HINT_MAX_SIZE)
-    {
-      size_hints.flags |= PMaxSize;
-      size_hints.max_width = MAX (geometry->max_width, 1) * impl->window_scale;
-      size_hints.max_height = MAX (geometry->max_height, 1) * impl->window_scale;
-    }
-  
-  if (geom_mask & GDK_HINT_BASE_SIZE)
-    {
-      size_hints.flags |= PBaseSize;
-      size_hints.base_width = geometry->base_width * impl->window_scale;
-      size_hints.base_height = geometry->base_height * impl->window_scale;
-    }
-  
-  if (geom_mask & GDK_HINT_RESIZE_INC)
-    {
-      size_hints.flags |= PResizeInc;
-      size_hints.width_inc = geometry->width_inc * impl->window_scale;
-      size_hints.height_inc = geometry->height_inc * impl->window_scale;
-    }
-  else if (impl->window_scale > 1)
-    {
-      size_hints.flags |= PResizeInc;
-      size_hints.width_inc = impl->window_scale;
-      size_hints.height_inc = impl->window_scale;
-    }
-
-  if (geom_mask & GDK_HINT_ASPECT)
-    {
-      size_hints.flags |= PAspect;
-      if (geometry->min_aspect <= 1)
-       {
-         size_hints.min_aspect.x = 65536 * geometry->min_aspect;
-         size_hints.min_aspect.y = 65536;
-       }
-      else
-       {
-         size_hints.min_aspect.x = 65536;
-         size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
-       }
-      if (geometry->max_aspect <= 1)
-       {
-         size_hints.max_aspect.x = 65536 * geometry->max_aspect;
-         size_hints.max_aspect.y = 65536;
-       }
-      else
-       {
-         size_hints.max_aspect.x = 65536;
-         size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
-       }
-    }
-
-  if (geom_mask & GDK_HINT_WIN_GRAVITY)
-    {
-      size_hints.flags |= PWinGravity;
-      size_hints.win_gravity = geometry->win_gravity;
-    }
-  
-  /* FIXME: Would it be better to delete this property if
-   *        geom_mask == 0? It would save space on the server
-   */
-  XSetWMNormalHints (GDK_SURFACE_XDISPLAY (window),
-                    GDK_SURFACE_XID (window),
-                    &size_hints);
-}
-
-static void
-gdk_surface_get_geometry_hints (GdkSurface      *window,
-                               GdkGeometry    *geometry,
-                               GdkSurfaceHints *geom_mask)
-{
-  GdkSurfaceImplX11 *impl;
-  XSizeHints *size_hints;  
-  glong junk_supplied_mask = 0;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (geometry != NULL);
-  g_return_if_fail (geom_mask != NULL);
-
-  *geom_mask = 0;
-  
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  size_hints = XAllocSizeHints ();
-  if (!size_hints)
-    return;
-  
-  if (!XGetWMNormalHints (GDK_SURFACE_XDISPLAY (window),
-                          GDK_SURFACE_XID (window),
-                          size_hints,
-                          &junk_supplied_mask))
-    size_hints->flags = 0;
-
-  if (size_hints->flags & PMinSize)
-    {
-      *geom_mask |= GDK_HINT_MIN_SIZE;
-      geometry->min_width = size_hints->min_width / impl->window_scale;
-      geometry->min_height = size_hints->min_height / impl->window_scale;
-    }
-
-  if (size_hints->flags & PMaxSize)
-    {
-      *geom_mask |= GDK_HINT_MAX_SIZE;
-      geometry->max_width = MAX (size_hints->max_width, 1) / impl->window_scale;
-      geometry->max_height = MAX (size_hints->max_height, 1) / impl->window_scale;
-    }
-
-  if (size_hints->flags & PResizeInc)
-    {
-      *geom_mask |= GDK_HINT_RESIZE_INC;
-      geometry->width_inc = size_hints->width_inc / impl->window_scale;
-      geometry->height_inc = size_hints->height_inc / impl->window_scale;
-    }
-
-  if (size_hints->flags & PAspect)
-    {
-      *geom_mask |= GDK_HINT_ASPECT;
-
-      geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
-      geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
-    }
-
-  if (size_hints->flags & PWinGravity)
-    {
-      *geom_mask |= GDK_HINT_WIN_GRAVITY;
-      geometry->win_gravity = size_hints->win_gravity;
-    }
-
-  XFree (size_hints);
-}
-
-static gboolean
-utf8_is_latin1 (const gchar *str)
-{
-  const char *p = str;
-
-  while (*p)
-    {
-      gunichar ch = g_utf8_get_char (p);
-
-      if (ch > 0xff)
-       return FALSE;
-      
-      p = g_utf8_next_char (p);
-    }
-
-  return TRUE;
-}
-
-/* Set the property to @utf8_str as STRING if the @utf8_str is fully
- * convertable to STRING, otherwise, set it as compound text
- */
-static void
-set_text_property (GdkDisplay  *display,
-                  Window       xwindow,
-                  Atom         property,
-                  const gchar *utf8_str)
-{
-  gchar *prop_text = NULL;
-  Atom prop_type;
-  gint prop_length;
-  gint prop_format;
-  gboolean is_compound_text;
-  
-  if (utf8_is_latin1 (utf8_str))
-    {
-      prop_type = XA_STRING;
-      prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
-      prop_length = prop_text ? strlen (prop_text) : 0;
-      prop_format = 8;
-      is_compound_text = FALSE;
-    }
-  else
-    {
-      GdkAtom gdk_type;
-
-      gdk_x11_display_utf8_to_compound_text (display,
-                                             utf8_str, &gdk_type, &prop_format,
-                                             (guchar **)&prop_text, &prop_length);
-      prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
-      is_compound_text = TRUE;
-    }
-
-  if (prop_text)
-    {
-      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
-                      xwindow,
-                      property,
-                      prop_type, prop_format,
-                      PropModeReplace, (guchar *)prop_text,
-                      prop_length);
-
-      if (is_compound_text)
-       gdk_x11_free_compound_text ((guchar *)prop_text);
-      else
-       g_free (prop_text);
-    }
-}
-
-/* Set WM_NAME and _NET_WM_NAME
- */
-static void
-set_wm_name (GdkDisplay  *display,
-            Window       xwindow,
-            const gchar *name)
-{
-  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
-                  gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
-                  gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
-                  PropModeReplace, (guchar *)name, strlen (name));
-  
-  set_text_property (display, xwindow,
-                    gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
-                    name);
-}
-
-static void
-gdk_x11_surface_set_title (GdkSurface   *window,
-                         const gchar *title)
-{
-  GdkDisplay *display;
-  Display *xdisplay;
-  Window xwindow;
-  
-  g_return_if_fail (title != NULL);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-  
-  display = gdk_surface_get_display (window);
-  xdisplay = GDK_DISPLAY_XDISPLAY (display);
-  xwindow = GDK_SURFACE_XID (window);
-
-  set_wm_name (display, xwindow, title);
-  
-  if (!gdk_surface_icon_name_set (window))
-    {
-      XChangeProperty (xdisplay, xwindow,
-                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
-                      gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
-                      PropModeReplace, (guchar *)title, strlen (title));
-      
-      set_text_property (display, xwindow,
-                        gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
-                        title);
-    }
-}
-
-static void
-gdk_x11_surface_set_role (GdkSurface   *window,
-                        const gchar *role)
-{
-  GdkDisplay *display;
-
-  display = gdk_surface_get_display (window);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (role)
-    XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
-                     gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
-                     XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
-  else
-    XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
-                     gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
-}
-
-static void
-gdk_x11_surface_set_startup_id (GdkSurface   *window,
-                              const gchar *startup_id)
-{
-  GdkDisplay *display;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  display = gdk_surface_get_display (window);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (startup_id)
-    XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
-                     gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"), 
-                     gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
-                     PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
-  else
-    XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
-                     gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
-}
-
-static void
-gdk_x11_surface_set_transient_for (GdkSurface *window,
-                                 GdkSurface *parent)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  /* XSetTransientForHint() doesn't allow unsetting, so do it manually */
-  if (parent && !GDK_SURFACE_DESTROYED (parent))
-    XSetTransientForHint (GDK_SURFACE_XDISPLAY (window), 
-                         GDK_SURFACE_XID (window),
-                         GDK_SURFACE_XID (parent));
-  else
-    XDeleteProperty (GDK_SURFACE_XDISPLAY (window),
-                     GDK_SURFACE_XID (window),
-                     gdk_x11_get_xatom_by_name_for_display (GDK_SURFACE_DISPLAY (window), "WM_TRANSIENT_FOR"));
-}
-
-GdkCursor *
-_gdk_x11_surface_get_cursor (GdkSurface *window)
-{
-  GdkSurfaceImplX11 *impl;
-  
-  g_return_val_if_fail (GDK_IS_SURFACE (window), NULL);
-    
-  impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  return impl->cursor;
-}
-
-static void
-gdk_surface_x11_get_geometry (GdkSurface *window,
-                             gint      *x,
-                             gint      *y,
-                             gint      *width,
-                             gint      *height)
-{
-  GdkSurfaceImplX11 *impl;
-  Window root;
-  gint tx;
-  gint ty;
-  guint twidth;
-  guint theight;
-  guint tborder_width;
-  guint tdepth;
-  
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-      XGetGeometry (GDK_SURFACE_XDISPLAY (window),
-                   GDK_SURFACE_XID (window),
-                   &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
-      
-      if (x)
-       *x = tx / impl->window_scale;
-      if (y)
-       *y = ty / impl->window_scale;
-      if (width)
-       *width = twidth / impl->window_scale;
-      if (height)
-       *height = theight / impl->window_scale;
-    }
-}
-
-static void
-gdk_surface_x11_get_root_coords (GdkSurface *window,
-                               gint       x,
-                               gint       y,
-                               gint      *root_x,
-                               gint      *root_y)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-  Window child;
-  gint tx;
-  gint ty;
-  
-  XTranslateCoordinates (GDK_SURFACE_XDISPLAY (window),
-                         GDK_SURFACE_XID (window),
-                         GDK_SURFACE_XROOTWIN (window),
-                         x * impl->window_scale, y * impl->window_scale, &tx, &ty,
-                         &child);
-
-  if (root_x)
-    *root_x = tx / impl->window_scale;
-  if (root_y)
-    *root_y = ty / impl->window_scale;
-}
-
-static void
-gdk_x11_surface_get_frame_extents (GdkSurface    *window,
-                                  GdkRectangle *rect)
-{
-  GdkDisplay *display;
-  GdkSurfaceImplX11 *impl;
-  Window xwindow;
-  Window xparent;
-  Window root;
-  Window child;
-  Window *children;
-  guchar *data;
-  Window *vroots;
-  Atom type_return;
-  guint nchildren;
-  guint nvroots;
-  gulong nitems_return;
-  gulong bytes_after_return;
-  gint format_return;
-  gint i;
-  guint ww, wh, wb, wd;
-  gint wx, wy;
-  gboolean got_frame_extents = FALSE;
-
-  g_return_if_fail (rect != NULL);
-
-  rect->x = 0;
-  rect->y = 0;
-  rect->width = 1;
-  rect->height = 1;
-
-  while (window->parent && (window->parent)->parent)
-    window = window->parent;
-
-  impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  /* Refine our fallback answer a bit using local information */
-  rect->x = window->x * impl->window_scale;
-  rect->y = window->y * impl->window_scale;
-  rect->width = window->width * impl->window_scale;
-  rect->height = window->height * impl->window_scale;
-
-  if (GDK_SURFACE_DESTROYED (window) || impl->override_redirect)
-    return;
-
-  nvroots = 0;
-  vroots = NULL;
-
-  display = gdk_surface_get_display (window);
-
-  gdk_x11_display_error_trap_push (display);
-
-  xwindow = GDK_SURFACE_XID (window);
-
-  /* first try: use _NET_FRAME_EXTENTS */
-  if (gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
-                                           g_intern_static_string ("_NET_FRAME_EXTENTS")) &&
-      XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
-                          gdk_x11_get_xatom_by_name_for_display (display,
-                                                                  "_NET_FRAME_EXTENTS"),
-                          0, G_MAXLONG, False, XA_CARDINAL, &type_return,
-                          &format_return, &nitems_return, &bytes_after_return,
-                          &data)
-      == Success)
-    {
-      if ((type_return == XA_CARDINAL) && (format_return == 32) &&
-         (nitems_return == 4) && (data))
-        {
-         gulong *ldata = (gulong *) data;
-         got_frame_extents = TRUE;
-
-         /* try to get the real client window geometry */
-         if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
-                           &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
-              XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
-                                    xwindow, root, 0, 0, &wx, &wy, &child))
-            {
-             rect->x = wx;
-             rect->y = wy;
-             rect->width = ww;
-             rect->height = wh;
-           }
-
-         /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
-         rect->x -= ldata[0];
-         rect->y -= ldata[2];
-         rect->width += ldata[0] + ldata[1];
-         rect->height += ldata[2] + ldata[3];
-       }
-
-      if (data)
-       XFree (data);
-    }
-
-  if (got_frame_extents)
-    goto out;
-
-  /* no frame extents property available, which means we either have a WM that
-     is not EWMH compliant or is broken - try fallback and walk up the window
-     tree to get our window's parent which hopefully is the window frame */
-
-  /* use NETWM_VIRTUAL_ROOTS if available */
-  root = GDK_SURFACE_XROOTWIN (window);
-
-  if (gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
-                                           g_intern_static_string ("_NET_VIRTUAL_ROOTS")) &&
-      XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
-                         gdk_x11_get_xatom_by_name_for_display (display, 
-                                                                "_NET_VIRTUAL_ROOTS"),
-                         0, G_MAXLONG, False, XA_WINDOW, &type_return,
-                         &format_return, &nitems_return, &bytes_after_return,
-                         &data)
-      == Success)
-    {
-      if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
-       {
-         nvroots = nitems_return;
-         vroots = (Window *)data;
-       }
-    }
-
-  xparent = GDK_SURFACE_XID (window);
-
-  do
-    {
-      xwindow = xparent;
-
-      if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
-                      &root, &xparent,
-                      &children, &nchildren))
-       goto out;
-      
-      if (children)
-       XFree (children);
-
-      /* check virtual roots */
-      for (i = 0; i < nvroots; i++)
-       {
-         if (xparent == vroots[i])
-           {
-             root = xparent;
-             break;
-           }
-       }
-    }
-  while (xparent != root);
-
-  if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
-                   &root, &wx, &wy, &ww, &wh, &wb, &wd))
-    {
-      rect->x = wx;
-      rect->y = wy;
-      rect->width = ww;
-      rect->height = wh;
-    }
-
- out:
-  if (vroots)
-    XFree (vroots);
-
-  /* Here we extend the size to include the extra pixels if we round x/y down
-     as well as round the size up when we divide by scale so that the returned
-     size is guaranteed to cover the real pixels, but it may overshoot a bit
-     in case the window is not positioned/sized according to the scale */
-  rect->width = (rect->width + rect->x % impl->window_scale + impl->window_scale - 1) / impl->window_scale;
-  rect->height = (rect->height + rect->y % impl->window_scale + impl->window_scale - 1) / impl->window_scale;
-  rect->x = rect->x / impl->window_scale;
-  rect->y = rect->y / impl->window_scale;
-  gdk_x11_display_error_trap_pop_ignored (display);
-}
-
-static gboolean
-gdk_surface_x11_get_device_state (GdkSurface       *window,
-                                 GdkDevice       *device,
-                                 gdouble         *x,
-                                 gdouble         *y,
-                                 GdkModifierType *mask)
-{
-  GdkSurface *child;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return FALSE;
-
-  /*HIDPI: handle coords here?*/
-  GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
-                                              &child,
-                                              NULL, NULL,
-                                              x, y, mask);
-  return child != NULL;
-}
-
-static GdkEventMask
-gdk_surface_x11_get_events (GdkSurface *window)
-{
-  XWindowAttributes attrs;
-  GdkEventMask event_mask;
-  GdkEventMask filtered;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return 0;
-  else
-    {
-      XGetWindowAttributes (GDK_SURFACE_XDISPLAY (window),
-                           GDK_SURFACE_XID (window),
-                           &attrs);
-      event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
-      /* if property change was filtered out before, keep it filtered out */
-      filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
-      window->event_mask = event_mask & ((window->event_mask & filtered) | ~filtered);
-
-      return event_mask;
-    }
-}
-static void
-gdk_surface_x11_set_events (GdkSurface    *window,
-                           GdkEventMask  event_mask)
-{
-  long xevent_mask = 0;
-  
-  if (!GDK_SURFACE_DESTROYED (window))
-    {
-      GdkX11Display *display_x11;
-
-      if (GDK_SURFACE_XID (window) != GDK_SURFACE_XROOTWIN (window))
-        xevent_mask = StructureNotifyMask | PropertyChangeMask;
-
-      display_x11 = GDK_X11_DISPLAY (gdk_surface_get_display (window));
-      gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
-                                          GDK_SURFACE_XID (window), event_mask,
-                                          xevent_mask);
-    }
-}
-
-static inline void
-do_shape_combine_region (GdkSurface       *window,
-                        const cairo_region_t *shape_region,
-                        gint             offset_x,
-                        gint             offset_y,
-                        gint             shape)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (shape_region == NULL)
-    {
-      /* Use NULL mask to unset the shape */
-      if (shape == ShapeBounding
-         ? gdk_display_supports_shapes (GDK_SURFACE_DISPLAY (window))
-         : gdk_display_supports_input_shapes (GDK_SURFACE_DISPLAY (window)))
-       {
-         XShapeCombineMask (GDK_SURFACE_XDISPLAY (window),
-                            GDK_SURFACE_XID (window),
-                            shape,
-                            0, 0,
-                            None,
-                            ShapeSet);
-       }
-      return;
-    }
-  
-  if (shape == ShapeBounding
-      ? gdk_display_supports_shapes (GDK_SURFACE_DISPLAY (window))
-      : gdk_display_supports_input_shapes (GDK_SURFACE_DISPLAY (window)))
-    {
-      gint n_rects = 0;
-      XRectangle *xrects = NULL;
-
-      _gdk_x11_region_get_xrectangles (shape_region,
-                                       0, 0, impl->window_scale,
-                                       &xrects, &n_rects);
-      
-      XShapeCombineRectangles (GDK_SURFACE_XDISPLAY (window),
-                               GDK_SURFACE_XID (window),
-                               shape,
-                               offset_x * impl->window_scale,
-                               offset_y * impl->window_scale,
-                               xrects, n_rects,
-                               ShapeSet,
-                               YXBanded);
-      
-      g_free (xrects);
-    }
-}
-
-static void
-gdk_surface_x11_shape_combine_region (GdkSurface       *window,
-                                     const cairo_region_t *shape_region,
-                                     gint             offset_x,
-                                     gint             offset_y)
-{
-  do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
-}
-
-static void 
-gdk_surface_x11_input_shape_combine_region (GdkSurface       *window,
-                                          const cairo_region_t *shape_region,
-                                          gint             offset_x,
-                                          gint             offset_y)
-{
-#ifdef ShapeInput
-  do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
-#endif
-}
-
-static void
-gdk_x11_surface_set_accept_focus (GdkSurface *window,
-                                gboolean accept_focus)
-{
-  accept_focus = accept_focus != FALSE;
-
-  if (window->accept_focus != accept_focus)
-    {
-      window->accept_focus = accept_focus;
-
-      if (!GDK_SURFACE_DESTROYED (window) &&
-         WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-       update_wm_hints (window, FALSE);
-    }
-}
-
-static void
-gdk_x11_surface_set_focus_on_map (GdkSurface *window,
-                                gboolean focus_on_map)
-{
-  focus_on_map = focus_on_map != FALSE;
-
-  if (window->focus_on_map != focus_on_map)
-    {
-      window->focus_on_map = focus_on_map;
-      
-      if ((!GDK_SURFACE_DESTROYED (window)) &&
-         (!window->focus_on_map) &&
-         WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-       gdk_x11_surface_set_user_time (window, 0);
-    }
-}
-
-/**
- * gdk_x11_surface_set_user_time:
- * @window: (type GdkX11Surface): A toplevel #GdkSurface
- * @timestamp: An XServer timestamp to which the property should be set
- *
- * The application can use this call to update the _NET_WM_USER_TIME
- * property on a toplevel window.  This property stores an Xserver
- * time which represents the time of the last user input event
- * received for this window.  This property may be used by the window
- * manager to alter the focus, stacking, and/or placement behavior of
- * windows when they are mapped depending on whether the new window
- * was created by a user action or is a "pop-up" window activated by a
- * timer or some other event.
- *
- * Note that this property is automatically updated by GDK, so this
- * function should only be used by applications which handle input
- * events bypassing GDK.
- **/
-void
-gdk_x11_surface_set_user_time (GdkSurface *window,
-                              guint32    timestamp)
-{
-  GdkDisplay *display;
-  GdkX11Display *display_x11;
-  GdkToplevelX11 *toplevel;
-  glong timestamp_long = (glong)timestamp;
-  Window xid;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  display = gdk_surface_get_display (window);
-  display_x11 = GDK_X11_DISPLAY (display);
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-
-  if (!toplevel)
-    {
-      g_warning ("gdk_surface_set_user_time called on non-toplevel\n");
-      return;
-    }
-
-  if (toplevel->focus_window != None &&
-      gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
-                                           g_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
-    xid = toplevel->focus_window;
-  else
-    xid = GDK_SURFACE_XID (window);
-
-  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
-                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
-                   XA_CARDINAL, 32, PropModeReplace,
-                   (guchar *)&timestamp_long, 1);
-
-  if (timestamp_long != GDK_CURRENT_TIME &&
-      (display_x11->user_time == GDK_CURRENT_TIME ||
-       XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
-    display_x11->user_time = timestamp_long;
-
-  if (toplevel)
-    toplevel->user_time = timestamp_long;
-}
-
-/**
- * gdk_x11_surface_set_utf8_property:
- * @window: (type GdkX11Surface): a #GdkSurface
- * @name: Property name, will be interned as an X atom
- * @value: (allow-none): Property value, or %NULL to delete
- *
- * This function modifies or removes an arbitrary X11 window
- * property of type UTF8_STRING.  If the given @window is
- * not a toplevel window, it is ignored.
- */
-void
-gdk_x11_surface_set_utf8_property  (GdkSurface *window,
-                                  const gchar *name,
-                                  const gchar *value)
-{
-  GdkDisplay *display;
-
-  if (!WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  display = gdk_surface_get_display (window);
-
-  if (value != NULL)
-    {
-      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
-                       GDK_SURFACE_XID (window),
-                       gdk_x11_get_xatom_by_name_for_display (display, name),
-                       gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
-                       PropModeReplace, (guchar *)value, strlen (value));
-    }
-  else
-    {
-      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
-                       GDK_SURFACE_XID (window),
-                       gdk_x11_get_xatom_by_name_for_display (display, name));
-    }
-}
-
-static void
-gdk_x11_surface_set_shadow_width (GdkSurface *window,
-                                 int        left,
-                                 int        right,
-                                 int        top,
-                                 int        bottom)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-  Atom frame_extents;
-  gulong data[4] = {
-    left * impl->window_scale,
-    right * impl->window_scale,
-    top * impl->window_scale,
-    bottom * impl->window_scale
-  };
-
-  frame_extents = gdk_x11_get_xatom_by_name_for_display (gdk_surface_get_display (window),
-                                                         "_GTK_FRAME_EXTENTS");
-  XChangeProperty (GDK_SURFACE_XDISPLAY (window),
-                   GDK_SURFACE_XID (window),
-                   frame_extents, XA_CARDINAL,
-                   32, PropModeReplace,
-                   (guchar *) &data, 4);
-}
-
-/**
- * gdk_x11_surface_set_theme_variant:
- * @window: (type GdkX11Surface): a #GdkSurface
- * @variant: the theme variant to export
- *
- * GTK+ applications can request a dark theme variant. In order to
- * make other applications - namely window managers using GTK+ for
- * themeing - aware of this choice, GTK+ uses this function to
- * export the requested theme variant as _GTK_THEME_VARIANT property
- * on toplevel windows.
- *
- * Note that this property is automatically updated by GTK+, so this
- * function should only be used by applications which do not use GTK+
- * to create toplevel windows.
- */
-void
-gdk_x11_surface_set_theme_variant (GdkSurface  *window,
-                                  const char *variant)
-{
-  gdk_x11_surface_set_utf8_property (window, "_GTK_THEME_VARIANT",
-                                    variant ? variant : "");
-}
-
-#define GDK_SELECTION_MAX_SIZE(display)                                 \
-  MIN(262144,                                                           \
-      XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0     \
-       ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100         \
-       : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
-
-static void
-gdk_surface_update_icon (GdkSurface *window,
-                        GList     *icon_list)
-{
-  GdkToplevelX11 *toplevel;
-  GdkTexture *best_icon;
-  GList *tmp_list;
-  int best_size;
-
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-
-  if (toplevel->icon_pixmap != NULL)
-    {
-      cairo_surface_destroy (toplevel->icon_pixmap);
-      toplevel->icon_pixmap = NULL;
-    }
-
-  if (toplevel->icon_mask != NULL)
-    {
-      cairo_surface_destroy (toplevel->icon_mask);
-      toplevel->icon_mask = NULL;
-    }
-
-#define IDEAL_SIZE 48
-
-  best_size = G_MAXINT;
-  best_icon = NULL;
-  for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
-    {
-      GdkTexture *texture = tmp_list->data;
-      int this;
-
-      /* average width and height - if someone passes in a rectangular
-       * icon they deserve what they get.
-       */
-      this = gdk_texture_get_width (texture) + gdk_texture_get_height (texture);
-      this /= 2;
-
-      if (best_icon == NULL)
-        {
-          best_icon = texture;
-          best_size = this;
-        }
-      else
-        {
-          /* icon is better if it's 32 pixels or larger, and closer to
-           * the ideal size than the current best.
-           */
-          if (this >= 32 &&
-              (ABS (best_size - IDEAL_SIZE) <
-               ABS (this - IDEAL_SIZE)))
-            {
-              best_icon = texture;
-              best_size = this;
-            }
-        }
-    }
-
-  if (best_icon)
-    {
-      int width = gdk_texture_get_width (best_icon);
-      int height = gdk_texture_get_height (best_icon);
-      cairo_surface_t *surface;
-      cairo_t *cr;
-
-      toplevel->icon_pixmap = gdk_x11_surface_create_pixmap_surface (window, width, height);
-
-      surface = gdk_texture_download_surface (best_icon);
-
-      cr = cairo_create (toplevel->icon_pixmap);
-      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-      cairo_set_source_surface (cr, surface, 0, 0);
-      if (cairo_surface_get_content (surface) == CAIRO_CONTENT_COLOR_ALPHA)
-        {
-          /* Saturate the image, so it has bilevel alpha */
-          cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
-          cairo_paint (cr);
-          cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
-          cairo_paint (cr);
-          cairo_pop_group_to_source (cr);
-        }
-      cairo_paint (cr);
-      cairo_destroy (cr);
-
-      if (cairo_surface_get_content (surface) == CAIRO_CONTENT_COLOR_ALPHA)
-        {
-          GdkDisplay *display = gdk_surface_get_display (window);
-
-          toplevel->icon_mask = _gdk_x11_display_create_bitmap_surface (display, width, height);
-
-          cr = cairo_create (toplevel->icon_mask);
-          cairo_set_source_surface (cr, surface, 0, 0);
-          cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-          cairo_paint (cr);
-          cairo_destroy (cr);
-        }
-
-      cairo_surface_destroy (surface);
-    }
-
-  update_wm_hints (window, FALSE);
-}
-
-static void
-gdk_x11_surface_set_icon_list (GdkSurface *window,
-                             GList     *textures)
-{
-  gulong *data;
-  gulong *p;
-  gint size;
-  GList *l;
-  gint width, height;
-  GdkTexture *texture;
-  GdkDisplay *display;
-  gint i, n;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  display = gdk_surface_get_display (window);
-
-  size = 0;
-  n = 0;
-  for (l = textures; l != NULL; l = l->next)
-    {
-      texture = l->data;
-
-      width = gdk_texture_get_width (texture);
-      height = gdk_texture_get_height (texture);
-
-      /* silently ignore overlarge icons */
-      if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
-        break;
-
-      n++;
-      size += 2 + width * height;
-    }
-
-  data = g_malloc (size * sizeof (gulong));
-
-  p = data;
-  for (l = textures; l != NULL && n > 0; l = l->next)
-    {
-      texture = l->data;
-
-      width = gdk_texture_get_width (texture);
-      height = gdk_texture_get_height (texture);
-
-      *p++ = width;
-      *p++ = height;
-
-      gdk_texture_download (texture, (guchar *) p, width * 4);
-      if (sizeof (gulong) > 4)
-        {
-          i = width * height;
-          while (i-- > 0)
-            p[i] = ((guint32 *) p)[i];
-        }
-
-      p += width * height;
-      n--;
-    }
-
-  if (size > 0)
-    {
-      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
-                       GDK_SURFACE_XID (window),
-                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
-                       XA_CARDINAL, 32,
-                       PropModeReplace,
-                       (guchar*) data, size);
-    }
-  else
-    {
-      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
-                       GDK_SURFACE_XID (window),
-                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
-    }
-  
-  g_free (data);
-
-  gdk_surface_update_icon (window, textures);
-}
-
-static gboolean
-gdk_surface_icon_name_set (GdkSurface *window)
-{
-  return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
-                                              g_quark_from_static_string ("gdk-icon-name-set")));
-}
-
-static void
-gdk_x11_surface_set_icon_name (GdkSurface   *window,
-                             const gchar *name)
-{
-  GdkDisplay *display;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  display = gdk_surface_get_display (window);
-
-  g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
-                      GUINT_TO_POINTER (name != NULL));
-
-  if (name != NULL)
-    {
-      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
-                       GDK_SURFACE_XID (window),
-                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
-                       gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
-                       PropModeReplace, (guchar *)name, strlen (name));
-
-      set_text_property (display, GDK_SURFACE_XID (window),
-                         gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
-                         name);
-    }
-  else
-    {
-      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
-                       GDK_SURFACE_XID (window),
-                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
-      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
-                       GDK_SURFACE_XID (window),
-                       gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
-    }
-}
-
-static void
-gdk_x11_surface_iconify (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {  
-      XIconifyWindow (GDK_SURFACE_XDISPLAY (window),
-                     GDK_SURFACE_XID (window),
-                     gdk_x11_screen_get_screen_number (GDK_SURFACE_SCREEN (window)));
-    }
-  else
-    {
-      /* Flip our client side flag, the real work happens on map. */
-      gdk_synthesize_window_state (window,
-                                   0,
-                                   GDK_SURFACE_STATE_ICONIFIED);
-      gdk_wmspec_change_state (TRUE, window,
-                               g_intern_static_string ("_NET_WM_STATE_HIDDEN"),
-                               NULL);
-    }
-}
-
-static void
-gdk_x11_surface_deiconify (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {  
-      gdk_surface_show (window);
-      gdk_wmspec_change_state (FALSE, window,
-                               g_intern_static_string ("_NET_WM_STATE_HIDDEN"),
-                               NULL);
-    }
-  else
-    {
-      /* Flip our client side flag, the real work happens on map. */
-      gdk_synthesize_window_state (window,
-                                   GDK_SURFACE_STATE_ICONIFIED,
-                                   0);
-      gdk_wmspec_change_state (FALSE, window,
-                               g_intern_static_string ("_NET_WM_STATE_HIDDEN"),
-                               NULL);
-    }
-}
-
-static void
-gdk_x11_surface_stick (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      /* "stick" means stick to all desktops _and_ do not scroll with the
-       * viewport. i.e. glue to the monitor glass in all cases.
-       */
-      
-      XClientMessageEvent xclient;
-
-      /* Request stick during viewport scroll */
-      gdk_wmspec_change_state (TRUE, window,
-                              g_intern_static_string ("_NET_WM_STATE_STICKY"),
-                              NULL);
-
-      /* Request desktop 0xFFFFFFFF */
-      memset (&xclient, 0, sizeof (xclient));
-      xclient.type = ClientMessage;
-      xclient.window = GDK_SURFACE_XID (window);
-      xclient.display = GDK_SURFACE_XDISPLAY (window);
-      xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_SURFACE_DISPLAY (window), 
-                                                                       "_NET_WM_DESKTOP");
-      xclient.format = 32;
-
-      xclient.data.l[0] = 0xFFFFFFFF;
-      xclient.data.l[1] = 0;
-      xclient.data.l[2] = 0;
-      xclient.data.l[3] = 0;
-      xclient.data.l[4] = 0;
-
-      XSendEvent (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XROOTWIN (window), False,
-                  SubstructureRedirectMask | SubstructureNotifyMask,
-                  (XEvent *)&xclient);
-    }
-  else
-    {
-      /* Flip our client side flag, the real work happens on map. */
-      gdk_synthesize_window_state (window,
-                                   0,
-                                   GDK_SURFACE_STATE_STICKY);
-    }
-}
-
-static void
-gdk_x11_surface_unstick (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      /* Request unstick from viewport */
-      gdk_wmspec_change_state (FALSE, window,
-                              g_intern_static_string ("_NET_WM_STATE_STICKY"),
-                              NULL);
-
-      move_to_current_desktop (window);
-    }
-  else
-    {
-      /* Flip our client side flag, the real work happens on map. */
-      gdk_synthesize_window_state (window,
-                                   GDK_SURFACE_STATE_STICKY,
-                                   0);
-
-    }
-}
-
-static void
-gdk_x11_surface_maximize (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    gdk_wmspec_change_state (TRUE, window,
-                            g_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
-                            g_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
-  else
-    gdk_synthesize_window_state (window,
-                                0,
-                                GDK_SURFACE_STATE_MAXIMIZED);
-}
-
-static void
-gdk_x11_surface_unmaximize (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    gdk_wmspec_change_state (FALSE, window,
-                            g_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
-                            g_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
-  else
-    gdk_synthesize_window_state (window,
-                                GDK_SURFACE_STATE_MAXIMIZED,
-                                0);
-}
-
-static void
-gdk_x11_surface_apply_fullscreen_mode (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  /* _NET_WM_FULLSCREEN_MONITORS gives an indication to the window manager as
-   * to which monitors so span across when the window is fullscreen, but it's
-   * not a state in itself so this would have no effect if the window is not
-   * mapped.
-   */
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      XClientMessageEvent xclient;
-      gint                monitors[4];
-      gint                i;
-
-      memset (&xclient, 0, sizeof (xclient));
-      xclient.type = ClientMessage;
-      xclient.window = GDK_SURFACE_XID (window);
-      xclient.display = GDK_SURFACE_XDISPLAY (window);
-      xclient.format = 32;
-
-      switch (window->fullscreen_mode)
-       {
-       case GDK_FULLSCREEN_ON_CURRENT_MONITOR:
-
-         /* FIXME: This is not part of the EWMH spec!
-          *
-          * There is no documented mechanism to remove the property
-          * _NET_WM_FULLSCREEN_MONITORS once set, so we use use a set of
-          * invalid, largest possible value.
-          *
-          * When given values larger than actual possible monitor values, most
-          * window managers who support the _NET_WM_FULLSCREEN_MONITORS spec
-          * will simply unset _NET_WM_FULLSCREEN_MONITORS and revert to their
-          * default behavior.
-          *
-          * Successfully tested on mutter/metacity, kwin, compiz and xfwm4.
-          *
-          * Note, this (non documented) mechanism is unlikely to be an issue
-          * as it's used only for transitionning back from "all monitors" to
-          * "current monitor" mode.
-          *
-          * Applications who don't change the default mode won't trigger this
-          * mechanism.
-          */
-         for (i = 0; i < 4; ++i)
-           xclient.data.l[i] = G_MAXLONG;
-
-         break;
-
-       case GDK_FULLSCREEN_ON_ALL_MONITORS:
-
-         _gdk_x11_screen_get_edge_monitors (GDK_SURFACE_SCREEN (window),
-                                            &monitors[0],
-                                            &monitors[1],
-                                            &monitors[2],
-                                            &monitors[3]);
-         /* Translate all 4 monitors from the GDK set into XINERAMA indices */
-         for (i = 0; i < 4; ++i)
-           {
-             xclient.data.l[i] = monitors[i];
-             /* Sanity check, if XINERAMA is not available, we could have invalid
-              * negative values for the XINERAMA indices.
-              */
-             if (xclient.data.l[i] < 0)
-               {
-                 g_warning ("gdk_x11_surface_apply_fullscreen_mode: Invalid XINERAMA monitor index");
-                 return;
-               }
-           }
-         break;
-
-       default:
-         g_warning ("gdk_x11_surface_apply_fullscreen_mode: Unhandled fullscreen mode %d",
-                    window->fullscreen_mode);
-         return;
-       }
-
-      /* Send fullscreen monitors client message */
-      xclient.data.l[4] = 1; /* source indication */
-      xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_SURFACE_DISPLAY (window),
-                                                                   "_NET_WM_FULLSCREEN_MONITORS");
-      XSendEvent (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XROOTWIN (window), False,
-                  SubstructureRedirectMask | SubstructureNotifyMask,
-                  (XEvent *)&xclient);
-    }
-}
-
-static void
-gdk_x11_surface_fullscreen (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      gdk_wmspec_change_state (TRUE, window,
-                              g_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
-                               NULL);
-      /* Actual XRandR layout may have change since we computed the fullscreen
-       * monitors in GDK_FULLSCREEN_ON_ALL_MONITORS mode.
-       */
-      if (window->fullscreen_mode == GDK_FULLSCREEN_ON_ALL_MONITORS)
-       gdk_x11_surface_apply_fullscreen_mode (window);
-    }
-  else
-    gdk_synthesize_window_state (window,
-                                 0,
-                                 GDK_SURFACE_STATE_FULLSCREEN);
-}
-
-static void
-gdk_x11_surface_fullscreen_on_monitor (GdkSurface  *window,
-                                      GdkMonitor *monitor)
-{
-  GdkRectangle geom;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  gdk_monitor_get_geometry (monitor, &geom);
-  gdk_surface_move (window, geom.x, geom.y);
-
-  gdk_surface_set_fullscreen_mode (window, GDK_FULLSCREEN_ON_CURRENT_MONITOR);
-  gdk_x11_surface_fullscreen (window);
-}
-
-static void
-gdk_x11_surface_unfullscreen (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    gdk_wmspec_change_state (FALSE, window,
-                            g_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
-                             NULL);
-
-  else
-    gdk_synthesize_window_state (window,
-                                GDK_SURFACE_STATE_FULLSCREEN,
-                                0);
-}
-
-static void
-gdk_x11_surface_set_keep_above (GdkSurface *window,
-                              gboolean   setting)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      if (setting)
-       gdk_wmspec_change_state (FALSE, window,
-                                g_intern_static_string ("_NET_WM_STATE_BELOW"),
-                                NULL);
-      gdk_wmspec_change_state (setting, window,
-                              g_intern_static_string ("_NET_WM_STATE_ABOVE"),
-                              NULL);
-    }
-  else
-    gdk_synthesize_window_state (window,
-                                setting ? GDK_SURFACE_STATE_BELOW : GDK_SURFACE_STATE_ABOVE,
-                                setting ? GDK_SURFACE_STATE_ABOVE : 0);
-}
-
-static void
-gdk_x11_surface_set_keep_below (GdkSurface *window, gboolean setting)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      if (setting)
-       gdk_wmspec_change_state (FALSE, window,
-                                g_intern_static_string ("_NET_WM_STATE_ABOVE"),
-                                NULL);
-      gdk_wmspec_change_state (setting, window,
-                              g_intern_static_string ("_NET_WM_STATE_BELOW"),
-                              NULL);
-    }
-  else
-    gdk_synthesize_window_state (window,
-                                setting ? GDK_SURFACE_STATE_ABOVE : GDK_SURFACE_STATE_BELOW,
-                                setting ? GDK_SURFACE_STATE_BELOW : 0);
-}
-
-static GdkSurface *
-gdk_x11_surface_get_group (GdkSurface *window)
-{
-  GdkToplevelX11 *toplevel;
-  
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return NULL;
-  
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-
-  return toplevel->group_leader;
-}
-
-static void
-gdk_x11_surface_set_group (GdkSurface *window,
-                         GdkSurface *leader)
-{
-  GdkToplevelX11 *toplevel;
-  
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (GDK_SURFACE_TYPE (window) != GDK_SURFACE_CHILD);
-  g_return_if_fail (leader == NULL || GDK_IS_SURFACE (leader));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      (leader != NULL && GDK_SURFACE_DESTROYED (leader)) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  toplevel = _gdk_x11_surface_get_toplevel (window);
-
-  if (leader == NULL)
-    leader = gdk_display_get_default_group (gdk_surface_get_display (window));
-  
-  if (toplevel->group_leader != leader)
-    {
-      if (toplevel->group_leader)
-       g_object_unref (toplevel->group_leader);
-      toplevel->group_leader = g_object_ref (leader);
-      (_gdk_x11_surface_get_toplevel (leader))->is_leader = TRUE;      
-    }
-
-  update_wm_hints (window, FALSE);
-}
-
-static MotifWmHints *
-gdk_surface_get_mwm_hints (GdkSurface *window)
-{
-  GdkDisplay *display;
-  Atom hints_atom = None;
-  guchar *data;
-  Atom type;
-  gint format;
-  gulong nitems;
-  gulong bytes_after;
-  
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  display = gdk_surface_get_display (window);
-  
-  hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
-
-  XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (window),
-                     hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
-                     False, AnyPropertyType, &type, &format, &nitems,
-                     &bytes_after, &data);
-
-  if (type == None)
-    return NULL;
-  
-  return (MotifWmHints *)data;
-}
-
-static void
-gdk_surface_set_mwm_hints (GdkSurface *window,
-                         MotifWmHints *new_hints)
-{
-  GdkDisplay *display;
-  Atom hints_atom = None;
-  guchar *data;
-  MotifWmHints *hints;
-  Atom type;
-  gint format;
-  gulong nitems;
-  gulong bytes_after;
-  
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-  
-  display = gdk_surface_get_display (window);
-  
-  hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
-
-  XGetWindowProperty (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XID (window),
-                     hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
-                     False, AnyPropertyType, &type, &format, &nitems,
-                     &bytes_after, &data);
-  
-  if (type == None)
-    hints = new_hints;
-  else
-    {
-      hints = (MotifWmHints *)data;
-       
-      if (new_hints->flags & MWM_HINTS_FUNCTIONS)
-       {
-         hints->flags |= MWM_HINTS_FUNCTIONS;
-         hints->functions = new_hints->functions;
-       }
-      if (new_hints->flags & MWM_HINTS_DECORATIONS)
-       {
-         hints->flags |= MWM_HINTS_DECORATIONS;
-         hints->decorations = new_hints->decorations;
-       }
-    }
-  
-  XChangeProperty (GDK_SURFACE_XDISPLAY (window), GDK_SURFACE_XID (window),
-                  hints_atom, hints_atom, 32, PropModeReplace,
-                  (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
-  
-  if (hints != new_hints)
-    XFree (hints);
-}
-
-static void
-gdk_x11_surface_set_decorations (GdkSurface      *window,
-                               GdkWMDecoration decorations)
-{
-  MotifWmHints hints;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-  
-  /* initialize to zero to avoid writing uninitialized data to socket */
-  memset(&hints, 0, sizeof(hints));
-  hints.flags = MWM_HINTS_DECORATIONS;
-  hints.decorations = decorations;
-  
-  gdk_surface_set_mwm_hints (window, &hints);
-}
-
-static gboolean
-gdk_x11_surface_get_decorations(GdkSurface       *window,
-                              GdkWMDecoration *decorations)
-{
-  MotifWmHints *hints;
-  gboolean result = FALSE;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return FALSE;
-  
-  hints = gdk_surface_get_mwm_hints (window);
-  
-  if (hints)
-    {
-      if (hints->flags & MWM_HINTS_DECORATIONS)
-       {
-         if (decorations)
-           *decorations = hints->decorations;
-         result = TRUE;
-       }
-      
-      XFree (hints);
-    }
-
-  return result;
-}
-
-static void
-gdk_x11_surface_set_functions (GdkSurface    *window,
-                              GdkWMFunction functions)
-{
-  MotifWmHints hints;
-  
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-  
-  /* initialize to zero to avoid writing uninitialized data to socket */
-  memset(&hints, 0, sizeof(hints));
-  hints.flags = MWM_HINTS_FUNCTIONS;
-  hints.functions = functions;
-  
-  gdk_surface_set_mwm_hints (window, &hints);
-}
-
-cairo_region_t *
-_gdk_x11_xwindow_get_shape (Display *xdisplay,
-                            Window   window,
-                            gint     scale,
-                            gint     shape_type)
-{
-  cairo_region_t *shape;
-  GdkRectangle *rl;
-  XRectangle *xrl;
-  gint rn, ord, i;
-
-  shape = NULL;
-  rn = 0;
-
-  /* Note that XShapeGetRectangles returns NULL in two situations:
-   * - the server doesn't support the SHAPE extension
-   * - the shape is empty
-   *
-   * Since we can't discriminate these here, we always return
-   * an empty shape. It is the callers responsibility to check
-   * whether the server supports the SHAPE extensions beforehand.
-   */
-  xrl = XShapeGetRectangles (xdisplay, window, shape_type, &rn, &ord);
-
-  if (rn == 0)
-    return cairo_region_create (); /* Empty */
-
-  if (ord != YXBanded)
-    {
-      /* This really shouldn't happen with any xserver, as they
-       * generally convert regions to YXBanded internally
-       */
-      g_warning ("non YXBanded shape masks not supported");
-      XFree (xrl);
-      return NULL;
-    }
-
-  /* NOTE: The scale divisions here may lose some precision if someone
-     else set the shape to be non-scale precision */
-  rl = g_new (GdkRectangle, rn);
-  for (i = 0; i < rn; i++)
-    {
-      rl[i].x = xrl[i].x / scale;
-      rl[i].y = xrl[i].y / scale;
-      rl[i].width = xrl[i].width / scale;
-      rl[i].height = xrl[i].height / scale;
-    }
-  XFree (xrl);
-
-  shape = cairo_region_create_rectangles (rl, rn);
-  g_free (rl);
-
-  return shape;
-}
-
-/* From the WM spec */
-#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT      0
-#define _NET_WM_MOVERESIZE_SIZE_TOP          1
-#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT     2
-#define _NET_WM_MOVERESIZE_SIZE_RIGHT        3
-#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT  4
-#define _NET_WM_MOVERESIZE_SIZE_BOTTOM       5
-#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT   6
-#define _NET_WM_MOVERESIZE_SIZE_LEFT         7
-#define _NET_WM_MOVERESIZE_MOVE              8   /* movement only */
-#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD     9   /* size via keyboard */
-#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD    10   /* move via keyboard */
-#define _NET_WM_MOVERESIZE_CANCEL           11   /* cancel operation */
-
-static void
-wmspec_send_message (GdkDisplay *display,
-                     GdkSurface  *window,
-                     gint        root_x,
-                     gint        root_y,
-                     gint        action,
-                     gint        button)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-  XClientMessageEvent xclient;
-
-  memset (&xclient, 0, sizeof (xclient));
-  xclient.type = ClientMessage;
-  xclient.window = GDK_SURFACE_XID (window);
-  xclient.message_type =
-    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
-  xclient.format = 32;
-  xclient.data.l[0] = root_x * impl->window_scale;
-  xclient.data.l[1] = root_y * impl->window_scale;
-  xclient.data.l[2] = action;
-  xclient.data.l[3] = button;
-  xclient.data.l[4] = 1;  /* source indication */
-
-  XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XROOTWIN (window), False,
-              SubstructureRedirectMask | SubstructureNotifyMask,
-              (XEvent *)&xclient);
-}
-
-static void
-handle_wmspec_button_release (GdkDisplay   *display,
-                              const XEvent *xevent)
-{
-  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
-  GdkSurface *window;
-
-#if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
-  XIEvent *xiev = (XIEvent *) xevent->xcookie.data;
-  XIDeviceEvent *xidev = (XIDeviceEvent *) xiev;
-
-  if (xevent->xany.type == GenericEvent)
-    window = gdk_x11_surface_lookup_for_display (display, xidev->event);
-  else
-#endif
-    window = gdk_x11_surface_lookup_for_display (display, xevent->xany.window);
-
-  if (display_x11->wm_moveresize_button != 0 && window != NULL)
-    {
-      if ((xevent->xany.type == ButtonRelease &&
-           xevent->xbutton.button == display_x11->wm_moveresize_button)
-#if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
-          ||
-          (xevent->xany.type == GenericEvent &&
-           xiev->evtype == XI_ButtonRelease &&
-           xidev->detail == display_x11->wm_moveresize_button)
-#endif
-          )
-        {
-          display_x11->wm_moveresize_button = 0;
-          wmspec_send_message (display, window, 0, 0, _NET_WM_MOVERESIZE_CANCEL, 0);
-        }
-    }
-}
-
-static void
-wmspec_moveresize (GdkSurface *window,
-                   gint       direction,
-                   GdkDevice *device,
-                   gint       button,
-                   gint       root_x,
-                   gint       root_y,
-                   guint32    timestamp)
-{
-  GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
-
-  if (button != 0)
-    gdk_seat_ungrab (gdk_device_get_seat (device)); /* Release passive grab */
-  GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
-
-  wmspec_send_message (display, window, root_x, root_y, direction, button);
-}
-
-static void
-wmspec_resize_drag (GdkSurface     *window,
-                    GdkSurfaceEdge  edge,
-                    GdkDevice     *device,
-                    gint           button,
-                    gint           root_x,
-                    gint           root_y,
-                    guint32        timestamp)
-{
-  gint direction;
-  
-  if (button == 0)
-    direction = _NET_WM_MOVERESIZE_SIZE_KEYBOARD;
-  else
-    switch (edge)
-      {
-      /* Let the compiler turn a switch into a table, instead
-       * of doing the table manually, this way is easier to verify.
-       */
-      case GDK_SURFACE_EDGE_NORTH_WEST:
-        direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
-        break;
-
-      case GDK_SURFACE_EDGE_NORTH:
-        direction = _NET_WM_MOVERESIZE_SIZE_TOP;
-        break;
-
-      case GDK_SURFACE_EDGE_NORTH_EAST:
-        direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
-        break;
-
-      case GDK_SURFACE_EDGE_WEST:
-        direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
-        break;
-
-      case GDK_SURFACE_EDGE_EAST:
-        direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
-        break;
-
-      case GDK_SURFACE_EDGE_SOUTH_WEST:
-        direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
-        break;
-
-      case GDK_SURFACE_EDGE_SOUTH:
-        direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
-        break;
-
-      case GDK_SURFACE_EDGE_SOUTH_EAST:
-        direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
-        break;
-
-      default:
-        g_warning ("gdk_surface_begin_resize_drag: bad resize edge %d!",
-                   edge);
-        return;
-      }
-  
-  wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
-}
-
-typedef struct _MoveResizeData MoveResizeData;
-
-struct _MoveResizeData
-{
-  GdkDisplay *display;
-
-  GdkSurface *moveresize_window;
-  GdkSurface *moveresize_emulation_window;
-  gboolean is_resize;
-  GdkSurfaceEdge resize_edge;
-  GdkDevice *device;
-  gint moveresize_button;
-  gint moveresize_x;
-  gint moveresize_y;
-  gint moveresize_orig_x;
-  gint moveresize_orig_y;
-  gint moveresize_orig_width;
-  gint moveresize_orig_height;
-  GdkSurfaceHints moveresize_geom_mask;
-  GdkGeometry moveresize_geometry;
-  Time moveresize_process_time;
-  XEvent *moveresize_pending_event;
-};
-
-static MoveResizeData *
-get_move_resize_data (GdkDisplay *display,
-                     gboolean    create)
-{
-  MoveResizeData *mv_resize;
-  static GQuark move_resize_quark = 0;
-
-  if (!move_resize_quark)
-    move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
-  
-  mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
-
-  if (!mv_resize && create)
-    {
-      mv_resize = g_new0 (MoveResizeData, 1);
-      mv_resize->display = display;
-      
-      g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
-    }
-
-  return mv_resize;
-}
-
-static void
-check_maximize (MoveResizeData *mv_resize,
-                gdouble         x_root,
-                gdouble         y_root)
-{
-  GdkSurfaceState state;
-  gint y;
-
-  if (mv_resize->is_resize)
-    return;
-
-  state = gdk_surface_get_state (mv_resize->moveresize_window);
-
-  if (state & GDK_SURFACE_STATE_MAXIMIZED)
-    return;
-
-  y = mv_resize->moveresize_orig_y + (y_root - mv_resize->moveresize_y);
-
-  if (y < 10)
-    gdk_surface_maximize (mv_resize->moveresize_window);
-}
-
-static void
-check_unmaximize (MoveResizeData *mv_resize,
-                  gdouble         x_root,
-                  gdouble         y_root)
-{
-  GdkSurfaceState state;
-  gint dx, dy;
-
-  if (mv_resize->is_resize)
-    return;
-
-  state = gdk_surface_get_state (mv_resize->moveresize_window);
-
-  if ((state & (GDK_SURFACE_STATE_MAXIMIZED | GDK_SURFACE_STATE_TILED)) == 0)
-    return;
-
-  dx = x_root - mv_resize->moveresize_x;
-  dy = y_root - mv_resize->moveresize_y;
-
-  if (ABS (dx) > 20 || ABS (dy) > 20)
-    gdk_surface_unmaximize (mv_resize->moveresize_window);
-}
-
-static void
-update_pos (MoveResizeData *mv_resize,
-           gint            new_root_x,
-           gint            new_root_y)
-{
-  gint dx, dy;
-
-  check_unmaximize (mv_resize, new_root_x, new_root_y);
-  dx = new_root_x - mv_resize->moveresize_x;
-  dy = new_root_y - mv_resize->moveresize_y;
-
-  if (mv_resize->is_resize)
-    {
-      gint x, y, w, h;
-
-      x = mv_resize->moveresize_orig_x;
-      y = mv_resize->moveresize_orig_y;
-
-      w = mv_resize->moveresize_orig_width;
-      h = mv_resize->moveresize_orig_height;
-
-      switch (mv_resize->resize_edge)
-       {
-       case GDK_SURFACE_EDGE_NORTH_WEST:
-         x += dx;
-         y += dy;
-         w -= dx;
-         h -= dy;
-         break;
-       case GDK_SURFACE_EDGE_NORTH:
-         y += dy;
-         h -= dy;
-         break;
-       case GDK_SURFACE_EDGE_NORTH_EAST:
-         y += dy;
-         h -= dy;
-         w += dx;
-         break;
-       case GDK_SURFACE_EDGE_SOUTH_WEST:
-         h += dy;
-         x += dx;
-         w -= dx;
-         break;
-       case GDK_SURFACE_EDGE_SOUTH_EAST:
-         w += dx;
-         h += dy;
-         break;
-       case GDK_SURFACE_EDGE_SOUTH:
-         h += dy;
-         break;
-       case GDK_SURFACE_EDGE_EAST:
-         w += dx;
-         break;
-       case GDK_SURFACE_EDGE_WEST:
-         x += dx;
-         w -= dx;
-         break;
-        default:
-          break;
-       }
-
-      x = MAX (x, 0);
-      y = MAX (y, 0);
-      w = MAX (w, 1);
-      h = MAX (h, 1);
-
-      if (mv_resize->moveresize_geom_mask)
-       {
-         gdk_surface_constrain_size (&mv_resize->moveresize_geometry,
-                                    mv_resize->moveresize_geom_mask,
-                                    w, h, &w, &h);
-       }
-
-      gdk_surface_move_resize (mv_resize->moveresize_window, x, y, w, h);
-    }
-  else
-    {
-      gint x, y;
-
-      x = mv_resize->moveresize_orig_x + dx;
-      y = mv_resize->moveresize_orig_y + dy;
-
-      gdk_surface_move (mv_resize->moveresize_window, x, y);
-    }
-}
-
-static void
-finish_drag (MoveResizeData *mv_resize)
-{
-  gdk_surface_destroy (mv_resize->moveresize_emulation_window);
-  mv_resize->moveresize_emulation_window = NULL;
-  g_clear_object (&mv_resize->moveresize_window);
-  g_clear_pointer (&mv_resize->moveresize_pending_event, g_free);
-}
-
-static int
-lookahead_motion_predicate (Display *xdisplay,
-                           XEvent  *event,
-                           XPointer arg)
-{
-  gboolean *seen_release = (gboolean *)arg;
-  GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
-  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
-
-  if (*seen_release)
-    return False;
-
-  switch (event->xany.type)
-    {
-    case ButtonRelease:
-      *seen_release = TRUE;
-      break;
-    case MotionNotify:
-      mv_resize->moveresize_process_time = event->xmotion.time;
-      break;
-    default:
-      break;
-    }
-
-  return False;
-}
-
-static gboolean
-moveresize_lookahead (MoveResizeData *mv_resize,
-                     const XEvent   *event)
-{
-  XEvent tmp_event;
-  gboolean seen_release = FALSE;
-
-  if (mv_resize->moveresize_process_time)
-    {
-      if (event->xmotion.time == mv_resize->moveresize_process_time)
-        {
-          mv_resize->moveresize_process_time = 0;
-          return TRUE;
-        }
-      else
-        return FALSE;
-    }
-
-  XCheckIfEvent (event->xany.display, &tmp_event,
-                 lookahead_motion_predicate, (XPointer) & seen_release);
-
-  return mv_resize->moveresize_process_time == 0;
-}
-
-gboolean
-_gdk_x11_moveresize_handle_event (const XEvent *event)
-{
-  guint button_mask = 0;
-  GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
-  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
-  GdkSurfaceImplX11 *impl;
-
-  if (!mv_resize || !mv_resize->moveresize_window)
-    {
-      handle_wmspec_button_release (display, event);
-      return FALSE;
-    }
-
-  impl = GDK_SURFACE_IMPL_X11 (mv_resize->moveresize_window->impl);
-
-  if (mv_resize->moveresize_button != 0)
-    button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
-
-  switch (event->xany.type)
-    {
-    case MotionNotify:
-      if (mv_resize->moveresize_window->resize_count > 0)
-        {
-          if (mv_resize->moveresize_pending_event)
-            *mv_resize->moveresize_pending_event = *event;
-          else
-            mv_resize->moveresize_pending_event =
-              g_memdup (event, sizeof (XEvent));
-
-          break;
-        }
-      if (!moveresize_lookahead (mv_resize, event))
-        break;
-
-      update_pos (mv_resize,
-                  event->xmotion.x_root / impl->window_scale,
-                  event->xmotion.y_root / impl->window_scale);
-
-      /* This should never be triggered in normal cases, but in the
-       * case where the drag started without an implicit grab being
-       * in effect, we could miss the release if it occurs before
-       * we grab the pointer; this ensures that we will never
-       * get a permanently stuck grab.
-       */
-      if ((event->xmotion.state & button_mask) == 0)
-        {
-          check_maximize (mv_resize,
-                          event->xmotion.x_root / impl->window_scale,
-                          event->xmotion.y_root / impl->window_scale);
-          finish_drag (mv_resize);
-        }
-      break;
-
-    case ButtonRelease:
-      update_pos (mv_resize,
-                  event->xbutton.x_root / impl->window_scale,
-                  event->xbutton.y_root / impl->window_scale);
-
-      if (event->xbutton.button == mv_resize->moveresize_button)
-        {
-          check_maximize (mv_resize,
-                          event->xmotion.x_root / impl->window_scale,
-                          event->xmotion.y_root / impl->window_scale);
-          finish_drag (mv_resize);
-        }
-      break;
-
-#if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
-    case GenericEvent:
-      {
-        /* we just assume this is an XI2 event */
-        XIEvent *ev = (XIEvent *) event->xcookie.data;
-        XIDeviceEvent *xev = (XIDeviceEvent *)ev;
-        gint state;
-        switch (ev->evtype)
-          {
-          case XI_Motion:
-            update_pos (mv_resize, xev->root_x / impl->window_scale, xev->root_y / impl->window_scale);
-            state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
-            if ((state & button_mask) == 0)
-              {
-                check_maximize (mv_resize,
-                                xev->root_x / impl->window_scale,
-                                xev->root_y / impl->window_scale);
-                finish_drag (mv_resize);
-              }
-            break;
-
-          case XI_ButtonRelease:
-            update_pos (mv_resize, xev->root_x / impl->window_scale, xev->root_y / impl->window_scale);
-            if (xev->detail == mv_resize->moveresize_button)
-              {
-                check_maximize (mv_resize,
-                                xev->root_x / impl->window_scale,
-                                xev->root_y / impl->window_scale);
-                finish_drag (mv_resize);
-              }
-            break;
-          default:
-            break;
-          }
-      }
-      break;
-#endif
-
-    default:
-      break;
-
-    }
-  return TRUE;
-}
-
-gboolean
-_gdk_x11_moveresize_configure_done (GdkDisplay *display,
-                                    GdkSurface  *window)
-{
-  XEvent *tmp_event;
-  MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
-
-  if (!mv_resize || window != mv_resize->moveresize_window)
-    return FALSE;
-
-  if (mv_resize->moveresize_pending_event)
-    {
-      tmp_event = mv_resize->moveresize_pending_event;
-      mv_resize->moveresize_pending_event = NULL;
-      _gdk_x11_moveresize_handle_event (tmp_event);
-      g_free (tmp_event);
-    }
-
-  return TRUE;
-}
-
-static void
-create_moveresize_window (MoveResizeData *mv_resize,
-                          guint32         timestamp)
-{
-  GdkGrabStatus status;
-
-  g_assert (mv_resize->moveresize_emulation_window == NULL);
-
-  mv_resize->moveresize_emulation_window = gdk_surface_new_temp (mv_resize->display);
-  gdk_surface_show (mv_resize->moveresize_emulation_window);
-
-  status = gdk_seat_grab (gdk_device_get_seat (mv_resize->device),
-                          mv_resize->moveresize_emulation_window,
-                          GDK_SEAT_CAPABILITY_POINTER, FALSE,
-                          NULL, NULL, NULL, NULL);
-
-  if (status != GDK_GRAB_SUCCESS)
-    {
-      /* If this fails, some other client has grabbed the window
-       * already.
-       */
-      finish_drag (mv_resize);
-    }
-
-  mv_resize->moveresize_process_time = 0;
-}
-
-/* 
-   Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
-   so that calling XMoveWindow with these coordinates will not move the 
-   window.
-   Note that this depends on the WM to implement ICCCM-compliant reference
-   point handling.
-*/
-static void 
-calculate_unmoving_origin (MoveResizeData *mv_resize)
-{
-  GdkRectangle rect;
-  gint width, height;
-
-  if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
-      mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
-    {
-      gdk_surface_get_origin (mv_resize->moveresize_window,
-                            &mv_resize->moveresize_orig_x,
-                            &mv_resize->moveresize_orig_y);
-    }
-  else
-    {
-      gdk_surface_get_frame_extents (mv_resize->moveresize_window, &rect);
-      gdk_surface_get_geometry (mv_resize->moveresize_window, 
-                              NULL, NULL, &width, &height);
-      
-      switch (mv_resize->moveresize_geometry.win_gravity) 
-       {
-       case GDK_GRAVITY_NORTH_WEST:
-         mv_resize->moveresize_orig_x = rect.x;
-         mv_resize->moveresize_orig_y = rect.y;
-         break;
-       case GDK_GRAVITY_NORTH:
-         mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
-         mv_resize->moveresize_orig_y = rect.y;
-         break;          
-       case GDK_GRAVITY_NORTH_EAST:
-         mv_resize->moveresize_orig_x = rect.x + rect.width - width;
-         mv_resize->moveresize_orig_y = rect.y;
-         break;
-       case GDK_GRAVITY_WEST:
-         mv_resize->moveresize_orig_x = rect.x;
-         mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
-         break;
-       case GDK_GRAVITY_CENTER:
-         mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
-         mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
-         break;
-       case GDK_GRAVITY_EAST:
-         mv_resize->moveresize_orig_x = rect.x + rect.width - width;
-         mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
-         break;
-       case GDK_GRAVITY_SOUTH_WEST:
-         mv_resize->moveresize_orig_x = rect.x;
-         mv_resize->moveresize_orig_y = rect.y + rect.height - height;
-         break;
-       case GDK_GRAVITY_SOUTH:
-         mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
-         mv_resize->moveresize_orig_y = rect.y + rect.height - height;
-         break;
-       case GDK_GRAVITY_SOUTH_EAST:
-         mv_resize->moveresize_orig_x = rect.x + rect.width - width;
-         mv_resize->moveresize_orig_y = rect.y + rect.height - height;
-         break;
-       case GDK_GRAVITY_STATIC:
-       default:
-         mv_resize->moveresize_orig_x = rect.x;
-         mv_resize->moveresize_orig_y = rect.y;
-         break; 
-       }
-    }  
-}
-
-static void
-emulate_resize_drag (GdkSurface     *window,
-                     GdkSurfaceEdge  edge,
-                     GdkDevice     *device,
-                     gint           button,
-                     gint           root_x,
-                     gint           root_y,
-                     guint32        timestamp)
-{
-  MoveResizeData *mv_resize = get_move_resize_data (GDK_SURFACE_DISPLAY (window), TRUE);
-
-  if (mv_resize->moveresize_window != NULL)
-    return; /* already a drag operation in progress */
-
-  mv_resize->is_resize = TRUE;
-  mv_resize->moveresize_button = button;
-  mv_resize->resize_edge = edge;
-  mv_resize->device = device;
-  mv_resize->moveresize_x = root_x;
-  mv_resize->moveresize_y = root_y;
-  mv_resize->moveresize_window = g_object_ref (window);
-
-  mv_resize->moveresize_orig_width = gdk_surface_get_width (window);
-  mv_resize->moveresize_orig_height = gdk_surface_get_height (window);
-
-  mv_resize->moveresize_geom_mask = 0;
-  gdk_surface_get_geometry_hints (window,
-                                &mv_resize->moveresize_geometry,
-                                &mv_resize->moveresize_geom_mask);
-
-  calculate_unmoving_origin (mv_resize);
-
-  create_moveresize_window (mv_resize, timestamp);
-}
-
-static void
-emulate_move_drag (GdkSurface     *window,
-                   GdkDevice     *device,
-                   gint           button,
-                   gint           root_x,
-                   gint           root_y,
-                   guint32        timestamp)
-{
-  MoveResizeData *mv_resize = get_move_resize_data (GDK_SURFACE_DISPLAY (window), TRUE);
-
-  if (mv_resize->moveresize_window != NULL)
-    return; /* already a drag operation in progress */
-
-  mv_resize->is_resize = FALSE;
-  mv_resize->device = device;
-  mv_resize->moveresize_button = button;
-  mv_resize->moveresize_x = root_x;
-  mv_resize->moveresize_y = root_y;
-
-  mv_resize->moveresize_window = g_object_ref (window);
-
-  calculate_unmoving_origin (mv_resize);
-
-  create_moveresize_window (mv_resize, timestamp);
-}
-
-static gboolean
-_should_perform_ewmh_drag (GdkSurface *window,
-                           GdkDevice *device)
-{
-  GdkPointerSurfaceInfo *info;
-  GdkDisplay *display;
-
-  display = gdk_surface_get_display (window);
-  info = _gdk_display_get_pointer_info (display, device);
-
-  if ((!info->last_slave || gdk_device_get_source (info->last_slave) != GDK_SOURCE_TOUCHSCREEN) &&
-      gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
-                                           g_intern_static_string ("_NET_WM_MOVERESIZE")))
-    return TRUE;
-
-  return FALSE;
-}
-
-static void
-gdk_x11_surface_begin_resize_drag (GdkSurface     *window,
-                                  GdkSurfaceEdge  edge,
-                                  GdkDevice     *device,
-                                  gint           button,
-                                  gint           root_x,
-                                  gint           root_y,
-                                  guint32        timestamp)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
-    return;
-
-  /* Avoid EWMH for touch devices */
-  if (_should_perform_ewmh_drag (window, device))
-    wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
-  else
-    emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
-}
-
-static void
-gdk_x11_surface_begin_move_drag (GdkSurface *window,
-                                GdkDevice *device,
-                               gint       button,
-                               gint       root_x,
-                               gint       root_y,
-                               guint32    timestamp)
-{
-  gint direction;
-
-  if (GDK_SURFACE_DESTROYED (window) || !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  if (button == 0)
-    direction = _NET_WM_MOVERESIZE_MOVE_KEYBOARD;
-  else
-    direction = _NET_WM_MOVERESIZE_MOVE;
-
-  /* Avoid EWMH for touch devices */
-  if (_should_perform_ewmh_drag (window, device))
-    wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
-  else
-    emulate_move_drag (window, device, button, root_x, root_y, timestamp);
-}
-
-static gboolean
-gdk_x11_surface_beep (GdkSurface *window)
-{
-  GdkDisplay *display;
-
-  display = GDK_SURFACE_DISPLAY (window);
-
-#ifdef HAVE_XKB
-  if (GDK_X11_DISPLAY (display)->use_xkb)
-    {
-      XkbBell (GDK_DISPLAY_XDISPLAY (display),
-               GDK_SURFACE_XID (window),
-               0,
-               None);
-      return TRUE;
-    }
-#endif
-
-  return FALSE;
-}
-
-static void
-gdk_x11_surface_set_opacity (GdkSurface *window,
-                           gdouble    opacity)
-{
-  GdkDisplay *display;
-  gulong cardinal;
-  
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
-    return;
-
-  display = gdk_surface_get_display (window);
-
-  if (opacity < 0)
-    opacity = 0;
-  else if (opacity > 1)
-    opacity = 1;
-
-  cardinal = opacity * 0xffffffff;
-
-  if (cardinal == 0xffffffff)
-    XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
-                    GDK_SURFACE_XID (window),
-                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
-  else
-    XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
-                    GDK_SURFACE_XID (window),
-                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
-                    XA_CARDINAL, 32,
-                    PropModeReplace,
-                    (guchar *) &cardinal, 1);
-}
-
-static Bool
-timestamp_predicate (Display *display,
-                    XEvent  *xevent,
-                    XPointer arg)
-{
-  Window xwindow = GPOINTER_TO_UINT (arg);
-  GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
-
-  if (xevent->type == PropertyNotify &&
-      xevent->xproperty.window == xwindow &&
-      xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
-                                                                      "GDK_TIMESTAMP_PROP"))
-    return True;
-
-  return False;
-}
-
-/**
- * gdk_x11_get_server_time:
- * @window: (type GdkX11Surface): a #GdkSurface, used for communication
- *          with the server.  The window must have
- *          GDK_PROPERTY_CHANGE_MASK in its events mask or a hang will
- *          result.
- *
- * Routine to get the current X server time stamp.
- *
- * Returns: the time stamp.
- **/
-guint32
-gdk_x11_get_server_time (GdkSurface *window)
-{
-  Display *xdisplay;
-  Window   xwindow;
-  guchar c = 'a';
-  XEvent xevent;
-  Atom timestamp_prop_atom;
-
-  g_return_val_if_fail (GDK_IS_SURFACE (window), 0);
-  g_return_val_if_fail (!GDK_SURFACE_DESTROYED (window), 0);
-
-  xdisplay = GDK_SURFACE_XDISPLAY (window);
-  xwindow = GDK_SURFACE_XID (window);
-  timestamp_prop_atom =
-    gdk_x11_get_xatom_by_name_for_display (GDK_SURFACE_DISPLAY (window),
-                                          "GDK_TIMESTAMP_PROP");
-
-  XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
-                  timestamp_prop_atom,
-                  8, PropModeReplace, &c, 1);
-
-  XIfEvent (xdisplay, &xevent,
-           timestamp_predicate, GUINT_TO_POINTER(xwindow));
-
-  return xevent.xproperty.time;
-}
-
-/**
- * gdk_x11_surface_get_xid:
- * @window: (type GdkX11Surface): a native #GdkSurface.
- * 
- * Returns the X resource (window) belonging to a #GdkSurface.
- * 
- * Returns: the ID of @drawable’s X resource.
- **/
-XID
-gdk_x11_surface_get_xid (GdkSurface *window)
-{
-  if (!GDK_SURFACE_IS_X11 (window) ||
-      !_gdk_surface_has_impl (window))
-    {
-      g_warning (G_STRLOC " drawable is not a native X11 window");
-      return None;
-    }
-  
-  return GDK_SURFACE_IMPL_X11 (window->impl)->xid;
-}
-
-static gint
-gdk_x11_surface_get_scale_factor (GdkSurface *window)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return 1;
-
-  return impl->window_scale;
-}
-
-/**
- * gdk_x11_surface_set_frame_sync_enabled:
- * @window: (type GdkX11Surface): a native #GdkSurface
- * @frame_sync_enabled: whether frame-synchronization should be enabled
- *
- * This function can be used to disable frame synchronization for a window.
- * Normally frame synchronziation will be enabled or disabled based on whether
- * the system has a compositor that supports frame synchronization, but if
- * the window is not directly managed by the window manager, then frame
- * synchronziation may need to be disabled. This is the case for a window
- * embedded via the XEMBED protocol.
- */
-void
-gdk_x11_surface_set_frame_sync_enabled (GdkSurface *window,
-                                       gboolean   frame_sync_enabled)
-{
-  if (!GDK_SURFACE_IS_X11 (window) ||
-      !_gdk_surface_has_impl (window))
-    {
-      g_warning (G_STRLOC " drawable is not a native X11 window");
-      return;
-    }
-
-  GDK_SURFACE_IMPL_X11 (window->impl)->frame_sync_enabled = FALSE;
-}
-
-static void
-gdk_x11_surface_set_opaque_region (GdkSurface      *window,
-                                  cairo_region_t *region)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-  GdkDisplay *display;
-  int nitems;
-  gulong *data;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (region != NULL)
-    {
-      int i, nrects;
-
-      nrects = cairo_region_num_rectangles (region);
-      nitems = nrects * 4;
-      data = g_new (gulong, nitems);
-
-      for (i = 0; i < nrects; i++)
-        {
-          cairo_rectangle_int_t rect;
-          cairo_region_get_rectangle (region, i, &rect);
-          data[i*4+0] = rect.x * impl->window_scale;
-          data[i*4+1] = rect.y * impl->window_scale;
-          data[i*4+2] = rect.width * impl->window_scale;
-          data[i*4+3] = rect.height * impl->window_scale;
-        }
-    }
-  else
-    {
-      nitems = 0;
-      data = NULL;
-    }
-
-  display = gdk_surface_get_display (window);
-
-  XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
-                   GDK_SURFACE_XID (window),
-                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_OPAQUE_REGION"),
-                   XA_CARDINAL, 32, PropModeReplace,
-                   (guchar *) data, nitems);
-
-  g_free (data);
-}
-
-static gboolean
-gdk_x11_surface_show_window_menu (GdkSurface *window,
-                                 GdkEvent  *event)
-{
-  GdkSurfaceImplX11 *impl = GDK_SURFACE_IMPL_X11 (window->impl);
-  GdkDisplay *display = GDK_SURFACE_DISPLAY (window);
-  GdkDevice *device;
-  int device_id;
-  double x_root, y_root;
-  XClientMessageEvent xclient = { 0 };
-
-  switch ((guint) event->any.type)
-    {
-    case GDK_BUTTON_PRESS:
-    case GDK_BUTTON_RELEASE:
-      break;
-    default:
-      return FALSE;
-    }
-
-  if (!gdk_x11_screen_supports_net_wm_hint (GDK_SURFACE_SCREEN (window),
-                                            g_intern_static_string ("_GTK_SHOW_WINDOW_MENU")))
-    return FALSE;
-
-  gdk_event_get_root_coords (event, &x_root, &y_root);
-  device = gdk_event_get_device (event);
-  g_object_get (G_OBJECT (device),
-                "device-id", &device_id,
-                NULL);
-
-  /* Ungrab the implicit grab */
-  gdk_seat_ungrab (gdk_device_get_seat (device));
-
-  xclient.type = ClientMessage;
-  xclient.window = GDK_SURFACE_XID (window);
-  xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_GTK_SHOW_WINDOW_MENU");
-  xclient.data.l[0] = device_id;
-  xclient.data.l[1] = x_root * impl->window_scale;
-  xclient.data.l[2] = y_root * impl->window_scale;
-  xclient.format = 32;
-
-  XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XROOTWIN (window), False,
-              SubstructureRedirectMask | SubstructureNotifyMask,
-              (XEvent *)&xclient);
-
-  return TRUE;
-}
-
-static void
-gdk_surface_impl_x11_class_init (GdkSurfaceImplX11Class *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_CLASS (klass);
-  
-  object_class->finalize = gdk_surface_impl_x11_finalize;
-  
-  impl_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
-  impl_class->show = gdk_surface_x11_show;
-  impl_class->hide = gdk_surface_x11_hide;
-  impl_class->withdraw = gdk_surface_x11_withdraw;
-  impl_class->set_events = gdk_surface_x11_set_events;
-  impl_class->get_events = gdk_surface_x11_get_events;
-  impl_class->raise = gdk_surface_x11_raise;
-  impl_class->lower = gdk_surface_x11_lower;
-  impl_class->restack_toplevel = gdk_surface_x11_restack_toplevel;
-  impl_class->move_resize = gdk_surface_x11_move_resize;
-  impl_class->get_geometry = gdk_surface_x11_get_geometry;
-  impl_class->get_root_coords = gdk_surface_x11_get_root_coords;
-  impl_class->get_device_state = gdk_surface_x11_get_device_state;
-  impl_class->shape_combine_region = gdk_surface_x11_shape_combine_region;
-  impl_class->input_shape_combine_region = gdk_surface_x11_input_shape_combine_region;
-  impl_class->queue_antiexpose = _gdk_x11_surface_queue_antiexpose;
-  impl_class->destroy = gdk_x11_surface_destroy;
-  impl_class->beep = gdk_x11_surface_beep;
-
-  impl_class->focus = gdk_x11_surface_focus;
-  impl_class->set_type_hint = gdk_x11_surface_set_type_hint;
-  impl_class->get_type_hint = gdk_x11_surface_get_type_hint;
-  impl_class->set_modal_hint = gdk_x11_surface_set_modal_hint;
-  impl_class->set_skip_taskbar_hint = gdk_x11_surface_set_skip_taskbar_hint;
-  impl_class->set_skip_pager_hint = gdk_x11_surface_set_skip_pager_hint;
-  impl_class->set_urgency_hint = gdk_x11_surface_set_urgency_hint;
-  impl_class->set_geometry_hints = gdk_x11_surface_set_geometry_hints;
-  impl_class->set_title = gdk_x11_surface_set_title;
-  impl_class->set_role = gdk_x11_surface_set_role;
-  impl_class->set_startup_id = gdk_x11_surface_set_startup_id;
-  impl_class->set_transient_for = gdk_x11_surface_set_transient_for;
-  impl_class->get_frame_extents = gdk_x11_surface_get_frame_extents;
-  impl_class->set_accept_focus = gdk_x11_surface_set_accept_focus;
-  impl_class->set_focus_on_map = gdk_x11_surface_set_focus_on_map;
-  impl_class->set_icon_list = gdk_x11_surface_set_icon_list;
-  impl_class->set_icon_name = gdk_x11_surface_set_icon_name;
-  impl_class->iconify = gdk_x11_surface_iconify;
-  impl_class->deiconify = gdk_x11_surface_deiconify;
-  impl_class->stick = gdk_x11_surface_stick;
-  impl_class->unstick = gdk_x11_surface_unstick;
-  impl_class->maximize = gdk_x11_surface_maximize;
-  impl_class->unmaximize = gdk_x11_surface_unmaximize;
-  impl_class->fullscreen = gdk_x11_surface_fullscreen;
-  impl_class->fullscreen_on_monitor = gdk_x11_surface_fullscreen_on_monitor;
-  impl_class->apply_fullscreen_mode = gdk_x11_surface_apply_fullscreen_mode;
-  impl_class->unfullscreen = gdk_x11_surface_unfullscreen;
-  impl_class->set_keep_above = gdk_x11_surface_set_keep_above;
-  impl_class->set_keep_below = gdk_x11_surface_set_keep_below;
-  impl_class->get_group = gdk_x11_surface_get_group;
-  impl_class->set_group = gdk_x11_surface_set_group;
-  impl_class->set_decorations = gdk_x11_surface_set_decorations;
-  impl_class->get_decorations = gdk_x11_surface_get_decorations;
-  impl_class->set_functions = gdk_x11_surface_set_functions;
-  impl_class->begin_resize_drag = gdk_x11_surface_begin_resize_drag;
-  impl_class->begin_move_drag = gdk_x11_surface_begin_move_drag;
-  impl_class->set_opacity = gdk_x11_surface_set_opacity;
-  impl_class->destroy_notify = gdk_x11_surface_destroy_notify;
-  impl_class->register_dnd = _gdk_x11_surface_register_dnd;
-  impl_class->drag_begin = _gdk_x11_surface_drag_begin;
-  impl_class->get_scale_factor = gdk_x11_surface_get_scale_factor;
-  impl_class->set_opaque_region = gdk_x11_surface_set_opaque_region;
-  impl_class->set_shadow_width = gdk_x11_surface_set_shadow_width;
-  impl_class->show_window_menu = gdk_x11_surface_show_window_menu;
-  impl_class->create_gl_context = gdk_x11_surface_create_gl_context;
-  impl_class->get_unscaled_size = gdk_x11_surface_get_unscaled_size;
-  impl_class->supports_edge_constraints = gdk_x11_surface_supports_edge_constraints;
-}
diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h
deleted file mode 100644 (file)
index b824240..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/* 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-#ifndef __GDK_SURFACE_X11_H__
-#define __GDK_SURFACE_X11_H__
-
-#include "gdk/x11/gdkprivate-x11.h"
-#include "gdk/gdkwindowimpl.h"
-
-#include <X11/Xlib.h>
-
-#ifdef HAVE_XDAMAGE
-#include <X11/extensions/Xdamage.h>
-#endif
-
-#ifdef HAVE_XSYNC
-#include <X11/Xlib.h>
-#include <X11/extensions/sync.h>
-#endif
-
-G_BEGIN_DECLS
-
-typedef struct _GdkToplevelX11 GdkToplevelX11;
-typedef struct _GdkSurfaceImplX11 GdkSurfaceImplX11;
-typedef struct _GdkSurfaceImplX11Class GdkSurfaceImplX11Class;
-typedef struct _GdkXPositionInfo GdkXPositionInfo;
-
-/* Window implementation for X11
- */
-
-#define GDK_TYPE_SURFACE_IMPL_X11              (gdk_surface_impl_x11_get_type ())
-#define GDK_SURFACE_IMPL_X11(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_X11, GdkSurfaceImplX11))
-#define GDK_SURFACE_IMPL_X11_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_X11, GdkSurfaceImplX11Class))
-#define GDK_IS_SURFACE_IMPL_X11(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_X11))
-#define GDK_IS_SURFACE_IMPL_X11_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_X11))
-#define GDK_SURFACE_IMPL_X11_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_X11, GdkSurfaceImplX11Class))
-
-struct _GdkSurfaceImplX11
-{
-  GdkSurfaceImpl parent_instance;
-
-  GdkSurface *wrapper;
-
-  Window xid;
-
-  GdkToplevelX11 *toplevel;    /* Toplevel-specific information */
-  GdkCursor *cursor;
-
-  guint no_bg : 1;        /* Set when the window background is temporarily
-                           * unset during resizing and scaling */
-  guint override_redirect : 1;
-  guint frame_clock_connected : 1;
-  guint frame_sync_enabled : 1;
-  guint tracking_damage: 1;
-
-  gint window_scale;
-
-  /* Width and height not divided by window_scale - this matters in the
-   * corner-case where the window manager assigns us a size that isn't
-   * a multiple of window_scale - for example for a maximized window
-   * with an odd-sized title-bar.
-   */
-  gint unscaled_width;
-  gint unscaled_height;
-
-  cairo_surface_t *cairo_surface;
-
-#if defined (HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
-  Damage damage;
-#endif
-};
-struct _GdkSurfaceImplX11Class 
-{
-  GdkSurfaceImplClass parent_class;
-};
-
-struct _GdkToplevelX11
-{
-
-  /* Set if the window, or any descendent of it, is the server's focus window
-   */
-  guint has_focus_window : 1;
-
-  /* Set if window->has_focus_window and the focus isn't grabbed elsewhere.
-   */
-  guint has_focus : 1;
-
-  /* Set if the pointer is inside this window. (This is needed for
-   * for focus tracking)
-   */
-  guint has_pointer : 1;
-  
-  /* Set if the window is a descendent of the focus window and the pointer is
-   * inside it. (This is the case where the window will receive keystroke
-   * events even window->has_focus_window is FALSE)
-   */
-  guint has_pointer_focus : 1;
-
-  /* Set if we are requesting these hints */
-  guint skip_taskbar_hint : 1;
-  guint skip_pager_hint : 1;
-  guint urgency_hint : 1;
-
-  guint on_all_desktops : 1;   /* _NET_WM_STICKY == 0xFFFFFFFF */
-
-  guint have_sticky : 1;       /* _NET_WM_STATE_STICKY */
-  guint have_maxvert : 1;       /* _NET_WM_STATE_MAXIMIZED_VERT */
-  guint have_maxhorz : 1;       /* _NET_WM_STATE_MAXIMIZED_HORZ */
-  guint have_fullscreen : 1;    /* _NET_WM_STATE_FULLSCREEN */
-  guint have_hidden : 1;       /* _NET_WM_STATE_HIDDEN */
-
-  guint is_leader : 1;
-
-  /* Set if the WM is presenting us as focused, i.e. with active decorations
-   */
-  guint have_focused : 1;
-
-  guint in_frame : 1;
-
-  /* If we're expecting a response from the compositor after painting a frame */
-  guint frame_pending : 1;
-
-  /* Whether pending_counter_value/configure_counter_value are updates
-   * to the extended update counter */
-  guint pending_counter_value_is_extended : 1;
-  guint configure_counter_value_is_extended : 1;
-
-  gulong map_serial;   /* Serial of last transition from unmapped */
-  
-  cairo_surface_t *icon_pixmap;
-  cairo_surface_t *icon_mask;
-  GdkSurface *group_leader;
-
-  /* Time of most recent user interaction. */
-  gulong user_time;
-
-  /* We use an extra X window for toplevel windows that we XSetInputFocus()
-   * to in order to avoid getting keyboard events redirected to subwindows
-   * that might not even be part of this app
-   */
-  Window focus_window;
-
-  GdkSurfaceHints last_geometry_hints_mask;
-  GdkGeometry last_geometry_hints;
-  
-  /* Constrained edge information */
-  guint edge_constraints;
-
-#ifdef HAVE_XSYNC
-  XID update_counter;
-  XID extended_update_counter;
-  gint64 pending_counter_value; /* latest _NET_WM_SYNC_REQUEST value received */
-  gint64 configure_counter_value; /* Latest _NET_WM_SYNC_REQUEST value received
-                                * where we have also seen the corresponding
-                                * ConfigureNotify
-                                */
-  gint64 current_counter_value;
-
-  /* After a _NET_WM_FRAME_DRAWN message, this is the soonest that we think
-   * frame after will be presented */
-  gint64 throttled_presentation_time;
-#endif
-};
-
-GType gdk_surface_impl_x11_get_type (void);
-
-GdkToplevelX11 *_gdk_x11_surface_get_toplevel        (GdkSurface *window);
-
-GdkCursor      *_gdk_x11_surface_get_cursor          (GdkSurface *window);
-
-void            _gdk_x11_surface_update_size         (GdkSurfaceImplX11 *impl);
-void            _gdk_x11_surface_set_window_scale    (GdkSurface *window,
-                                                    int        scale);
-
-G_END_DECLS
-
-#endif /* __GDK_SURFACE_X11_H__ */
index 153b4a501e994068ed715ff7dceba006f7fdc191..9fa9cb071151bfda5e2e616203164ce6146d7ca4 100644 (file)
@@ -48,7 +48,7 @@
 #include <gdk/x11/gdkx11screen.h>
 #include <gdk/x11/gdkx11selection.h>
 #include <gdk/x11/gdkx11utils.h>
-#include <gdk/x11/gdkx11window.h>
+#include <gdk/x11/gdkx11surface.h>
 
 #include <gdk/x11/gdkx-autocleanups.h>
 
diff --git a/gdk/x11/gdkx11surface.h b/gdk/x11/gdkx11surface.h
new file mode 100644 (file)
index 0000000..d2fc1e4
--- /dev/null
@@ -0,0 +1,113 @@
+/* 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/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GDK_X11_SURFACE_H__
+#define __GDK_X11_SURFACE_H__
+
+#if !defined (__GDKX_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdkx.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_X11_SURFACE              (gdk_x11_surface_get_type ())
+#define GDK_X11_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_X11_SURFACE, GdkX11Surface))
+#define GDK_X11_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_X11_SURFACE, GdkX11SurfaceClass))
+#define GDK_IS_X11_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_X11_SURFACE))
+#define GDK_IS_X11_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_X11_SURFACE))
+#define GDK_X11_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_X11_SURFACE, GdkX11SurfaceClass))
+
+#ifdef GDK_COMPILATION
+typedef struct _GdkX11Surface GdkX11Surface;
+#else
+typedef GdkSurface GdkX11Surface;
+#endif
+typedef struct _GdkX11SurfaceClass GdkX11SurfaceClass;
+
+GDK_AVAILABLE_IN_ALL
+GType    gdk_x11_surface_get_type          (void);
+
+GDK_AVAILABLE_IN_ALL
+Window   gdk_x11_surface_get_xid           (GdkSurface   *window);
+GDK_AVAILABLE_IN_ALL
+void     gdk_x11_surface_set_user_time     (GdkSurface   *window,
+                                           guint32      timestamp);
+GDK_AVAILABLE_IN_ALL
+void     gdk_x11_surface_set_utf8_property    (GdkSurface *window,
+                                             const gchar *name,
+                                             const gchar *value);
+GDK_AVAILABLE_IN_ALL
+void     gdk_x11_surface_set_theme_variant (GdkSurface   *window,
+                                           const char  *variant);
+GDK_AVAILABLE_IN_ALL
+void     gdk_x11_surface_move_to_current_desktop (GdkSurface   *window);
+
+GDK_AVAILABLE_IN_ALL
+guint32  gdk_x11_surface_get_desktop             (GdkSurface   *window);
+GDK_AVAILABLE_IN_ALL
+void     gdk_x11_surface_move_to_desktop         (GdkSurface   *window,
+                                                 guint32      desktop);
+
+GDK_AVAILABLE_IN_ALL
+void     gdk_x11_surface_set_frame_sync_enabled (GdkSurface *window,
+                                                gboolean   frame_sync_enabled);
+
+/**
+ * GDK_SURFACE_XDISPLAY:
+ * @win: a #GdkSurface.
+ *
+ * Returns the display of a #GdkSurface.
+ *
+ * Returns: an Xlib Display*.
+ */
+#define GDK_SURFACE_XDISPLAY(win)      (GDK_DISPLAY_XDISPLAY (gdk_surface_get_display (win)))
+
+/**
+ * GDK_SURFACE_XID:
+ * @win: a #GdkSurface.
+ *
+ * Returns the X window belonging to a #GdkSurface.
+ *
+ * Returns: the Xlib Window of @win.
+ */
+#define GDK_SURFACE_XID(win)           (gdk_x11_surface_get_xid (win))
+
+GDK_AVAILABLE_IN_ALL
+guint32       gdk_x11_get_server_time  (GdkSurface       *window);
+
+GDK_AVAILABLE_IN_ALL
+GdkSurface  *gdk_x11_surface_foreign_new_for_display (GdkDisplay *display,
+                                                    Window      window);
+GDK_AVAILABLE_IN_ALL
+GdkSurface  *gdk_x11_surface_lookup_for_display      (GdkDisplay *display,
+                                                    Window      window);
+
+G_END_DECLS
+
+#endif /* __GDK_X11_SURFACE_H__ */
diff --git a/gdk/x11/gdkx11window.h b/gdk/x11/gdkx11window.h
deleted file mode 100644 (file)
index d2fc1e4..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/* 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/>.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-#ifndef __GDK_X11_SURFACE_H__
-#define __GDK_X11_SURFACE_H__
-
-#if !defined (__GDKX_H_INSIDE__) && !defined (GDK_COMPILATION)
-#error "Only <gdk/gdkx.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_X11_SURFACE              (gdk_x11_surface_get_type ())
-#define GDK_X11_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_X11_SURFACE, GdkX11Surface))
-#define GDK_X11_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_X11_SURFACE, GdkX11SurfaceClass))
-#define GDK_IS_X11_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_X11_SURFACE))
-#define GDK_IS_X11_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_X11_SURFACE))
-#define GDK_X11_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_X11_SURFACE, GdkX11SurfaceClass))
-
-#ifdef GDK_COMPILATION
-typedef struct _GdkX11Surface GdkX11Surface;
-#else
-typedef GdkSurface GdkX11Surface;
-#endif
-typedef struct _GdkX11SurfaceClass GdkX11SurfaceClass;
-
-GDK_AVAILABLE_IN_ALL
-GType    gdk_x11_surface_get_type          (void);
-
-GDK_AVAILABLE_IN_ALL
-Window   gdk_x11_surface_get_xid           (GdkSurface   *window);
-GDK_AVAILABLE_IN_ALL
-void     gdk_x11_surface_set_user_time     (GdkSurface   *window,
-                                           guint32      timestamp);
-GDK_AVAILABLE_IN_ALL
-void     gdk_x11_surface_set_utf8_property    (GdkSurface *window,
-                                             const gchar *name,
-                                             const gchar *value);
-GDK_AVAILABLE_IN_ALL
-void     gdk_x11_surface_set_theme_variant (GdkSurface   *window,
-                                           const char  *variant);
-GDK_AVAILABLE_IN_ALL
-void     gdk_x11_surface_move_to_current_desktop (GdkSurface   *window);
-
-GDK_AVAILABLE_IN_ALL
-guint32  gdk_x11_surface_get_desktop             (GdkSurface   *window);
-GDK_AVAILABLE_IN_ALL
-void     gdk_x11_surface_move_to_desktop         (GdkSurface   *window,
-                                                 guint32      desktop);
-
-GDK_AVAILABLE_IN_ALL
-void     gdk_x11_surface_set_frame_sync_enabled (GdkSurface *window,
-                                                gboolean   frame_sync_enabled);
-
-/**
- * GDK_SURFACE_XDISPLAY:
- * @win: a #GdkSurface.
- *
- * Returns the display of a #GdkSurface.
- *
- * Returns: an Xlib Display*.
- */
-#define GDK_SURFACE_XDISPLAY(win)      (GDK_DISPLAY_XDISPLAY (gdk_surface_get_display (win)))
-
-/**
- * GDK_SURFACE_XID:
- * @win: a #GdkSurface.
- *
- * Returns the X window belonging to a #GdkSurface.
- *
- * Returns: the Xlib Window of @win.
- */
-#define GDK_SURFACE_XID(win)           (gdk_x11_surface_get_xid (win))
-
-GDK_AVAILABLE_IN_ALL
-guint32       gdk_x11_get_server_time  (GdkSurface       *window);
-
-GDK_AVAILABLE_IN_ALL
-GdkSurface  *gdk_x11_surface_foreign_new_for_display (GdkDisplay *display,
-                                                    Window      window);
-GDK_AVAILABLE_IN_ALL
-GdkSurface  *gdk_x11_surface_lookup_for_display      (GdkDisplay *display,
-                                                    Window      window);
-
-G_END_DECLS
-
-#endif /* __GDK_X11_SURFACE_H__ */
index 53213818fb80ed165ff8469b866896e49e596316..3912031c185ba6ef101477651ff99e8bcf9de632 100644 (file)
@@ -26,7 +26,7 @@ gdk_x11_sources = files([
   'gdktextlistconverter-x11.c',
   'gdkvisual-x11.c',
   'gdkvulkancontext-x11.c',
-  'gdkwindow-x11.c',
+  'gdksurface-x11.c',
   'gdkxftdefaults.c',
   'gdkxid.c',
   'xsettings-client.c',
@@ -50,7 +50,7 @@ gdk_x11_public_headers = files([
   'gdkx11screen.h',
   'gdkx11selection.h',
   'gdkx11utils.h',
-  'gdkx11window.h',
+  'gdkx11surface.h',
 ])
 
 install_headers(gdk_x11_public_headers, subdir: 'gtk-4.0/gdk/x11/')
index 571388232074e91d656f0656f6d20fa5ad6811f9..9adfcf27d47d4bc92253d5c06e5575106dbf1997 100644 (file)
@@ -28,7 +28,7 @@
 #include <gdk/x11/gdkx11display.h>
 #include <gdk/x11/gdkx11property.h>
 #include <gdk/x11/gdkx11screen.h>
-#include <gdk/x11/gdkx11window.h>
+#include <gdk/x11/gdkx11surface.h>
 #include <gdk/x11/gdkprivate-x11.h>
 #include <gdk/x11/gdkdisplay-x11.h>
 #include <gdk/x11/gdkscreen-x11.h>
index 01cb0238bfd225ba5577224b3ea5321bf6493ab7..a91235b7d876280a0d78fa18d7ee924b09b501e0 100644 (file)
@@ -1091,7 +1091,7 @@ gtk_drag_begin_idle (gpointer arg)
 }
 /* Fake protocol to let us call GdkNSView gdkWindow without including
  * gdk/GdkNSView.h (which we can’t because it pulls in the internal-only
- * gdkwindow.h).
+ * gdksurface.h).
  */
 @protocol GdkNSView
 - (GdkSurface *)gdkWindow;
index 23310300545c53499a5b66c37a214261797d755d..ec5ded38f498059a920bbb727cf2dc65b14d8d18 100644 (file)
@@ -5974,7 +5974,7 @@ gtk_window_finalize (GObject *object)
   G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
 }
 
-/* copied from gdkwindow-x11.c */
+/* copied from gdksurface-x11.c */
 static const gchar *
 get_default_title (void)
 {