]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkwindow-x11.c
Delete EWMH properties if no private->state flags are set. (#66754)
[~andy/gtk] / gdk / x11 / gdkwindow-x11.c
index a715af5e848910b04927fcec0f65c71d539d45fa..55238fd374e396a3a6342ea21d84c42ff29aa1d2 100644 (file)
@@ -83,6 +83,9 @@ static void     gdk_window_set_static_win_gravity (GdkWindow  *window,
 static gboolean gdk_window_have_shape_ext         (GdkDisplay *display);
 static gboolean gdk_window_icon_name_set          (GdkWindow  *window);
 static void     gdk_window_add_colormap_windows   (GdkWindow  *window);
+static void     set_wm_name                       (GdkDisplay  *display,
+                                                  Window       xwindow,
+                                                  const gchar *name);
 
 static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
 static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
@@ -225,7 +228,7 @@ gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
   impl = GDK_WINDOW_IMPL_X11 (drawable);
   draw_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
 
-  if (GDK_WINDOW_DESTROYED (draw_impl->wrapper))
+  if (cmap && GDK_WINDOW_DESTROYED (draw_impl->wrapper))
     return;
 
   /* chain up */
@@ -291,7 +294,8 @@ _gdk_windowing_window_init (GdkScreen * screen)
 
   g_assert (screen_x11->root_window == NULL);
 
-  screen_x11->default_colormap = gdk_screen_get_system_colormap (screen);
+  gdk_screen_set_default_colormap (screen,
+                                  gdk_screen_get_system_colormap (screen));
 
   XGetGeometry (screen_x11->xdisplay, screen_x11->xroot_window,
                &screen_x11->xroot_window, &x, &y, &width, &height, &border_width, &depth);
@@ -306,6 +310,7 @@ _gdk_windowing_window_init (GdkScreen * screen)
   draw_impl->xid = screen_x11->xroot_window;
   draw_impl->wrapper = GDK_DRAWABLE (private);
   draw_impl->colormap = gdk_screen_get_system_colormap (screen);
+  g_object_ref (draw_impl->colormap);
   
   private->window_type = GDK_WINDOW_ROOT;
   private->depth = depth;
@@ -333,6 +338,33 @@ set_wm_protocols (GdkWindow *window)
   XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, 3);
 }
 
+static const gchar *
+get_default_title (void)
+{
+  const char *title;
+
+  title = g_get_application_name ();
+  if (!title)
+    title = g_get_prgname ();
+
+  return title;
+}
+
+static void
+check_leader_window_title (GdkDisplay *display)
+{
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+
+  if (!display_x11->leader_window_title_set)
+    {
+      set_wm_name (display,
+                  display_x11->leader_window,
+                  get_default_title ());
+      
+      display_x11->leader_window_title_set = TRUE;
+    }
+}
+
 /**
  * gdk_window_new:
  * @parent: a #GdkWindow, or %NULL to create the window as a child of
@@ -341,7 +373,7 @@ set_wm_protocols (GdkWindow *window)
  * @attributes_mask: mask indicating which fields in @attributes are valid
  * 
  * Creates a new #GdkWindow using the attributes from
- * @attributes. Seep #GdkWindowAttr and #GdkWindowAttributesType for
+ * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
  * more details.  Note: to use this on displays other than the default
  * display, @parent must be specified.
  * 
@@ -373,7 +405,7 @@ gdk_window_new (GdkWindow     *parent,
   int x, y, depth;
   
   unsigned int class;
-  char *title;
+  const char *title;
   int i;
   long pid;
   
@@ -624,6 +656,8 @@ gdk_window_new (GdkWindow     *parent,
   size_hints.flags = PSize;
   size_hints.width = impl->width;
   size_hints.height = impl->height;
+
+  check_leader_window_title (screen_x11->display);
   
   wm_hints.flags = StateHint | WindowGroupHint;
   wm_hints.window_group = GDK_DISPLAY_X11 (screen_x11->display)->leader_window;
@@ -656,7 +690,7 @@ gdk_window_new (GdkWindow     *parent,
   if (attributes_mask & GDK_WA_TITLE)
     title = attributes->title;
   else
-    title = g_get_prgname ();
+    title = get_default_title ();
 
   gdk_window_set_title (window, title);
   
@@ -700,6 +734,8 @@ x_event_mask_to_gdk_event_mask (long mask)
  * 
  * Return value: the newly-created #GdkWindow wrapper for the 
  *    native window or %NULL if the window has been destroyed.
+ *
+ * Since: 2.2
  **/
 GdkWindow *
 gdk_window_foreign_new_for_display (GdkDisplay     *display,
@@ -786,6 +822,8 @@ gdk_window_foreign_new_for_display (GdkDisplay     *display,
  *
  * Return value: the #GdkWindow wrapper for the native window, 
  *    or %NULL if there is none.
+ *
+ * Since: 2.2
  **/
 GdkWindow *
 gdk_window_lookup_for_display (GdkDisplay *display, GdkNativeWindow anid)
@@ -906,26 +944,27 @@ gdk_window_destroy_notify (GdkWindow *window)
 static void
 set_initial_hints (GdkWindow *window)
 {
+  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+  Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  Window xwindow = GDK_WINDOW_XID (window);  
   GdkWindowObject *private;
   Atom atoms[6];
   gint i;
-  
-  private = (GdkWindowObject*) window;
 
+  private = (GdkWindowObject*) window;
+  
   if (private->state & GDK_WINDOW_STATE_ICONIFIED)
     {
       XWMHints *wm_hints;
       
-      wm_hints = XGetWMHints (GDK_WINDOW_XDISPLAY (window),
-                              GDK_WINDOW_XID (window));
+      wm_hints = XGetWMHints (xdisplay, xwindow);
       if (!wm_hints)
         wm_hints = XAllocWMHints ();
 
       wm_hints->flags |= StateHint;
       wm_hints->initial_state = IconicState;
       
-      XSetWMHints (GDK_WINDOW_XDISPLAY (window),
-                   GDK_WINDOW_XID (window), wm_hints);
+      XSetWMHints (xdisplay, xwindow, wm_hints);
       XFree (wm_hints);
     }
 
@@ -938,53 +977,65 @@ set_initial_hints (GdkWindow *window)
 
   if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
     {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (xdisplay,
                                                        "_NET_WM_STATE_MAXIMIZED_VERT");
       ++i;
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (xdisplay,
                                                        "_NET_WM_STATE_MAXIMIZED_HORZ");
       ++i;
     }
 
   if (private->state & GDK_WINDOW_STATE_STICKY)
     {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (xdisplay,
                                                        "_NET_WM_STATE_STICKY");
       ++i;
     }
 
   if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
     {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (xdisplay,
                                                        "_NET_WM_STATE_FULLSCREEN");
       ++i;
     }
   
   if (private->modal_hint)
     {
-      atoms[i] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+      atoms[i] = gdk_x11_get_xatom_by_name_for_display (xdisplay,
                                                        "_NET_WM_STATE_MODAL");
       ++i;
     }
 
   if (i > 0)
     {
-      XChangeProperty (GDK_WINDOW_XDISPLAY (window),
-                       GDK_WINDOW_XID (window),
-                      gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), "_NET_WM_STATE"),
+      XChangeProperty (xdisplay,
+                       xwindow,
+                      gdk_x11_get_xatom_by_name_for_display (xdisplay, "_NET_WM_STATE"),
                        XA_ATOM, 32, PropModeReplace,
                        (guchar*) atoms, i);
     }
+  else 
+    {
+      XDeleteProperty (xdisplay,
+                       xwindow,
+                      gdk_x11_get_xatom_by_name_for_display (xdisplay, "_NET_WM_STATE"));
+    }
 
   if (private->state & GDK_WINDOW_STATE_STICKY)
     {
       atoms[0] = 0xFFFFFFFF;
-      XChangeProperty (GDK_WINDOW_XDISPLAY (window),
-                       GDK_WINDOW_XID (window),
-                      gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), "_NET_WM_DESKTOP"),
+      XChangeProperty (xdisplay,
+                       xwindow,
+                      gdk_x11_get_xatom_by_name_for_display (xdisplay, "_NET_WM_DESKTOP"),
                        XA_CARDINAL, 32, PropModeReplace,
                        (guchar*) atoms, 1);
     }
+  else
+    {
+      XDeleteProperty (xdisplay,
+                       xwindow,
+                      gdk_x11_get_xatom_by_name_for_display (xdisplay, "_NET_WM_DESKTOP"));
+    }
 }
 
 static void
@@ -1630,7 +1681,7 @@ gdk_window_set_type_hint (GdkWindow        *window,
       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
       break;
     case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
-      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASHSCREEN");
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
       break;
     case GDK_WINDOW_TYPE_HINT_DOCK:
       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
@@ -1727,6 +1778,8 @@ gdk_window_set_modal_hint (GdkWindow *window,
  * function should NOT be called in addition, instead you should allow
  * the window to be treated according to standard policy for its
  * semantic type.
+ *
+ * Since: 2.2
  **/
 void
 gdk_window_set_skip_taskbar_hint (GdkWindow *window,
@@ -1764,6 +1817,8 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
  * already fully describes the window, this function should NOT be
  * called in addition, instead you should allow the window to be
  * treated according to standard policy for its semantic type.
+ *
+ * Since: 2.2
  **/
 void
 gdk_window_set_skip_pager_hint (GdkWindow *window,
@@ -2002,7 +2057,8 @@ utf8_is_latin1 (const gchar *str)
  * convertable to STRING, otherwise, set it as compound text
  */
 static void
-set_text_property (GdkWindow   *window,
+set_text_property (GdkDisplay  *display,
+                  Window       xwindow,
                   Atom         property,
                   const gchar *utf8_str)
 {
@@ -2022,17 +2078,16 @@ set_text_property (GdkWindow   *window,
     {
       GdkAtom gdk_type;
       
-      gdk_utf8_to_compound_text_for_display (gdk_drawable_get_display (window),
+      gdk_utf8_to_compound_text_for_display (display,
                                             utf8_str, &gdk_type, &prop_format,
                                             &prop_text, &prop_length);
-      prop_type = gdk_x11_atom_to_xatom_for_display 
-       (GDK_WINDOW_DISPLAY (window), gdk_type);
+      prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
     }
 
   if (prop_text)
     {
-      XChangeProperty (GDK_WINDOW_XDISPLAY (window),
-                      GDK_WINDOW_XID (window),
+      XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                      xwindow,
                       property,
                       prop_type, prop_format,
                       PropModeReplace, prop_text,
@@ -2042,6 +2097,23 @@ set_text_property (GdkWindow   *window,
     }
 }
 
+/* Set WM_NAME and _NET_WM_NAME
+ */
+static void
+set_wm_name (GdkDisplay  *display,
+            Window       xwindow,
+            const gchar *name)
+{
+  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
+                  gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
+                  gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
+                  PropModeReplace, name, strlen (name));
+  
+  set_text_property (display, xwindow,
+                    gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
+                    name);
+}
+
 /**
  * gdk_window_set_title:
  * @window: a toplevel #GdkWindow
@@ -2058,6 +2130,8 @@ gdk_window_set_title (GdkWindow   *window,
                      const gchar *title)
 {
   GdkDisplay *display;
+  Display *xdisplay;
+  Window xwindow;
   
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
@@ -2067,24 +2141,19 @@ gdk_window_set_title (GdkWindow   *window,
     return;
   
   display = gdk_drawable_get_display (window);
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  xwindow = GDK_WINDOW_XID (window);
 
-  XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
-                  gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
-                  gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
-                  PropModeReplace, title, strlen (title));
-  
-  set_text_property (window,
-                    gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
-                    title);
+  set_wm_name (display, xwindow, title);
   
   if (!gdk_window_icon_name_set (window))
     {
-      XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
+      XChangeProperty (xdisplay, xwindow,
                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
                       gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
                       PropModeReplace, title, strlen (title));
       
-      set_text_property (window,
+      set_text_property (display, xwindow,
                         gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
                         title);
     }
@@ -3243,13 +3312,13 @@ gdk_window_set_icon_name (GdkWindow   *window,
   g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
                      GUINT_TO_POINTER (TRUE));
 
-  XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+  XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
                   GDK_WINDOW_XID (window),
                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
                   gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
                   PropModeReplace, name, strlen (name));
   
-  set_text_property (window,
+  set_text_property (display, GDK_WINDOW_XID (window),
                     gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
                     name);
 }
@@ -3547,6 +3616,7 @@ gdk_window_unmaximize (GdkWindow *window)
  * most standard window managers, and GDK makes a best effort to get
  * it to happen.
  *
+ * Since: 2.2
  **/
 void
 gdk_window_fullscreen (GdkWindow *window)
@@ -3580,8 +3650,9 @@ gdk_window_fullscreen (GdkWindow *window)
  * don't have a concept of "fullscreen"; so you can't rely on the
  * unfullscreenification actually happening. But it will happen with
  * most standard window managers, and GDK makes a best effort to get
- * it to happen.
- * 
+ * it to happen. 
+ *
+ * Since: 2.2
  **/
 void
 gdk_window_unfullscreen (GdkWindow *window)
@@ -4498,19 +4569,54 @@ update_pos (MoveResizeData *mv_resize,
 
   if (mv_resize->is_resize)
     {
-      gint w, h;
+      gint x, y, w, h;
+
+      x = mv_resize->moveresize_orig_x;
+      y = mv_resize->moveresize_orig_y;
 
       w = mv_resize->moveresize_orig_width;
       h = mv_resize->moveresize_orig_height;
 
       switch (mv_resize->resize_edge)
        {
+       case GDK_WINDOW_EDGE_NORTH_WEST:
+         x += dx;
+         y += dy;
+         w -= dx;
+         h -= dy;
+         break;
+       case GDK_WINDOW_EDGE_NORTH:
+         y += dy;
+         h -= dy;
+         break;
+       case GDK_WINDOW_EDGE_NORTH_EAST:
+         y += dy;
+         h -= dy;
+         w += dx;
+         break;
+       case GDK_WINDOW_EDGE_SOUTH_WEST:
+         h += dy;
+         x += dx;
+         w -= dx;
+         break;
        case GDK_WINDOW_EDGE_SOUTH_EAST:
          w += dx;
          h += dy;
          break;
+       case GDK_WINDOW_EDGE_SOUTH:
+         h += dy;
+         break;
+       case GDK_WINDOW_EDGE_EAST:
+         w += dx;
+         break;
+       case GDK_WINDOW_EDGE_WEST:
+         x += dx;
+         w -= dx;
+         break;
        }
 
+      x = MAX (x, 0);
+      y = MAX (y, 0);
       w = MAX (w, 1);
       h = MAX (h, 1);
 
@@ -4521,7 +4627,7 @@ update_pos (MoveResizeData *mv_resize,
                                     w, h, &w, &h);
        }
 
-      gdk_window_resize (mv_resize->moveresize_window, w, h);
+      gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
     }
   else
     {
@@ -4604,10 +4710,10 @@ _gdk_moveresize_handle_event (XEvent *event)
 {
   guint button_mask = 0;
   GdkWindowObject *window_private;
-  GdkDisplay *display= gdk_x11_lookup_xdisplay (event->xany.display);
+  GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
   MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
 
-  if (!mv_resize || mv_resize->moveresize_window)
+  if (!mv_resize || !mv_resize->moveresize_window)
     return FALSE;
 
   window_private = (GdkWindowObject *) mv_resize->moveresize_window;
@@ -4725,6 +4831,78 @@ create_moveresize_window (MoveResizeData *mv_resize,
   mv_resize->moveresize_process_time = 0;
 }
 
+/* 
+   Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
+   so that calling XMoveWindow with these coordinates will not move the 
+   window.
+   Note that this depends on the WM to implement ICCCM-compliant reference
+   point handling.
+*/
+static void 
+calculate_unmoving_origin (MoveResizeData *mv_resize)
+{
+  GdkRectangle rect;
+  gint width, height;
+
+  if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
+      mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
+    {
+      gdk_window_get_origin (mv_resize->moveresize_window,
+                            &mv_resize->moveresize_orig_x,
+                            &mv_resize->moveresize_orig_y);
+    }
+  else
+    {
+      gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
+      gdk_window_get_geometry (mv_resize->moveresize_window, 
+                              NULL, NULL, &width, &height, NULL);
+      
+      switch (mv_resize->moveresize_geometry.win_gravity) 
+       {
+       case GDK_GRAVITY_NORTH_WEST:
+         mv_resize->moveresize_orig_x = rect.x;
+         mv_resize->moveresize_orig_y = rect.y;
+         break;
+       case GDK_GRAVITY_NORTH:
+         mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
+         mv_resize->moveresize_orig_y = rect.y;
+         break;          
+       case GDK_GRAVITY_NORTH_EAST:
+         mv_resize->moveresize_orig_x = rect.x + rect.width - width;
+         mv_resize->moveresize_orig_y = rect.y;
+         break;
+       case GDK_GRAVITY_WEST:
+         mv_resize->moveresize_orig_x = rect.x;
+         mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
+         break;
+       case GDK_GRAVITY_CENTER:
+         mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
+         mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
+         break;
+       case GDK_GRAVITY_EAST:
+         mv_resize->moveresize_orig_x = rect.x + rect.width - width;
+         mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
+         break;
+       case GDK_GRAVITY_SOUTH_WEST:
+         mv_resize->moveresize_orig_x = rect.x;
+         mv_resize->moveresize_orig_y = rect.y + rect.height - height;
+         break;
+       case GDK_GRAVITY_SOUTH:
+         mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
+         mv_resize->moveresize_orig_y = rect.y + rect.height - height;
+         break;
+       case GDK_GRAVITY_SOUTH_EAST:
+         mv_resize->moveresize_orig_x = rect.x + rect.width - width;
+         mv_resize->moveresize_orig_y = rect.y + rect.height - height;
+         break;
+       default:
+         mv_resize->moveresize_orig_x = rect.x;
+         mv_resize->moveresize_orig_y = rect.y;
+         break; 
+       }
+    }  
+}
+
 static void
 emulate_resize_drag (GdkWindow     *window,
                      GdkWindowEdge  edge,
@@ -4751,6 +4929,8 @@ emulate_resize_drag (GdkWindow     *window,
                                 &mv_resize->moveresize_geometry,
                                 &mv_resize->moveresize_geom_mask);
 
+  calculate_unmoving_origin (mv_resize);
+
   create_moveresize_window (mv_resize, timestamp);
 }
 
@@ -4770,9 +4950,7 @@ emulate_move_drag (GdkWindow     *window,
 
   mv_resize->moveresize_window = g_object_ref (window);
 
-  gdk_window_get_deskrelative_origin (mv_resize->moveresize_window,
-                                     &mv_resize->moveresize_orig_x,
-                                     &mv_resize->moveresize_orig_y);
+  calculate_unmoving_origin (mv_resize);
 
   create_moveresize_window (mv_resize, timestamp);
 }