]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkwindow-x11.c
Change FSF Address
[~andy/gtk] / gdk / x11 / gdkwindow-x11.c
index e7af2aa0ad54017e3a58edbee7f7a930a00864a5..a1c3f97d2af1e3d2f5b95f088b44f1a453479607 100644 (file)
@@ -13,9 +13,7 @@
  * 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
 
 #include "gdkwindow-x11.h"
 
-#include "gdkx.h"
 #include "gdkwindow.h"
 #include "gdkwindowimpl.h"
-#include "gdkasync.h"
-#include "gdkdisplay-x11.h"
-#include "gdkprivate-x11.h"
 #include "gdkvisualprivate.h"
 #include "gdkinternals.h"
 #include "gdkdeviceprivate.h"
+#include "gdkasync.h"
 #include "gdkeventsource.h"
+#include "gdkdisplay-x11.h"
+#include "gdkprivate-x11.h"
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -72,7 +69,7 @@
 #include <X11/extensions/Xdamage.h>
 #endif
 
-const int _gdk_event_mask_table[21] =
+const int _gdk_x11_event_mask_table[21] =
 {
   ExposureMask,
   PointerMotionMask,
@@ -91,12 +88,13 @@ const int _gdk_event_mask_table[21] =
   StructureNotifyMask,
   PropertyChangeMask,
   VisibilityChangeMask,
-  0,                           /* PROXIMITY_IN */
-  0,                           /* PROXIMTY_OUT */
+  0,                    /* PROXIMITY_IN */
+  0,                    /* PROXIMTY_OUT */
   SubstructureNotifyMask,
   ButtonPressMask      /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
 };
-const int _gdk_nenvent_masks = sizeof (_gdk_event_mask_table) / sizeof (int);
+
+const gint _gdk_x11_event_mask_table_size = G_N_ELEMENTS (_gdk_x11_event_mask_table);
 
 /* Forward declarations */
 static void     gdk_window_set_static_win_gravity (GdkWindow  *window,
@@ -128,14 +126,35 @@ static void        gdk_window_impl_x11_finalize   (GObject            *object);
     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
   )
 
+struct _GdkX11Window {
+  GdkWindow parent;
+};
+
+struct _GdkX11WindowClass {
+  GdkWindowClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkX11Window, gdk_x11_window, GDK_TYPE_WINDOW)
+
+static void
+gdk_x11_window_class_init (GdkX11WindowClass *x11_window_class)
+{
+}
+
+static void
+gdk_x11_window_init (GdkX11Window *x11_window)
+{
+}
+
+
 G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_WINDOW_IMPL)
 
 static void
 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
 {  
   impl->toplevel_window_type = -1;
-  impl->device_cursor = g_hash_table_new_full (NULL, NULL, NULL,
-                                               (GDestroyNotify) gdk_cursor_unref);
+  impl->device_cursor = g_hash_table_new_full (NULL, NULL,
+                                               NULL, g_object_unref);
 }
 
 GdkToplevelX11 *
@@ -231,28 +250,28 @@ gdk_window_impl_x11_finalize (GObject *object)
 {
   GdkWindow *wrapper;
   GdkWindowImplX11 *impl;
-  
+
   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
 
   impl = GDK_WINDOW_IMPL_X11 (object);
-  
+
   wrapper = impl->wrapper;
 
-  _gdk_xgrab_check_destroy (wrapper);
+  _gdk_x11_window_grab_check_destroy (wrapper);
 
   if (!GDK_WINDOW_DESTROYED (wrapper))
     {
       GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
-      
-      _gdk_xid_table_remove (display, impl->xid);
+
+      _gdk_x11_display_remove_window (display, impl->xid);
       if (impl->toplevel && impl->toplevel->focus_window)
-       _gdk_xid_table_remove (display, impl->toplevel->focus_window);
+        _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
     }
 
   g_free (impl->toplevel);
 
   if (impl->cursor)
-    gdk_cursor_unref (impl->cursor);
+    g_object_unref (impl->cursor);
 
   g_hash_table_destroy (impl->device_cursor);
 
@@ -312,7 +331,7 @@ _gdk_x11_window_create_bitmap_surface (GdkWindow *window,
                           width, height, 1);
   surface = cairo_xlib_surface_create_for_bitmap (GDK_WINDOW_XDISPLAY (window),
                                                   pixmap,
-                                                  GDK_SCREEN_XSCREEN (GDK_WINDOW_SCREEN (window)),
+                                                  GDK_X11_SCREEN (GDK_WINDOW_SCREEN (window))->xscreen,
                                                   width, height);
   attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
 
@@ -450,17 +469,17 @@ _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
 }
 
 void
-_gdk_windowing_window_init (GdkScreen * screen)
+_gdk_x11_screen_init_root_window (GdkScreen *screen)
 {
   GdkWindow *window;
   GdkWindowImplX11 *impl;
-  GdkScreenX11 *screen_x11;
+  GdkX11Screen *x11_screen;
 
-  screen_x11 = GDK_SCREEN_X11 (screen);
+  x11_screen = GDK_X11_SCREEN (screen);
 
-  g_assert (screen_x11->root_window == NULL);
+  g_assert (x11_screen->root_window == NULL);
 
-  window = screen_x11->root_window = g_object_new (GDK_TYPE_WINDOW, NULL);
+  window = x11_screen->root_window = _gdk_display_create_window (gdk_screen_get_display (screen));
 
   window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
   window->impl_window = window;
@@ -468,28 +487,28 @@ _gdk_windowing_window_init (GdkScreen * screen)
 
   impl = GDK_WINDOW_IMPL_X11 (window->impl);
   
-  impl->xid = screen_x11->xroot_window;
+  impl->xid = x11_screen->xroot_window;
   impl->wrapper = window;
   
   window->window_type = GDK_WINDOW_ROOT;
-  window->depth = DefaultDepthOfScreen (screen_x11->xscreen);
+  window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
 
   window->x = 0;
   window->y = 0;
   window->abs_x = 0;
   window->abs_y = 0;
-  window->width = WidthOfScreen (screen_x11->xscreen);
-  window->height = HeightOfScreen (screen_x11->xscreen);
+  window->width = WidthOfScreen (x11_screen->xscreen);
+  window->height = HeightOfScreen (x11_screen->xscreen);
   window->viewable = TRUE;
 
   /* see init_randr_support() in gdkscreen-x11.c */
   window->event_mask = GDK_STRUCTURE_MASK;
 
-  _gdk_window_update_size (screen_x11->root_window);
-  
-  _gdk_xid_table_insert (screen_x11->display,
-                        &screen_x11->xroot_window,
-                        screen_x11->root_window);
+  _gdk_window_update_size (x11_screen->root_window);
+
+  _gdk_x11_display_add_window (x11_screen->display,
+                               &x11_screen->xroot_window,
+                               x11_screen->root_window);
 }
 
 static void
@@ -504,7 +523,7 @@ set_wm_protocols (GdkWindow *window)
   protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
 
 #ifdef HAVE_XSYNC
-  if (GDK_DISPLAY_X11 (display)->use_sync)
+  if (GDK_X11_DISPLAY (display)->use_sync)
     protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
 #endif
   
@@ -528,7 +547,7 @@ get_default_title (void)
 static void
 check_leader_window_title (GdkDisplay *display)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
 
   if (display_x11->leader_window && !display_x11->leader_window_title_set)
     {
@@ -544,13 +563,13 @@ static Window
 create_focus_window (GdkDisplay *display,
                     XID         parent)
 {
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   GdkEventMask event_mask;
   Display *xdisplay;
   Window focus_window;
 
   xdisplay = GDK_DISPLAY_XDISPLAY (display);
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
 
   focus_window = XCreateSimpleWindow (xdisplay, parent,
                                       -1, -1, 1, 1, 0,
@@ -562,9 +581,9 @@ create_focus_window (GdkDisplay *display,
                 GDK_KEY_RELEASE_MASK |
                 GDK_FOCUS_CHANGE_MASK);
 
-  gdk_event_source_select_events ((GdkEventSource *) display_x11->event_source,
-                                  focus_window,
-                                  event_mask, 0);
+  gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
+                                      focus_window,
+                                      event_mask, 0);
 
   XMapWindow (xdisplay, focus_window);
 
@@ -583,7 +602,7 @@ ensure_sync_counter (GdkWindow *window)
 
       if (toplevel && impl->use_synchronized_configure &&
          toplevel->update_counter == None &&
-         GDK_DISPLAY_X11 (display)->use_sync)
+         GDK_X11_DISPLAY (display)->use_sync)
        {
          Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
          XSyncValue value;
@@ -615,7 +634,7 @@ setup_toplevel_window (GdkWindow *window,
   GdkDisplay *display = gdk_window_get_display (window);
   Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
   XID xid = GDK_WINDOW_XID (window);
-  GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (parent));
+  GdkX11Screen *x11_screen = GDK_X11_SCREEN (GDK_WINDOW_SCREEN (parent));
   XSizeHints size_hints;
   long pid;
   Window leader_window;
@@ -628,11 +647,13 @@ setup_toplevel_window (GdkWindow *window,
        * press events so they don't get sent to child windows.
        */
       toplevel->focus_window = create_focus_window (display, xid);
-      _gdk_xid_table_insert (screen_x11->display, &toplevel->focus_window, window);
+      _gdk_x11_display_add_window (x11_screen->display,
+                                   &toplevel->focus_window,
+                                   window);
     }
-  
-  check_leader_window_title (screen_x11->display);
-  
+
+  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???
@@ -648,45 +669,46 @@ setup_toplevel_window (GdkWindow *window,
   
   pid = getpid ();
   XChangeProperty (xdisplay, xid,
-                  gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "_NET_WM_PID"),
+                  gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
                   XA_CARDINAL, 32,
                   PropModeReplace,
                   (guchar *)&pid, 1);
 
-  leader_window = GDK_DISPLAY_X11 (screen_x11->display)->leader_window;
+  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 (screen_x11->display, "WM_CLIENT_LEADER"),
+                  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 (screen_x11->display, "_NET_WM_USER_TIME_WINDOW"),
+                     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_window_set_user_time (window, 0);
-  else if (GDK_DISPLAY_X11 (screen_x11->display)->user_time != 0)
-    gdk_x11_window_set_user_time (window, GDK_DISPLAY_X11 (screen_x11->display)->user_time);
+  else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
+    gdk_x11_window_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
 
   ensure_sync_counter (window);
 }
 
 void
-_gdk_window_impl_new (GdkWindow     *window,
-                     GdkWindow     *real_parent,
-                     GdkScreen     *screen,
-                     GdkEventMask   event_mask,
-                     GdkWindowAttr *attributes,
-                     gint           attributes_mask)
+_gdk_x11_display_create_window_impl (GdkDisplay    *display,
+                                     GdkWindow     *window,
+                                     GdkWindow     *real_parent,
+                                     GdkScreen     *screen,
+                                     GdkEventMask   event_mask,
+                                     GdkWindowAttr *attributes,
+                                     gint           attributes_mask)
 {
   GdkWindowImplX11 *impl;
-  GdkScreenX11 *screen_x11;
-  GdkDisplayX11 *display_x11;
-  
+  GdkX11Screen *x11_screen;
+  GdkX11Display *display_x11;
+
   Window xparent;
   Visual *xvisual;
   Display *xdisplay;
@@ -694,81 +716,81 @@ _gdk_window_impl_new (GdkWindow     *window,
   XSetWindowAttributes xattributes;
   long xattributes_mask;
   XClassHint *class_hint;
-  
+
   unsigned int class;
   const char *title;
-  
-  screen_x11 = GDK_SCREEN_X11 (screen);
+
+  display_x11 = GDK_X11_DISPLAY (display);
   xparent = GDK_WINDOW_XID (real_parent);
-  display_x11 = GDK_DISPLAY_X11 (GDK_SCREEN_DISPLAY (screen));
-  
+  x11_screen = GDK_X11_SCREEN (screen);
+
   impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
   window->impl = GDK_WINDOW_IMPL (impl);
   impl->wrapper = GDK_WINDOW (window);
-  
-  xdisplay = screen_x11->xdisplay;
+
+  xdisplay = x11_screen->xdisplay;
 
   xattributes_mask = 0;
 
   xvisual = gdk_x11_visual_get_xvisual (window->visual);
-  
+
   if (attributes_mask & GDK_WA_NOREDIR)
     {
       xattributes.override_redirect =
-       (attributes->override_redirect == FALSE)?False:True;
+        (attributes->override_redirect == FALSE)?False:True;
       xattributes_mask |= CWOverrideRedirect;
-    } 
+    }
   else
     xattributes.override_redirect = False;
 
   impl->override_redirect = xattributes.override_redirect;
-  
+
   if (window->parent && window->parent->guffaw_gravity)
     {
       xattributes.win_gravity = StaticGravity;
       xattributes_mask |= CWWinGravity;
     }
-  
+
   /* Sanity checks */
   switch (window->window_type)
     {
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_TEMP:
       if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
-       {
-         /* The common code warns for this case */
-         xparent = GDK_SCREEN_XROOTWIN (screen);
-       }
+        {
+          /* The common code warns for this case */
+          xparent = GDK_SCREEN_XROOTWIN (screen);
+        }
     }
-         
+
   if (!window->input_only)
     {
       class = InputOutput;
 
-      xattributes.background_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
+      xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
 
-      xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
+      xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
       xattributes_mask |= CWBorderPixel | CWBackPixel;
 
       if (window->guffaw_gravity)
-       xattributes.bit_gravity = StaticGravity;
+        xattributes.bit_gravity = StaticGravity;
       else
-       xattributes.bit_gravity = NorthWestGravity;
-      
+        xattributes.bit_gravity = NorthWestGravity;
+
       xattributes_mask |= CWBitGravity;
 
       xattributes.colormap = _gdk_visual_get_x11_colormap (window->visual);
       xattributes_mask |= CWColormap;
 
       if (window->window_type == GDK_WINDOW_TEMP)
-       {
-         xattributes.save_under = True;
-         xattributes.override_redirect = True;
-         xattributes.cursor = None;
-         xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
+        {
+          xattributes.save_under = True;
+          xattributes.override_redirect = True;
+          xattributes.cursor = None;
+          xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
 
-         impl->override_redirect = TRUE;
-       }
+          impl->override_redirect = TRUE;
+        }
     }
   else
     {
@@ -779,13 +801,13 @@ _gdk_window_impl_new (GdkWindow     *window,
       window->height > 65535)
     {
       g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
-      
+
       if (window->width > 65535)
-       window->width = 65535;
+        window->width = 65535;
       if (window->height > 65535)
-       window->height = 65535;
+        window->height = 65535;
     }
-  
+
   impl->xid = XCreateWindow (xdisplay, xparent,
                              window->x + window->parent->abs_x,
                              window->y + window->parent->abs_y,
@@ -794,28 +816,28 @@ _gdk_window_impl_new (GdkWindow     *window,
                              xattributes_mask, &xattributes);
 
   g_object_ref (window);
-  _gdk_xid_table_insert (screen_x11->display, &impl->xid, window);
+  _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
 
   switch (GDK_WINDOW_TYPE (window))
     {
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_TEMP:
       if (attributes_mask & GDK_WA_TITLE)
-       title = attributes->title;
+        title = attributes->title;
       else
-       title = get_default_title ();
-      
+        title = get_default_title ();
+
       gdk_window_set_title (window, title);
-      
+
       if (attributes_mask & GDK_WA_WMCLASS)
-       {
-         class_hint = XAllocClassHint ();
-         class_hint->res_name = attributes->wmclass_name;
-         class_hint->res_class = attributes->wmclass_class;
-         XSetClassHint (xdisplay, impl->xid, class_hint);
-         XFree (class_hint);
-       }
-  
+        {
+          class_hint = XAllocClassHint ();
+          class_hint->res_name = attributes->wmclass_name;
+          class_hint->res_class = attributes->wmclass_class;
+          XSetClassHint (xdisplay, impl->xid, class_hint);
+          XFree (class_hint);
+        }
+
       setup_toplevel_window (window, window->parent);
       break;
 
@@ -827,9 +849,9 @@ _gdk_window_impl_new (GdkWindow     *window,
   if (attributes_mask & GDK_WA_TYPE_HINT)
     gdk_window_set_type_hint (window, attributes->type_hint);
 
-  gdk_event_source_select_events ((GdkEventSource *) display_x11->event_source,
-                                  GDK_WINDOW_XID (window), event_mask,
-                                  StructureNotifyMask | PropertyChangeMask);
+  gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
+                                      GDK_WINDOW_XID (window), event_mask,
+                                      StructureNotifyMask | PropertyChangeMask);
 }
 
 static GdkEventMask
@@ -838,9 +860,9 @@ x_event_mask_to_gdk_event_mask (long mask)
   GdkEventMask event_mask = 0;
   int i;
 
-  for (i = 0; i < _gdk_nenvent_masks; i++)
+  for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
     {
-      if (mask & _gdk_event_mask_table[i])
+      if (mask & _gdk_x11_event_mask_table[i])
        event_mask |= 1 << (i + 1);
     }
 
@@ -852,7 +874,9 @@ x_event_mask_to_gdk_event_mask (long mask)
  * @display: the #GdkDisplay where the window handle comes from.
  * @window: an XLib <type>Window</type>
  *
- * Wraps a native window in a #GdkWindow.
+ * Wraps a native window in a #GdkWindow. The function will try to
+ * look up the window using gdk_x11_window_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
@@ -862,7 +886,7 @@ x_event_mask_to_gdk_event_mask (long mask)
  *   window, or %NULL if the window has been destroyed. The wrapper
  *   will be newly created, if one doesn't exist already.
  *
- * Since: 3.0
+ * Since: 2.24
  */
 GdkWindow *
 gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
@@ -871,7 +895,7 @@ gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
   GdkScreen *screen;
   GdkWindow *win;
   GdkWindowImplX11 *impl;
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   XWindowAttributes attrs;
   Window root, parent;
   Window *children = NULL;
@@ -880,9 +904,9 @@ gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
 
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
 
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
 
-  if ((win = gdk_xid_table_lookup_for_display (display, window)) != NULL)
+  if ((win = gdk_x11_window_lookup_for_display (display, window)) != NULL)
     return g_object_ref (win);
 
   gdk_x11_display_error_trap_push (display);
@@ -903,7 +927,7 @@ gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
 
   screen = _gdk_x11_display_screen_for_xrootwin (display, root);
 
-  win = g_object_new (GDK_TYPE_WINDOW, NULL);
+  win = _gdk_display_create_window (display);
   win->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
   win->impl_window = win;
   win->visual = gdk_x11_screen_lookup_visual (screen,
@@ -912,7 +936,7 @@ gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
   impl = GDK_WINDOW_IMPL_X11 (win->impl);
   impl->wrapper = win;
 
-  win->parent = gdk_xid_table_lookup_for_display (display, parent);
+  win->parent = gdk_x11_window_lookup_for_display (display, parent);
 
   if (!win->parent || GDK_WINDOW_TYPE (win->parent) == GDK_WINDOW_FOREIGN)
     win->parent = gdk_screen_get_root_window (screen);
@@ -939,7 +963,7 @@ gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
   win->depth = attrs.depth;
 
   g_object_ref (win);
-  _gdk_xid_table_insert (display, &GDK_WINDOW_XID (win), win);
+  _gdk_x11_display_add_window (display, &GDK_WINDOW_XID (win), win);
 
   /* Update the clip region, etc */
   _gdk_window_update_size (win);
@@ -947,25 +971,6 @@ gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
   return win;
 }
 
-/**
- * gdk_x11_window_lookup_for_display:
- * @display: the #GdkDisplay corresponding to the window handle
- * @window: an XLib <type>Window</type>
- *
- * Looks up the #GdkWindow that wraps the given native window handle.
- *
- * Return value: (transfer none): the #GdkWindow wrapper for the native
- *    window, or %NULL if there is none.
- *
- * Since: 3.0
- */
-GdkWindow *
-gdk_x11_window_lookup_for_display (GdkDisplay *display,
-                                   Window      window)
-{
-  return (GdkWindow*) gdk_xid_table_lookup_for_display (display, window);
-}
-
 static void
 gdk_toplevel_x11_free_contents (GdkDisplay *display,
                                GdkToplevelX11 *toplevel)
@@ -1007,7 +1012,7 @@ gdk_x11_window_destroy (GdkWindow *window,
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  _gdk_selection_window_destroyed (window);
+  _gdk_x11_selection_window_destroyed (window);
 
   toplevel = _gdk_x11_window_get_toplevel (window);
   if (toplevel)
@@ -1091,16 +1096,42 @@ gdk_x11_window_destroy_notify (GdkWindow *window)
 
       _gdk_window_destroy (window, TRUE);
     }
-  
-  _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
+
+  _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
   if (window_impl->toplevel && window_impl->toplevel->focus_window)
-    _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
+    _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
+
+  _gdk_x11_window_grab_check_destroy (window);
 
-  _gdk_xgrab_check_destroy (window);
-  
   g_object_unref (window);
 }
 
+static GdkDragProtocol
+gdk_x11_window_get_drag_protocol (GdkWindow *window,
+                                  GdkWindow **target)
+{
+  GdkDragProtocol protocol;
+  GdkDisplay *display;
+  guint version;
+  Window xid;
+
+  display = gdk_window_get_display (window);
+  xid = _gdk_x11_display_get_drag_protocol (display,
+                                            GDK_WINDOW_XID (window->impl_window),
+                                            &protocol,
+                                            &version);
+
+  if (target)
+    {
+      if (xid != None)
+        *target = gdk_x11_window_foreign_new_for_display (display, xid);
+      else
+        *target = NULL;
+    }
+
+  return protocol;
+}
+
 static void
 update_wm_hints (GdkWindow *window,
                 gboolean   force)
@@ -1143,7 +1174,7 @@ update_wm_hints (GdkWindow *window,
       wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
     }
   else
-    wm_hints.window_group = GDK_DISPLAY_X11 (display)->leader_window;
+    wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
 
   if (toplevel->urgency_hint)
     wm_hints.flags |= XUrgencyHint;
@@ -1278,7 +1309,7 @@ static void
 gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
 {
   GdkDisplay *display;
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   GdkToplevelX11 *toplevel;
   GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
   Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
@@ -1291,7 +1322,7 @@ gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
   if (WINDOW_IS_TOPLEVEL (window))
     {
       display = gdk_window_get_display (window);
-      display_x11 = GDK_DISPLAY_X11 (display);
+      display_x11 = GDK_X11_DISPLAY (display);
       toplevel = _gdk_x11_window_get_toplevel (window);
       
       if (toplevel->user_time != 0 &&
@@ -1368,8 +1399,8 @@ gdk_window_x11_hide (GdkWindow *window)
    * but checking here makes things more consistent if we are
    * just doing stuff ourself.
    */
-  _gdk_xgrab_check_unmap (window,
-                         NextRequest (GDK_WINDOW_XDISPLAY (window)));
+  _gdk_x11_window_grab_check_unmap (window,
+                                    NextRequest (GDK_WINDOW_XDISPLAY (window)));
 
   /* You can't simply unmap toplevel windows. */
   switch (window->window_type)
@@ -1423,9 +1454,9 @@ window_x11_move (GdkWindow *window,
 
   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
     {
-      _gdk_window_move_resize_child (window,
-                                     x, y,
-                                     window->width, window->height);
+      _gdk_x11_window_move_resize_child (window,
+                                         x, y,
+                                         window->width, window->height);
     }
   else
     {
@@ -1454,9 +1485,9 @@ window_x11_resize (GdkWindow *window,
 
   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
     {
-      _gdk_window_move_resize_child (window,
-                                     window->x, window->y,
-                                     width, height);
+      _gdk_x11_window_move_resize_child (window,
+                                         window->x, window->y,
+                                         width, height);
     }
   else
     {
@@ -1497,7 +1528,7 @@ window_x11_move_resize (GdkWindow *window,
 
   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
     {
-      _gdk_window_move_resize_child (window, x, y, width, height);
+      _gdk_x11_window_move_resize_child (window, x, y, width, height);
       _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
     }
   else
@@ -1602,7 +1633,7 @@ gdk_window_x11_reparent (GdkWindow *window,
          if (impl->toplevel->focus_window)
            {
              XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
-             _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
+              _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
            }
          
          gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
@@ -1666,7 +1697,7 @@ gdk_window_x11_lower (GdkWindow *window)
 
 /**
  * gdk_x11_window_move_to_current_desktop:
- * @window: a #GdkWindow
+ * @window: (type GdkX11Window): a #GdkWindow
  * 
  * Moves the window to the correct workspace when running under a 
  * window manager that supports multiple workspaces, as described
@@ -1732,7 +1763,7 @@ move_to_current_desktop (GdkWindow *window)
           xclient.format = 32;
 
           xclient.data.l[0] = *current_desktop;
-          xclient.data.l[1] = 0;
+          xclient.data.l[1] = 1; /* source indication */
           xclient.data.l[2] = 0;
           xclient.data.l[3] = 0;
           xclient.data.l[4] = 0;
@@ -1771,7 +1802,7 @@ gdk_x11_window_focus (GdkWindow *window,
       xclient.type = ClientMessage;
       xclient.window = GDK_WINDOW_XID (window);
       xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
-                                                                       "_NET_ACTIVE_WINDOW");
+                                                                    "_NET_ACTIVE_WINDOW");
       xclient.format = 32;
       xclient.data.l[0] = 1; /* requestor type; we're an app */
       xclient.data.l[1] = timestamp;
@@ -1788,11 +1819,14 @@ gdk_x11_window_focus (GdkWindow *window,
       XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
 
       /* There is no way of knowing reliably whether we are viewable;
-       * _gdk_x11_set_input_focus_safe() traps errors asynchronously.
+       * so trap errors asynchronously around the XSetInputFocus call
        */
-      _gdk_x11_set_input_focus_safe (display, GDK_WINDOW_XID (window),
-                                    RevertToParent,
-                                    timestamp);
+      gdk_x11_display_error_trap_push (display);
+      XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
+                      GDK_WINDOW_XID (window),
+                      RevertToParent,
+                      timestamp);
+      gdk_x11_display_error_trap_pop_ignored (display);
     }
 }
 
@@ -1952,7 +1986,7 @@ gdk_wmspec_change_state (gboolean   add,
   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] = 0;
+  xclient.data.l[3] = 1; /* source indication */
   xclient.data.l[4] = 0;
   
   XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
@@ -2239,7 +2273,7 @@ set_text_property (GdkDisplay  *display,
   if (utf8_is_latin1 (utf8_str))
     {
       prop_type = XA_STRING;
-      prop_text = gdk_utf8_to_string_target (utf8_str);
+      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;
@@ -2247,10 +2281,10 @@ set_text_property (GdkDisplay  *display,
   else
     {
       GdkAtom gdk_type;
-      
-      gdk_utf8_to_compound_text_for_display (display,
-                                            utf8_str, &gdk_type, &prop_format,
-                                            (guchar **)&prop_text, &prop_length);
+
+      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;
     }
@@ -2265,7 +2299,7 @@ set_text_property (GdkDisplay  *display,
                       prop_length);
 
       if (is_compound_text)
-       gdk_free_compound_text ((guchar *)prop_text);
+       gdk_x11_free_compound_text ((guchar *)prop_text);
       else
        g_free (prop_text);
     }
@@ -2525,7 +2559,7 @@ gdk_window_x11_set_device_cursor (GdkWindow *window,
     {
       _gdk_x11_cursor_update_theme (cursor);
       g_hash_table_replace (impl->device_cursor,
-                            device, gdk_cursor_ref (cursor));
+                            device, g_object_ref (cursor));
     }
 
   if (!GDK_WINDOW_DESTROYED (window))
@@ -2620,7 +2654,7 @@ gdk_x11_window_get_root_origin (GdkWindow *window,
 
 static void
 gdk_x11_window_get_frame_extents (GdkWindow    *window,
-                                 GdkRectangle *rect)
+                                  GdkRectangle *rect)
 {
   GdkDisplay *display;
   GdkWindowImplX11 *impl;
@@ -2641,14 +2675,14 @@ gdk_x11_window_get_frame_extents (GdkWindow    *window,
   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;
 
@@ -2665,18 +2699,19 @@ gdk_x11_window_get_frame_extents (GdkWindow    *window,
   nvroots = 0;
   vroots = NULL;
 
-  gdk_error_trap_push();
-  
   display = gdk_window_get_display (window);
+
+  gdk_x11_display_error_trap_push (display);
+
   xwindow = GDK_WINDOW_XID (window);
 
   /* first try: use _NET_FRAME_EXTENTS */
   if (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)
+                          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) &&
@@ -2758,8 +2793,8 @@ gdk_x11_window_get_frame_extents (GdkWindow    *window,
        }
     }
   while (xparent != root);
-  
-  if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow, 
+
+  if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
                    &root, &wx, &wy, &ww, &wh, &wb, &wd))
     {
       rect->x = wx;
@@ -2772,7 +2807,7 @@ gdk_x11_window_get_frame_extents (GdkWindow    *window,
   if (vroots)
     XFree (vroots);
 
-  gdk_error_trap_pop_ignored ();
+  gdk_x11_display_error_trap_pop_ignored (display);
 }
 
 static gboolean
@@ -2826,15 +2861,15 @@ gdk_window_x11_set_events (GdkWindow    *window,
   
   if (!GDK_WINDOW_DESTROYED (window))
     {
-      GdkDisplayX11 *display_x11;
+      GdkX11Display *display_x11;
 
       if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
         xevent_mask = StructureNotifyMask | PropertyChangeMask;
 
-      display_x11 = GDK_DISPLAY_X11 (gdk_window_get_display (window));
-      gdk_event_source_select_events ((GdkEventSource *) display_x11->event_source,
-                                      GDK_WINDOW_XID (window), event_mask,
-                                      xevent_mask);
+      display_x11 = GDK_X11_DISPLAY (gdk_window_get_display (window));
+      gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
+                                          GDK_WINDOW_XID (window), event_mask,
+                                          xevent_mask);
     }
 }
 
@@ -2882,9 +2917,9 @@ do_shape_combine_region (GdkWindow       *window,
       gint n_rects = 0;
       XRectangle *xrects = NULL;
 
-      _gdk_region_get_xrectangles (shape_region,
-                                   0, 0,
-                                   &xrects, &n_rects);
+      _gdk_x11_region_get_xrectangles (shape_region,
+                                       0, 0,
+                                       &xrects, &n_rects);
       
       if (shape == ShapeBounding)
        {
@@ -2986,7 +3021,7 @@ gdk_x11_window_set_focus_on_map (GdkWindow *window,
 
 /**
  * gdk_x11_window_set_user_time:
- * @window: A toplevel #GdkWindow
+ * @window: (type GdkX11Window): A toplevel #GdkWindow
  * @timestamp: An XServer timestamp to which the property should be set
  *
  * The application can use this call to update the _NET_WM_USER_TIME
@@ -3009,7 +3044,7 @@ gdk_x11_window_set_user_time (GdkWindow *window,
                               guint32    timestamp)
 {
   GdkDisplay *display;
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   GdkToplevelX11 *toplevel;
   glong timestamp_long = (glong)timestamp;
   Window xid;
@@ -3019,7 +3054,7 @@ gdk_x11_window_set_user_time (GdkWindow *window,
     return;
 
   display = gdk_window_get_display (window);
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
   toplevel = _gdk_x11_window_get_toplevel (window);
 
   if (!toplevel)
@@ -3049,6 +3084,113 @@ gdk_x11_window_set_user_time (GdkWindow *window,
     toplevel->user_time = timestamp_long;
 }
 
+/**
+ * gdk_x11_window_set_utf8_property:
+ * @window: (type GdkX11Window): a #GdkWindow
+ * @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.
+ *
+ * Since: 3.4
+ */
+void
+gdk_x11_window_set_utf8_property  (GdkWindow *window,
+                                  const gchar *name,
+                                  const gchar *value)
+{
+  GdkDisplay *display;
+
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  display = gdk_window_get_display (window);
+
+  if (value != NULL)
+    {
+      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_WINDOW_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_WINDOW_XID (window),
+                       gdk_x11_get_xatom_by_name_for_display (display, name));
+    }
+}
+
+/**
+ * gdk_x11_window_set_hide_titlebar_when_maximized:
+ * @window: (type GdkX11Window): a #GdkWindow
+ * @hide_titlebar_when_maximized: whether to hide the titlebar when
+ *                                maximized
+ *
+ * Set a hint for the window manager, requesting that the titlebar
+ * should be hidden when the window is maximized.
+ *
+ * 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.
+ *
+ * Since: 3.4
+ */
+void
+gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
+                                                 gboolean   hide_titlebar_when_maximized)
+{
+  GdkDisplay *display;
+
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  display = gdk_window_get_display (window);
+
+  if (hide_titlebar_when_maximized)
+    {
+      guint32 hide = 1;
+      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_WINDOW_XID (window),
+                       gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"),
+                       XA_CARDINAL, 32,
+                       PropModeReplace, (guchar *)&hide, 1);
+    }
+  else
+    {
+      XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
+                       GDK_WINDOW_XID (window),
+                       gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"));
+    }
+}
+
+/**
+ * gdk_x11_window_set_theme_variant:
+ * @window: (type GdkX11Window): a #GdkWindow
+ * @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.
+ *
+ * Since: 3.2
+ */
+void
+gdk_x11_window_set_theme_variant (GdkWindow *window,
+                                  char      *variant)
+{
+  return gdk_x11_window_set_utf8_property (window, "_GTK_THEME_VARIANT", variant);
+}
+
 #define GDK_SELECTION_MAX_SIZE(display)                                 \
   MIN(262144,                                                           \
       XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0     \
@@ -3736,9 +3878,9 @@ gdk_x11_window_set_functions (GdkWindow    *window,
 }
 
 cairo_region_t *
-_xwindow_get_shape (Display *xdisplay,
-                   Window window,
-                   gint shape_type)
+_gdk_x11_xwindow_get_shape (Display *xdisplay,
+                            Window   window,
+                            gint     shape_type)
 {
   cairo_region_t *shape;
   GdkRectangle *rl;
@@ -3748,17 +3890,24 @@ _xwindow_get_shape (Display *xdisplay,
   shape = NULL;
   rn = 0;
 
-  xrl = XShapeGetRectangles (xdisplay,
-                            window,
-                            shape_type, &rn, &ord);
+  /* 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 (xrl == NULL || rn == 0)
+  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 */
+       * generally convert regions to YXBanded internally
+       */
       g_warning ("non YXBanded shape masks not supported");
       XFree (xrl);
       return NULL;
@@ -3773,10 +3922,10 @@ _xwindow_get_shape (Display *xdisplay,
       rl[i].height = xrl[i].height;
     }
   XFree (xrl);
-  
+
   shape = cairo_region_create_rectangles (rl, rn);
   g_free (rl);
-  
+
   return shape;
 }
 
@@ -3786,8 +3935,9 @@ gdk_x11_window_get_shape (GdkWindow *window)
 {
   if (!GDK_WINDOW_DESTROYED (window) &&
       gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
-    return _xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
-                             GDK_WINDOW_XID (window), ShapeBounding);
+    return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+                                       GDK_WINDOW_XID (window),
+                                       ShapeBounding);
 
   return NULL;
 }
@@ -3797,10 +3947,10 @@ gdk_x11_window_get_input_shape (GdkWindow *window)
 {
 #if defined(ShapeInput)
   if (!GDK_WINDOW_DESTROYED (window) &&
-      gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
-    return _xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
-                             GDK_WINDOW_XID (window),
-                             ShapeInput);
+      gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
+    return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+                                       GDK_WINDOW_XID (window),
+                                       ShapeInput);
 #endif
 
   return NULL;
@@ -3868,20 +4018,30 @@ gdk_window_x11_set_static_gravities (GdkWindow *window,
   return TRUE;
 }
 
+/* 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_moveresize (GdkWindow *window,
-                   gint       direction,
-                   gint       root_x,
-                   gint       root_y,
-                   guint32    timestamp)     
+wmspec_send_message (GdkDisplay *display,
+                     GdkWindow  *window,
+                     gint        root_x,
+                     gint        root_y,
+                     gint        action,
+                     gint        button)
 {
-  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
-  
   XClientMessageEvent xclient;
 
-  /* Release passive grab */
-  gdk_display_pointer_ungrab (display, timestamp);
-
   memset (&xclient, 0, sizeof (xclient));
   xclient.type = ClientMessage;
   xclient.window = GDK_WINDOW_XID (window);
@@ -3890,52 +4050,75 @@ wmspec_moveresize (GdkWindow *window,
   xclient.format = 32;
   xclient.data.l[0] = root_x;
   xclient.data.l[1] = root_y;
-  xclient.data.l[2] = direction;
-  xclient.data.l[3] = 0;
-  xclient.data.l[4] = 0;
-  
+  xclient.data.l[2] = action;
+  xclient.data.l[3] = button;
+  xclient.data.l[4] = 1;  /* source indication */
+
   XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
-             SubstructureRedirectMask | SubstructureNotifyMask,
-             (XEvent *)&xclient);
+              SubstructureRedirectMask | SubstructureNotifyMask,
+              (XEvent *)&xclient);
 }
 
-typedef struct _MoveResizeData MoveResizeData;
+static gboolean
+handle_wmspec_button_release (GdkDisplay *display,
+                              XEvent     *xevent)
+{
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
+  GdkWindow *window;
 
-struct _MoveResizeData
+#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_window_lookup_for_display (display, xidev->event);
+  else
+#endif
+    window = gdk_x11_window_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);
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+static void
+wmspec_moveresize (GdkWindow *window,
+                   gint       direction,
+                   GdkDevice *device,
+                   gint       button,
+                   gint       root_x,
+                   gint       root_y,
+                   guint32    timestamp)
 {
-  GdkDisplay *display;
-  
-  GdkWindow *moveresize_window;
-  GdkWindow *moveresize_emulation_window;
-  gboolean is_resize;
-  GdkWindowEdge 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;
-  GdkWindowHints moveresize_geom_mask;
-  GdkGeometry moveresize_geometry;
-  Time moveresize_process_time;
-  XEvent *moveresize_pending_event;
-};
+  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
 
-/* 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
+  /* Release passive grab */
+  gdk_device_ungrab (device, timestamp);
+  GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
+
+  wmspec_send_message (display, window, root_x, root_y, direction, button);
+}
 
 static void
 wmspec_resize_drag (GdkWindow     *window,
                     GdkWindowEdge  edge,
+                    GdkDevice     *device,
                     gint           button,
                     gint           root_x,
                     gint           root_y,
@@ -3986,9 +4169,33 @@ wmspec_resize_drag (GdkWindow     *window,
       return;
     }
   
-  wmspec_moveresize (window, direction, root_x, root_y, timestamp);
+  wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
 }
 
+typedef struct _MoveResizeData MoveResizeData;
+
+struct _MoveResizeData
+{
+  GdkDisplay *display;
+
+  GdkWindow *moveresize_window;
+  GdkWindow *moveresize_emulation_window;
+  gboolean is_resize;
+  GdkWindowEdge 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;
+  GdkWindowHints moveresize_geom_mask;
+  GdkGeometry moveresize_geometry;
+  Time moveresize_process_time;
+  XEvent *moveresize_pending_event;
+};
+
 static MoveResizeData *
 get_move_resize_data (GdkDisplay *display,
                      gboolean    create)
@@ -4147,27 +4354,30 @@ moveresize_lookahead (MoveResizeData *mv_resize,
   if (mv_resize->moveresize_process_time)
     {
       if (event->xmotion.time == mv_resize->moveresize_process_time)
-       {
-         mv_resize->moveresize_process_time = 0;
-         return TRUE;
-       }
+        {
+          mv_resize->moveresize_process_time = 0;
+          return TRUE;
+        }
       else
-       return FALSE;
+        return FALSE;
     }
 
   XCheckIfEvent (event->xany.display, &tmp_event,
-                lookahead_motion_predicate, (XPointer) & seen_release);
+                 lookahead_motion_predicate, (XPointer) & seen_release);
 
   return mv_resize->moveresize_process_time == 0;
 }
-       
+
 gboolean
-_gdk_moveresize_handle_event (XEvent *event)
+_gdk_x11_moveresize_handle_event (XEvent *event)
 {
   guint button_mask = 0;
   GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
 
+  if (handle_wmspec_button_release (display, event))
+    return TRUE;
+
   if (!mv_resize || !mv_resize->moveresize_window)
     return FALSE;
 
@@ -4177,21 +4387,21 @@ _gdk_moveresize_handle_event (XEvent *event)
     {
     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));
+        {
+          if (mv_resize->moveresize_pending_event)
+            *mv_resize->moveresize_pending_event = *event;
+          else
+            mv_resize->moveresize_pending_event =
+              g_memdup (event, sizeof (XEvent));
 
-         break;
-       }
+          break;
+        }
       if (!moveresize_lookahead (mv_resize, event))
-       break;
+        break;
 
       update_pos (mv_resize,
-                 event->xmotion.x_root,
-                 event->xmotion.y_root);
+                  event->xmotion.x_root,
+                  event->xmotion.y_root);
 
       /* This should never be triggered in normal cases, but in the
        * case where the drag started without an implicit grab being
@@ -4200,28 +4410,57 @@ _gdk_moveresize_handle_event (XEvent *event)
        * get a permanently stuck grab.
        */
       if ((event->xmotion.state & button_mask) == 0)
-       finish_drag (mv_resize);
+        finish_drag (mv_resize);
       break;
 
     case ButtonRelease:
       update_pos (mv_resize,
-                 event->xbutton.x_root,
-                 event->xbutton.y_root);
+                  event->xbutton.x_root,
+                  event->xbutton.y_root);
 
       if (event->xbutton.button == mv_resize->moveresize_button)
-       finish_drag (mv_resize);
+        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, xev->root_y);
+            state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+            if ((state & button_mask) == 0)
+            finish_drag (mv_resize);
+            break;
+
+          case XI_ButtonRelease:
+            update_pos (mv_resize, xev->root_x, xev->root_y);
+            if (xev->detail == mv_resize->moveresize_button)
+              finish_drag (mv_resize);
+            break;
+          }
+      }
+      break;
+#endif
+
     }
   return TRUE;
 }
 
-gboolean 
-_gdk_moveresize_configure_done (GdkDisplay *display,
-                               GdkWindow  *window)
+gboolean
+_gdk_x11_moveresize_configure_done (GdkDisplay *display,
+                                    GdkWindow  *window)
 {
   XEvent *tmp_event;
   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
-  
+
+  GDK_X11_DISPLAY (display)->wm_moveresize_button = 0;
+
   if (!mv_resize || window != mv_resize->moveresize_window)
     return FALSE;
 
@@ -4229,16 +4468,16 @@ _gdk_moveresize_configure_done (GdkDisplay *display,
     {
       tmp_event = mv_resize->moveresize_pending_event;
       mv_resize->moveresize_pending_event = NULL;
-      _gdk_moveresize_handle_event (tmp_event);
+      _gdk_x11_moveresize_handle_event (tmp_event);
       g_free (tmp_event);
     }
-  
+
   return TRUE;
 }
 
 static void
 create_moveresize_window (MoveResizeData *mv_resize,
-                         guint32         timestamp)
+                          guint32         timestamp)
 {
   GdkWindowAttr attributes;
   gint attributes_mask;
@@ -4264,13 +4503,13 @@ create_moveresize_window (MoveResizeData *mv_resize,
 
   gdk_window_show (mv_resize->moveresize_emulation_window);
 
-  status = gdk_pointer_grab (mv_resize->moveresize_emulation_window,
-                             FALSE,
-                             GDK_BUTTON_RELEASE_MASK |
-                             GDK_POINTER_MOTION_MASK,
-                             NULL,
-                             NULL,
-                             timestamp);
+  status = gdk_device_grab (mv_resize->device,
+                            mv_resize->moveresize_emulation_window,
+                            GDK_OWNERSHIP_NONE,
+                            FALSE,
+                            GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
+                            NULL,
+                            timestamp);
 
   if (status != GDK_GRAB_SUCCESS)
     {
@@ -4358,6 +4597,7 @@ calculate_unmoving_origin (MoveResizeData *mv_resize)
 static void
 emulate_resize_drag (GdkWindow     *window,
                      GdkWindowEdge  edge,
+                     GdkDevice     *device,
                      gint           button,
                      gint           root_x,
                      gint           root_y,
@@ -4368,6 +4608,7 @@ emulate_resize_drag (GdkWindow     *window,
   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);
@@ -4387,6 +4628,7 @@ emulate_resize_drag (GdkWindow     *window,
 
 static void
 emulate_move_drag (GdkWindow     *window,
+                   GdkDevice     *device,
                    gint           button,
                    gint           root_x,
                    gint           root_y,
@@ -4395,6 +4637,7 @@ emulate_move_drag (GdkWindow     *window,
   MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
   
   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;
@@ -4408,11 +4651,12 @@ emulate_move_drag (GdkWindow     *window,
 
 static void
 gdk_x11_window_begin_resize_drag (GdkWindow     *window,
-                                 GdkWindowEdge  edge,
-                                 gint           button,
-                                 gint           root_x,
-                                 gint           root_y,
-                                 guint32        timestamp)
+                                  GdkWindowEdge  edge,
+                                  GdkDevice     *device,
+                                  gint           button,
+                                  gint           root_x,
+                                  gint           root_y,
+                                  guint32        timestamp)
 {
   if (GDK_WINDOW_DESTROYED (window) ||
       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
@@ -4420,13 +4664,14 @@ gdk_x11_window_begin_resize_drag (GdkWindow     *window,
 
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
                                           gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
-    wmspec_resize_drag (window, edge, button, root_x, root_y, timestamp);
+    wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
   else
-    emulate_resize_drag (window, edge, button, root_x, root_y, timestamp);
+    emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
 }
 
 static void
 gdk_x11_window_begin_move_drag (GdkWindow *window,
+                                GdkDevice *device,
                                gint       button,
                                gint       root_x,
                                gint       root_y,
@@ -4438,10 +4683,10 @@ gdk_x11_window_begin_move_drag (GdkWindow *window,
 
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
                                           gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
-    wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE, root_x, root_y,
-                      timestamp);
+    wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
+                       device, button, root_x, root_y, timestamp);
   else
-    emulate_move_drag (window, button, root_x, root_y, timestamp);
+    emulate_move_drag (window, device, button, root_x, root_y, timestamp);
 }
 
 static void
@@ -4484,7 +4729,7 @@ gdk_x11_window_configure_finished (GdkWindow *window)
       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
 
       if (toplevel && toplevel->update_counter != None &&
-         GDK_DISPLAY_X11 (display)->use_sync &&
+         GDK_X11_DISPLAY (display)->use_sync &&
          !XSyncValueIsZero (toplevel->current_counter_value))
        {
          XSyncSetCounter (GDK_WINDOW_XDISPLAY (window), 
@@ -4505,7 +4750,7 @@ gdk_x11_window_beep (GdkWindow *window)
   display = GDK_WINDOW_DISPLAY (window);
 
 #ifdef HAVE_XKB
-  if (GDK_DISPLAY_X11 (display)->use_xkb)
+  if (GDK_X11_DISPLAY (display)->use_xkb)
     {
       XkbBell (GDK_DISPLAY_XDISPLAY (display),
                GDK_WINDOW_XID (window),
@@ -4619,9 +4864,10 @@ timestamp_predicate (Display *display,
 
 /**
  * gdk_x11_get_server_time:
- * @window: a #GdkWindow, used for communication with the server.
- *          The window must have GDK_PROPERTY_CHANGE_MASK in its
- *          events mask or a hang will result.
+ * @window: (type GdkX11Window): a #GdkWindow, 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.
  *
@@ -4657,7 +4903,7 @@ gdk_x11_get_server_time (GdkWindow *window)
 
 /**
  * gdk_x11_window_get_xid:
- * @window: a native #GdkWindow.
+ * @window: (type GdkX11Window): a native #GdkWindow.
  * 
  * Returns the X resource (window) belonging to a #GdkWindow.
  * 
@@ -4770,7 +5016,14 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
   impl_class->set_opacity = gdk_x11_window_set_opacity;
   impl_class->set_composited = gdk_x11_window_set_composited;
   impl_class->destroy_notify = gdk_x11_window_destroy_notify;
+  impl_class->get_drag_protocol = gdk_x11_window_get_drag_protocol;
   impl_class->register_dnd = _gdk_x11_window_register_dnd;
   impl_class->drag_begin = _gdk_x11_window_drag_begin;
   impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
+  impl_class->sync_rendering = _gdk_x11_window_sync_rendering;
+  impl_class->simulate_key = _gdk_x11_window_simulate_key;
+  impl_class->simulate_button = _gdk_x11_window_simulate_button;
+  impl_class->get_property = _gdk_x11_window_get_property;
+  impl_class->change_property = _gdk_x11_window_change_property;
+  impl_class->delete_property = _gdk_x11_window_delete_property;
 }