]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkdisplay-x11.c
Add GdkFrameHistory and GdkFrameTimings, handle _NET_WM_FRAME_TIMINGS
[~andy/gtk] / gdk / x11 / gdkdisplay-x11.c
index 60265adff5ce4a5840eedffda58b82d9d0272eff..ae4aaafb0f5cc47c79b1f2b9e14052b42994ed06 100644 (file)
@@ -17,9 +17,7 @@
  * 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, 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 "config.h"
@@ -88,23 +86,21 @@ struct _GdkErrorTrap
   int error_code;
 };
 
-static void   gdk_display_x11_dispose            (GObject            *object);
-static void   gdk_display_x11_finalize           (GObject            *object);
+static void   gdk_x11_display_dispose            (GObject            *object);
+static void   gdk_x11_display_finalize           (GObject            *object);
 
-static void     gdk_display_x11_event_translator_init (GdkEventTranslatorIface *iface);
+static void     gdk_x11_display_event_translator_init (GdkEventTranslatorIface *iface);
 
-static gboolean gdk_display_x11_translate_event (GdkEventTranslator *translator,
+static gboolean gdk_x11_display_translate_event (GdkEventTranslator *translator,
                                                  GdkDisplay         *display,
                                                  GdkEvent           *event,
                                                  XEvent             *xevent);
 
-#ifdef HAVE_X11R6
 static void gdk_internal_connection_watch (Display  *display,
                                           XPointer  arg,
                                           gint      fd,
                                           gboolean  opening,
                                           XPointer *watch_data);
-#endif /* HAVE_X11R6 */
 
 typedef struct _GdkEventTypeX11 GdkEventTypeX11;
 
@@ -155,27 +151,28 @@ static const char *const precache_atoms[] = {
   "_NET_WM_WINDOW_TYPE_NORMAL",
   "_NET_WM_USER_TIME",
   "_NET_VIRTUAL_ROOTS",
-  "GDK_SELECTION"
+  "GDK_SELECTION",
+  "_NET_WM_STATE_FOCUSED"
 };
 
 static char *gdk_sm_client_id;
 
-G_DEFINE_TYPE_WITH_CODE (GdkDisplayX11, _gdk_display_x11, GDK_TYPE_DISPLAY,
+G_DEFINE_TYPE_WITH_CODE (GdkX11Display, gdk_x11_display, GDK_TYPE_DISPLAY,
                          G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
-                                                gdk_display_x11_event_translator_init))
+                                                gdk_x11_display_event_translator_init))
 
 
 static void
-_gdk_display_x11_init (GdkDisplayX11 *display)
+gdk_x11_display_init (GdkX11Display *display)
 {
   _gdk_x11_display_manager_add_display (gdk_display_manager_get (),
-                                        GDK_DISPLAY_OBJECT (display));
+                                        GDK_DISPLAY (display));
 }
 
 static void
-gdk_display_x11_event_translator_init (GdkEventTranslatorIface *iface)
+gdk_x11_display_event_translator_init (GdkEventTranslatorIface *iface)
 {
-  iface->translate_event = gdk_display_x11_translate_event;
+  iface->translate_event = gdk_x11_display_translate_event;
 }
 
 static void
@@ -202,7 +199,7 @@ do_net_wm_state_changes (GdkWindow *window)
     }
   else
     {
-      if (toplevel->have_sticky || toplevel->on_all_desktops)
+      if (toplevel->have_sticky && toplevel->on_all_desktops)
         gdk_synthesize_window_state (window,
                                      0,
                                      GDK_WINDOW_STATE_STICKY);
@@ -240,6 +237,36 @@ do_net_wm_state_changes (GdkWindow *window)
                                      0,
                                      GDK_WINDOW_STATE_MAXIMIZED);
     }
+
+  if (old_state & GDK_WINDOW_STATE_FOCUSED)
+    {
+      if (!toplevel->have_focused)
+        gdk_synthesize_window_state (window,
+                                     GDK_WINDOW_STATE_FOCUSED,
+                                     0);
+    }
+  else
+    {
+      if (toplevel->have_focused)
+        gdk_synthesize_window_state (window,
+                                     0,
+                                     GDK_WINDOW_STATE_FOCUSED);
+    }
+
+  if (old_state & GDK_WINDOW_STATE_ICONIFIED)
+    {
+      if (!toplevel->have_hidden)
+        gdk_synthesize_window_state (window,
+                                     GDK_WINDOW_STATE_ICONIFIED,
+                                     0);
+    }
+  else
+    {
+      if (toplevel->have_hidden)
+        gdk_synthesize_window_state (window,
+                                     0,
+                                     GDK_WINDOW_STATE_ICONIFIED);
+    }
 }
 
 static void
@@ -268,7 +295,7 @@ gdk_check_wm_desktop_changed (GdkWindow *window)
   if (type != None)
     {
       desktop = (gulong *)data;
-      toplevel->on_all_desktops = (*desktop == 0xFFFFFFFF);
+      toplevel->on_all_desktops = ((*desktop & 0xFFFFFFFF) == 0xFFFFFFFF);
       XFree (desktop);
     }
   else
@@ -282,6 +309,7 @@ gdk_check_wm_state_changed (GdkWindow *window)
 {
   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+  GdkScreen *screen = GDK_WINDOW_SCREEN (window);
 
   Atom type;
   gint format;
@@ -297,6 +325,8 @@ gdk_check_wm_state_changed (GdkWindow *window)
   toplevel->have_maxvert = FALSE;
   toplevel->have_maxhorz = FALSE;
   toplevel->have_fullscreen = FALSE;
+  toplevel->have_focused = FALSE;
+  toplevel->have_hidden = FALSE;
 
   type = None;
   gdk_x11_display_error_trap_push (display);
@@ -312,6 +342,8 @@ gdk_check_wm_state_changed (GdkWindow *window)
       Atom maxvert_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT");
       Atom maxhorz_atom        = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ");
       Atom fullscreen_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FULLSCREEN");
+      Atom focused_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FOCUSED");
+      Atom hidden_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_HIDDEN");
 
       atoms = (Atom *)data;
 
@@ -326,6 +358,10 @@ gdk_check_wm_state_changed (GdkWindow *window)
             toplevel->have_maxhorz = TRUE;
           else if (atoms[i] == fullscreen_atom)
             toplevel->have_fullscreen = TRUE;
+          else if (atoms[i] == focused_atom)
+            toplevel->have_focused = TRUE;
+          else if (atoms[i] == hidden_atom)
+            toplevel->have_hidden = TRUE;
 
           ++i;
         }
@@ -333,6 +369,10 @@ gdk_check_wm_state_changed (GdkWindow *window)
       XFree (atoms);
     }
 
+  if (!gdk_x11_screen_supports_net_wm_hint (screen,
+                                            gdk_atom_intern_static_string ("_NET_WM_STATE_FOCUSED")))
+    toplevel->have_focused = TRUE;
+
   /* When have_sticky is turned on, we have to check the DESKTOP property
    * as well.
    */
@@ -342,15 +382,11 @@ gdk_check_wm_state_changed (GdkWindow *window)
     do_net_wm_state_changes (window);
 }
 
-static GdkWindow *
-get_event_window (GdkEventTranslator *translator,
-                  XEvent             *xevent)
+static Window
+get_event_xwindow (XEvent             *xevent)
 {
-  GdkDisplay *display;
   Window xwindow;
 
-  display = (GdkDisplay *) translator;
-
   switch (xevent->type)
     {
     case DestroyNotify:
@@ -365,34 +401,52 @@ get_event_window (GdkEventTranslator *translator,
     case ConfigureNotify:
       xwindow = xevent->xconfigure.window;
       break;
+    case ReparentNotify:
+      xwindow = xevent->xreparent.window;
+      break;
+    case GravityNotify:
+      xwindow = xevent->xgravity.window;
+      break;
+    case CirculateNotify:
+      xwindow = xevent->xcirculate.window;
+      break;
     default:
       xwindow = xevent->xany.window;
     }
 
-  return gdk_x11_window_lookup_for_display (display, xwindow);
+  return xwindow;
 }
 
 static gboolean
-gdk_display_x11_translate_event (GdkEventTranslator *translator,
+gdk_x11_display_translate_event (GdkEventTranslator *translator,
                                  GdkDisplay         *display,
                                  GdkEvent           *event,
                                  XEvent             *xevent)
 {
+  Window xwindow;
   GdkWindow *window;
+  gboolean is_substructure;
   GdkWindowImplX11 *window_impl = NULL;
   GdkScreen *screen = NULL;
-  GdkScreenX11 *screen_x11 = NULL;
+  GdkX11Screen *x11_screen = NULL;
   GdkToplevelX11 *toplevel = NULL;
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
   gboolean return_val;
-  Window xwindow = None;
 
-  /* Find the GdkWindow that this event relates to.
-   * Basically this means substructure events
-   * are reported same as structure events
+  /* Find the GdkWindow that this event relates to. If that's
+   * not the same as the window that the event was sent to,
+   * we are getting an event from SubstructureNotifyMask.
+   * We ignore such events for internal operation, but we
+   * need to report them to the application because of
+   * GDK_SUBSTRUCTURE_MASK (which should be removed at next
+   * opportunity.) The most likely reason for getting these
+   * events is when we are used in the Metacity or Mutter
+   * window managers.
    */
-  window = get_event_window (translator, xevent);
+  xwindow = get_event_xwindow (xevent);
+  is_substructure = xwindow != xevent->xany.window;
 
+  window = gdk_x11_window_lookup_for_display (display, xwindow);
   if (window)
     {
       /* We may receive events such as NoExpose/GraphicsExpose
@@ -402,10 +456,9 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
         return FALSE;
 
       screen = GDK_WINDOW_SCREEN (window);
-      screen_x11 = GDK_SCREEN_X11 (screen);
+      x11_screen = GDK_X11_SCREEN (screen);
       toplevel = _gdk_x11_window_get_toplevel (window);
       window_impl = GDK_WINDOW_IMPL_X11 (window->impl);
-      xwindow = GDK_WINDOW_XID (window);
 
       g_object_ref (window);
     }
@@ -422,7 +475,7 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
        }
     }
 
-  if (xevent->type == DestroyNotify)
+  if (xevent->type == DestroyNotify && !is_substructure)
     {
       int i, n;
 
@@ -430,14 +483,14 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
       for (i = 0; i < n; i++)
         {
           screen = gdk_display_get_screen (display, i);
-          screen_x11 = GDK_SCREEN_X11 (screen);
+          x11_screen = GDK_X11_SCREEN (screen);
 
-          if (screen_x11->wmspec_check_window == xwindow)
+          if (x11_screen->wmspec_check_window == xevent->xdestroywindow.window)
             {
-              screen_x11->wmspec_check_window = None;
-              screen_x11->last_wmspec_check_time = 0;
-              g_free (screen_x11->window_manager_name);
-              screen_x11->window_manager_name = g_strdup ("unknown");
+              x11_screen->wmspec_check_window = None;
+              x11_screen->last_wmspec_check_time = 0;
+              g_free (x11_screen->window_manager_name);
+              x11_screen->window_manager_name = g_strdup ("unknown");
 
               /* careful, reentrancy */
               _gdk_x11_screen_window_manager_changed (screen);
@@ -584,15 +637,14 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
                g_message ("destroy notify:\twindow: %ld",
                           xevent->xdestroywindow.window));
 
-      /* Ignore DestroyNotify from SubstructureNotifyMask */
-      if (xevent->xdestroywindow.window == xevent->xdestroywindow.event)
+      if (!is_substructure)
        {
          event->any.type = GDK_DESTROY;
          event->any.window = window;
 
          return_val = window && !GDK_WINDOW_DESTROYED (window);
 
-         if (window && GDK_WINDOW_XID (window) != screen_x11->xroot_window)
+         if (window && GDK_WINDOW_XID (window) != x11_screen->xroot_window)
            gdk_window_destroy_notify (window);
        }
       else
@@ -608,17 +660,36 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
       event->any.type = GDK_UNMAP;
       event->any.window = window;
 
-      /* If we are shown (not withdrawn) and get an unmap, it means we
-       * were iconified in the X sense. If we are withdrawn, and get
-       * an unmap, it means we hid the window ourselves, so we
-       * will have already flipped the iconified bit off.
-       */
-      if (window)
-        {
-          if (GDK_WINDOW_IS_MAPPED (window))
-            gdk_synthesize_window_state (window,
-                                         0,
-                                         GDK_WINDOW_STATE_ICONIFIED);
+      if (window && !is_substructure)
+       {
+          /* If the WM supports the _NET_WM_STATE_HIDDEN hint, we do not want to
+           * interpret UnmapNotify events as implying iconic state.
+           * http://bugzilla.gnome.org/show_bug.cgi?id=590726.
+           */
+          if (screen &&
+              !gdk_x11_screen_supports_net_wm_hint (screen,
+                                                    gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN")))
+            {
+              /* If we are shown (not withdrawn) and get an unmap, it means we were
+               * iconified in the X sense. If we are withdrawn, and get an unmap, it
+               * means we hid the window ourselves, so we will have already flipped
+               * the iconified bit off.
+               */
+              if (GDK_WINDOW_IS_MAPPED (window))
+                gdk_synthesize_window_state (window,
+                                             0,
+                                             GDK_WINDOW_STATE_ICONIFIED);
+            }
+
+          if (window_impl->toplevel &&
+              window_impl->toplevel->frame_pending)
+            {
+              window_impl->toplevel->frame_pending = FALSE;
+              gdk_frame_clock_thaw (gdk_window_get_frame_clock (event->any.window));
+            }
+
+         if (toplevel)
+            gdk_window_freeze_toplevel_updates_libgtk_only (window);
 
           _gdk_x11_window_grab_check_unmap (window, xevent->xany.serial);
         }
@@ -633,11 +704,17 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
       event->any.type = GDK_MAP;
       event->any.window = window;
 
-      /* Unset iconified if it was set */
-      if (window && (window->state & GDK_WINDOW_STATE_ICONIFIED))
-        gdk_synthesize_window_state (window,
-                                     GDK_WINDOW_STATE_ICONIFIED,
-                                     0);
+      if (window && !is_substructure)
+       {
+         /* Unset iconified if it was set */
+         if (window->state & GDK_WINDOW_STATE_ICONIFIED)
+           gdk_synthesize_window_state (window,
+                                        GDK_WINDOW_STATE_ICONIFIED,
+                                        0);
+
+         if (toplevel)
+           gdk_window_thaw_toplevel_updates_libgtk_only (window);
+       }
 
       break;
 
@@ -683,10 +760,10 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
         }
 
 #ifdef HAVE_XSYNC
-      if (toplevel && display_x11->use_sync && !XSyncValueIsZero (toplevel->pending_counter_value))
+      if (!is_substructure && toplevel && display_x11->use_sync && toplevel->pending_counter_value != 0)
        {
-         toplevel->current_counter_value = toplevel->pending_counter_value;
-         XSyncIntToValue (&toplevel->pending_counter_value, 0);
+         toplevel->configure_counter_value = toplevel->pending_counter_value;
+         toplevel->pending_counter_value = 0;
        }
 #endif
 
@@ -713,7 +790,7 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
              gdk_x11_display_error_trap_push (display);
              if (XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
                                         GDK_WINDOW_XID (window),
-                                        screen_x11->xroot_window,
+                                        x11_screen->xroot_window,
                                         0, 0,
                                         &tx, &ty,
                                         &child_window))
@@ -728,21 +805,24 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
              event->configure.x = xevent->xconfigure.x;
              event->configure.y = xevent->xconfigure.y;
            }
-         window->x = event->configure.x;
-         window->y = event->configure.y;
-         window->width = xevent->xconfigure.width;
-         window->height = xevent->xconfigure.height;
+         if (!is_substructure)
+           {
+             window->x = event->configure.x;
+             window->y = event->configure.y;
+             window->width = xevent->xconfigure.width;
+             window->height = xevent->xconfigure.height;
 
-         _gdk_window_update_size (window);
-         _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
+             _gdk_window_update_size (window);
+             _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
 
-          if (window->resize_count >= 1)
-            {
-              window->resize_count -= 1;
+             if (window->resize_count >= 1)
+               {
+                 window->resize_count -= 1;
 
-              if (window->resize_count == 0)
-                _gdk_x11_moveresize_configure_done (display, window);
-            }
+                 if (window->resize_count == 0)
+                   _gdk_x11_moveresize_configure_done (display, window);
+               }
+           }
         }
       break;
 
@@ -814,7 +894,11 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
       event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.selection);
       event->selection.target = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.target);
       event->selection.property = gdk_x11_xatom_to_atom_for_display (display, xevent->xselectionrequest.property);
-      event->selection.requestor = xevent->xselectionrequest.requestor;
+      if (xevent->xselectionrequest.requestor != None)
+        event->selection.requestor = gdk_x11_window_foreign_new_for_display (display,
+                                                                             xevent->xselectionrequest.requestor);
+      else
+        event->selection.requestor = NULL;
       event->selection.time = xevent->xselectionrequest.time;
 
       break;
@@ -846,56 +930,12 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
       break;
 
     case ClientMessage:
-      {
-       GList *tmp_list;
-       GdkFilterReturn result = GDK_FILTER_CONTINUE;
-       GdkAtom message_type = gdk_x11_xatom_to_atom_for_display (display, xevent->xclient.message_type);
-
-       GDK_NOTE (EVENTS,
-                 g_message ("client message:\twindow: %ld",
-                            xevent->xclient.window));
-
-       tmp_list = display_x11->client_filters;
-       while (tmp_list)
-         {
-           GdkClientFilter *filter = tmp_list->data;
-           tmp_list = tmp_list->next;
-
-           if (filter->type == message_type)
-             {
-               result = (*filter->function) (xevent, event, filter->data);
-               if (result != GDK_FILTER_CONTINUE)
-                 break;
-             }
-         }
-
-       switch (result)
-         {
-         case GDK_FILTER_REMOVE:
-           return_val = FALSE;
-           break;
-         case GDK_FILTER_TRANSLATE:
-           return_val = TRUE;
-           break;
-         case GDK_FILTER_CONTINUE:
-           /* Send unknown ClientMessage's on to Gtk for it to use */
-            if (window == NULL)
-              {
-                return_val = FALSE;
-              }
-            else
-              {
-                event->client.type = GDK_CLIENT_EVENT;
-                event->client.window = window;
-                event->client.message_type = message_type;
-                event->client.data_format = xevent->xclient.format;
-                memcpy(&event->client.data, &xevent->xclient.data,
-                       sizeof(event->client.data));
-              }
-            break;
-          }
-      }
+      GDK_NOTE (EVENTS,
+                g_message ("client message:\twindow: %ld",
+                           xevent->xclient.window));
 
+      /* Not currently handled */
+      return_val = FALSE;
       break;
 
     case MappingNotify:
@@ -919,7 +959,11 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
          
          event->owner_change.type = GDK_OWNER_CHANGE;
          event->owner_change.window = window;
-         event->owner_change.owner = selection_notify->owner;
+          if (selection_notify->owner != None)
+            event->owner_change.owner = gdk_x11_window_foreign_new_for_display (display,
+                                                                                selection_notify->owner);
+          else
+            event->owner_change.owner = NULL;
          event->owner_change.reason = selection_notify->subtype;
          event->owner_change.selection = 
            gdk_x11_xatom_to_atom_for_display (display, 
@@ -1012,21 +1056,113 @@ gdk_display_x11_translate_event (GdkEventTranslator *translator,
   return return_val;
 }
 
-static GdkFilterReturn
-gdk_wm_protocols_filter (GdkXEvent *xev,
-                        GdkEvent  *event,
-                        gpointer data)
+static GdkFrameTimings *
+find_frame_timings (GdkFrameClock *clock,
+                    guint64        serial)
+{
+  GdkFrameHistory *history = gdk_frame_clock_get_history (clock);
+  gint64 start_frame, end_frame, i;
+
+  start_frame = gdk_frame_history_get_start (history);
+  end_frame = gdk_frame_history_get_frame_counter (history);
+  for (i = end_frame; i >= start_frame; i--)
+    {
+      GdkFrameTimings *timings = gdk_frame_history_get_timings (history, i);
+
+      if (gdk_frame_timings_get_cookie (timings) == serial)
+        return timings;
+    }
+
+  return NULL;
+}
+
+GdkFilterReturn
+_gdk_wm_protocols_filter (GdkXEvent *xev,
+                         GdkEvent  *event,
+                         gpointer   data)
 {
   XEvent *xevent = (XEvent *)xev;
   GdkWindow *win = event->any.window;
   GdkDisplay *display;
   Atom atom;
 
-  if (!win)
-      return GDK_FILTER_REMOVE;
+  if (!GDK_IS_X11_WINDOW (win))
+    return GDK_FILTER_CONTINUE;
+
+  if (xevent->type != ClientMessage)
+    return GDK_FILTER_CONTINUE;
 
   display = GDK_WINDOW_DISPLAY (win);
-  atom = (Atom)xevent->xclient.data.l[0];
+
+  /* This isn't actually WM_PROTOCOLS because that wouldn't leave enough space
+   * in the message for everything that gets stuffed in */
+  if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_FRAME_DRAWN"))
+    {
+      GdkWindowImplX11 *window_impl;
+      window_impl = GDK_WINDOW_IMPL_X11 (event->any.window->impl);
+      if (window_impl->toplevel)
+        {
+          guint32 d0 = xevent->xclient.data.l[0];
+          guint32 d1 = xevent->xclient.data.l[1];
+          guint32 d2 = xevent->xclient.data.l[2];
+          guint32 d3 = xevent->xclient.data.l[3];
+
+          guint64 serial = ((guint64)d0 << 32) | d1;
+
+          GdkFrameClock *clock = gdk_window_get_frame_clock (event->any.window);
+          GdkFrameTimings *timings = find_frame_timings (clock, serial);
+
+          if (timings)
+            gdk_frame_timings_set_drawn_time (timings, ((guint64)d2 << 32) | d3);
+
+          if (window_impl->toplevel->frame_pending)
+            {
+              window_impl->toplevel->frame_pending = FALSE;
+              gdk_frame_clock_thaw (clock);
+            }
+        }
+
+      return GDK_FILTER_REMOVE;
+    }
+
+  if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_FRAME_TIMINGS"))
+    {
+      GdkWindowImplX11 *window_impl;
+      window_impl = GDK_WINDOW_IMPL_X11 (event->any.window->impl);
+      if (window_impl->toplevel)
+        {
+          guint32 d0 = xevent->xclient.data.l[0];
+          guint32 d1 = xevent->xclient.data.l[1];
+          guint32 d2 = xevent->xclient.data.l[2];
+          guint32 d3 = xevent->xclient.data.l[3];
+
+          guint64 serial = ((guint64)d0 << 32) | d1;
+
+          GdkFrameClock *clock = gdk_window_get_frame_clock (event->any.window);
+          GdkFrameTimings *timings = find_frame_timings (clock, serial);
+
+          if (timings)
+            {
+              gint64 drawn_time = gdk_frame_timings_get_drawn_time (timings);
+              gint32 presentation_time_offset = (gint32)d2;
+              gint32 refresh_interval = d3;
+
+              if (drawn_time && presentation_time_offset)
+                gdk_frame_timings_set_presentation_time (timings,
+                                                         drawn_time + presentation_time_offset);
+
+              if (refresh_interval)
+                gdk_frame_timings_set_refresh_interval (timings, refresh_interval);
+
+              gdk_frame_timings_set_complete (timings, TRUE);
+            }
+        }
+    }
+
+  if (xevent->xclient.message_type != gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS"))
+    return GDK_FILTER_CONTINUE;
+
+  atom = (Atom) xevent->xclient.data.l[0];
 
   if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
     {
@@ -1053,12 +1189,17 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.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
        */
       if (toplevel && win->accept_focus)
-       _gdk_x11_set_input_focus_safe (display, toplevel->focus_window,
-                                      RevertToParent,
-                                      xevent->xclient.data.l[1]);
+        {
+          gdk_x11_display_error_trap_push (display);
+          XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
+                          toplevel->focus_window,
+                          RevertToParent,
+                          xevent->xclient.data.l[1]);
+          gdk_x11_display_error_trap_pop_ignored (display);
+       }
 
       return GDK_FILTER_REMOVE;
     }
@@ -1077,15 +1218,13 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
       return GDK_FILTER_REMOVE;
     }
   else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST") &&
-          GDK_DISPLAY_X11 (display)->use_sync)
+          GDK_X11_DISPLAY (display)->use_sync)
     {
       GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window);
       if (toplevel)
        {
 #ifdef HAVE_XSYNC
-         XSyncIntsToValue (&toplevel->pending_counter_value,
-                           xevent->xclient.data.l[2],
-                           xevent->xclient.data.l[3]);
+         toplevel->pending_counter_value = xevent->xclient.data.l[2] + ((gint64)xevent->xclient.data.l[3] << 32);
 #endif
        }
       return GDK_FILTER_REMOVE;
@@ -1097,10 +1236,10 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
 static void
 gdk_event_init (GdkDisplay *display)
 {
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   GdkDeviceManager *device_manager;
 
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
   display_x11->event_source = gdk_x11_event_source_new (display);
 
   gdk_x11_event_source_add_translator ((GdkEventSource *) display_x11->event_source,
@@ -1109,22 +1248,17 @@ gdk_event_init (GdkDisplay *display)
   device_manager = gdk_display_get_device_manager (display);
   gdk_x11_event_source_add_translator ((GdkEventSource *) display_x11->event_source,
                                         GDK_EVENT_TRANSLATOR (device_manager));
-
-  gdk_display_add_client_message_filter (display,
-                                         gdk_atom_intern_static_string ("WM_PROTOCOLS"),
-                                         gdk_wm_protocols_filter,
-                                         NULL);
 }
 
 static void
 gdk_x11_display_init_input (GdkDisplay *display)
 {
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   GdkDeviceManager *device_manager;
   GdkDevice *device;
   GList *list, *l;
 
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
   device_manager = gdk_display_get_device_manager (display);
 
   /* For backwards compatibility, just add
@@ -1152,7 +1286,7 @@ gdk_x11_display_init_input (GdkDisplay *display)
 
   for (l = list; l; l = l->next)
     {
-      device = list->data;
+      device = l->data;
 
       if (gdk_device_get_source (device) != GDK_SOURCE_MOUSE)
         continue;
@@ -1172,7 +1306,7 @@ static void
 set_sm_client_id (GdkDisplay  *display,
                   const gchar *sm_client_id)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
 
   if (gdk_display_is_closed (display))
     return;
@@ -1187,23 +1321,12 @@ set_sm_client_id (GdkDisplay  *display,
                      gdk_x11_get_xatom_by_name_for_display (display, "SM_CLIENT_ID"));
 }
 
-/**
- * gdk_display_open:
- * @display_name: the name of the display to open
- *
- * Opens a display.
- *
- * Return value: (transfer none): a #GdkDisplay, or %NULL if the display
- *               could not be opened.
- *
- * Since: 2.2
- */
 GdkDisplay *
 _gdk_x11_display_open (const gchar *display_name)
 {
   Display *xdisplay;
   GdkDisplay *display;
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   GdkWindowAttr attr;
   gint argc;
   gchar *argv[1];
@@ -1217,20 +1340,19 @@ _gdk_x11_display_open (const gchar *display_name)
   xdisplay = XOpenDisplay (display_name);
   if (!xdisplay)
     return NULL;
-  
-  display = g_object_new (GDK_TYPE_DISPLAY_X11, NULL);
-  display_x11 = GDK_DISPLAY_X11 (display);
+
+  display = g_object_new (GDK_TYPE_X11_DISPLAY, NULL);
+  display_x11 = GDK_X11_DISPLAY (display);
 
   display_x11->xdisplay = xdisplay;
 
-#ifdef HAVE_X11R6  
   /* Set up handlers for Xlib internal connections */
   XAddConnectionWatch (xdisplay, gdk_internal_connection_watch, NULL);
-#endif /* HAVE_X11R6 */
-  
+
   _gdk_x11_precache_atoms (display, precache_atoms, G_N_ELEMENTS (precache_atoms));
 
   /* RandR must be initialized before we initialize the screens */
+  display_x11->have_randr12 = FALSE;
   display_x11->have_randr13 = FALSE;
 #ifdef HAVE_RANDR
   if (XRRQueryExtension (display_x11->xdisplay,
@@ -1240,8 +1362,11 @@ _gdk_x11_display_open (const gchar *display_name)
 
       XRRQueryVersion (display_x11->xdisplay, &major, &minor);
 
-      if ((major == 1 && minor >= 3) || major > 1)
-         display_x11->have_randr13 = TRUE;
+      if ((major == 1 && minor >= 2) || major > 1) {
+         display_x11->have_randr12 = TRUE;
+         if (minor >= 3 || major > 1)
+             display_x11->have_randr13 = TRUE;
+      }
 
        gdk_x11_register_standard_event_type (display, display_x11->xrandr_event_base, RRNumberEvents);
   }
@@ -1273,7 +1398,7 @@ _gdk_x11_display_open (const gchar *display_name)
   attr.height = 10;
   attr.event_mask = 0;
 
-  display_x11->leader_gdk_window = gdk_window_new (GDK_SCREEN_X11 (display_x11->default_screen)->root_window, 
+  display_x11->leader_gdk_window = gdk_window_new (GDK_X11_SCREEN (display_x11->default_screen)->root_window, 
                                                   &attr, GDK_WA_X | GDK_WA_Y);
   (_gdk_x11_window_get_toplevel (display_x11->leader_gdk_window))->is_leader = TRUE;
 
@@ -1349,7 +1474,7 @@ _gdk_x11_display_open (const gchar *display_name)
 
     gdk_x11_display_error_trap_push (display);
     XQueryPointer (display_x11->xdisplay,
-                  GDK_SCREEN_X11 (display_x11->default_screen)->xroot_window,
+                  GDK_X11_SCREEN (display_x11->default_screen)->xroot_window,
                   &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
     if (G_UNLIKELY (gdk_x11_display_error_trap_pop (display) == BadWindow))
       {
@@ -1362,15 +1487,14 @@ _gdk_x11_display_open (const gchar *display_name)
     XSynchronize (display_x11->xdisplay, True);
 
   class_hint = XAllocClassHint();
-  class_hint->res_name = g_get_prgname ();
-
+  class_hint->res_name = (char *) g_get_prgname ();
   class_hint->res_class = (char *)gdk_get_program_class ();
 
   /* XmbSetWMProperties sets the RESOURCE_NAME environment variable
    * from argv[0], so we just synthesize an argument array here.
    */
   argc = 1;
-  argv[0] = g_get_prgname ();
+  argv[0] = (char *) g_get_prgname ();
 
   XmbSetWMProperties (display_x11->xdisplay,
                      display_x11->leader_window,
@@ -1416,7 +1540,7 @@ _gdk_x11_display_open (const gchar *display_name)
            XkbSelectEventDetails (display_x11->xdisplay,
                                   XkbUseCoreKbd, XkbStateNotify,
                                   XkbAllStateComponentsMask,
-                                   XkbGroupLockMask|XkbModifierLockMask);
+                                   XkbModifierStateMask|XkbGroupStateMask);
 
            XkbSetDetectableAutoRepeat (display_x11->xdisplay,
                                        True,
@@ -1447,18 +1571,15 @@ _gdk_x11_display_open (const gchar *display_name)
 #endif
 
   gdk_x11_display_init_input (display);
-  _gdk_x11_display_init_dnd (display);
 
   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
     _gdk_x11_screen_setup (display_x11->screens[i]);
 
   g_signal_emit_by_name (display, "opened");
-  g_signal_emit_by_name (gdk_display_manager_get (), "display-opened", display);
 
   return display;
 }
 
-#ifdef HAVE_X11R6
 /*
  * XLib internal connection handling
  */
@@ -1478,11 +1599,11 @@ process_internal_connection (GIOChannel  *gioc,
 {
   GdkInternalConnection *connection = (GdkInternalConnection *)data;
 
-  GDK_THREADS_ENTER ();
+  gdk_threads_enter ();
 
   XProcessInternalConnection ((Display*)connection->display, connection->fd);
 
-  GDK_THREADS_LEAVE ();
+  gdk_threads_leave ();
 
   return TRUE;
 }
@@ -1537,43 +1658,42 @@ gdk_internal_connection_watch (Display  *display,
   else
     gdk_remove_connection_handler ((GdkInternalConnection *)*watch_data);
 }
-#endif /* HAVE_X11R6 */
 
-static G_CONST_RETURN gchar *
+static const gchar *
 gdk_x11_display_get_name (GdkDisplay *display)
 {
-  return (gchar *) DisplayString (GDK_DISPLAY_X11 (display)->xdisplay);
+  return (gchar *) DisplayString (GDK_X11_DISPLAY (display)->xdisplay);
 }
 
 static gint
 gdk_x11_display_get_n_screens (GdkDisplay *display)
 {
-  return ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay);
+  return ScreenCount (GDK_X11_DISPLAY (display)->xdisplay);
 }
 
 static GdkScreen *
 gdk_x11_display_get_screen (GdkDisplay *display,
                            gint        screen_num)
 {
-  g_return_val_if_fail (ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay) > screen_num, NULL);
+  g_return_val_if_fail (ScreenCount (GDK_X11_DISPLAY (display)->xdisplay) > screen_num, NULL);
 
-  return GDK_DISPLAY_X11 (display)->screens[screen_num];
+  return GDK_X11_DISPLAY (display)->screens[screen_num];
 }
 
 static GdkScreen *
 gdk_x11_display_get_default_screen (GdkDisplay *display)
 {
-  return GDK_DISPLAY_X11 (display)->default_screen;
+  return GDK_X11_DISPLAY (display)->default_screen;
 }
 
 gboolean
 _gdk_x11_display_is_root_window (GdkDisplay *display,
                                 Window      xroot_window)
 {
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   gint i;
 
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
 
   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
     {
@@ -1588,6 +1708,19 @@ struct XPointerUngrabInfo {
   guint32 time;
 };
 
+static void
+device_grab_update_callback (GdkDisplay *display,
+                             gpointer    data,
+                             gulong      serial)
+{
+  GdkPointerWindowInfo *pointer_info;
+  GdkDevice *device = data;
+
+  pointer_info = _gdk_display_get_pointer_info (display, device);
+  _gdk_display_device_grab_update (display, device,
+                                   pointer_info->last_slave, serial);
+}
+
 #define XSERVER_TIME_IS_LATER(time1, time2)                        \
   ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
@@ -1599,9 +1732,7 @@ _gdk_x11_display_update_grab_info (GdkDisplay *display,
                                    gint        status)
 {
   if (status == GrabSuccess)
-    _gdk_x11_roundtrip_async (display,
-                              (GdkRoundTripCallback)_gdk_display_device_grab_update,
-                              device);
+    _gdk_x11_roundtrip_async (display, device_grab_update_callback, device);
 }
 
 void
@@ -1621,9 +1752,7 @@ _gdk_x11_display_update_grab_info_ungrab (GdkDisplay *display,
        !XSERVER_TIME_IS_LATER (grab->time, time)))
     {
       grab->serial_end = serial;
-      _gdk_x11_roundtrip_async (display,
-                                (GdkRoundTripCallback)_gdk_display_device_grab_update,
-                                device);
+      _gdk_x11_roundtrip_async (display, device_grab_update_callback, device);
     }
 }
 
@@ -1661,12 +1790,12 @@ gdk_x11_display_get_default_group (GdkDisplay *display)
 {
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
 
-  return GDK_DISPLAY_X11 (display)->leader_gdk_window;
+  return GDK_X11_DISPLAY (display)->leader_gdk_window;
 }
 
 /**
  * gdk_x11_display_grab:
- * @display: a #GdkDisplay 
+ * @display: (type GdkX11Display): a #GdkDisplay 
  * 
  * Call XGrabServer() on @display. 
  * To ungrab the display again, use gdk_x11_display_ungrab(). 
@@ -1678,11 +1807,11 @@ gdk_x11_display_get_default_group (GdkDisplay *display)
 void
 gdk_x11_display_grab (GdkDisplay *display)
 {
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   
   g_return_if_fail (GDK_IS_DISPLAY (display));
   
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
   
   if (display_x11->grab_count == 0)
     XGrabServer (display_x11->xdisplay);
@@ -1691,7 +1820,7 @@ gdk_x11_display_grab (GdkDisplay *display)
 
 /**
  * gdk_x11_display_ungrab:
- * @display: a #GdkDisplay
+ * @display: (type GdkX11Display): a #GdkDisplay
  * 
  * Ungrab @display after it has been grabbed with 
  * gdk_x11_display_grab(). 
@@ -1701,11 +1830,11 @@ gdk_x11_display_grab (GdkDisplay *display)
 void
 gdk_x11_display_ungrab (GdkDisplay *display)
 {
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   
   g_return_if_fail (GDK_IS_DISPLAY (display));
   
-  display_x11 = GDK_DISPLAY_X11 (display);;
+  display_x11 = GDK_X11_DISPLAY (display);;
   g_return_if_fail (display_x11->grab_count > 0);
   
   display_x11->grab_count--;
@@ -1717,10 +1846,10 @@ gdk_x11_display_ungrab (GdkDisplay *display)
 }
 
 static void
-gdk_display_x11_dispose (GObject *object)
+gdk_x11_display_dispose (GObject *object)
 {
-  GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
+  GdkDisplay *display = GDK_DISPLAY (object);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (object);
   gint           i;
 
   _gdk_x11_display_manager_remove_display (gdk_display_manager_get (), display);
@@ -1737,13 +1866,13 @@ gdk_display_x11_dispose (GObject *object)
       display_x11->event_source = NULL;
     }
 
-  G_OBJECT_CLASS (_gdk_display_x11_parent_class)->dispose (object);
+  G_OBJECT_CLASS (gdk_x11_display_parent_class)->dispose (object);
 }
 
 static void
-gdk_display_x11_finalize (GObject *object)
+gdk_x11_display_finalize (GObject *object)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (object);
   gint           i;
 
   /* Keymap */
@@ -1758,7 +1887,10 @@ gdk_display_x11_finalize (GObject *object)
       g_free (display_x11->motif_target_lists);
     }
 
-  _gdk_x11_cursor_display_finalize (GDK_DISPLAY_OBJECT(display_x11));
+  _gdk_x11_cursor_display_finalize (GDK_DISPLAY (display_x11));
+
+  /* Empty the event queue */
+  _gdk_x11_display_free_translate_queue (GDK_DISPLAY (display_x11));
 
   /* Atom Hashtable */
   g_hash_table_destroy (display_x11->atom_from_virtual);
@@ -1767,21 +1899,15 @@ gdk_display_x11_finalize (GObject *object)
   /* Leader Window */
   XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);
 
-  /* list of filters for client messages */
-  g_list_foreach (display_x11->client_filters, (GFunc) g_free, NULL);
-  g_list_free (display_x11->client_filters);
-
   /* List of event window extraction functions */
   g_slist_foreach (display_x11->event_types, (GFunc)g_free, NULL);
   g_slist_free (display_x11->event_types);
 
   /* input GdkDevice list */
-  g_list_foreach (display_x11->input_devices, (GFunc) g_object_unref, NULL);
-  g_list_free (display_x11->input_devices);
+  g_list_free_full (display_x11->input_devices, g_object_unref);
 
   /* input GdkWindow list */
-  g_list_foreach (display_x11->input_windows, (GFunc) g_free, NULL);
-  g_list_free (display_x11->input_windows);
+  g_list_free_full (display_x11->input_windows, g_free);
 
   /* Free all GdkScreens */
   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
@@ -1810,7 +1936,7 @@ gdk_display_x11_finalize (GObject *object)
       g_slice_free (GdkErrorTrap, trap);
     }
 
-  G_OBJECT_CLASS (_gdk_display_x11_parent_class)->finalize (object);
+  G_OBJECT_CLASS (gdk_x11_display_parent_class)->finalize (object);
 }
 
 /**
@@ -1855,7 +1981,8 @@ gdk_x11_lookup_xdisplay (Display *xdisplay)
  * Given the root window ID of one of the screen's of a #GdkDisplay,
  * finds the screen.
  * 
- * Return value: the #GdkScreen corresponding to @xrootwin, or %NULL.
+ * Return value: (transfer none): the #GdkScreen corresponding to
+ *     @xrootwin, or %NULL.
  **/
 GdkScreen *
 _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
@@ -1863,7 +1990,7 @@ _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
 {
   gint i;
 
-  for (i = 0; i < ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay); i++)
+  for (i = 0; i < ScreenCount (GDK_X11_DISPLAY (display)->xdisplay); i++)
     {
       GdkScreen *screen = gdk_display_get_screen (display, i);
       if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
@@ -1875,24 +2002,25 @@ _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
 
 /**
  * gdk_x11_display_get_xdisplay:
- * @display: a #GdkDisplay
- * @returns: an X display.
+ * @display: (type GdkX11Display): a #GdkDisplay
  *
  * Returns the X display of a #GdkDisplay.
  *
+ * Returns: (transfer none): an X display
+ *
  * Since: 2.2
  */
 Display *
 gdk_x11_display_get_xdisplay (GdkDisplay *display)
 {
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-  return GDK_DISPLAY_X11 (display)->xdisplay;
+  return GDK_X11_DISPLAY (display)->xdisplay;
 }
 
 void
 _gdk_x11_display_make_default (GdkDisplay *display)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
   const gchar *startup_id;
 
   g_free (display_x11->startup_notification_id);
@@ -1928,7 +2056,7 @@ broadcast_xmessage (GdkDisplay *display,
   Atom type_atom_begin;
   Window xwindow;
 
-  if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
+  if (!G_LIKELY (GDK_X11_DISPLAY (display)->trusted_client))
     return;
 
   {
@@ -2006,7 +2134,7 @@ broadcast_xmessage (GdkDisplay *display,
 
 /**
  * gdk_x11_display_broadcast_startup_message:
- * @display: a #GdkDisplay
+ * @display: (type GdkX11Display): a #GdkDisplay
  * @message_type: startup notification message type ("new", "change",
  * or "remove")
  * @...: a list of key/value pairs (as strings), terminated by a
@@ -2076,7 +2204,7 @@ gdk_x11_display_notify_startup_complete (GdkDisplay  *display,
 {
   if (startup_id == NULL)
     {
-      startup_id = GDK_DISPLAY_X11 (display)->startup_notification_id;
+      startup_id = GDK_X11_DISPLAY (display)->startup_notification_id;
       if (startup_id == NULL)
         return;
     }
@@ -2089,7 +2217,7 @@ gdk_x11_display_notify_startup_complete (GdkDisplay  *display,
 static gboolean
 gdk_x11_display_supports_selection_notification (GdkDisplay *display)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
 
   return display_x11->have_xfixes;
 }
@@ -2100,7 +2228,7 @@ gdk_x11_display_request_selection_notification (GdkDisplay *display,
 
 {
 #ifdef HAVE_XFIXES
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
   Atom atom;
 
   if (display_x11->have_xfixes)
@@ -2127,7 +2255,7 @@ gdk_x11_display_supports_clipboard_persistence (GdkDisplay *display)
 
   /* It might make sense to cache this */
   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
-  return XGetSelectionOwner (GDK_DISPLAY_X11 (display)->xdisplay, clipboard_manager) != None;
+  return XGetSelectionOwner (GDK_X11_DISPLAY (display)->xdisplay, clipboard_manager) != None;
 }
 
 static void
@@ -2137,7 +2265,7 @@ gdk_x11_display_store_clipboard (GdkDisplay    *display,
                                 const GdkAtom *targets,
                                 gint           n_targets)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
   Atom clipboard_manager, save_targets;
 
   g_return_if_fail (GDK_WINDOW_IS_X11 (clipboard_window));
@@ -2179,7 +2307,7 @@ gdk_x11_display_store_clipboard (GdkDisplay    *display,
 
 /**
  * gdk_x11_display_get_user_time:
- * @display: a #GdkDisplay
+ * @display: (type GdkX11Display): a #GdkDisplay
  *
  * Returns the timestamp of the last user interaction on 
  * @display. The timestamp is taken from events caused
@@ -2193,25 +2321,25 @@ gdk_x11_display_store_clipboard (GdkDisplay    *display,
 guint32
 gdk_x11_display_get_user_time (GdkDisplay *display)
 {
-  return GDK_DISPLAY_X11 (display)->user_time;
+  return GDK_X11_DISPLAY (display)->user_time;
 }
 
 static gboolean
 gdk_x11_display_supports_shapes (GdkDisplay *display)
 {
-  return GDK_DISPLAY_X11 (display)->have_shapes;
+  return GDK_X11_DISPLAY (display)->have_shapes;
 }
 
 static gboolean
 gdk_x11_display_supports_input_shapes (GdkDisplay *display)
 {
-  return GDK_DISPLAY_X11 (display)->have_input_shapes;
+  return GDK_X11_DISPLAY (display)->have_input_shapes;
 }
 
 
 /**
  * gdk_x11_display_get_startup_notification_id:
- * @display: a #GdkDisplay
+ * @display: (type GdkX11Display): a #GdkDisplay
  *
  * Gets the startup notification ID for a display.
  * 
@@ -2219,15 +2347,15 @@ gdk_x11_display_supports_input_shapes (GdkDisplay *display)
  *
  * Since: 2.12
  */
-G_CONST_RETURN gchar *
+const gchar *
 gdk_x11_display_get_startup_notification_id (GdkDisplay *display)
 {
-  return GDK_DISPLAY_X11 (display)->startup_notification_id;
+  return GDK_X11_DISPLAY (display)->startup_notification_id;
 }
 
 /**
  * gdk_x11_display_set_startup_notification_id:
- * @display: a #GdkDisplay
+ * @display: (type GdkX11Display): a #GdkDisplay
  * @startup_id: the startup notification ID (must be valid utf8)
  *
  * Sets the startup notification ID for a display.
@@ -2251,10 +2379,10 @@ void
 gdk_x11_display_set_startup_notification_id (GdkDisplay  *display,
                                              const gchar *startup_id)
 {
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   gchar *time_str;
 
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
 
   g_free (display_x11->startup_notification_id);
   display_x11->startup_notification_id = g_strdup (startup_id);
@@ -2291,7 +2419,7 @@ gdk_x11_display_set_startup_notification_id (GdkDisplay  *display,
 static gboolean
 gdk_x11_display_supports_composite (GdkDisplay *display)
 {
-  GdkDisplayX11 *x11_display = GDK_DISPLAY_X11 (display);
+  GdkX11Display *x11_display = GDK_X11_DISPLAY (display);
 
   return x11_display->have_xcomposite &&
         x11_display->have_xdamage &&
@@ -2303,46 +2431,7 @@ gdk_x11_display_list_devices (GdkDisplay *display)
 {
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
 
-  return GDK_DISPLAY_X11 (display)->input_devices;
-}
-
-static gboolean
-gdk_x11_display_send_client_message (GdkDisplay     *display,
-                                    GdkEvent       *event,
-                                    GdkNativeWindow winid)
-{
-  XEvent sev;
-
-  g_return_val_if_fail(event != NULL, FALSE);
-
-  /* Set up our event to send, with the exception of its target window */
-  sev.xclient.type = ClientMessage;
-  sev.xclient.display = GDK_DISPLAY_XDISPLAY (display);
-  sev.xclient.format = event->client.data_format;
-  sev.xclient.window = winid;
-  memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data));
-  sev.xclient.message_type = gdk_x11_atom_to_xatom_for_display (display, event->client.message_type);
-
-  return _gdk_x11_display_send_xevent (display, winid, False, NoEventMask, &sev);
-}
-
-static void
-gdk_x11_display_add_client_message_filter (GdkDisplay   *display,
-                                          GdkAtom       message_type,
-                                          GdkFilterFunc func,
-                                          gpointer      data)
-{
-  GdkClientFilter *filter;
-  g_return_if_fail (GDK_IS_DISPLAY (display));
-  filter = g_new (GdkClientFilter, 1);
-
-  filter->type = message_type;
-  filter->function = func;
-  filter->data = data;
-
-  GDK_DISPLAY_X11(display)->client_filters =
-    g_list_append (GDK_DISPLAY_X11 (display)->client_filters,
-                  filter);
+  return GDK_X11_DISPLAY (display)->input_devices;
 }
 
 /**
@@ -2372,9 +2461,9 @@ gdk_x11_register_standard_event_type (GdkDisplay *display,
                                      gint        n_events)
 {
   GdkEventTypeX11 *event_type;
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
 
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
   event_type = g_new (GdkEventTypeX11, 1);
 
   event_type->base = event_base;
@@ -2391,11 +2480,11 @@ void
 _gdk_x11_display_error_event (GdkDisplay  *display,
                               XErrorEvent *error)
 {
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   GSList *tmp_list;
   gboolean ignore;
 
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
 
   ignore = FALSE;
   for (tmp_list = display_x11->error_traps;
@@ -2430,8 +2519,8 @@ _gdk_x11_display_error_event (GdkDisplay  *display,
                          "  (Details: serial %ld error_code %d request_code %d minor_code %d)\n"
                          "  (Note to programmers: normally, X errors are reported asynchronously;\n"
                          "   that is, you will receive the error a while after causing it.\n"
-                         "   To debug your program, run it with the --sync command line\n"
-                         "   option to change this behavior. You can then get a meaningful\n"
+                         "   To debug your program, run it with the GDK_SYNCHRONIZE environment\n"
+                         "   variable to change this behavior. You can then get a meaningful\n"
                          "   backtrace from your debugger if you break on the gdk_x_error() function.)",
                          g_get_prgname (),
                          buf,
@@ -2445,13 +2534,13 @@ _gdk_x11_display_error_event (GdkDisplay  *display,
 #else /* !G_ENABLE_DEBUG */
       g_warning ("%s\n", msg);
 
-      exit (1);
+      _exit (1);
 #endif /* G_ENABLE_DEBUG */
     }
 }
 
 static void
-delete_outdated_error_traps (GdkDisplayX11 *display_x11)
+delete_outdated_error_traps (GdkX11Display *display_x11)
 {
   GSList *tmp_list;
   gulong processed_sequence;
@@ -2482,7 +2571,7 @@ delete_outdated_error_traps (GdkDisplayX11 *display_x11)
 
 /**
  * gdk_x11_display_error_trap_push:
- * @display: a #GdkDisplay
+ * @display: (type GdkX11Display): a #GdkDisplay
  *
  * Begins a range of X requests on @display for which X error events
  * will be ignored. Unignored errors (when no trap is pushed) will abort
@@ -2497,10 +2586,10 @@ delete_outdated_error_traps (GdkDisplayX11 *display_x11)
 void
 gdk_x11_display_error_trap_push (GdkDisplay *display)
 {
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   GdkErrorTrap *trap;
 
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
 
   delete_outdated_error_traps (display_x11);
 
@@ -2520,12 +2609,12 @@ static gint
 gdk_x11_display_error_trap_pop_internal (GdkDisplay *display,
                                          gboolean    need_code)
 {
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   GdkErrorTrap *trap;
   GSList *tmp_list;
   int result;
 
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
 
   g_return_val_if_fail (display_x11->error_traps != NULL, Success);
 
@@ -2587,7 +2676,7 @@ gdk_x11_display_error_trap_pop_internal (GdkDisplay *display,
 
 /**
  * gdk_x11_display_error_trap_pop:
- * @display: the display
+ * @display: (type GdkX11Display): the display
  *
  * Pops the error trap pushed by gdk_x11_display_error_trap_push().
  * Will XSync() if necessary and will always block until
@@ -2607,14 +2696,14 @@ gdk_x11_display_error_trap_pop_internal (GdkDisplay *display,
 gint
 gdk_x11_display_error_trap_pop (GdkDisplay *display)
 {
-  g_return_val_if_fail (GDK_IS_DISPLAY_X11 (display), Success);
+  g_return_val_if_fail (GDK_IS_X11_DISPLAY (display), Success);
 
   return gdk_x11_display_error_trap_pop_internal (display, TRUE);
 }
 
 /**
  * gdk_x11_display_error_trap_pop_ignored:
- * @display: the display
+ * @display: (type GdkX11Display): the display
  *
  * Pops the error trap pushed by gdk_x11_display_error_trap_push().
  * Does not block to see if an error occurred; merely records the
@@ -2629,18 +2718,11 @@ gdk_x11_display_error_trap_pop (GdkDisplay *display)
 void
 gdk_x11_display_error_trap_pop_ignored (GdkDisplay *display)
 {
-  g_return_if_fail (GDK_IS_DISPLAY_X11 (display));
+  g_return_if_fail (GDK_IS_X11_DISPLAY (display));
 
   gdk_x11_display_error_trap_pop_internal (display, FALSE);
 }
 
-extern GdkAppLaunchContext *_gdk_x11_display_get_app_launch_context (GdkDisplay *display);
-extern GdkNativeWindow      _gdk_x11_display_get_drag_protocol      (GdkDisplay *display,
-                                                                     GdkNativeWindow  xid,
-                                                                     GdkDragProtocol *protocol,
-                                                                     guint           *version);
-
-
 /**
  * gdk_x11_set_sm_client_id:
  * @sm_client_id: the client id assigned by the session manager when the
@@ -2701,12 +2783,12 @@ pop_error_trap (GdkDisplay *display,
 static GdkKeymap *
 gdk_x11_display_get_keymap (GdkDisplay *display)
 {
-  GdkDisplayX11 *display_x11;
+  GdkX11Display *display_x11;
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-  display_x11 = GDK_DISPLAY_X11 (display);
+  display_x11 = GDK_X11_DISPLAY (display);
 
   if (!display_x11->keymap)
-    display_x11->keymap = g_object_new (_gdk_keymap_x11_get_type (), NULL);
+    display_x11->keymap = g_object_new (GDK_TYPE_X11_KEYMAP, NULL);
 
   display_x11->keymap->display = display;
 
@@ -2714,13 +2796,15 @@ gdk_x11_display_get_keymap (GdkDisplay *display)
 }
 
 static void
-_gdk_display_x11_class_init (GdkDisplayX11Class * class)
+gdk_x11_display_class_init (GdkX11DisplayClass * class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
   GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (class);
 
-  object_class->dispose = gdk_display_x11_dispose;
-  object_class->finalize = gdk_display_x11_finalize;
+  object_class->dispose = gdk_x11_display_dispose;
+  object_class->finalize = gdk_x11_display_finalize;
+
+  display_class->window_type = GDK_TYPE_X11_WINDOW;
 
   display_class->get_name = gdk_x11_display_get_name;
   display_class->get_n_screens = gdk_x11_display_get_n_screens;
@@ -2740,10 +2824,7 @@ _gdk_display_x11_class_init (GdkDisplayX11Class * class)
   display_class->supports_input_shapes = gdk_x11_display_supports_input_shapes;
   display_class->supports_composite = gdk_x11_display_supports_composite;
   display_class->list_devices = gdk_x11_display_list_devices;
-  display_class->send_client_message = gdk_x11_display_send_client_message;
-  display_class->add_client_message_filter = gdk_x11_display_add_client_message_filter;
   display_class->get_app_launch_context = _gdk_x11_display_get_app_launch_context;
-  display_class->get_drag_protocol = _gdk_x11_display_get_drag_protocol;
   display_class->get_cursor_for_type = _gdk_x11_display_get_cursor_for_type;
   display_class->get_cursor_for_name = _gdk_x11_display_get_cursor_for_name;
   display_class->get_cursor_for_pixbuf = _gdk_x11_display_get_cursor_for_pixbuf;