]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkevents-x11.c
Various cleanups. (#315359, Kjartan Maraas)
[~andy/gtk] / gdk / x11 / gdkevents-x11.c
index 4e3db600cb1d6a86e6408cbe0fe4751145a071d6..d2e6a0d7c33ec7786c68a20506a7b83854946d35 100644 (file)
@@ -24,6 +24,8 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <config.h>
+
 #include "gdk.h"
 #include "gdkprivate-x11.h"
 #include "gdkinternals.h"
 
 #include "xsettings-client.h"
 
-#if HAVE_CONFIG_H
-#  include <config.h>
-#  if STDC_HEADERS
-#    include <string.h>
-#  endif
-#endif
+#include <string.h>
 
 #include "gdkinputprivate.h"
 
+#include "gdkalias.h"
+
 #ifdef HAVE_XKB
 #include <X11/XKBlib.h>
 #endif
 
+#ifdef HAVE_XSYNC
+#include <X11/extensions/sync.h>
+#endif
+
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+
 #include <X11/Xatom.h>
 
 typedef struct _GdkIOClosure GdkIOClosure;
 typedef struct _GdkDisplaySource GdkDisplaySource;
-
-#define DOUBLE_CLICK_TIME      250
-#define TRIPLE_CLICK_TIME      500
-#define DOUBLE_CLICK_DIST      5
-#define TRIPLE_CLICK_DIST      5
+typedef struct _GdkEventTypeX11 GdkEventTypeX11;
 
 struct _GdkIOClosure
 {
@@ -75,6 +78,12 @@ struct _GdkDisplaySource
   GPollFD event_poll_fd;
 };
 
+struct _GdkEventTypeX11
+{
+  gint base;
+  gint n_events;
+};
+
 /* 
  * Private function declarations
  */
@@ -143,6 +152,22 @@ gdk_check_xpending (GdkDisplay *display)
  * Functions for maintaining the event queue *
  *********************************************/
 
+static void
+refcounted_grab_server (Display *xdisplay)
+{
+  GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
+
+  gdk_x11_display_grab (display);
+}
+
+static void
+refcounted_ungrab_server (Display *xdisplay)
+{
+  GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
+  
+  gdk_x11_display_ungrab (display);
+}
+
 void
 _gdk_x11_events_init_screen (GdkScreen *screen)
 {
@@ -156,6 +181,10 @@ _gdk_x11_events_init_screen (GdkScreen *screen)
                                                       gdk_xsettings_notify_cb,
                                                       gdk_xsettings_watch_cb,
                                                       screen);
+  xsettings_client_set_grab_func (screen_x11->xsettings_client,
+                                 refcounted_grab_server);
+  xsettings_client_set_ungrab_func (screen_x11->xsettings_client,
+                                   refcounted_ungrab_server);
   screen_x11->xsettings_in_init = FALSE;
 }
 
@@ -192,11 +221,10 @@ _gdk_events_init (GdkDisplay *display)
 
   display_sources = g_list_prepend (display_sources,display_source);
 
-  gdk_display_add_client_message_filter (
-       display,
-       gdk_atom_intern ("WM_PROTOCOLS", FALSE), 
-       gdk_wm_protocols_filter,   
-       NULL);
+  gdk_display_add_client_message_filter (display,
+                                        gdk_atom_intern_static_string ("WM_PROTOCOLS"), 
+                                        gdk_wm_protocols_filter,   
+                                        NULL);
 }
 
 
@@ -333,8 +361,8 @@ gdk_display_add_client_message_filter (GdkDisplay   *display,
   filter->data = data;
   
   GDK_DISPLAY_X11(display)->client_filters = 
-    g_list_prepend (GDK_DISPLAY_X11 (display)->client_filters,
-                   filter);
+    g_list_append (GDK_DISPLAY_X11 (display)->client_filters,
+                  filter);
 }
 
 /**
@@ -359,9 +387,8 @@ gdk_add_client_message_filter (GdkAtom       message_type,
 
 static void
 do_net_wm_state_changes (GdkWindow *window)
-{  
-  GdkWindowObject *window_private = (GdkWindowObject *)window;
-  GdkWindowImplX11 *window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
+{
+  GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
   GdkWindowState old_state;
   
   if (GDK_WINDOW_DESTROYED (window) ||
@@ -375,14 +402,14 @@ do_net_wm_state_changes (GdkWindow *window)
    */
   if (old_state & GDK_WINDOW_STATE_STICKY)
     {
-      if (!(window_impl->have_sticky && window_impl->on_all_desktops))
+      if (!(toplevel->have_sticky && toplevel->on_all_desktops))
         gdk_synthesize_window_state (window,
                                      GDK_WINDOW_STATE_STICKY,
                                      0);
     }
   else
     {
-      if (window_impl->have_sticky && window_impl->on_all_desktops)
+      if (toplevel->have_sticky || toplevel->on_all_desktops)
         gdk_synthesize_window_state (window,
                                      0,
                                      GDK_WINDOW_STATE_STICKY);
@@ -390,14 +417,14 @@ do_net_wm_state_changes (GdkWindow *window)
 
   if (old_state & GDK_WINDOW_STATE_FULLSCREEN)
     {
-      if (!window_impl->have_fullscreen)
+      if (!toplevel->have_fullscreen)
         gdk_synthesize_window_state (window,
                                      GDK_WINDOW_STATE_FULLSCREEN,
                                      0);
     }
   else
     {
-      if (window_impl->have_fullscreen)
+      if (toplevel->have_fullscreen)
         gdk_synthesize_window_state (window,
                                      0,
                                      GDK_WINDOW_STATE_FULLSCREEN);
@@ -408,14 +435,14 @@ do_net_wm_state_changes (GdkWindow *window)
    */
   if (old_state & GDK_WINDOW_STATE_MAXIMIZED)
     {
-      if (!(window_impl->have_maxvert && window_impl->have_maxhorz))
+      if (!(toplevel->have_maxvert && toplevel->have_maxhorz))
         gdk_synthesize_window_state (window,
                                      GDK_WINDOW_STATE_MAXIMIZED,
                                      0);
     }
   else
     {
-      if (window_impl->have_maxvert && window_impl->have_maxhorz)
+      if (toplevel->have_maxvert && toplevel->have_maxhorz)
         gdk_synthesize_window_state (window,
                                      0,
                                      GDK_WINDOW_STATE_MAXIMIZED);
@@ -425,58 +452,66 @@ do_net_wm_state_changes (GdkWindow *window)
 static void
 gdk_check_wm_desktop_changed (GdkWindow *window)
 {
-  GdkWindowObject *window_private = (GdkWindowObject *)window;
-  GdkWindowImplX11 *window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
+  GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
 
   Atom type;
   gint format;
   gulong nitems;
   gulong bytes_after;
+  guchar *data;
+  gulong *desktop;
 
-  if (window_impl->have_sticky)
-    {
-      gulong *desktop;
-      
-      XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), 
-                         GDK_WINDOW_XID (window),
-                          gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
-                         0, G_MAXLONG, False, XA_CARDINAL, &type, 
-                         &format, &nitems,
-                          &bytes_after, (guchar **)&desktop);
+  type = None;
+  gdk_error_trap_push ();
+  XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), 
+                      GDK_WINDOW_XID (window),
+                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
+                      0, G_MAXLONG, False, XA_CARDINAL, &type, 
+                      &format, &nitems,
+                      &bytes_after, &data);
+  gdk_error_trap_pop ();
 
-      if (type != None)
-        {
-          window_impl->on_all_desktops = (*desktop == 0xFFFFFFFF);
-          XFree (desktop);
-        }
-      else
-       window_impl->on_all_desktops = FALSE;
-      
-      do_net_wm_state_changes (window);
+  if (type != None)
+    {
+      desktop = (gulong *)data;
+      toplevel->on_all_desktops = (*desktop == 0xFFFFFFFF);
+      XFree (desktop);
     }
+  else
+    toplevel->on_all_desktops = FALSE;
+      
+  do_net_wm_state_changes (window);
 }
 
 static void
 gdk_check_wm_state_changed (GdkWindow *window)
 {
-  GdkWindowObject *window_private = (GdkWindowObject *)window;
-  GdkWindowImplX11 *window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
+  GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
   
   Atom type;
   gint format;
   gulong nitems;
   gulong bytes_after;
+  guchar *data;
   Atom *atoms = NULL;
   gulong i;
 
-  gboolean had_sticky = window_impl->have_sticky;
+  gboolean had_sticky = toplevel->have_sticky;
+
+  toplevel->have_sticky = FALSE;
+  toplevel->have_maxvert = FALSE;
+  toplevel->have_maxhorz = FALSE;
+  toplevel->have_fullscreen = FALSE;
 
+  type = None;
+  gdk_error_trap_push ();
   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
                      0, G_MAXLONG, False, XA_ATOM, &type, &format, &nitems,
-                     &bytes_after, (guchar **)&atoms);
+                     &bytes_after, &data);
+  gdk_error_trap_pop ();
 
   if (type != None)
     {
@@ -484,18 +519,20 @@ 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");
-      
+
+      atoms = (Atom *)data;
+
       i = 0;
       while (i < nitems)
         {
           if (atoms[i] == sticky_atom)
-            window_impl->have_sticky = TRUE;
+            toplevel->have_sticky = TRUE;
           else if (atoms[i] == maxvert_atom)
-            window_impl->have_maxvert = TRUE;
+            toplevel->have_maxvert = TRUE;
           else if (atoms[i] == maxhorz_atom)
-            window_impl->have_maxhorz = TRUE;
+            toplevel->have_maxhorz = TRUE;
           else if (atoms[i] == fullscreen_atom)
-            window_impl->have_fullscreen = TRUE;
+            toplevel->have_fullscreen = TRUE;
           
           ++i;
         }
@@ -506,14 +543,14 @@ gdk_check_wm_state_changed (GdkWindow *window)
   /* When have_sticky is turned on, we have to check the DESKTOP property
    * as well.
    */
-  if (window_impl->have_sticky && !had_sticky)
+  if (toplevel->have_sticky && !had_sticky)
     gdk_check_wm_desktop_changed (window);
   else
     do_net_wm_state_changes (window);
 }
 
-#define HAS_FOCUS(window_impl)                           \
-  ((window_impl)->has_focus || (window_impl)->has_pointer_focus)
+#define HAS_FOCUS(toplevel)                           \
+  ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
 
 static void
 generate_focus_event (GdkWindow *window,
@@ -529,7 +566,7 @@ generate_focus_event (GdkWindow *window,
   gdk_event_put (&event);
 }
 
-static void
+static gboolean
 set_screen_from_root (GdkDisplay *display,
                      GdkEvent   *event,
                      Window      xrootwin)
@@ -537,9 +574,15 @@ set_screen_from_root (GdkDisplay *display,
   GdkScreen *screen;
 
   screen = _gdk_x11_display_screen_for_xrootwin (display, xrootwin);
-  g_assert (screen);
 
-  gdk_event_set_screen (event, screen);
+  if (screen)
+    {
+      gdk_event_set_screen (event, screen);
+
+      return TRUE;
+    }
+  
+  return FALSE;
 }
 
 static void
@@ -549,7 +592,7 @@ translate_key_event (GdkDisplay *display,
 {
   GdkKeymap *keymap = gdk_keymap_get_for_display (display);
   gunichar c = 0;
-  guchar buf[7];
+  gchar buf[7];
 
   event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
   event->key.time = xevent->xkey.time;
@@ -567,6 +610,9 @@ translate_key_event (GdkDisplay *display,
                                       &event->key.keyval,
                                       NULL, NULL, NULL);
 
+  _gdk_keymap_add_virtual_modifiers (keymap, &event->key.state);
+  event->key.is_modifier = _gdk_keymap_key_is_modifier (keymap, event->key.hardware_keycode);
+
   /* Fill in event->string crudely, since various programs
    * depend on it.
    */
@@ -642,62 +688,134 @@ translate_key_event (GdkDisplay *display,
   return;
 }
 
-/* Return the window this has to do with, if any, rather
- * than the frame or root window that was selecting
- * for substructure
- */
-static Window
-get_real_window (XEvent *event)
+/**
+ * gdk_x11_register_standard_event_type:
+ * @display: a #GdkDisplay
+ * @event_base: first event type code to register
+ * @n_events: number of event type codes to register
+ * 
+ * Registers interest in receiving extension events with type codes
+ * between @event_base and <literal>event_base + n_events - 1</literal>.
+ * The registered events must have the window field in the same place
+ * as core X events (this is not the case for e.g. XKB extension events).
+ *
+ * If an event type is registered, events of this type will go through
+ * global and window-specific filters (see gdk_window_add_filter()). 
+ * Unregistered events will only go through global filters.
+ * GDK may register the events of some X extensions on its own.
+ * 
+ * This function should only be needed in unusual circumstances, e.g.
+ * when filtering XInput extension events on the root window.
+ *
+ * Since: 2.4
+ **/
+void
+gdk_x11_register_standard_event_type (GdkDisplay          *display,
+                                     gint                 event_base,
+                                     gint                 n_events)
 {
-  switch (event->type)
-    {      
-    case CreateNotify:
-      return event->xcreatewindow.window;
-      
-    case DestroyNotify:
-      return event->xdestroywindow.window;
-
-    case UnmapNotify:
-      return event->xunmap.window;
+  GdkEventTypeX11 *event_type;
+  GdkDisplayX11 *display_x11;
 
-    case MapNotify:
-      return event->xmap.window;
+  display_x11 = GDK_DISPLAY_X11 (display);
+  event_type = g_new (GdkEventTypeX11, 1);
 
-    case MapRequest:
-      return event->xmaprequest.window;
+  event_type->base = event_base;
+  event_type->n_events = n_events;
 
-    case ReparentNotify:
-     return event->xreparent.window;
-      
-    case ConfigureNotify:
-      return event->xconfigure.window;
-      
-    case ConfigureRequest:
-      return event->xconfigurerequest.window;
-
-    case GravityNotify:
-      return event->xgravity.window;
+  display_x11->event_types = g_slist_prepend (display_x11->event_types, event_type);
+}
 
-    case CirculateNotify:
-      return event->xcirculate.window;
+/* Return the window this has to do with, if any, rather
+ * than the frame or root window that was selecting
+ * for substructure
+ */
+static void
+get_real_window (GdkDisplay *display,
+                XEvent     *event,
+                Window     *event_window,
+                Window     *filter_window)
+{
+  /* Core events all have an event->xany.window field, but that's
+   * not true for extension events
+   */
+  if (event->type >= KeyPress &&
+      event->type <= MappingNotify)
+    {
+      *filter_window = event->xany.window;
+      switch (event->type)
+       {      
+       case CreateNotify:
+         *event_window = event->xcreatewindow.window;
+         break;
+       case DestroyNotify:
+         *event_window = event->xdestroywindow.window;
+         break;
+       case UnmapNotify:
+         *event_window = event->xunmap.window;
+         break;
+       case MapNotify:
+         *event_window = event->xmap.window;
+         break;
+       case MapRequest:
+         *event_window = event->xmaprequest.window;
+         break;
+       case ReparentNotify:
+         *event_window = event->xreparent.window;
+         break;
+       case ConfigureNotify:
+         *event_window = event->xconfigure.window;
+         break;
+       case ConfigureRequest:
+         *event_window = event->xconfigurerequest.window;
+         break;
+       case GravityNotify:
+         *event_window = event->xgravity.window;
+         break;
+       case CirculateNotify:
+         *event_window = event->xcirculate.window;
+         break;
+       case CirculateRequest:
+         *event_window = event->xcirculaterequest.window;
+         break;
+       default:
+         *event_window = event->xany.window;
+       }
+    }
+  else
+    {
+      GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+      GSList *tmp_list;
 
-    case CirculateRequest:
-      return event->xcirculaterequest.window;
+      for (tmp_list = display_x11->event_types;
+          tmp_list;
+          tmp_list = tmp_list->next)
+       {
+         GdkEventTypeX11 *event_type = tmp_list->data;
 
-    default:
-      return event->xany.window;
+         if (event->type >= event_type->base &&
+             event->type < event_type->base + event_type->n_events)
+           {
+             *event_window = event->xany.window;
+             *filter_window = event->xany.window;
+             return;
+           }
+       }
+          
+      *event_window = None;
+      *filter_window = None;
     }
 }
 
 #ifdef G_ENABLE_DEBUG
-static const char notify_modes[][18] = {
+static const char notify_modes[][19] = {
   "NotifyNormal",
   "NotifyGrab",
   "NotifyUngrab",
   "NotifyWhileGrabbed"
 };
 
-static const char notify_details[][22] = {
+static const char notify_details[][23] = {
   "NotifyAncestor",
   "NotifyVirtual",
   "NotifyInferior",
@@ -709,6 +827,23 @@ static const char notify_details[][22] = {
 };
 #endif
 
+static void
+set_user_time (GdkWindow *window,
+              GdkEvent  *event)
+{
+  g_return_if_fail (event != NULL);
+
+  window = gdk_window_get_toplevel (event->client.window);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  /* If an event doesn't have a valid timestamp, we shouldn't use it
+   * to update the latest user interaction time.
+   */
+  if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
+    gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+                                  gdk_event_get_time (event));
+}
+
 static gboolean
 gdk_event_translate (GdkDisplay *display,
                     GdkEvent   *event,
@@ -724,8 +859,9 @@ gdk_event_translate (GdkDisplay *display,
   gint xoffset, yoffset;
   GdkScreen *screen = NULL;
   GdkScreenX11 *screen_x11 = NULL;
+  GdkToplevelX11 *toplevel = NULL;
   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
-  Window xwindow;
+  Window xwindow, filter_xwindow;
   
   return_val = FALSE;
 
@@ -752,53 +888,55 @@ gdk_event_translate (GdkDisplay *display,
    * Basically this means substructure events
    * are reported same as structure events
    */
-  xwindow = get_real_window (xevent);
+  get_real_window (display, xevent, &xwindow, &filter_xwindow);
   
   window = gdk_window_lookup_for_display (display, xwindow);
+  /* We may receive events such as NoExpose/GraphicsExpose
+   * and ShmCompletion for pixmaps
+   */
+  if (window && !GDK_IS_WINDOW (window))
+    window = NULL;
   window_private = (GdkWindowObject *) window;
 
   /* We always run the filters for the window where the event
    * is delivered, not the window that it relates to
    */
-  if (xevent->xany.window == xwindow)
+  if (filter_xwindow == xwindow)
     filter_window = window;
   else
-    filter_window = gdk_window_lookup_for_display (display, xevent->xany.window);
+    {
+      filter_window = gdk_window_lookup_for_display (display, filter_xwindow);
+      if (filter_window && !GDK_IS_WINDOW (filter_window))
+       filter_window = NULL;
+    }
 
   if (window)
     {
       screen = GDK_WINDOW_SCREEN (window);
       screen_x11 = GDK_SCREEN_X11 (screen);
+      toplevel = _gdk_x11_window_get_toplevel (window);
     }
     
   if (window != NULL)
     {
-      /* Window may be a pixmap, so check its type.
-       * (This check is probably too expensive unless
-       *  GLib short-circuits an exact type match,
-       *  which has been proposed)
-       */
-      if (GDK_IS_WINDOW (window))
-        {
-          window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
-
-          /* Move key events on focus window to the real toplevel, and
-           * filter out all other events on focus window
-           */          
-          if (xwindow == window_impl->focus_window)
-            {
-              switch (xevent->type)
-                {
-                case KeyPress:
-                case KeyRelease:
-                  xwindow = GDK_WINDOW_XID (window);
-                  xevent->xany.window = xwindow;
-                  break;
-                default:
-                  return FALSE;
-                }
-            }
-        }
+      window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
+      
+      /* Move key events on focus window to the real toplevel, and
+       * filter out all other events on focus window
+       */          
+      if (toplevel && xwindow == toplevel->focus_window)
+       {
+         switch (xevent->type)
+           {
+           case KeyPress:
+           case KeyRelease:
+             xwindow = GDK_WINDOW_XID (window);
+             xevent->xany.window = xwindow;
+             break;
+           default:
+             return FALSE;
+           }
+       }
 
       g_object_ref (window);
     }
@@ -899,6 +1037,7 @@ gdk_event_translate (GdkDisplay *display,
           break;
         }
       translate_key_event (display, event, xevent);
+      set_user_time (window, event);
       break;
 
     case KeyRelease:
@@ -973,8 +1112,12 @@ gdk_event_translate (GdkDisplay *display,
          event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
          event->scroll.state = (GdkModifierType) xevent->xbutton.state;
          event->scroll.device = display->core_pointer;
-
-         set_screen_from_root (display, event, xevent->xbutton.root);
+         
+         if (!set_screen_from_root (display, event, xevent->xbutton.root))
+           {
+             return_val = FALSE;
+             break;
+           }
          
           break;
           
@@ -991,12 +1134,19 @@ gdk_event_translate (GdkDisplay *display,
          event->button.button = xevent->xbutton.button;
          event->button.device = display->core_pointer;
          
-         set_screen_from_root (display, event, xevent->xbutton.root);
+         if (!set_screen_from_root (display, event, xevent->xbutton.root))
+           {
+             return_val = FALSE;
+             break;
+           }
 
          _gdk_event_button_generate (display, event);
           break;
        }
 
+      set_user_time (window, event);
+
+      _gdk_xgrab_check_button_event (window, xevent);
       break;
       
     case ButtonRelease:
@@ -1034,8 +1184,13 @@ gdk_event_translate (GdkDisplay *display,
       event->button.button = xevent->xbutton.button;
       event->button.device = display->core_pointer;
 
-      set_screen_from_root (display, event, xevent->xbutton.root);
-      
+      if (!set_screen_from_root (display, event, xevent->xbutton.root))
+       {
+         return_val = FALSE;
+         break;
+       }
+
+      _gdk_xgrab_check_button_event (window, xevent);
       break;
       
     case MotionNotify:
@@ -1052,7 +1207,7 @@ gdk_event_translate (GdkDisplay *display,
          return_val = FALSE;
          break;
        }
-      
+
       event->motion.type = GDK_MOTION_NOTIFY;
       event->motion.window = window;
       event->motion.time = xevent->xmotion.time;
@@ -1065,8 +1220,12 @@ gdk_event_translate (GdkDisplay *display,
       event->motion.is_hint = xevent->xmotion.is_hint;
       event->motion.device = display->core_pointer;
       
-      set_screen_from_root (display, event, xevent->xmotion.root);
-      
+      if (!set_screen_from_root (display, event, xevent->xbutton.root))
+       {
+         return_val = FALSE;
+         break;
+       }
+            
       break;
       
     case EnterNotify:
@@ -1082,18 +1241,26 @@ gdk_event_translate (GdkDisplay *display,
           break;
         }
       
+      if (!set_screen_from_root (display, event, xevent->xbutton.root))
+       {
+         return_val = FALSE;
+         break;
+       }
+      
       /* Handle focusing (in the case where no window manager is running */
-      if (window &&
-         GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
-         xevent->xcrossing.detail != NotifyInferior &&
-         xevent->xcrossing.focus && !window_impl->has_focus_window)
+      if (toplevel && xevent->xcrossing.detail != NotifyInferior)
        {
-         gboolean had_focus = HAS_FOCUS (window_impl);
+         toplevel->has_pointer = TRUE;
 
-         window_impl->has_pointer_focus = TRUE;
-
-         if (HAS_FOCUS (window_impl) != had_focus)
-           generate_focus_event (window, TRUE);
+         if (xevent->xcrossing.focus && !toplevel->has_focus_window)
+           {
+             gboolean had_focus = HAS_FOCUS (toplevel);
+             
+             toplevel->has_pointer_focus = TRUE;
+             
+             if (HAS_FOCUS (toplevel) != had_focus)
+               generate_focus_event (window, TRUE);
+           }
        }
 
       /* Tell XInput stuff about it if appropriate */
@@ -1119,8 +1286,6 @@ gdk_event_translate (GdkDisplay *display,
       event->crossing.x_root = xevent->xcrossing.x_root;
       event->crossing.y_root = xevent->xcrossing.y_root;
       
-      set_screen_from_root (display, event, xevent->xcrossing.root);
-      
       /* Translate the crossing mode into Gdk terms.
        */
       switch (xevent->xcrossing.mode)
@@ -1176,19 +1341,27 @@ gdk_event_translate (GdkDisplay *display,
           return_val = FALSE;
           break;
         }
-      
+
+      if (!set_screen_from_root (display, event, xevent->xbutton.root))
+       {
+         return_val = FALSE;
+         break;
+       }
+                  
       /* Handle focusing (in the case where no window manager is running */
-      if (window &&
-         GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&
-         xevent->xcrossing.detail != NotifyInferior &&
-         xevent->xcrossing.focus && !window_impl->has_focus_window)
+      if (toplevel && xevent->xcrossing.detail != NotifyInferior)
        {
-         gboolean had_focus = HAS_FOCUS (window_impl);
-         
-         window_impl->has_pointer_focus = FALSE;
-         
-         if (HAS_FOCUS (window_impl) != had_focus)
-           generate_focus_event (window, FALSE);
+         toplevel->has_pointer = FALSE;
+
+         if (xevent->xcrossing.focus && !toplevel->has_focus_window)
+           {
+             gboolean had_focus = HAS_FOCUS (toplevel);
+             
+             toplevel->has_pointer_focus = FALSE;
+             
+             if (HAS_FOCUS (toplevel) != had_focus)
+               generate_focus_event (window, FALSE);
+           }
        }
 
       event->crossing.type = GDK_LEAVE_NOTIFY;
@@ -1208,8 +1381,6 @@ gdk_event_translate (GdkDisplay *display,
       event->crossing.x_root = xevent->xcrossing.x_root;
       event->crossing.y_root = xevent->xcrossing.y_root;
       
-      set_screen_from_root (display, event, xevent->xcrossing.root);
-      
       /* Translate the crossing mode into Gdk terms.
        */
       switch (xevent->xcrossing.mode)
@@ -1264,31 +1435,47 @@ gdk_event_translate (GdkDisplay *display,
                           notify_details[xevent->xfocus.detail],
                           notify_modes[xevent->xfocus.mode]));
       
-      if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
+      if (toplevel)
        {
-         gboolean had_focus = HAS_FOCUS (window_impl);
+         gboolean had_focus = HAS_FOCUS (toplevel);
          
          switch (xevent->xfocus.detail)
            {
            case NotifyAncestor:
-           case NotifyNonlinear:
            case NotifyVirtual:
+             /* When the focus moves from an ancestor of the window to
+              * the window or a descendent of the window, *and* the
+              * pointer is inside the window, then we were previously
+              * receiving keystroke events in the has_pointer_focus
+              * case and are now receiving them in the
+              * has_focus_window case.
+              */
+             if (toplevel->has_pointer &&
+                 xevent->xfocus.mode != NotifyGrab &&
+                 xevent->xfocus.mode != NotifyUngrab)
+               toplevel->has_pointer_focus = FALSE;
+             
+             /* fall through */
+           case NotifyNonlinear:
            case NotifyNonlinearVirtual:
-             window_impl->has_focus_window = TRUE;
+             if (xevent->xfocus.mode != NotifyGrab &&
+                 xevent->xfocus.mode != NotifyUngrab)
+               toplevel->has_focus_window = TRUE;
              /* We pretend that the focus moves to the grab
               * window, so we pay attention to NotifyGrab
               * NotifyUngrab, and ignore NotifyWhileGrabbed
               */
              if (xevent->xfocus.mode != NotifyWhileGrabbed)
-               window_impl->has_focus = TRUE;
+               toplevel->has_focus = TRUE;
              break;
            case NotifyPointer:
              /* The X server sends NotifyPointer/NotifyGrab,
               * but the pointer focus is ignored while a
               * grab is in effect
               */
-             if (xevent->xfocus.mode != NotifyGrab)
-               window_impl->has_pointer_focus = TRUE;
+             if (xevent->xfocus.mode != NotifyGrab &&
+                 xevent->xfocus.mode != NotifyUngrab)
+               toplevel->has_pointer_focus = TRUE;
              break;
            case NotifyInferior:
            case NotifyPointerRoot:
@@ -1296,7 +1483,7 @@ gdk_event_translate (GdkDisplay *display,
              break;
            }
 
-         if (HAS_FOCUS (window_impl) != had_focus)
+         if (HAS_FOCUS (toplevel) != had_focus)
            generate_focus_event (window, TRUE);
        }
       break;
@@ -1307,23 +1494,39 @@ gdk_event_translate (GdkDisplay *display,
                           notify_details[xevent->xfocus.detail],
                           notify_modes[xevent->xfocus.mode]));
       
-      if (window && GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
+      if (toplevel)
        {
-         gboolean had_focus = HAS_FOCUS (window_impl);
+         gboolean had_focus = HAS_FOCUS (toplevel);
            
          switch (xevent->xfocus.detail)
            {
            case NotifyAncestor:
-           case NotifyNonlinear:
            case NotifyVirtual:
+             /* When the focus moves from the window or a descendent
+              * of the window to an ancestor of the window, *and* the
+              * pointer is inside the window, then we were previously
+              * receiving keystroke events in the has_focus_window
+              * case and are now receiving them in the
+              * has_pointer_focus case.
+              */
+             if (toplevel->has_pointer &&
+                 xevent->xfocus.mode != NotifyGrab &&
+                 xevent->xfocus.mode != NotifyUngrab)
+               toplevel->has_pointer_focus = TRUE;
+
+             /* fall through */
+           case NotifyNonlinear:
            case NotifyNonlinearVirtual:
-             window_impl->has_focus_window = FALSE;
+             if (xevent->xfocus.mode != NotifyGrab &&
+                 xevent->xfocus.mode != NotifyUngrab)
+               toplevel->has_focus_window = FALSE;
              if (xevent->xfocus.mode != NotifyWhileGrabbed)
-               window_impl->has_focus = FALSE;
+               toplevel->has_focus = FALSE;
              break;
            case NotifyPointer:
-             if (xevent->xfocus.mode != NotifyUngrab)
-               window_impl->has_pointer_focus = FALSE;
+             if (xevent->xfocus.mode != NotifyGrab &&
+                 xevent->xfocus.mode != NotifyUngrab)
+               toplevel->has_pointer_focus = FALSE;
            break;
            case NotifyInferior:
            case NotifyPointerRoot:
@@ -1331,7 +1534,7 @@ gdk_event_translate (GdkDisplay *display,
              break;
            }
 
-         if (HAS_FOCUS (window_impl) != had_focus)
+         if (HAS_FOCUS (toplevel) != had_focus)
            generate_focus_event (window, FALSE);
        }
       break;
@@ -1606,8 +1809,16 @@ gdk_event_translate (GdkDisplay *display,
          !GDK_WINDOW_DESTROYED (window) &&
          (window_private->extension_events != 0))
        _gdk_input_configure_event (&xevent->xconfigure, window);
+      
+#ifdef HAVE_XSYNC
+      if (toplevel && display_x11->use_sync && !XSyncValueIsZero (toplevel->pending_counter_value))
+       {
+         toplevel->current_counter_value = toplevel->pending_counter_value;
+         XSyncIntToValue (&toplevel->pending_counter_value, 0);
+       }
+#endif
 
-      if (!window ||
+    if (!window ||
          xevent->xconfigure.event != xevent->xconfigure.window ||
           GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
           GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
@@ -1647,8 +1858,11 @@ gdk_event_translate (GdkDisplay *display,
            }
          window_private->x = event->configure.x;
          window_private->y = event->configure.y;
-         GDK_WINDOW_IMPL_X11 (window_private->impl)->width = xevent->xconfigure.width;
-         GDK_WINDOW_IMPL_X11 (window_private->impl)->height = xevent->xconfigure.height;
+         window_impl->width = xevent->xconfigure.width;
+         window_impl->height = xevent->xconfigure.height;
+         
+         _gdk_x11_drawable_update_size (window_private->impl);
+         
          if (window_private->resize_count >= 1)
            {
              window_private->resize_count -= 1;
@@ -1677,7 +1891,8 @@ gdk_event_translate (GdkDisplay *display,
       /* We compare with the serial of the last time we mapped the
        * window to avoid refetching properties that we set ourselves
        */
-      if (xevent->xproperty.serial >= GDK_WINDOW_IMPL_X11 (window_private->impl)->map_serial)
+      if (toplevel &&
+         xevent->xproperty.serial >= toplevel->map_serial)
        {
          if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"))
            gdk_check_wm_state_changed (window);
@@ -1769,13 +1984,14 @@ gdk_event_translate (GdkDisplay *display,
        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);
-               break;
+               if (result != GDK_FILTER_CONTINUE)
+                 break;
              }
-           
-           tmp_list = tmp_list->next;
          }
 
        switch (result)
@@ -1839,6 +2055,24 @@ gdk_event_translate (GdkDisplay *display,
            }
        }
       else
+#endif
+#ifdef HAVE_XFIXES
+      if (xevent->type - display_x11->xfixes_event_base == XFixesSelectionNotify)
+       {
+         XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)xevent;
+         event->owner_change.type = GDK_OWNER_CHANGE;
+         event->owner_change.window = window;
+         event->owner_change.owner = selection_notify->owner;
+         event->owner_change.reason = selection_notify->subtype;
+         event->owner_change.selection = 
+           gdk_x11_xatom_to_atom_for_display (display, 
+                                              selection_notify->selection);
+         event->owner_change.time = selection_notify->timestamp;
+         event->owner_change.selection_time = selection_notify->selection_timestamp;
+
+         return_val = TRUE;
+       }
+      else
 #endif
        {
          /* something else - (e.g., a Xinput event) */
@@ -1884,9 +2118,16 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
 {
   XEvent *xevent = (XEvent *)xev;
   GdkWindow *win = event->any.window;
-  GdkDisplay *display = GDK_WINDOW_DISPLAY (win);
+  GdkDisplay *display;
+  Atom atom;
+
+  if (!win)
+      return GDK_FILTER_REMOVE;    
 
-  if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
+  display = GDK_WINDOW_DISPLAY (win);
+  atom = (Atom)xevent->xclient.data.l[0];
+
+  if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
     {
   /* The delete window request specifies a window
    *  to delete. We don't actually destroy the
@@ -1902,21 +2143,26 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
       
       event->any.type = GDK_DELETE;
 
+      gdk_x11_window_set_user_time (win, xevent->xclient.data.l[1]);
+
       return GDK_FILTER_TRANSLATE;
     }
-  else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"))
+  else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"))
     {
-      GdkWindow *win = event->any.window;
-      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)win)->impl);
+      GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (event->any.window);
+      GdkWindowObject *private = (GdkWindowObject *)win;
 
       /* There is no way of knowing reliably whether we are viewable;
        * _gdk_x11_set_input_focus_safe() traps errors asynchronously.
        */
-      _gdk_x11_set_input_focus_safe (display, impl->focus_window,
-                                    RevertToParent,
-                                    xevent->xclient.data.l[1]);
+      if (toplevel && private->accept_focus)
+       _gdk_x11_set_input_focus_safe (display, toplevel->focus_window,
+                                      RevertToParent,
+                                      xevent->xclient.data.l[1]);
+
+      return GDK_FILTER_REMOVE;
     }
-  else if ((Atom) xevent->xclient.data.l[0] == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING") &&
+  else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING") &&
           !_gdk_x11_display_is_root_window (display,
                                             xevent->xclient.window))
     {
@@ -1927,9 +2173,25 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
                  xev.xclient.window,
                  False, 
                  SubstructureRedirectMask | SubstructureNotifyMask, &xev);
-    }
 
-  return GDK_FILTER_REMOVE;
+      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)
+    {
+      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]);
+#endif
+       }
+      return GDK_FILTER_REMOVE;
+    }
+  
+  return GDK_FILTER_CONTINUE;
 }
 
 void
@@ -2043,12 +2305,15 @@ gdk_event_dispatch (GSource    *source,
  * gdk_event_send_client_message_for_display:
  * @display: the #GdkDisplay for the window where the message is to be sent.
  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
- * @winid: the window to send the X ClientMessage event to.
+ * @winid: the window to send the client message to.
  *
- * Sends an X ClientMessage event to a given window.
+ * On X11, sends an X ClientMessage event to a given window. On
+ * Windows, sends a message registered with the name
+ * GDK_WIN32_CLIENT_MESSAGE.
  *
- * This could be used for communicating between different applications,
- * though the amount of data is limited to 20 bytes.
+ * This could be used for communicating between different
+ * applications, though the amount of data is limited to 20 bytes on
+ * X11, and to just four bytes on Windows.
  *
  * Returns: non-zero on success.
  *
@@ -2077,7 +2342,7 @@ gdk_event_send_client_message_for_display (GdkDisplay     *display,
 
 
 /* Sends a ClientMessage to all toplevel client windows */
-gboolean
+static gboolean
 gdk_event_send_client_message_to_all_recurse (GdkDisplay *display,
                                              XEvent     *xev, 
                                              guint32     xid,
@@ -2097,7 +2362,7 @@ gdk_event_send_client_message_to_all_recurse (GdkDisplay *display,
   gdk_error_trap_push ();
   
   if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xid, 
-                         gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
+                         gdk_x11_get_xatom_by_name_for_display (display, "WM_STATE"),
                          0, 0, False, AnyPropertyType,
                          &type, &format, &nitems, &after, &data) != Success)
     goto out;
@@ -2141,13 +2406,18 @@ gdk_event_send_client_message_to_all_recurse (GdkDisplay *display,
  * @screen: the #GdkScreen where the event will be broadcasted.
  * @event: the #GdkEvent.
  *
- * Sends an X ClientMessage event to all toplevel windows on @screen.
+ * On X11, sends an X ClientMessage event to all toplevel windows on
+ * @screen. 
  *
  * Toplevel windows are determined by checking for the WM_STATE property, 
  * as described in the Inter-Client Communication Conventions Manual (ICCCM).
  * If no windows are found with the WM_STATE property set, the message is 
  * sent to all children of the root window.
  *
+ * On Windows, broadcasts a message registered with the name
+ * GDK_WIN32_CLIENT_MESSAGE to all top-level windows. The amount of
+ * data is limited to one long, i.e. four bytes.
+ *
  * Since: 2.2
  */
 
@@ -2271,6 +2541,7 @@ fetch_net_wm_check_window (GdkScreen *screen)
   gint format;
   gulong n_items;
   gulong bytes_after;
+  guchar *data;
   Window *xwindow;
   
   /* This function is very slow on every call if you are not running a
@@ -2287,27 +2558,38 @@ fetch_net_wm_check_window (GdkScreen *screen)
   if (screen_x11->wmspec_check_window != None)
     return; /* already have it */
   
+  data = NULL;
   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
                      gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTING_WM_CHECK"),
                      0, G_MAXLONG, False, XA_WINDOW, &type, &format, 
-                     &n_items, &bytes_after, (guchar **) & xwindow);
+                     &n_items, &bytes_after, &data);
   
   if (type != XA_WINDOW)
-    return;
+    {
+      if (data)
+        XFree (data);
+      return;
+    }
+
+  xwindow = (Window *)data;
 
   gdk_error_trap_push ();
   
   /* Find out if this WM goes away, so we can reset everything. */
   XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask);
+  gdk_display_sync (display);
 
-  screen_x11->wmspec_check_window = *xwindow;
-  XFree (xwindow);
+  if (gdk_error_trap_pop () == Success)
+    {
+      screen_x11->wmspec_check_window = *xwindow;
+      screen_x11->need_refetch_net_supported = TRUE;
+      screen_x11->need_refetch_wm_name = TRUE;
+      
+      /* Careful, reentrancy */
+      _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
+    }
 
-  screen_x11->need_refetch_net_supported = TRUE;
-  screen_x11->need_refetch_wm_name = TRUE;
-  
-  /* Careful, reentrancy */
-  _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
+  XFree (xwindow);    
 }
 
 /**
@@ -2345,9 +2627,11 @@ gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
           gint format;
           gulong n_items;
           gulong bytes_after;
-          guchar *name;
+          gchar *name;
           
           name = NULL;
+
+         gdk_error_trap_push ();
           
           XGetWindowProperty (GDK_DISPLAY_XDISPLAY (screen_x11->display),
                               screen_x11->wmspec_check_window,
@@ -2493,13 +2777,18 @@ gdk_net_wm_supports (GdkAtom property)
   return gdk_x11_screen_supports_net_wm_hint (gdk_screen_get_default (), property);
 }
 
-static struct
+static const struct
 {
   const char *xsettings_name;
   const char *gdk_name;
 } settings_map[] = {
   { "Net/DoubleClickTime", "gtk-double-click-time" },
+  { "Net/DoubleClickDistance", "gtk-double-click-distance" },
   { "Net/DndDragThreshold", "gtk-dnd-drag-threshold" },
+  { "Net/CursorBlink", "gtk-cursor-blink" },
+  { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
+  { "Net/ThemeName", "gtk-theme-name" },
+  { "Net/IconThemeName", "gtk-icon-theme-name" },
   { "Gtk/CanChangeAccels", "gtk-can-change-accels" },
   { "Gtk/ColorPalette", "gtk-color-palette" },
   { "Gtk/FontName", "gtk-font-name" },
@@ -2509,10 +2798,18 @@ static struct
   { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
   { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
   { "Gtk/IMStatusStyle", "gtk-im-status-style" },
-  { "Net/CursorBlink", "gtk-cursor-blink" },
-  { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
-  { "Net/ThemeName", "gtk-theme-name" },
-  { "Net/IconThemeName", "gtk-icon-theme-name" },
+  { "Gtk/Modules", "gtk-modules" },
+  { "Gtk/FileChooserBackend", "gtk-file-chooser-backend" },
+  { "Gtk/ButtonImages", "gtk-button-images" },
+  { "Gtk/MenuImages", "gtk-menu-images" },
+  { "Gtk/MenuBarAccel", "gtk-menu-bar-accel" },
+  { "Gtk/CursorThemeName", "gtk-cursor-theme-name" },
+  { "Gtk/CursorThemeSize", "gtk-cursor-theme-size" },
+  { "Xft/Antialias", "gtk-xft-antialias" },
+  { "Xft/Hinting", "gtk-xft-hinting" },
+  { "Xft/HintStyle", "gtk-xft-hintstyle" },
+  { "Xft/RGBA", "gtk-xft-rgba" },
+  { "Xft/DPI", "gtk-xft-dpi" },
 };
 
 static void
@@ -2540,7 +2837,6 @@ gdk_xsettings_notify_cb (const char       *name,
        new_event.setting.name = (char *)settings_map[i].gdk_name;
        break;
       }
-
   
   if (!new_event.setting.name)
     return;
@@ -2603,7 +2899,7 @@ gdk_screen_get_setting (GdkScreen   *screen,
 
   const char *xsettings_name = NULL;
   XSettingsResult result;
-  XSettingsSetting *setting;
+  XSettingsSetting *setting = NULL;
   GdkScreenX11 *screen_x11;
   gboolean success = FALSE;
   gint i;
@@ -2621,12 +2917,12 @@ gdk_screen_get_setting (GdkScreen   *screen,
       }
 
   if (!xsettings_name)
-    return FALSE;
+    goto out;
 
   result = xsettings_client_get_setting (screen_x11->xsettings_client, 
                                         xsettings_name, &setting);
   if (result != XSETTINGS_SUCCESS)
-    return FALSE;
+    goto out;
 
   switch (setting->type)
     {
@@ -2673,9 +2969,14 @@ gdk_screen_get_setting (GdkScreen   *screen,
   
   g_value_unset (&tmp_val);
 
-  xsettings_setting_free (setting);
+ out:
+  if (setting)
+    xsettings_setting_free (setting);
 
-  return success;
+  if (success)
+    return TRUE;
+  else
+    return _gdk_x11_get_xft_setting (screen, name, value);
 }
 
 static GdkFilterReturn 
@@ -2718,3 +3019,6 @@ gdk_xsettings_watch_cb (Window   window,
       g_object_unref (gdkwin);
     }
 }
+
+#define __GDK_EVENTS_X11_C__
+#include "gdkaliasdef.c"