]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkwindow-x11.c
Zero out some stack-allocated X structures, to avoid valgrind warnings
[~andy/gtk] / gdk / x11 / gdkwindow-x11.c
index af7835d6a0a5a2fe4f0f351d89b02e60eb85e104..2a71b22ada3f302c5e439679ed40f6c00268d2f8 100644 (file)
@@ -88,6 +88,7 @@ static void     gdk_window_add_colormap_windows   (GdkWindow  *window);
 static void     set_wm_name                       (GdkDisplay  *display,
                                                   Window       xwindow,
                                                   const gchar *name);
+static void     move_to_current_desktop           (GdkWindow *window);
 
 static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
 static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
@@ -257,6 +258,13 @@ tmp_reset_bg (GdkWindow *window)
     }
 }
 
+/* Unsetting and resetting window backgrounds.
+ *
+ * In many cases it is possible to avoid flicker by unsetting the
+ * background of windows. For example if the background of the
+ * parent window is unset when a window is unmapped, a brief flicker
+ * of background painting is avoided.
+ */
 void
 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
                              gboolean   recurse)
@@ -724,6 +732,17 @@ gdk_window_new (GdkWindow     *parent,
   else
     private->window_type = attributes->window_type;
 
+  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows 
+   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
+   */
+  if (attributes->wclass == GDK_INPUT_ONLY &&
+      GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT &&
+      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
+    {
+      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
+      attributes->wclass = GDK_INPUT_OUTPUT;
+    }
+
   _gdk_window_init_position (GDK_WINDOW (private));
   if (impl->position_info.big)
     private->guffaw_gravity = TRUE;
@@ -2000,7 +2019,13 @@ gdk_x11_window_move_to_current_desktop (GdkWindow *window)
 
   if (toplevel->on_all_desktops)
     return;
+  
+  move_to_current_desktop (window);
+}
 
+static void
+move_to_current_desktop (GdkWindow *window)
+{
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
                                           gdk_atom_intern_static_string ("_NET_WM_DESKTOP")))
     {
@@ -2297,7 +2322,7 @@ gdk_window_get_type_hint (GdkWindow *window)
       if ((type_return == XA_ATOM) && (format_return == 32) &&
           (data) && (nitems_return == 1))
         {
-          Atom atom = (Atom) *data;
+          Atom atom = *(Atom*)data;
 
           if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
             type = GDK_WINDOW_TYPE_HINT_DIALOG;
@@ -3421,6 +3446,8 @@ _gdk_windowing_get_pointer (GdkDisplay       *display,
                            GdkModifierType  *mask)
 {
   GdkScreen *default_screen;
+  Display *xdisplay;
+  Window xwindow;
   Window root = None;
   Window child;
   int rootx, rooty;
@@ -3432,10 +3459,27 @@ _gdk_windowing_get_pointer (GdkDisplay       *display,
     return;
 
   default_screen = gdk_display_get_default_screen (display);
+
+  xdisplay = GDK_SCREEN_XDISPLAY (default_screen);
+  xwindow = GDK_SCREEN_XROOTWIN (default_screen);
   
-  XQueryPointer (GDK_SCREEN_XDISPLAY (default_screen),
-                GDK_SCREEN_XROOTWIN (default_screen),
-                &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+  if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) 
+    {
+      XQueryPointer (xdisplay, xwindow,
+                    &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+    } 
+  else 
+    {
+      XSetWindowAttributes attributes;
+      Window w;
+      
+      w = XCreateWindow (xdisplay, xwindow, 0, 0, 1, 1, 0, 
+                        CopyFromParent, InputOnly, CopyFromParent, 
+                        0, &attributes);
+      XQueryPointer (xdisplay, w, 
+                    &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+      XDestroyWindow (xdisplay, w);
+    }
   
   if (root != None)
     {
@@ -3469,13 +3513,28 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
   _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
 
   return_val = NULL;
-  if (!GDK_WINDOW_DESTROYED (window) &&
-      XQueryPointer (GDK_WINDOW_XDISPLAY (window),
-                    GDK_WINDOW_XID (window),
-                    &root, &child, &rootx, &rooty, &winx, &winy, &xmask))
+  if (!GDK_WINDOW_DESTROYED (window)) 
     {
-      if (child)
-       return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child);
+      if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) 
+       {
+         if (XQueryPointer (GDK_WINDOW_XDISPLAY (window),
+                            GDK_WINDOW_XID (window),
+                            &root, &child, &rootx, &rooty, &winx, &winy, &xmask))
+           {
+             if (child)
+               return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child);
+           }
+       } 
+      else 
+       {
+         GdkScreen *screen;
+         int originx, originy;
+         _gdk_windowing_get_pointer (gdk_drawable_get_display (window), &screen, 
+                                     &rootx, &rooty, &xmask);
+         gdk_window_get_origin (window, &originx, &originy);
+         winx = rootx - originx;
+         winy = rooty - originy;
+       }
     }
   
   *x = winx + xoffset;
@@ -3548,24 +3607,89 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
    * and the result.
    */
   gdk_x11_display_grab (display);
-  XQueryPointer (xdisplay, xwindow,
-                &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
-
-  if (root == xwindow)
-    xwindow = child;
-  else
-    xwindow = root;
-  
-  while (xwindow)
+  if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) 
     {
-      xwindow_last = xwindow;
       XQueryPointer (xdisplay, xwindow,
-                    &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
+                    &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+      if (root == xwindow)
+       xwindow = child;
+      else
+       xwindow = root;
+      
+      while (xwindow)
+       {
+         xwindow_last = xwindow;
+         XQueryPointer (xdisplay, xwindow,
+                        &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
+       }
+    } 
+  else 
+    {
+      gint i, screens, width, height;
+      GList *toplevels, *list;
+      Window pointer_window;
+      
+      pointer_window = None;
+      screens = gdk_display_get_n_screens (display);
+      for (i = 0; i < screens; ++i) {
+       screen = gdk_display_get_screen (display, i);
+       toplevels = gdk_screen_get_toplevel_windows (screen);
+       for (list = toplevels; list != NULL; list = g_list_next (list)) {
+         window = GDK_WINDOW (list->data);
+         xwindow = GDK_WINDOW_XWINDOW (window);
+         gdk_error_trap_push ();
+         XQueryPointer (xdisplay, xwindow,
+                        &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+         gdk_flush ();
+         if (gdk_error_trap_pop ())
+           continue;
+         if (child != None) 
+           {
+             pointer_window = child;
+             break;
+           }
+         gdk_window_get_geometry (window, NULL, NULL, &width, &height, NULL);
+         if (winx >= 0 && winy >= 0 && winx < width && winy < height) 
+           {
+             /* A childless toplevel, or below another window? */
+             XSetWindowAttributes attributes;
+             Window w;
+             
+             w = XCreateWindow (xdisplay, xwindow, winx, winy, 1, 1, 0, 
+                                CopyFromParent, InputOnly, CopyFromParent, 
+                                0, &attributes);
+             XMapWindow (xdisplay, w);
+             XQueryPointer (xdisplay, xwindow, 
+                            &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+             XDestroyWindow (xdisplay, w);
+             if (child == w) 
+               {
+                 pointer_window = xwindow;
+                 break;
+               }
+           }
+       }
+       g_list_free (toplevels);
+       if (pointer_window != None)
+         break;
+      }
+      xwindow = pointer_window;
+
+      while (xwindow)
+       {
+         xwindow_last = xwindow;
+         gdk_error_trap_push ();
+         XQueryPointer (xdisplay, xwindow,
+                        &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
+         gdk_flush ();
+         if (gdk_error_trap_pop ())
+           break;
+       }
     }
+  
   gdk_x11_display_ungrab (display);
 
-  window = gdk_window_lookup_for_display (GDK_SCREEN_DISPLAY(screen),
-                                         xwindow_last);
+  window = gdk_window_lookup_for_display (display, xwindow_last);
   *win_x = window ? winx : -1;
   *win_y = window ? winy : -1;
 
@@ -4473,52 +4597,12 @@ gdk_window_unstick (GdkWindow *window)
 
   if (GDK_WINDOW_IS_MAPPED (window))
     {
-      XEvent xev;
-      Atom type;
-      gint format;
-      gulong nitems;
-      gulong bytes_after;
-      guchar *data;
-      gulong *current_desktop;
-      GdkDisplay *display = gdk_drawable_get_display (window);
-      
       /* Request unstick from viewport */
       gdk_wmspec_change_state (FALSE, window,
                               gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
                               NULL);
 
-      /* Get current desktop, then set it; this is a race, but not
-       * one that matters much in practice.
-       */
-      XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window),
-                         gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
-                          0, G_MAXLONG,
-                          False, XA_CARDINAL, &type, &format, &nitems,
-                          &bytes_after, &data);
-
-      if (type == XA_CARDINAL)
-        {
-         current_desktop = (gulong *)data;
-         
-          xev.xclient.type = ClientMessage;
-          xev.xclient.serial = 0;
-          xev.xclient.send_event = True;
-          xev.xclient.window = GDK_WINDOW_XWINDOW (window);
-         xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
-          xev.xclient.format = 32;
-
-          xev.xclient.data.l[0] = *current_desktop;
-          xev.xclient.data.l[1] = 0;
-          xev.xclient.data.l[2] = 0;
-          xev.xclient.data.l[3] = 0;
-          xev.xclient.data.l[4] = 0;
-      
-          XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
-                      SubstructureRedirectMask | SubstructureNotifyMask,
-                      &xev);
-
-          XFree (current_desktop);
-        }
+      move_to_current_desktop (window);
     }
   else
     {
@@ -4937,6 +5021,8 @@ gdk_window_set_decorations (GdkWindow      *window,
   
   g_return_if_fail (GDK_IS_WINDOW (window));
   
+  /* initialize to zero to avoid writing uninitialized data to socket */
+  memset(&hints, 0, sizeof(hints));
   hints.flags = MWM_HINTS_DECORATIONS;
   hints.decorations = decorations;
   
@@ -4982,9 +5068,11 @@ gdk_window_get_decorations(GdkWindow       *window,
  * @window: a toplevel #GdkWindow
  * @functions: bitmask of operations to allow on @window
  *
- * This function isn't really good for much. It sets the traditional
- * Motif window manager hint for which operations the window manager
- * should allow on a toplevel window. However, few window managers do
+ * Sets hints about the window management functions to make available
+ * via buttons on the window frame.
+ * 
+ * On the X backend, this function sets the traditional Motif window 
+ * manager hint for this purpose. However, few window managers do
  * anything reliable or interesting with this hint. Many ignore it
  * entirely.
  *
@@ -5003,6 +5091,8 @@ gdk_window_set_functions (GdkWindow    *window,
   
   g_return_if_fail (GDK_IS_WINDOW (window));
   
+  /* initialize to zero to avoid writing uninitialized data to socket */
+  memset(&hints, 0, sizeof(hints));
   hints.flags = MWM_HINTS_FUNCTIONS;
   hints.functions = functions;