]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkevents-x11.c
Merge branch 'master' into client-side-windows
[~andy/gtk] / gdk / x11 / gdkevents-x11.c
index bb121dc22d2141b6c52b42c763a8d91897306c9d..8d3141a8ee2b79b0b0c96942d24e7b9be8cb80fb 100644 (file)
@@ -1,5 +1,6 @@
 /* GDK - The GIMP Drawing Kit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
+ * Josh MacDonald, Ryan Lortie
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  */
 
 /*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * Modified by the GTK+ Team and others 1997-2007.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
-#include <config.h>
+#include "config.h"
 
-#include "gdkalias.h"
 #include "gdk.h"
 #include "gdkprivate-x11.h"
 #include "gdkinternals.h"
@@ -42,6 +42,9 @@
 #include <string.h>
 
 #include "gdkinputprivate.h"
+#include "gdksettings.c"
+#include "gdkalias.h"
+
 
 #ifdef HAVE_XKB
 #include <X11/XKBlib.h>
 #include <X11/extensions/Xfixes.h>
 #endif
 
+#ifdef HAVE_RANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+
 #include <X11/Xatom.h>
 
 typedef struct _GdkIOClosure GdkIOClosure;
@@ -65,7 +72,7 @@ struct _GdkIOClosure
 {
   GdkInputFunction function;
   GdkInputCondition condition;
-  GdkDestroyNotify notify;
+  GDestroyNotify notify;
   gpointer data;
 };
 
@@ -109,7 +116,7 @@ static GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,
 static GSource *gdk_display_source_new (GdkDisplay *display);
 static gboolean gdk_check_xpending     (GdkDisplay *display);
 
-static void gdk_xsettings_watch_cb  (Window            window,
+static Bool gdk_xsettings_watch_cb  (Window            window,
                                     Bool              is_start,
                                     long              mask,
                                     void             *cb_data);
@@ -175,15 +182,13 @@ _gdk_x11_events_init_screen (GdkScreen *screen)
   /* Keep a flag to avoid extra notifies that we don't need
    */
   screen_x11->xsettings_in_init = TRUE;
-  screen_x11->xsettings_client = xsettings_client_new (screen_x11->xdisplay,
-                                                      screen_x11->screen_num,
-                                                      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_client = xsettings_client_new_with_grab_funcs (screen_x11->xdisplay,
+                                                                      screen_x11->screen_num,
+                                                                      gdk_xsettings_notify_cb,
+                                                                      gdk_xsettings_watch_cb,
+                                                                      screen,
+                                                                       refcounted_grab_server,
+                                                                       refcounted_ungrab_server);
   screen_x11->xsettings_in_init = FALSE;
 }
 
@@ -192,8 +197,11 @@ _gdk_x11_events_uninit_screen (GdkScreen *screen)
 {
   GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
 
-  xsettings_client_destroy (screen_x11->xsettings_client);
-  screen_x11->xsettings_client = NULL;
+  if (screen_x11->xsettings_client)
+    {
+      xsettings_client_destroy (screen_x11->xsettings_client);
+      screen_x11->xsettings_client = NULL;
+    }
 }
 
 void 
@@ -221,11 +229,25 @@ _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_atom_intern_static_string ("WM_PROTOCOLS"), 
                                         gdk_wm_protocols_filter,   
                                         NULL);
 }
 
+void
+_gdk_events_uninit (GdkDisplay *display)
+{
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+
+  if (display_x11->event_source)
+    {
+      display_sources = g_list_remove (display_sources,
+                                       display_x11->event_source);
+      g_source_destroy (display_x11->event_source);
+      g_source_unref (display_x11->event_source);
+      display_x11->event_source = NULL;
+    }
+}
 
 /**
  * gdk_events_pending:
@@ -291,7 +313,7 @@ gdk_event_get_graphics_expose (GdkWindow *window)
   GdkEvent *event;
   
   g_return_val_if_fail (window != NULL, NULL);
-  
+
   XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent, 
            graphics_expose_predicate, (XPointer) window);
   
@@ -342,6 +364,8 @@ gdk_event_apply_filters (XEvent *xevent,
  * @data: user data to pass to @func.
  *
  * Adds a filter to be called when X ClientMessage events are received.
+ * See gdk_window_add_filter() if you are interested in filtering other
+ * types of events.
  *
  * Since: 2.2
  **/ 
@@ -408,7 +432,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);
@@ -458,31 +482,29 @@ gdk_check_wm_desktop_changed (GdkWindow *window)
   gint format;
   gulong nitems;
   gulong bytes_after;
+  guchar *data;
+  gulong *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 (toplevel->have_sticky)
+  if (type != None)
     {
-      gulong *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, (guchar **)&desktop);
-      gdk_error_trap_pop ();
-
-      if (type != None)
-        {
-          toplevel->on_all_desktops = (*desktop == 0xFFFFFFFF);
-          XFree (desktop);
-        }
-      else
-       toplevel->on_all_desktops = FALSE;
-      
-      do_net_wm_state_changes (window);
+      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
@@ -495,6 +517,7 @@ gdk_check_wm_state_changed (GdkWindow *window)
   gint format;
   gulong nitems;
   gulong bytes_after;
+  guchar *data;
   Atom *atoms = NULL;
   gulong i;
 
@@ -510,7 +533,7 @@ gdk_check_wm_state_changed (GdkWindow *window)
   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)
@@ -520,6 +543,8 @@ gdk_check_wm_state_changed (GdkWindow *window)
       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)
         {
@@ -564,7 +589,7 @@ generate_focus_event (GdkWindow *window,
   gdk_event_put (&event);
 }
 
-static void
+static gboolean
 set_screen_from_root (GdkDisplay *display,
                      GdkEvent   *event,
                      Window      xrootwin)
@@ -572,9 +597,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
@@ -584,7 +615,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;
@@ -602,6 +633,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.
    */
@@ -833,6 +867,24 @@ set_user_time (GdkWindow *window,
                                   gdk_event_get_time (event));
 }
 
+static gboolean
+is_parent_of (GdkWindow *parent,
+              GdkWindow *child)
+{
+  GdkWindow *w;
+
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+       return TRUE;
+
+      w = gdk_window_get_parent (w);
+    }
+
+  return FALSE;
+}
+
 static gboolean
 gdk_event_translate (GdkDisplay *display,
                     GdkEvent   *event,
@@ -845,7 +897,6 @@ gdk_event_translate (GdkDisplay *display,
   GdkWindow *filter_window;
   GdkWindowImplX11 *window_impl = NULL;
   gboolean return_val;
-  gint xoffset, yoffset;
   GdkScreen *screen = NULL;
   GdkScreenX11 *screen_x11 = NULL;
   GdkToplevelX11 *toplevel = NULL;
@@ -908,6 +959,24 @@ gdk_event_translate (GdkDisplay *display,
     
   if (window != NULL)
     {
+      /* Apply keyboard grabs to non-native windows */
+      if (/* Is key event */
+         (xevent->type == KeyPress || xevent->type == KeyRelease) &&
+         /* And we have a grab */
+         display->keyboard_grab.window != NULL &&
+         (
+          /* The window is not a descendant of the grabbed window */
+          !is_parent_of ((GdkWindow *)display->keyboard_grab.window, window) ||
+          /* Or owner event is false */
+          !display->keyboard_grab.owner_events
+          )
+         )
+        {
+         /* Report key event against grab window */
+          window = display->keyboard_grab.window;;
+          window_private = (GdkWindowObject *) window;
+        }
+
       window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
       
       /* Move key events on focus window to the real toplevel, and
@@ -1007,16 +1076,6 @@ gdk_event_translate (GdkDisplay *display,
 
   return_val = TRUE;
 
-  if (window)
-    {
-      _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
-    }
-  else
-    {
-      xoffset = 0;
-      yoffset = 0;
-    }
-
   switch (xevent->type)
     {
     case KeyPress:
@@ -1095,14 +1154,18 @@ gdk_event_translate (GdkDisplay *display,
 
          event->scroll.window = window;
          event->scroll.time = xevent->xbutton.time;
-         event->scroll.x = xevent->xbutton.x + xoffset;
-         event->scroll.y = xevent->xbutton.y + yoffset;
+         event->scroll.x = xevent->xbutton.x;
+         event->scroll.y = xevent->xbutton.y;
          event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
          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;
           
@@ -1110,8 +1173,8 @@ gdk_event_translate (GdkDisplay *display,
          event->button.type = GDK_BUTTON_PRESS;
          event->button.window = window;
          event->button.time = xevent->xbutton.time;
-         event->button.x = xevent->xbutton.x + xoffset;
-         event->button.y = xevent->xbutton.y + yoffset;
+         event->button.x = xevent->xbutton.x;
+         event->button.y = xevent->xbutton.y;
          event->button.x_root = (gfloat)xevent->xbutton.x_root;
          event->button.y_root = (gfloat)xevent->xbutton.y_root;
          event->button.axes = NULL;
@@ -1119,13 +1182,16 @@ 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);
-
-         _gdk_event_button_generate (display, event);
+         if (!set_screen_from_root (display, event, xevent->xbutton.root))
+           {
+             return_val = FALSE;
+             break;
+           }
           break;
        }
 
       set_user_time (window, event);
+
       break;
       
     case ButtonRelease:
@@ -1154,8 +1220,8 @@ gdk_event_translate (GdkDisplay *display,
       event->button.type = GDK_BUTTON_RELEASE;
       event->button.window = window;
       event->button.time = xevent->xbutton.time;
-      event->button.x = xevent->xbutton.x + xoffset;
-      event->button.y = xevent->xbutton.y + yoffset;
+      event->button.x = xevent->xbutton.x;
+      event->button.y = xevent->xbutton.y;
       event->button.x_root = (gfloat)xevent->xbutton.x_root;
       event->button.y_root = (gfloat)xevent->xbutton.y_root;
       event->button.axes = NULL;
@@ -1163,7 +1229,8 @@ 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;
       
@@ -1181,12 +1248,12 @@ 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;
-      event->motion.x = xevent->xmotion.x + xoffset;
-      event->motion.y = xevent->xmotion.y + yoffset;
+      event->motion.x = xevent->xmotion.x;
+      event->motion.y = xevent->xmotion.y;
       event->motion.x_root = (gfloat)xevent->xmotion.x_root;
       event->motion.y_root = (gfloat)xevent->xmotion.y_root;
       event->motion.axes = NULL;
@@ -1194,8 +1261,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:
@@ -1211,17 +1282,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 (toplevel &&
-         xevent->xcrossing.detail != NotifyInferior &&
-         xevent->xcrossing.focus && !toplevel->has_focus_window)
+      if (toplevel && xevent->xcrossing.detail != NotifyInferior)
        {
-         gboolean had_focus = HAS_FOCUS (toplevel);
-
-         toplevel->has_pointer_focus = TRUE;
+         toplevel->has_pointer = TRUE;
 
-         if (HAS_FOCUS (toplevel) != 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 */
@@ -1242,13 +1322,11 @@ gdk_event_translate (GdkDisplay *display,
        event->crossing.subwindow = NULL;
       
       event->crossing.time = xevent->xcrossing.time;
-      event->crossing.x = xevent->xcrossing.x + xoffset;
-      event->crossing.y = xevent->xcrossing.y + yoffset;
+      event->crossing.x = xevent->xcrossing.x;
+      event->crossing.y = xevent->xcrossing.y;
       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)
@@ -1304,18 +1382,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 (toplevel &&
-         xevent->xcrossing.detail != NotifyInferior &&
-         xevent->xcrossing.focus && !toplevel->has_focus_window)
+      if (toplevel && xevent->xcrossing.detail != NotifyInferior)
        {
-         gboolean had_focus = HAS_FOCUS (toplevel);
-         
-         toplevel->has_pointer_focus = FALSE;
-         
-         if (HAS_FOCUS (toplevel) != 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;
@@ -1330,13 +1417,11 @@ gdk_event_translate (GdkDisplay *display,
        event->crossing.subwindow = NULL;
       
       event->crossing.time = xevent->xcrossing.time;
-      event->crossing.x = xevent->xcrossing.x + xoffset;
-      event->crossing.y = xevent->xcrossing.y + yoffset;
+      event->crossing.x = xevent->xcrossing.x;
+      event->crossing.y = xevent->xcrossing.y;
       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)
@@ -1398,10 +1483,25 @@ gdk_event_translate (GdkDisplay *display,
          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:
-             toplevel->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
@@ -1414,7 +1514,8 @@ gdk_event_translate (GdkDisplay *display,
               * but the pointer focus is ignored while a
               * grab is in effect
               */
-             if (xevent->xfocus.mode != NotifyGrab)
+             if (xevent->xfocus.mode != NotifyGrab &&
+                 xevent->xfocus.mode != NotifyUngrab)
                toplevel->has_pointer_focus = TRUE;
              break;
            case NotifyInferior:
@@ -1441,15 +1542,31 @@ gdk_event_translate (GdkDisplay *display,
          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:
-             toplevel->has_focus_window = FALSE;
+             if (xevent->xfocus.mode != NotifyGrab &&
+                 xevent->xfocus.mode != NotifyUngrab)
+               toplevel->has_focus_window = FALSE;
              if (xevent->xfocus.mode != NotifyWhileGrabbed)
                toplevel->has_focus = FALSE;
              break;
            case NotifyPointer:
-             if (xevent->xfocus.mode != NotifyUngrab)
+             if (xevent->xfocus.mode != NotifyGrab &&
+                 xevent->xfocus.mode != NotifyUngrab)
                toplevel->has_pointer_focus = FALSE;
            break;
            case NotifyInferior:
@@ -1497,8 +1614,8 @@ gdk_event_translate (GdkDisplay *display,
       {
        GdkRectangle expose_rect;
 
-       expose_rect.x = xevent->xexpose.x + xoffset;
-       expose_rect.y = xevent->xexpose.y + yoffset;
+       expose_rect.x = xevent->xexpose.x;
+       expose_rect.y = xevent->xexpose.y;
        expose_rect.width = xevent->xexpose.width;
        expose_rect.height = xevent->xexpose.height;
 
@@ -1537,8 +1654,8 @@ gdk_event_translate (GdkDisplay *display,
             break;
           }
         
-       expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
-       expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
+       expose_rect.x = xevent->xgraphicsexpose.x;
+       expose_rect.y = xevent->xgraphicsexpose.y;
        expose_rect.width = xevent->xgraphicsexpose.width;
        expose_rect.height = xevent->xgraphicsexpose.height;
            
@@ -1726,7 +1843,13 @@ gdk_event_translate (GdkDisplay *display,
                           ? " (discarding substructure)"
                           : ""));
       if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
-       _gdk_x11_screen_size_changed (screen, xevent);
+        { 
+         window_private->width = xevent->xconfigure.width;
+         window_private->height = xevent->xconfigure.height;
+
+         _gdk_x11_drawable_update_size (window_private->impl);
+         _gdk_x11_screen_size_changed (screen, xevent);
+        }
 
       if (window &&
          xevent->xconfigure.event == xevent->xconfigure.window &&
@@ -1742,7 +1865,7 @@ gdk_event_translate (GdkDisplay *display,
        }
 #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)
@@ -1782,8 +1905,12 @@ gdk_event_translate (GdkDisplay *display,
            }
          window_private->x = event->configure.x;
          window_private->y = event->configure.y;
-         window_impl->width = xevent->xconfigure.width;
-         window_impl->height = xevent->xconfigure.height;
+         window_private->width = xevent->xconfigure.width;
+         window_private->height = xevent->xconfigure.height;
+         
+         _gdk_window_update_size (window);
+         _gdk_x11_drawable_update_size (window_private->impl);
+         
          if (window_private->resize_count >= 1)
            {
              window_private->resize_count -= 1;
@@ -1877,7 +2004,10 @@ gdk_event_translate (GdkDisplay *display,
       event->selection.window = window;
       event->selection.selection = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.selection);
       event->selection.target = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.target);
-      event->selection.property = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.property);
+      if (xevent->xselection.property == None)
+        event->selection.property = GDK_NONE;
+      else
+        event->selection.property = gdk_x11_xatom_to_atom_for_display (display, xevent->xselection.property);
       event->selection.time = xevent->xselection.time;
       
       break;
@@ -1971,7 +2101,7 @@ gdk_event_translate (GdkDisplay *display,
              break;
              
            case XkbStateNotify:
-             _gdk_keymap_state_changed (display);
+             _gdk_keymap_state_changed (display, xevent);
              break;
            }
        }
@@ -1981,6 +2111,9 @@ gdk_event_translate (GdkDisplay *display,
       if (xevent->type - display_x11->xfixes_event_base == XFixesSelectionNotify)
        {
          XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)xevent;
+
+         _gdk_x11_screen_process_owner_change (screen, xevent);
+         
          event->owner_change.type = GDK_OWNER_CHANGE;
          event->owner_change.window = window;
          event->owner_change.owner = selection_notify->owner;
@@ -1990,6 +2123,44 @@ gdk_event_translate (GdkDisplay *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
+#ifdef HAVE_RANDR
+      if (xevent->type - display_x11->xrandr_event_base == RRScreenChangeNotify ||
+          xevent->type - display_x11->xrandr_event_base == RRNotify)
+       {
+          if (screen)
+            _gdk_x11_screen_size_changed (screen, xevent);
+       }
+      else
+#endif
+#if defined(HAVE_XCOMPOSITE) && defined (HAVE_XDAMAGE) && defined (HAVE_XFIXES)
+      if (display_x11->have_xdamage && window_private && window_private->composited &&
+         xevent->type == display_x11->xdamage_event_base + XDamageNotify &&
+         ((XDamageNotifyEvent *) xevent)->damage == window_impl->damage)
+       {
+         XDamageNotifyEvent *damage_event = (XDamageNotifyEvent *) xevent;
+         XserverRegion repair;
+         GdkRectangle rect;
+
+         rect.x = window_private->x + damage_event->area.x;
+         rect.y = window_private->y + damage_event->area.y;
+         rect.width = damage_event->area.width;
+         rect.height = damage_event->area.height;
+
+         repair = XFixesCreateRegion (display_x11->xdisplay,
+                                      &damage_event->area, 1);
+         XDamageSubtract (display_x11->xdisplay,
+                          window_impl->damage,
+                          repair, None);
+         XFixesDestroyRegion (display_x11->xdisplay, repair);
+
+         if (window_private->parent != NULL)
+           _gdk_window_process_expose (GDK_WINDOW (window_private->parent),
+                                       damage_event->serial, &rect);
 
          return_val = TRUE;
        }
@@ -2028,7 +2199,7 @@ gdk_event_translate (GdkDisplay *display,
   
   if (window)
     g_object_unref (window);
-  
+
   return return_val;
 }
 
@@ -2039,8 +2210,14 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
 {
   XEvent *xevent = (XEvent *)xev;
   GdkWindow *win = event->any.window;
-  GdkDisplay *display = GDK_WINDOW_DISPLAY (win);
-  Atom atom = (Atom)xevent->xclient.data.l[0];
+  GdkDisplay *display;
+  Atom atom;
+
+  if (!win)
+      return GDK_FILTER_REMOVE;    
+
+  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"))
     {
@@ -2058,6 +2235,8 @@ 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 == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"))
@@ -2079,13 +2258,13 @@ gdk_wm_protocols_filter (GdkXEvent *xev,
           !_gdk_x11_display_is_root_window (display,
                                             xevent->xclient.window))
     {
-      XEvent xev = *xevent;
+      XClientMessageEvent xclient = xevent->xclient;
       
-      xev.xclient.window = GDK_WINDOW_XROOTWIN (win);
+      xclient.window = GDK_WINDOW_XROOTWIN (win);
       XSendEvent (GDK_WINDOW_XDISPLAY (win), 
-                 xev.xclient.window,
+                 xclient.window,
                  False, 
-                 SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+                 SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xclient);
 
       return GDK_FILTER_REMOVE;
     }
@@ -2141,6 +2320,7 @@ _gdk_events_queue (GdkDisplay *display)
       if (gdk_event_translate (display, event, &xevent, FALSE))
        {
          ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+          _gdk_windowing_got_event (display, node, event, xevent.xany.serial);
        }
       else
        {
@@ -2151,13 +2331,6 @@ _gdk_events_queue (GdkDisplay *display)
     }
 }
 
-static gboolean
-has_events_already (GdkDisplay *display)
-{
-    gboolean r = XEventsQueued (GDK_DISPLAY_XDISPLAY (display), QueuedAlready);
-    return r;
-}
-
 static gboolean  
 gdk_event_prepare (GSource  *source,
                   gint     *timeout)
@@ -2169,7 +2342,7 @@ gdk_event_prepare (GSource  *source,
 
   *timeout = -1;
   retval = (_gdk_event_queue_find_first (display) != NULL || 
-           has_events_already (display));
+           gdk_check_xpending (display));
   
   GDK_THREADS_LEAVE ();
 
@@ -2206,15 +2379,15 @@ gdk_event_dispatch (GSource    *source,
   GDK_THREADS_ENTER ();
 
   _gdk_events_queue (display);
-
   event = _gdk_event_unqueue (display);
 
   if (event)
     {
       if (_gdk_event_func)
        (*_gdk_event_func) (event, _gdk_event_data);
+      
       gdk_event_free (event);
-    }  
+    }
   
   GDK_THREADS_LEAVE ();
 
@@ -2461,29 +2634,42 @@ 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
-   * spec-supporting WM. For now not optimized, because it isn't in
-   * any critical code paths, but if you used it somewhere that had to
-   * be fast you want to avoid "GTK is slow with old WMs" complaints.
-   * Probably at that point the function should be changed to query
-   * _NET_SUPPORTING_WM_CHECK only once every 10 seconds or something.
-   */
+  GTimeVal tv;
   
   screen_x11 = GDK_SCREEN_X11 (screen);
   display = screen_x11->display;
+
+  g_return_if_fail (GDK_DISPLAY_X11 (display)->trusted_client);
   
-  if (screen_x11->wmspec_check_window != None)
-    return; /* already have it */
-  
+  g_get_current_time (&tv);
+      
+  if (ABS  (tv.tv_sec - screen_x11->last_wmspec_check_time) < 15)
+    return; /* we've checked recently */
+
+  screen_x11->last_wmspec_check_time = tv.tv_sec;
+
+  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;
+
+  if (screen_x11->wmspec_check_window == *xwindow)
+    {
+      XFree (xwindow);
+      return;
+    }
 
   gdk_error_trap_push ();
   
@@ -2494,14 +2680,14 @@ fetch_net_wm_check_window (GdkScreen *screen)
   if (gdk_error_trap_pop () == Success)
     {
       screen_x11->wmspec_check_window = *xwindow;
-      XFree (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));
     }
+
+  XFree (xwindow);    
 }
 
 /**
@@ -2523,6 +2709,9 @@ gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
 
   screen_x11 = GDK_SCREEN_X11 (screen);
   
+  if (!G_LIKELY (GDK_DISPLAY_X11 (screen_x11->display)->trusted_client))
+    return screen_x11->window_manager_name;
+
   fetch_net_wm_check_window (screen);
 
   if (screen_x11->need_refetch_wm_name)
@@ -2539,7 +2728,7 @@ gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
           gint format;
           gulong n_items;
           gulong bytes_after;
-          guchar *name;
+          gchar *name;
           
           name = NULL;
 
@@ -2580,6 +2769,15 @@ struct _NetWmSupportedAtoms
   gulong n_atoms;
 };
 
+static void
+cleanup_atoms(gpointer data)
+{
+  NetWmSupportedAtoms *supported_atoms = data;
+  if (supported_atoms->atoms)
+      XFree (supported_atoms->atoms);
+  g_free (supported_atoms);
+}
+
 /**
  * gdk_x11_screen_supports_net_wm_hint:
  * @screen: the relevant #GdkScreen.
@@ -2618,11 +2816,14 @@ gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
   screen_x11 = GDK_SCREEN_X11 (screen);
   display = screen_x11->display;
 
+  if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
+    return FALSE;
+
   supported_atoms = g_object_get_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms");
   if (!supported_atoms)
     {
       supported_atoms = g_new0 (NetWmSupportedAtoms, 1);
-      g_object_set_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms", supported_atoms);
+      g_object_set_data_full (G_OBJECT (screen), "gdk-net-wm-supported-atoms", supported_atoms, cleanup_atoms);
     }
 
   fetch_net_wm_check_window (screen);
@@ -2689,38 +2890,6 @@ gdk_net_wm_supports (GdkAtom property)
   return gdk_x11_screen_supports_net_wm_hint (gdk_screen_get_default (), property);
 }
 
-static 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" },
-  { "Gtk/IconSizes", "gtk-icon-sizes" },
-  { "Gtk/KeyThemeName", "gtk-key-theme-name" },
-  { "Gtk/ToolbarStyle", "gtk-toolbar-style" },
-  { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
-  { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
-  { "Gtk/IMStatusStyle", "gtk-im-status-style" },
-  { "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" },
-  { "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
 gdk_xsettings_notify_cb (const char       *name,
@@ -2741,10 +2910,10 @@ gdk_xsettings_notify_cb (const char       *name,
   new_event.setting.send_event = FALSE;
   new_event.setting.name = NULL;
 
-  for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
-    if (strcmp (settings_map[i].xsettings_name, name) == 0)
+  for (i = 0; i < GDK_SETTINGS_N_ELEMENTS() ; i++)
+    if (strcmp (GDK_SETTINGS_X_NAME (i), name) == 0)
       {
-       new_event.setting.name = (char *)settings_map[i].gdk_name;
+       new_event.setting.name = (char*) GDK_SETTINGS_GDK_NAME (i);
        break;
       }
   
@@ -2774,7 +2943,7 @@ check_transform (const gchar *xsettings_name,
 {
   if (!g_value_type_transformable (src_type, dest_type))
     {
-      g_warning ("Cannot tranform xsetting %s of type %s to type %s\n",
+      g_warning ("Cannot transform xsetting %s of type %s to type %s\n",
                 xsettings_name,
                 g_type_name (src_type),
                 g_type_name (dest_type));
@@ -2809,7 +2978,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;
@@ -2819,20 +2988,20 @@ gdk_screen_get_setting (GdkScreen   *screen,
   
   screen_x11 = GDK_SCREEN_X11 (screen);
 
-  for (i = 0; i < G_N_ELEMENTS (settings_map) ; i++)
-    if (strcmp (settings_map[i].gdk_name, name) == 0)
+  for (i = 0; i < GDK_SETTINGS_N_ELEMENTS(); i++)
+    if (strcmp (GDK_SETTINGS_GDK_NAME (i), name) == 0)
       {
-       xsettings_name = settings_map[i].xsettings_name;
+       xsettings_name = GDK_SETTINGS_X_NAME (i);
        break;
       }
 
   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)
     {
@@ -2879,9 +3048,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 
@@ -2897,7 +3071,7 @@ gdk_xsettings_client_event_filter (GdkXEvent *xevent,
     return GDK_FILTER_CONTINUE;
 }
 
-static void 
+static Bool
 gdk_xsettings_watch_cb (Window   window,
                        Bool     is_start,
                        long     mask,
@@ -2910,17 +3084,51 @@ gdk_xsettings_watch_cb (Window   window,
 
   if (is_start)
     {
-      if (!gdkwin)
-       gdkwin = gdk_window_foreign_new_for_display (gdk_screen_get_display (screen), window);
-      else
+      if (gdkwin)
        g_object_ref (gdkwin);
-      
+      else
+       {
+         gdkwin = gdk_window_foreign_new_for_display (gdk_screen_get_display (screen), window);
+         
+         /* gdk_window_foreign_new_for_display() can fail and return NULL if the
+          * window has already been destroyed.
+          */
+         if (!gdkwin)
+           return False;
+       }
+
       gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
     }
   else
     {
-      g_assert (gdkwin);
+      if (!gdkwin)
+       {
+         /* gdkwin should not be NULL here, since if starting the watch succeeded
+          * we have a reference on the window. It might mean that the caller didn't
+          * remove the watch when it got a DestroyNotify event. Or maybe the
+          * caller ignored the return value when starting the watch failed.
+          */
+         g_warning ("gdk_xsettings_watch_cb(): Couldn't find window to unwatch");
+         return False;
+       }
+      
       gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
       g_object_unref (gdkwin);
     }
+
+  return True;
 }
+
+void
+_gdk_windowing_event_data_copy (const GdkEvent *src,
+                                GdkEvent       *dst)
+{
+}
+
+void
+_gdk_windowing_event_data_free (GdkEvent *event)
+{
+}
+
+#define __GDK_EVENTS_X11_C__
+#include "gdkaliasdef.c"