[gtk+/wip/frame-window] csd: add a frame window



commit 40ea871e78322e183954b0c91d1e9eb6250c4b91
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Apr 28 17:49:49 2013 -0400

    csd: add a frame window
    
    To improve the compatibility of client-side decorations with
    traditional decorations, we introduce a frame window, which is
    the actual toplevel. widget->window for the GtkWindow is a child
    of this window, and just as with traditional window decorations,
    corresponds to the window content.
    
    All sizes (default size, size allocation, parameters given
    to gtk_window_resize, etc) refer to the size of the content.
    
    The resize handle windows and the titlebar widgets are children
    of the frame window.

 gtk/gtkwindow.c |  807 ++++++++++++++++++++++++-------------------------------
 1 files changed, 346 insertions(+), 461 deletions(-)
---
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index f32f63b..53b6f69 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -150,6 +150,7 @@ struct _GtkWindowPrivate
   GtkWidget *popup_menu;
 
   GdkWindow *border_window[8];
+  GdkWindow *frame_window;
 
   /* The following flags are initially TRUE (before a window is mapped).
    * They cause us to compute a configure request that involves
@@ -290,6 +291,7 @@ typedef struct {
   GdkGeometry    geometry; /* Last set of geometry hints we set */
   GdkWindowHints flags;
   GdkRectangle   configure_request;
+  gint title_height;
 } GtkWindowLastGeometryInfo;
 
 struct _GtkWindowGeometryInfo
@@ -332,7 +334,7 @@ struct _GtkWindowGeometryInfo
    * increments and affect the geometry widget only
    */
   guint          resize_is_geometry : 1;
-  
+
   GtkWindowLastGeometryInfo last;
 };
 
@@ -485,6 +487,9 @@ static void gtk_window_get_preferred_height_for_width (GtkWidget *widget,
                                                        gint      *minimum_size,
                                                        gint      *natural_size);
 
+static void get_decoration_size (GtkWindow *window,
+                                 GtkBorder *decorations);
+
 static GSList      *toplevel_list = NULL;
 static guint        window_signals[LAST_SIGNAL] = { 0 };
 static GList       *default_icon_list = NULL;
@@ -1192,11 +1197,11 @@ gtk_window_class_init (GtkWindowClass *klass)
 static gboolean
 gtk_window_get_maximized (GtkWindow *window)
 {
-  GdkWindow *gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
+  GtkWindowPrivate *priv = window->priv;
   gboolean maximized = FALSE;
 
-  if (gdk_window)
-    maximized = (gdk_window_get_state (gdk_window) & GDK_WINDOW_STATE_MAXIMIZED);
+  if (priv->frame_window)
+    maximized = (gdk_window_get_state (priv->frame_window) & GDK_WINDOW_STATE_MAXIMIZED);
 
   return maximized;
 }
@@ -1223,12 +1228,13 @@ gtk_window_title_max_clicked (GtkWidget *widget, gpointer data)
 static gboolean
 send_delete_event (gpointer data)
 {
-  GtkWidget *window = GTK_WIDGET (data);
+  GtkWindow *window = GTK_WINDOW (data);
+  GtkWindowPrivate *priv = window->priv;
   GdkEvent *event;
 
   event = gdk_event_new (GDK_DELETE);
 
-  event->any.window = g_object_ref (gtk_widget_get_window (window));
+  event->any.window = g_object_ref (priv->frame_window);
   event->any.send_event = TRUE;
 
   gtk_main_do_event (event);
@@ -1761,7 +1767,7 @@ gtk_window_set_title (GtkWindow   *window,
   priv->title = new_title;
 
   if (gtk_widget_get_realized (widget))
-    gdk_window_set_title (gtk_widget_get_window (widget), priv->title);
+    gdk_window_set_title (priv->frame_window, priv->title);
 
   if (priv->title_box != NULL)
     gtk_header_bar_set_title (GTK_HEADER_BAR (priv->title_box), priv->title);
@@ -1859,8 +1865,7 @@ gtk_window_set_role (GtkWindow   *window,
   priv->wm_role = new_role;
 
   if (gtk_widget_get_realized (GTK_WIDGET (window)))
-    gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)),
-                         priv->wm_role);
+    gdk_window_set_role (priv->frame_window, priv->wm_role);
 
   g_object_notify (G_OBJECT (window), "role");
 }
@@ -1900,14 +1905,11 @@ gtk_window_set_startup_id (GtkWindow   *window,
 
   if (gtk_widget_get_realized (widget))
     {
-      GdkWindow *gdk_window;
       guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
 
-      gdk_window = gtk_widget_get_window (widget);
-
 #ifdef GDK_WINDOWING_X11
-      if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(gdk_window))
-       gdk_x11_window_set_user_time (gdk_window, timestamp);
+      if (timestamp != GDK_CURRENT_TIME && GDK_IS_X11_WINDOW(priv->frame_window))
+       gdk_x11_window_set_user_time (priv->frame_window, timestamp);
 #endif
 
       /* Here we differentiate real and "fake" startup notification IDs,
@@ -1917,8 +1919,7 @@ gtk_window_set_startup_id (GtkWindow   *window,
        gtk_window_present_with_time (window, timestamp);
       else 
         {
-          gdk_window_set_startup_id (gdk_window,
-                                     priv->startup_id);
+          gdk_window_set_startup_id (priv->frame_window, priv->startup_id);
           
           /* If window is mapped, terminate the startup-notification too */
           if (gtk_widget_get_mapped (widget) &&
@@ -3290,16 +3291,13 @@ void
 gtk_window_set_hide_titlebar_when_maximized (GtkWindow *window,
                                              gboolean   setting)
 {
+  GtkWindowPrivate *priv = window->priv;
   g_return_if_fail (GTK_IS_WINDOW (window));
 
 #ifdef GDK_WINDOWING_X11
   {
-    GdkWindow *gdk_window;
-
-    gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
-
-    if (GDK_IS_X11_WINDOW (gdk_window))
-      gdk_x11_window_set_hide_titlebar_when_maximized (gdk_window, setting);
+    if (GDK_IS_X11_WINDOW (priv->frame_window))
+      gdk_x11_window_set_hide_titlebar_when_maximized (priv->frame_window, setting);
   }
 #endif
 
@@ -3352,6 +3350,7 @@ gtk_window_get_geometry_info (GtkWindow *window,
       info->last.configure_request.y = 0;
       info->last.configure_request.width = -1;
       info->last.configure_request.height = -1;
+      info->last.title_height = 0;
       info->widget = NULL;
       info->mask = 0;
       priv->geometry_info = info;
@@ -3478,7 +3477,6 @@ gtk_window_set_decorated (GtkWindow *window,
                           gboolean   setting)
 {
   GtkWindowPrivate *priv;
-  GdkWindow *gdk_window;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
 
@@ -3491,20 +3489,19 @@ gtk_window_set_decorated (GtkWindow *window,
 
   priv->decorated = setting;
 
-  gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
-  if (gdk_window)
+  if (priv->frame_window)
     {
       if (priv->decorated)
         {
           if (priv->client_decorated)
-            gdk_window_set_decorations (gdk_window, 0);
+            gdk_window_set_decorations (priv->frame_window, 0);
           else if (priv->custom_title)
-            gdk_window_set_decorations (gdk_window, GDK_DECOR_BORDER);
+            gdk_window_set_decorations (priv->frame_window, GDK_DECOR_BORDER);
           else
-            gdk_window_set_decorations (gdk_window, GDK_DECOR_ALL);
+            gdk_window_set_decorations (priv->frame_window, GDK_DECOR_ALL);
         }
       else
-        gdk_window_set_decorations (gdk_window, 0);
+        gdk_window_set_decorations (priv->frame_window, 0);
     }
 
   update_window_buttons (window);
@@ -3553,7 +3550,6 @@ gtk_window_set_deletable (GtkWindow *window,
                          gboolean   setting)
 {
   GtkWindowPrivate *priv;
-  GdkWindow *gdk_window;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
 
@@ -3566,14 +3562,13 @@ gtk_window_set_deletable (GtkWindow *window,
 
   priv->deletable = setting;
 
-  gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
-  if (gdk_window)
+  if (priv->frame_window)
     {
       if (priv->deletable)
-        gdk_window_set_functions (gdk_window,
+        gdk_window_set_functions (priv->frame_window,
                                  GDK_FUNC_ALL);
       else
-        gdk_window_set_functions (gdk_window,
+        gdk_window_set_functions (priv->frame_window,
                                  GDK_FUNC_ALL | GDK_FUNC_CLOSE);
     }
 
@@ -3709,13 +3704,11 @@ gtk_window_realize_icon (GtkWindow *window)
   GtkWindowPrivate *priv = window->priv;
   GtkWidget *widget;
   GtkWindowIconInfo *info;
-  GdkWindow *gdk_window;
   GList *icon_list;
 
   widget = GTK_WIDGET (window);
-  gdk_window = gtk_widget_get_window (widget);
 
-  g_return_if_fail (gdk_window != NULL);
+  g_return_if_fail (priv->frame_window != NULL);
 
   /* no point setting an icon on override-redirect */
   if (priv->type == GTK_WINDOW_POPUP)
@@ -3768,7 +3761,7 @@ gtk_window_realize_icon (GtkWindow *window)
 
   info->realized = TRUE;
 
-  gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list);
+  gdk_window_set_icon_list (priv->frame_window, icon_list);
   set_title_icon (window, icon_list);
 
   if (info->using_themed_icon) 
@@ -4643,12 +4636,13 @@ gtk_window_move (GtkWindow *window,
 {
   GtkWindowGeometryInfo *info;
   GtkWidget *widget;
+  GtkWindowPrivate *priv = window->priv;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
 
   widget = GTK_WIDGET (window);
 
-  info = gtk_window_get_geometry_info (window, TRUE);  
+  info = gtk_window_get_geometry_info (window, TRUE);
 
   if (gtk_widget_get_mapped (widget))
     {
@@ -4683,7 +4677,7 @@ gtk_window_move (GtkWindow *window,
        * the same as the position being changed by the window
        * manager.
        */
-      gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y);
+      gdk_window_move (priv->frame_window, x, y);
     }
   else
     {
@@ -4748,13 +4742,11 @@ gtk_window_get_position (GtkWindow *window,
 {
   GtkWindowPrivate *priv;
   GtkWidget *widget;
-  GdkWindow *gdk_window;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
 
   priv = window->priv;
   widget = GTK_WIDGET (window);
-  gdk_window = gtk_widget_get_window (widget);
 
   if (priv->gravity == GDK_GRAVITY_STATIC)
     {
@@ -4767,7 +4759,7 @@ gtk_window_get_position (GtkWindow *window,
            * do. We should likely be consistent about whether we get
            * the client-side info or the server-side info.
            */
-          gdk_window_get_origin (gdk_window, root_x, root_y);
+          gdk_window_get_origin (gtk_widget_get_window (widget), root_x, root_y);
         }
       else
         {
@@ -4790,7 +4782,7 @@ gtk_window_get_position (GtkWindow *window,
       
       if (gtk_widget_get_mapped (widget))
         {
-          gdk_window_get_frame_extents (gdk_window, &frame_extents);
+          gdk_window_get_frame_extents (priv->frame_window, &frame_extents);
           x = frame_extents.x;
           y = frame_extents.y;
           gtk_window_get_size (window, &w, &h);
@@ -4799,6 +4791,7 @@ gtk_window_get_position (GtkWindow *window,
         {
           /* We just say the frame has 0 size on all sides.
            * Not sure what else to do.
+           * FIXME: could do better here for csd
            */
           gtk_window_compute_configure_request (window,
                                                 &frame_extents,
@@ -5177,6 +5170,8 @@ create_decoration (GtkWidget *widget)
   if (priv->title_box == NULL)
     {
       priv->title_box = gtk_header_bar_new ();
+      if (gtk_widget_get_realized (widget))
+        gtk_widget_set_parent_window (priv->title_box, priv->frame_window);
       g_object_set (priv->title_box,
                     "spacing", 0,
                     "hpadding", 0,
@@ -5243,14 +5238,14 @@ gtk_window_show (GtkWidget *widget)
                                             &configure_request,
                                             &new_geometry,
                                             &new_flags);
-      
+
       /* We update this because we are going to go ahead
        * and gdk_window_resize() below, rather than
        * queuing it.
        */
       info->last.configure_request.width = configure_request.width;
       info->last.configure_request.height = configure_request.height;
-      
+
       /* and allocate the window - this is normally done
        * in move_resize in response to configure notify
        */
@@ -5322,7 +5317,6 @@ gtk_window_map (GtkWidget *widget)
   GtkWidget *child;
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = window->priv;
-  GdkWindow *gdk_window;
   gboolean auto_mnemonics;
   GtkPolicyType visible_focus;
 
@@ -5341,31 +5335,29 @@ gtk_window_map (GtkWidget *widget)
   if (priv->title_box != NULL)
     gtk_widget_map (priv->title_box);
 
-  gdk_window = gtk_widget_get_window (widget);
-
   if (priv->maximize_initially)
-    gdk_window_maximize (gdk_window);
+    gdk_window_maximize (priv->frame_window);
   else
-    gdk_window_unmaximize (gdk_window);
+    gdk_window_unmaximize (priv->frame_window);
 
   if (priv->stick_initially)
-    gdk_window_stick (gdk_window);
+    gdk_window_stick (priv->frame_window);
   else
-    gdk_window_unstick (gdk_window);
+    gdk_window_unstick (priv->frame_window);
 
   if (priv->iconify_initially)
-    gdk_window_iconify (gdk_window);
+    gdk_window_iconify (priv->frame_window);
   else
-    gdk_window_deiconify (gdk_window);
+    gdk_window_deiconify (priv->frame_window);
 
   if (priv->fullscreen_initially)
-    gdk_window_fullscreen (gdk_window);
+    gdk_window_fullscreen (priv->frame_window);
   else
-    gdk_window_unfullscreen (gdk_window);
+    gdk_window_unfullscreen (priv->frame_window);
 
-  gdk_window_set_keep_above (gdk_window, priv->above_initially);
+  gdk_window_set_keep_above (priv->frame_window, priv->above_initially);
 
-  gdk_window_set_keep_below (gdk_window, priv->below_initially);
+  gdk_window_set_keep_below (priv->frame_window, priv->below_initially);
 
   if (priv->type == GTK_WINDOW_TOPLEVEL)
     {
@@ -5384,15 +5376,17 @@ gtk_window_map (GtkWidget *widget)
        * Some applications use X directly to change the properties;
        * in that case, we shouldn't overwrite what they did.
        */
-      gdk_window_set_type_hint (gdk_window, priv->gdk_type_hint);
+      gdk_window_set_type_hint (priv->frame_window, priv->gdk_type_hint);
       priv->reset_type_hint = FALSE;
     }
 
-  gdk_window_show (gdk_window);
+  gdk_window_show (gtk_widget_get_window (widget));
 
   if (priv->grip_window)
     gdk_window_show (priv->grip_window);
 
+  gdk_window_show (priv->frame_window);
+
   if (!disable_startup_notification)
     {
       /* Do we have a custom startup-notification id? */
@@ -5445,7 +5439,7 @@ gtk_window_map_event (GtkWidget   *widget,
        * the window being unmapped. more details can be found in:
        *   http://bugzilla.gnome.org/show_bug.cgi?id=316180
        */
-      gdk_window_hide (gtk_widget_get_window (widget));
+      gdk_window_hide (GTK_WINDOW (widget)->priv->frame_window);
     }
   return FALSE;
 }
@@ -5457,7 +5451,6 @@ gtk_window_unmap (GtkWidget *widget)
   GtkWindowPrivate *priv = window->priv;
   GtkWidget *child;
   GtkWindowGeometryInfo *info;
-  GdkWindow *gdk_window;
   GdkWindowState state;
 
   if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
@@ -5466,10 +5459,8 @@ gtk_window_unmap (GtkWidget *widget)
       return;
     }
 
-  gdk_window = gtk_widget_get_window (widget);
-
   gtk_widget_set_mapped (widget, FALSE);
-  gdk_window_withdraw (gdk_window);
+  gdk_window_withdraw (priv->frame_window);
 
   priv->configure_request_count = 0;
   priv->configure_notify_received = FALSE;
@@ -5487,7 +5478,7 @@ gtk_window_unmap (GtkWidget *widget)
       info->position_constraints_changed = FALSE;
     }
 
-  state = gdk_window_get_state (gdk_window);
+  state = gdk_window_get_state (priv->frame_window);
   priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0;
   priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
   priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
@@ -5608,6 +5599,8 @@ gtk_window_realize (GtkWidget *widget)
   GdkWindowAttr attributes;
   gint attributes_mask;
   GtkWindowPrivate *priv;
+  GtkBorder border;
+  gint title_height = 0;
   gint i;
 
   window = GTK_WINDOW (widget);
@@ -5668,14 +5661,14 @@ gtk_window_realize (GtkWidget *widget)
          allocation.height = 200;
        }
       gtk_widget_size_allocate (widget, &allocation);
-      
+
       _gtk_container_queue_resize (GTK_CONTAINER (widget));
 
       g_return_if_fail (!gtk_widget_get_realized (widget));
     }
-  
+
   gtk_widget_set_realized (widget, TRUE);
-  
+
   switch (priv->type)
     {
     case GTK_WINDOW_TOPLEVEL:
@@ -5699,8 +5692,15 @@ gtk_window_realize (GtkWidget *widget)
   parent_window = gtk_widget_get_root_window (widget);
 
   gtk_widget_get_allocation (widget, &allocation);
-  attributes.width = allocation.width;
-  attributes.height = allocation.height;
+  if (priv->title_box)
+    gtk_widget_get_preferred_height_for_width (priv->title_box,
+                                               allocation.width,
+                                               NULL,
+                                               &title_height);
+  get_decoration_size (window, &border);
+
+  attributes.width = allocation.width + border.left + border.right;
+  attributes.height = allocation.height + border.top + border.bottom + title_height;
   attributes.event_mask = gtk_widget_get_events (widget);
   attributes.event_mask |= (GDK_EXPOSURE_MASK |
                            GDK_BUTTON_PRESS_MASK |
@@ -5721,7 +5721,17 @@ gtk_window_realize (GtkWidget *widget)
   attributes_mask |= (priv->title ? GDK_WA_TITLE : 0);
   attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0);
 
-  gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask);
+  priv->frame_window = gdk_window_new (parent_window, &attributes, attributes_mask);
+  gtk_widget_register_window (widget, priv->frame_window);
+
+  attributes.x = border.left;
+  attributes.y = border.top + title_height;
+  attributes.width = allocation.width;
+  attributes.height = allocation.height;
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes_mask |= GDK_WA_X | GDK_WA_Y;
+
+  gdk_window = gdk_window_new (priv->frame_window, &attributes, attributes_mask);
   gtk_widget_set_window (widget, gdk_window);
   gtk_widget_register_window (widget, gdk_window);
 
@@ -5731,19 +5741,6 @@ gtk_window_realize (GtkWidget *widget)
   if (!priv->client_decorated)
     gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window);
 
-  attributes.x = allocation.x;
-  attributes.y = allocation.y;
-  attributes.width = allocation.width;
-  attributes.height = allocation.height;
-  attributes.window_type = GDK_WINDOW_CHILD;
-
-  attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
-
-  attributes.visual = gtk_widget_get_visual (widget);
-  attributes.wclass = GDK_INPUT_OUTPUT;
-
-  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
-
   if (priv->client_decorated)
     {
       GdkCursorType cursor_type[8] = {
@@ -5766,7 +5763,7 @@ gtk_window_realize (GtkWidget *widget)
       for (i = 0; i < 8; i++)
         {
           attributes.cursor = gdk_cursor_new (cursor_type[i]);
-          priv->border_window[i] = gdk_window_new (gdk_window, &attributes, attributes_mask);
+          priv->border_window[i] = gdk_window_new (priv->frame_window, &attributes, attributes_mask);
           g_object_unref (attributes.cursor);
 
           gdk_window_show (priv->border_window[i]);
@@ -5776,60 +5773,60 @@ gtk_window_realize (GtkWidget *widget)
 
   if (priv->transient_parent &&
       gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)))
-    gdk_window_set_transient_for (gdk_window,
+    gdk_window_set_transient_for (priv->frame_window,
                                   gtk_widget_get_window (GTK_WIDGET (priv->transient_parent)));
 
   if (priv->wm_role)
-    gdk_window_set_role (gdk_window, priv->wm_role);
+    gdk_window_set_role (priv->frame_window, priv->wm_role);
   
   if (!priv->decorated || priv->client_decorated)
-    gdk_window_set_decorations (gdk_window, 0);
+    gdk_window_set_decorations (priv->frame_window, 0);
   else if (priv->custom_title)
-    gdk_window_set_decorations (gdk_window, GDK_DECOR_BORDER);
+    gdk_window_set_decorations (priv->frame_window, GDK_DECOR_BORDER);
   
   if (!priv->deletable)
-    gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
+    gdk_window_set_functions (priv->frame_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE);
   
   if (gtk_window_get_skip_pager_hint (window))
-    gdk_window_set_skip_pager_hint (gdk_window, TRUE);
+    gdk_window_set_skip_pager_hint (priv->frame_window, TRUE);
   
   if (gtk_window_get_skip_taskbar_hint (window))
-    gdk_window_set_skip_taskbar_hint (gdk_window, TRUE);
+    gdk_window_set_skip_taskbar_hint (priv->frame_window, TRUE);
   
   if (gtk_window_get_accept_focus (window))
-    gdk_window_set_accept_focus (gdk_window, TRUE);
+    gdk_window_set_accept_focus (priv->frame_window, TRUE);
   else
-    gdk_window_set_accept_focus (gdk_window, FALSE);
+    gdk_window_set_accept_focus (priv->frame_window, FALSE);
   
   if (gtk_window_get_focus_on_map (window))
-    gdk_window_set_focus_on_map (gdk_window, TRUE);
+    gdk_window_set_focus_on_map (priv->frame_window, TRUE);
   else
-    gdk_window_set_focus_on_map (gdk_window, FALSE);
+    gdk_window_set_focus_on_map (priv->frame_window, FALSE);
   
   if (priv->modal)
-    gdk_window_set_modal_hint (gdk_window, TRUE);
+    gdk_window_set_modal_hint (priv->frame_window, TRUE);
   else
-    gdk_window_set_modal_hint (gdk_window, FALSE);
+    gdk_window_set_modal_hint (priv->frame_window, FALSE);
 
   if (priv->startup_id)
     {
 #ifdef GDK_WINDOWING_X11
-      if (GDK_IS_X11_WINDOW (gdk_window))
+      if (GDK_IS_X11_WINDOW (priv->frame_window))
         {
           guint32 timestamp = extract_time_from_startup_id (priv->startup_id);
           if (timestamp != GDK_CURRENT_TIME)
-            gdk_x11_window_set_user_time (gdk_window, timestamp);
+            gdk_x11_window_set_user_time (priv->frame_window, timestamp);
         }
 #endif
       if (!startup_id_is_fake (priv->startup_id))
-        gdk_window_set_startup_id (gdk_window, priv->startup_id);
+        gdk_window_set_startup_id (priv->frame_window, priv->startup_id);
     }
 
 #ifdef GDK_WINDOWING_X11
   if (priv->initial_timestamp != GDK_CURRENT_TIME)
     {
-      if (GDK_IS_X11_WINDOW (gdk_window))
-        gdk_x11_window_set_user_time (gdk_window, priv->initial_timestamp);
+      if (GDK_IS_X11_WINDOW (priv->frame_window))
+        gdk_x11_window_set_user_time (priv->frame_window, priv->initial_timestamp);
     }
 #endif
 
@@ -5838,6 +5835,9 @@ gtk_window_realize (GtkWidget *widget)
 
   if (priv->has_resize_grip)
     resize_grip_create_window (window);
+
+  if (priv->title_box)
+    gtk_widget_set_parent_window (priv->title_box, priv->frame_window);
 }
 
 static void
@@ -5890,6 +5890,10 @@ gtk_window_unrealize (GtkWidget *widget)
     }
 
   GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
+
+  gtk_widget_unregister_window (widget, priv->frame_window);
+  gdk_window_destroy (priv->frame_window);
+  priv->frame_window = NULL;
 }
 
 static GtkJunctionSides
@@ -6060,10 +6064,10 @@ sum_borders (GtkBorder *one,
 }
 
 static void
-get_decoration_size (GtkWidget *widget,
+get_decoration_size (GtkWindow *window,
                      GtkBorder *decorations)
 {
-  GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
+  GtkWindowPrivate *priv = window->priv;
   GtkBorder border = { 0 };
   GtkBorder margin;
   GtkStyleContext *context;
@@ -6075,11 +6079,11 @@ get_decoration_size (GtkWidget *widget,
   if (!priv->client_decorated)
     return;
 
-  if (gtk_window_get_maximized (GTK_WINDOW (widget)))
+  if (gtk_window_get_maximized (window))
     return;
 
-  state = gtk_widget_get_state_flags (widget);
-  context = gtk_widget_get_style_context (widget);
+  state = gtk_widget_get_state_flags (GTK_WIDGET (window));
+  context = gtk_widget_get_style_context (GTK_WIDGET (window));
 
   gtk_style_context_save (context);
   gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND);
@@ -6155,8 +6159,8 @@ update_border_windows (GtkWindow *window)
                         "decoration-resize-handle", &handle,
                         NULL);
 
-  width = gtk_widget_get_allocated_width (widget) - (border.left + border.right);
-  height = gtk_widget_get_allocated_height (widget) - (border.top + border.bottom);
+  width = gdk_window_get_width (priv->frame_window) - (border.left + border.right);
+  height = gdk_window_get_height (priv->frame_window) - (border.top + border.bottom);
 
   if (resize_h && resize_v)
     {
@@ -6332,7 +6336,6 @@ _gtk_window_set_allocation (GtkWindow           *window,
 {
   GtkWidget *widget = (GtkWidget *)window;
   GtkWindowPrivate *priv = window->priv;
-  GtkAllocation child_allocation;
   guint border_width;
   GtkBorder window_border = { 0 };
   gint title_height = 0;
@@ -6342,14 +6345,9 @@ _gtk_window_set_allocation (GtkWindow           *window,
 
   gtk_widget_set_allocation (widget, allocation);
 
-  get_decoration_size (widget, &window_border);
+  get_decoration_size (window, &window_border);
   border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
 
-  child_allocation.x = 0;
-  child_allocation.y = 0;
-  child_allocation.width = allocation->width;
-  child_allocation.height = allocation->height;
-
   if (priv->title_box != NULL &&
       priv->decorated &&
       !priv->fullscreen)
@@ -6358,9 +6356,7 @@ _gtk_window_set_allocation (GtkWindow           *window,
 
       title_allocation.x = window_border.left;
       title_allocation.y = window_border.top;
-      title_allocation.width =
-        MAX (1, (gint) allocation->width -
-             window_border.left - window_border.right);
+      title_allocation.width = allocation->width;
 
       gtk_widget_get_preferred_height_for_width (priv->title_box,
                                                  title_allocation.width,
@@ -6372,15 +6368,6 @@ _gtk_window_set_allocation (GtkWindow           *window,
       gtk_widget_size_allocate (priv->title_box, &title_allocation);
     }
 
-  if (priv->decorated &&
-      !priv->fullscreen)
-    {
-      child_allocation.x += window_border.left;
-      child_allocation.y += window_border.top + title_height;
-      child_allocation.width -= window_border.left + window_border.right;
-      child_allocation.height -= window_border.top + window_border.bottom +
-                                title_height;
-    }
 
   if (gtk_widget_get_realized (widget))
     {
@@ -6398,15 +6385,18 @@ _gtk_window_set_allocation (GtkWindow           *window,
           update_grip_visibility (window);
           set_grip_position (window);
           update_border_windows (window);
+
+          gdk_window_move_resize (gtk_widget_get_window (widget),
+                                  window_border.left,
+                                  window_border.top + title_height,
+                                  allocation->width, allocation->height);
         }
     }
 
-  child_allocation.x += border_width;
-  child_allocation.y += border_width;
-  child_allocation.width = MAX (1, child_allocation.width - border_width * 2);
-  child_allocation.height = MAX (1, child_allocation.height - border_width * 2);
-
-  *allocation_out = child_allocation;
+  allocation_out->x = border_width;
+  allocation_out->y = border_width;
+  allocation_out->width = MAX (1, allocation->width - border_width * 2);
+  allocation_out->height = MAX (1, allocation->height - border_width * 2);
 }
 
 static void
@@ -6428,7 +6418,6 @@ static gint
 gtk_window_configure_event (GtkWidget         *widget,
                            GdkEventConfigure *event)
 {
-  GtkAllocation allocation;
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = window->priv;
   gboolean expected_reply = priv->configure_request_count > 0;
@@ -6456,9 +6445,10 @@ gtk_window_configure_event (GtkWidget         *widget,
   if (priv->configure_request_count > 0)
     {
       priv->configure_request_count -= 1;
-      gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget));
+      gdk_window_thaw_toplevel_updates_libgtk_only (priv->frame_window);
     }
-  
+
+#if 0
   /* As an optimization, we avoid a resize when possible.
    *
    * The only times we can avoid a resize are:
@@ -6466,13 +6456,13 @@ gtk_window_configure_event (GtkWidget         *widget,
    *   - we know we have made more requests and so will get more
    *     notifies and can wait to resize when we get them
    */
-  gtk_widget_get_allocation (widget, &allocation);
   if (!expected_reply &&
-      (allocation.width == event->width &&
-       allocation.height == event->height))
+      (gdk_window_get_width (priv->frame_window) == event->width &&
+       gdk_window_get_height (priv->frame_window) == event->height))
     {
       return TRUE;
     }
+#endif
 
   /*
    * If we do need to resize, we do that by:
@@ -6485,7 +6475,7 @@ gtk_window_configure_event (GtkWidget         *widget,
   
   priv->configure_notify_received = TRUE;
 
-  gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
+  gdk_window_invalidate_rect (priv->frame_window, NULL, FALSE); // XXX - What was this for again?
 
   _gtk_container_queue_resize (GTK_CONTAINER (widget));
   
@@ -6560,8 +6550,7 @@ gtk_window_style_updated (GtkWidget *widget)
 
   if (gtk_widget_get_realized (widget))
     {
-      gdk_window_set_background_rgba (gtk_widget_get_window (widget),
-                                      &transparent);
+      gdk_window_set_background_rgba (priv->frame_window, &transparent);
       gtk_widget_queue_resize (widget);
     }
 }
@@ -6725,7 +6714,7 @@ gtk_window_resize_grip_is_visible (GtkWindow *window)
     {
       GdkWindowState state;
 
-      state = gdk_window_get_state (gtk_widget_get_window (widget));
+      state = gdk_window_get_state (priv->frame_window);
 
       if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
         return FALSE;
@@ -6777,14 +6766,12 @@ gtk_window_get_resize_grip_area (GtkWindow    *window,
   GtkAllocation allocation;
   gint grip_width;
   gint grip_height;
-  GtkBorder window_border = { 0 };
 
   g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
 
   if (!priv->has_resize_grip)
     return FALSE;
 
-  get_decoration_size (widget, &window_border);
   gtk_widget_get_allocation (widget, &allocation);
 
   gtk_widget_style_get (widget,
@@ -6800,12 +6787,10 @@ gtk_window_get_resize_grip_area (GtkWindow    *window,
 
   rect->width = grip_width;
   rect->height = grip_height;
-  rect->y = allocation.y + allocation.height -
-    grip_height - window_border.bottom;
+  rect->y = allocation.y + allocation.height - grip_height;
 
   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
-    rect->x = allocation.x + allocation.width -
-      grip_width - window_border.right;
+    rect->x = allocation.x + allocation.width - grip_width;
   else
     rect->x = allocation.x;
 
@@ -6980,14 +6965,11 @@ gtk_window_button_press_event (GtkWidget      *widget,
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = window->priv;
   GdkWindowEdge edge;
-  GdkWindow *gdk_window;
-
-  gdk_window = gtk_widget_get_window (widget);
 
   if (event->window == priv->grip_window)
     {
       if (get_drag_edge (widget, &edge))
-        gdk_window_begin_resize_drag_for_device (gdk_window,
+        gdk_window_begin_resize_drag_for_device (priv->frame_window,
                                                  edge,
                                                  gdk_event_get_device ((GdkEvent *) event),
                                                  event->button,
@@ -7029,7 +7011,7 @@ gtk_window_button_press_event (GtkWidget      *widget,
                   break;
                 case GTK_WINDOW_REGION_TITLE:
                 case GTK_WINDOW_REGION_EDGE:
-                   gdk_window_begin_move_drag_for_device (gdk_window,
+                   gdk_window_begin_move_drag_for_device (priv->frame_window,
                                                           gdk_event_get_device ((GdkEvent *) event),
                                                           event->button,
                                                           event->x_root,
@@ -7040,7 +7022,7 @@ gtk_window_button_press_event (GtkWidget      *widget,
                 default:
                   if (!maximized)
                     {
-                      gdk_window_begin_resize_drag_for_device (gdk_window,
+                      gdk_window_begin_resize_drag_for_device (priv->frame_window,
                                                                (GdkWindowEdge)region,
                                                                gdk_event_get_device ((GdkEvent *) event),
                                                                event->button,
@@ -7428,46 +7410,25 @@ gtk_window_get_preferred_width (GtkWidget *widget,
                                 gint      *minimum_size,
                                 gint      *natural_size)
 {
-  GtkWindow *window;
+  GtkWindow *window = GTK_WINDOW (widget);
   GtkWidget *child;
-  GtkWindowPrivate *priv;
-  guint border_width;
-  gint title_min = 0, title_nat = 0;
-  gint child_min = 0, child_nat = 0;
-  GtkBorder window_border = { 0 };
 
-  window = GTK_WINDOW (widget);
-  priv = window->priv;
   child  = gtk_bin_get_child (GTK_BIN (window));
 
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
-
-  if (priv->decorated &&
-      !priv->fullscreen)
-    {
-      get_decoration_size (widget, &window_border);
-
-      if (priv->title_box != NULL)
-        gtk_widget_get_preferred_width (priv->title_box,
-                                        &title_min, &title_nat);
-
-      title_min += border_width * 2 +
-                   window_border.left + window_border.right;
-      title_nat += border_width * 2 +
-                   window_border.left + window_border.right;
-    }
+  *minimum_size = 0;
+  *natural_size = 0;
 
   if (child && gtk_widget_get_visible (child))
     {
+      gint child_min, child_nat;
+      guint border_width;
+
       gtk_widget_get_preferred_width (child, &child_min, &child_nat);
-      child_min += border_width * 2 +
-                   window_border.left + window_border.right;
-      child_nat += border_width * 2 +
-                   window_border.left + window_border.right;
-    }
+      border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
 
-  *minimum_size = MAX (title_min, child_min);
-  *natural_size = MAX (title_nat, child_nat);
+      *minimum_size += child_min + border_width * 2;
+      *natural_size += child_nat + border_width * 2;
+    }
 }
 
 
@@ -7477,49 +7438,27 @@ gtk_window_get_preferred_width_for_height (GtkWidget *widget,
                                            gint      *minimum_size,
                                            gint      *natural_size)
 {
-  GtkWindow *window;
+  GtkWindow *window = GTK_WINDOW (widget);
   GtkWidget *child;
-  GtkWindowPrivate *priv;
-  guint border_width;
-  gint title_min = 0, title_nat = 0;
-  gint child_min = 0, child_nat = 0;
-  GtkBorder window_border = { 0 };
 
-  window = GTK_WINDOW (widget);
-  priv = window->priv;
   child  = gtk_bin_get_child (GTK_BIN (window));
 
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
-
-  if (priv->decorated &&
-      !priv->fullscreen)
-    {
-      get_decoration_size (widget, &window_border);
-
-      if (priv->title_box != NULL)
-        gtk_widget_get_preferred_width_for_height (priv->title_box,
-                                                   height,
-                                                   &title_min, &title_nat);
-
-      title_min += border_width * 2 +
-                   window_border.left + window_border.right;
-      title_nat += border_width * 2 +
-                   window_border.left + window_border.right;
-    }
+  *minimum_size = 0;
+  *natural_size = 0;
 
   if (child && gtk_widget_get_visible (child))
     {
+      gint child_min, child_nat;
+      guint border_width;
+
       gtk_widget_get_preferred_width_for_height (child,
                                                  height,
                                                  &child_min, &child_nat);
-      child_min += border_width * 2 +
-                   window_border.left + window_border.right;
-      child_nat += border_width * 2 +
-                   window_border.left + window_border.right;
-    }
+      border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
 
-  *minimum_size = MAX (title_min, child_min);
-  *natural_size = MAX (title_nat, child_nat);
+      *minimum_size += child_min + border_width * 2;
+      *natural_size += child_nat + border_width * 2;
+    }
 }
 
 static void
@@ -7527,44 +7466,21 @@ gtk_window_get_preferred_height (GtkWidget *widget,
                                  gint      *minimum_size,
                                  gint      *natural_size)
 {
-  GtkWindow *window;
-  GtkWindowPrivate *priv;
+  GtkWindow *window = GTK_WINDOW (widget);
   GtkWidget *child;
-  guint border_width;
-  int title_min = 0;
-  int title_height = 0;
-  GtkBorder window_border = { 0 };
 
-  window = GTK_WINDOW (widget);
-  priv = window->priv;
   child  = gtk_bin_get_child (GTK_BIN (window));
 
   *minimum_size = 0;
   *natural_size = 0;
 
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
-
-  if (priv->decorated &&
-      !priv->fullscreen)
-    {
-      get_decoration_size (widget, &window_border);
-
-      if (priv->title_box != NULL)
-        gtk_widget_get_preferred_height (priv->title_box,
-                                         &title_min,
-                                         &title_height);
-
-      *minimum_size = title_min +
-                      window_border.top + window_border.bottom;
-
-      *natural_size = title_height +
-                      window_border.top + window_border.bottom;
-    }
-
   if (child && gtk_widget_get_visible (child))
     {
       gint child_min, child_nat;
+      guint border_width;
+
       gtk_widget_get_preferred_height (child, &child_min, &child_nat);
+      border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
 
       *minimum_size += child_min + 2 * border_width;
       *natural_size += child_nat + 2 * border_width;
@@ -7578,46 +7494,22 @@ gtk_window_get_preferred_height_for_width (GtkWidget *widget,
                                            gint      *minimum_size,
                                            gint      *natural_size)
 {
-  GtkWindow *window;
-  GtkWindowPrivate *priv;
+  GtkWindow *window = GTK_WINDOW (widget);
   GtkWidget *child;
-  guint border_width;
-  int title_min = 0;
-  int title_height = 0;
-  GtkBorder window_border = { 0 };
 
-  window = GTK_WINDOW (widget);
-  priv = window->priv;
   child  = gtk_bin_get_child (GTK_BIN (window));
 
   *minimum_size = 0;
   *natural_size = 0;
 
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
-
-  if (priv->decorated &&
-      !priv->fullscreen)
-    {
-      get_decoration_size (widget, &window_border);
-
-      if (priv->title_box != NULL)
-        gtk_widget_get_preferred_height_for_width (priv->title_box,
-                                                   width,
-                                                   &title_min,
-                                                   &title_height);
-
-      *minimum_size = title_min +
-                      window_border.top + window_border.bottom;
-
-      *natural_size = title_height +
-                      window_border.top + window_border.bottom;
-    }
-
   if (child && gtk_widget_get_visible (child))
     {
       gint child_min, child_nat;
+      guint border_width;
+
       gtk_widget_get_preferred_height_for_width (child, width,
                                                  &child_min, &child_nat);
+      border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
 
       *minimum_size += child_min + 2 * border_width;
       *natural_size += child_nat + 2 * border_width;
@@ -7818,6 +7710,7 @@ geometry_size_to_pixels (GdkGeometry *geometry,
 }
 
 /* This function doesn't constrain to geometry hints */
+/* CSD: this function determines the requested size for the _content_ */
 static void 
 gtk_window_compute_configure_request_size (GtkWindow   *window,
                                            GdkGeometry *geometry,
@@ -8196,6 +8089,72 @@ gtk_window_constrain_position (GtkWindow    *window,
 }
 
 static void
+add_frame_size_to_geometry (GtkWindow      *window,
+                            GdkGeometry    *geometry)
+{
+  GtkWindowPrivate *priv = window->priv;
+  GtkBorder border;
+  gint title_height = 0;
+
+  if (!priv->client_decorated)
+    return;
+
+  get_decoration_size (window, &border);
+  if (priv->title_box)
+    title_height = gtk_widget_get_allocated_height (priv->title_box);
+
+  geometry->min_width += border.left + border.right;
+  geometry->max_width += border.left + border.right;
+  geometry->min_height += border.top + border.bottom + title_height;
+  geometry->max_height += border.top + border.bottom + title_height;
+}
+
+static void
+add_frame_size_to_allocation (GtkWindow    *window,
+                              GdkRectangle *rect)
+{
+  GtkWindowPrivate *priv = window->priv;
+  GtkBorder border;
+  GtkWindowGeometryInfo *info;
+
+  if (!priv->client_decorated)
+    return;
+
+  info = gtk_window_get_geometry_info (window, TRUE);
+  get_decoration_size (window, &border);
+
+  /* FIXME gravity */
+  rect->x -= border.left;
+  rect->y -= border.top;
+  rect->width += border.left + border.right;
+  rect->height += border.top + border.bottom + info->last.title_height;
+}
+
+static void
+subtract_frame_size_from_allocation (GtkWindow    *window,
+                                     GdkRectangle *rect)
+{
+  GtkWindowPrivate *priv = window->priv;
+  GtkBorder border;
+  GtkWindowGeometryInfo *info;
+
+  if (!priv->client_decorated)
+    return;
+
+  info = gtk_window_get_geometry_info (window, TRUE);
+  get_decoration_size (window, &border);
+
+  /* FIXME gravity */
+  rect->x += border.left;
+  rect->y += border.top;
+  rect->width -= border.left + border.right;
+  rect->height -= border.top + border.bottom + info->last.title_height;
+
+  rect->width = MAX (1, rect->width);
+  rect->height = MAX (1, rect->height);
+}
+
+static void
 gtk_window_move_resize (GtkWindow *window)
 {
   /* Overview:
@@ -8236,7 +8195,6 @@ gtk_window_move_resize (GtkWindow *window)
   GtkContainer *container;
   GtkWindowGeometryInfo *info;
   GdkGeometry new_geometry;
-  GdkWindow *gdk_window;
   guint new_flags;
   GdkRectangle new_request;
   gboolean configure_request_size_changed;
@@ -8246,7 +8204,6 @@ gtk_window_move_resize (GtkWindow *window)
   
   widget = GTK_WIDGET (window);
 
-  gdk_window = gtk_widget_get_window (widget);
   container = GTK_CONTAINER (widget);
   info = gtk_window_get_geometry_info (window, TRUE);
   
@@ -8342,19 +8299,17 @@ gtk_window_move_resize (GtkWindow *window)
         configure_request_pos_changed = FALSE;
     }
 
-#if 0
+#if 1
   if (priv->type == GTK_WINDOW_TOPLEVEL)
     {
       int notify_x, notify_y;
 
       /* this is the position from the last configure notify */
-      gdk_window_get_position (widget->window, &notify_x, &notify_y);
-    
+      gdk_window_get_position (priv->frame_window, &notify_x, &notify_y);
       g_message ("--- %s ---\n"
                 "last  : %d,%d\t%d x %d\n"
                 "this  : %d,%d\t%d x %d\n"
                 "alloc : %d,%d\t%d x %d\n"
-                "req   :      \t%d x %d\n"
                 "resize:      \t%d x %d\n" 
                 "size_changed: %d pos_changed: %d hints_changed: %d\n"
                 "configure_notify_received: %d\n"
@@ -8370,10 +8325,8 @@ gtk_window_move_resize (GtkWindow *window)
                 new_request.width,
                 new_request.height,
                 notify_x, notify_y,
-                widget->allocation.width,
-                widget->allocation.height,
-                widget->requisition.width,
-                widget->requisition.height,
+                gtk_widget_get_allocated_width (widget),
+                gtk_widget_get_allocated_height (widget),
                 info->resize_width,
                 info->resize_height,
                 configure_request_pos_changed,
@@ -8389,7 +8342,15 @@ gtk_window_move_resize (GtkWindow *window)
   info->last.geometry = new_geometry;
   info->last.flags = new_flags;
   info->last.configure_request = new_request;
-  
+
+  if (priv->title_box != NULL)
+    {
+      gtk_widget_get_preferred_height_for_width (priv->title_box,
+                                                 info->last.configure_request.width,
+                                                 NULL,
+                                                 &info->last.title_height);
+    }
+
   /* need to set PPosition so the WM will look at our position,
    * but we don't want to count PPosition coming and going as a hints
    * change for future iterations. So we saved info->last prior to
@@ -8418,14 +8379,19 @@ gtk_window_move_resize (GtkWindow *window)
   /* Set hints if necessary
    */
   if (hints_changed)
-    gdk_window_set_geometry_hints (gdk_window,
-                                  &new_geometry,
-                                  new_flags);
+    {
+      add_frame_size_to_geometry (window, &new_geometry);
+      gdk_window_set_geometry_hints (priv->frame_window, &new_geometry, new_flags);
+    }
 
   allocation.x = 0;
   allocation.y = 0;
-  allocation.width = gdk_window_get_width (gdk_window);
-  allocation.height = gdk_window_get_height (gdk_window);
+  allocation.width = gdk_window_get_width (priv->frame_window);
+  allocation.height = gdk_window_get_height (priv->frame_window);
+
+  subtract_frame_size_from_allocation (window, &allocation);
+  allocation.x = 0;
+  allocation.y = 0;
 
   /* handle resizing/moving and widget tree allocation
    */
@@ -8444,7 +8410,6 @@ gtk_window_move_resize (GtkWindow *window)
        */
       priv->configure_notify_received = FALSE;
 
-      /* gtk_window_configure_event() filled in widget->allocation */
       gtk_widget_size_allocate (widget, &allocation);
 
       set_grip_position (window);
@@ -8511,15 +8476,16 @@ gtk_window_move_resize (GtkWindow *window)
        */
 
       /* Now send the configure request */
+      add_frame_size_to_allocation (window, &new_request);
       if (configure_request_pos_changed)
         {
-          gdk_window_move_resize (gdk_window,
+          gdk_window_move_resize (priv->frame_window,
                                   new_request.x, new_request.y,
                                   new_request.width, new_request.height);
         }
       else  /* only size changed */
         {
-          gdk_window_resize (gdk_window,
+          gdk_window_resize (priv->frame_window,
                              new_request.width, new_request.height);
         }
 
@@ -8535,7 +8501,7 @@ gtk_window_move_resize (GtkWindow *window)
 
          gtk_widget_size_allocate (widget, &allocation);
 
-         gdk_window_process_updates (gdk_window, TRUE);
+         gdk_window_process_updates (priv->frame_window, TRUE);
 
          if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
            gtk_widget_queue_draw (widget);
@@ -8544,7 +8510,7 @@ gtk_window_move_resize (GtkWindow *window)
         {
          /* Increment the number of have-not-yet-received-notify requests */
          priv->configure_request_count += 1;
-         gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window);
+         gdk_window_freeze_toplevel_updates_libgtk_only (priv->frame_window);
 
          /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
           * configure event in response to our resizing request.
@@ -8572,9 +8538,10 @@ gtk_window_move_resize (GtkWindow *window)
     {
       /* Handle any position changes.
        */
+      add_frame_size_to_allocation (window, &new_request);
       if (configure_request_pos_changed)
         {
-          gdk_window_move (gdk_window,
+          gdk_window_move (priv->frame_window,
                            new_request.x, new_request.y);
         }
 
@@ -8820,20 +8787,18 @@ static gboolean
 gtk_window_draw (GtkWidget *widget,
                 cairo_t   *cr)
 {
-  GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkWindowPrivate *priv = window->priv;
   GtkStyleContext *context;
   gboolean ret = FALSE;
-  GtkAllocation allocation;
   GtkBorder window_border;
-  gint title_height;
+  gint x, y, width, height;
 
   context = gtk_widget_get_style_context (widget);
 
-  get_decoration_size (widget, &window_border);
-  gtk_widget_get_allocation (widget, &allocation);
+  get_decoration_size (window, &window_border);
 
-  if (!gtk_widget_get_app_paintable (widget) &&
-      gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
+  if (gtk_cairo_should_draw_window (cr, priv->frame_window))
     {
       if (priv->client_decorated &&
           priv->decorated &&
@@ -8842,48 +8807,49 @@ gtk_window_draw (GtkWidget *widget,
         {
           gtk_style_context_save (context);
 
+          /* The ::draw signal gets emitted for the frame window too,
+           * causing draw signal handlers on the window to draw there.
+           * This is hard to avoid, so we just clear everything to fully
+           * transparent before drawing our frames, to prevent window
+           * content from peeking through in the translucent frame parts.
+           */
+          cairo_save (cr);
+          cairo_set_source_rgba (cr, 0., 0., 0., 0.);
+          cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+          cairo_paint (cr);
+          cairo_restore (cr);
+
           gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND);
           gtk_style_context_add_class (context, "window-frame");
 
           gtk_render_background (context, cr,
                                  window_border.left, window_border.top,
-                                 allocation.width -
+                                 gdk_window_get_width (priv->frame_window) -
                                  (window_border.left + window_border.right),
-                                 allocation.height -
+                                 gdk_window_get_height (priv->frame_window) -
                                  (window_border.top + window_border.bottom));
           gtk_render_frame (context, cr,
                             window_border.left, window_border.top,
-                            allocation.width -
+                            gdk_window_get_width (priv->frame_window) -
                             (window_border.left + window_border.right),
-                            allocation.height -
+                            gdk_window_get_height (priv->frame_window) -
                             (window_border.top + window_border.bottom));
 
           gtk_style_context_restore (context);
         }
 
-      if (priv->title_box)
-        title_height = gtk_widget_get_allocated_height (priv->title_box);
-      else
-        title_height = 0;
-
-      gtk_render_background (context, cr,
-                             window_border.left,
-                             window_border.top + title_height,
-                             allocation.width -
-                             (window_border.left + window_border.right),
-                             allocation.height -
-                             (window_border.top + window_border.bottom +
-                              title_height));
-      gtk_render_frame (context, cr,
-                        window_border.left,
-                        window_border.top + title_height,
-                        allocation.width -
-                        (window_border.left + window_border.right),
-                        allocation.height -
-                        (window_border.top + window_border.bottom +
-                         title_height));
+      if (!gtk_widget_get_app_paintable (widget))
+        {
+          gdk_window_get_position (gtk_widget_get_window (widget), &x, &y);
+          width = gdk_window_get_width (gtk_widget_get_window (widget));
+          height = gdk_window_get_height (gtk_widget_get_window (widget));
+
+          gtk_render_background (context, cr, x, y, width, height);
+          gtk_render_frame (context, cr, x, y, width, height);
+        }
     }
 
+
   if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
     ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
 
@@ -8956,7 +8922,6 @@ gtk_window_present_with_time (GtkWindow *window,
 {
   GtkWindowPrivate *priv;
   GtkWidget *widget;
-  GdkWindow *gdk_window;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
 
@@ -8965,17 +8930,15 @@ gtk_window_present_with_time (GtkWindow *window,
 
   if (gtk_widget_get_visible (widget))
     {
-      gdk_window = gtk_widget_get_window (widget);
-
-      g_assert (gdk_window != NULL);
+      g_assert (priv->frame_window != NULL);
 
-      gdk_window_show (gdk_window);
+      gdk_window_show (priv->frame_window);
 
       /* Translate a timestamp of GDK_CURRENT_TIME appropriately */
       if (timestamp == GDK_CURRENT_TIME)
         {
 #ifdef GDK_WINDOWING_X11
-         if (GDK_IS_X11_WINDOW(gdk_window))
+         if (GDK_IS_X11_WINDOW (priv->frame_window))
            {
              GdkDisplay *display;
 
@@ -8987,7 +8950,7 @@ gtk_window_present_with_time (GtkWindow *window,
            timestamp = gtk_get_current_event_time ();
         }
 
-      gdk_window_focus (gdk_window, timestamp);
+      gdk_window_focus (priv->frame_window, timestamp);
     }
   else
     {
@@ -9019,21 +8982,14 @@ gtk_window_present_with_time (GtkWindow *window,
 void
 gtk_window_iconify (GtkWindow *window)
 {
-  GtkWindowPrivate *priv;
-  GtkWidget *widget;
-  GdkWindow *toplevel;
-  
+  GtkWindowPrivate *priv = window->priv;
+ 
   g_return_if_fail (GTK_IS_WINDOW (window));
 
-  priv = window->priv;
-  widget = GTK_WIDGET (window);
-
   priv->iconify_initially = TRUE;
 
-  toplevel = gtk_widget_get_window (widget);
-
-  if (toplevel != NULL)
-    gdk_window_iconify (toplevel);
+  if (priv->frame_window != NULL)
+    gdk_window_iconify (priv->frame_window);
 }
 
 /**
@@ -9052,21 +9008,14 @@ gtk_window_iconify (GtkWindow *window)
 void
 gtk_window_deiconify (GtkWindow *window)
 {
-  GtkWindowPrivate *priv;
-  GtkWidget *widget;
-  GdkWindow *toplevel;
-  
-  g_return_if_fail (GTK_IS_WINDOW (window));
+  GtkWindowPrivate *priv = window->priv;
 
-  priv = window->priv;
-  widget = GTK_WIDGET (window);
+  g_return_if_fail (GTK_IS_WINDOW (window));
 
   priv->iconify_initially = FALSE;
 
-  toplevel = gtk_widget_get_window (widget);
-
-  if (toplevel != NULL)
-    gdk_window_deiconify (toplevel);
+  if (priv->frame_window != NULL)
+    gdk_window_deiconify (priv->frame_window);
 }
 
 /**
@@ -9090,21 +9039,14 @@ gtk_window_deiconify (GtkWindow *window)
 void
 gtk_window_stick (GtkWindow *window)
 {
-  GtkWindowPrivate *priv;
-  GtkWidget *widget;
-  GdkWindow *toplevel;
-  
-  g_return_if_fail (GTK_IS_WINDOW (window));
+  GtkWindowPrivate *priv = window->priv;
 
-  priv = window->priv;
-  widget = GTK_WIDGET (window);
+  g_return_if_fail (GTK_IS_WINDOW (window));
 
   priv->stick_initially = TRUE;
 
-  toplevel = gtk_widget_get_window (widget);
-
-  if (toplevel != NULL)
-    gdk_window_stick (toplevel);
+  if (priv->frame_window != NULL)
+    gdk_window_stick (priv->frame_window);
 }
 
 /**
@@ -9125,21 +9067,14 @@ gtk_window_stick (GtkWindow *window)
 void
 gtk_window_unstick (GtkWindow *window)
 {
-  GtkWindowPrivate *priv;
-  GtkWidget *widget;
-  GdkWindow *toplevel;
-  
-  g_return_if_fail (GTK_IS_WINDOW (window));
+  GtkWindowPrivate *priv = window->priv;
 
-  priv = window->priv;
-  widget = GTK_WIDGET (window);
+  g_return_if_fail (GTK_IS_WINDOW (window));
 
   priv->stick_initially = FALSE;
 
-  toplevel = gtk_widget_get_window (widget);
-
-  if (toplevel != NULL)
-    gdk_window_unstick (toplevel);
+  if (priv->frame_window != NULL)
+    gdk_window_unstick (priv->frame_window);
 }
 
 /**
@@ -9165,21 +9100,14 @@ gtk_window_unstick (GtkWindow *window)
 void
 gtk_window_maximize (GtkWindow *window)
 {
-  GtkWindowPrivate *priv;
-  GtkWidget *widget;
-  GdkWindow *toplevel;
-  
-  g_return_if_fail (GTK_IS_WINDOW (window));
+  GtkWindowPrivate *priv = window->priv;
 
-  priv = window->priv;
-  widget = GTK_WIDGET (window);
+  g_return_if_fail (GTK_IS_WINDOW (window));
 
   priv->maximize_initially = TRUE;
 
-  toplevel = gtk_widget_get_window (widget);
-
-  if (toplevel != NULL)
-    gdk_window_maximize (toplevel);
+  if (priv->frame_window != NULL)
+    gdk_window_maximize (priv->frame_window);
 }
 
 /**
@@ -9200,21 +9128,14 @@ gtk_window_maximize (GtkWindow *window)
 void
 gtk_window_unmaximize (GtkWindow *window)
 {
-  GtkWindowPrivate *priv;
-  GtkWidget *widget;
-  GdkWindow *toplevel;
-  
-  g_return_if_fail (GTK_IS_WINDOW (window));
+  GtkWindowPrivate *priv = window->priv;
 
-  priv = window->priv;
-  widget = GTK_WIDGET (window);
+  g_return_if_fail (GTK_IS_WINDOW (window));
 
   priv->maximize_initially = FALSE;
 
-  toplevel = gtk_widget_get_window (widget);
-
-  if (toplevel != NULL)
-    gdk_window_unmaximize (toplevel);
+  if (priv->frame_window != NULL)
+    gdk_window_unmaximize (priv->frame_window);
 }
 
 /**
@@ -9237,21 +9158,14 @@ gtk_window_unmaximize (GtkWindow *window)
 void
 gtk_window_fullscreen (GtkWindow *window)
 {
-  GtkWindowPrivate *priv;
-  GtkWidget *widget;
-  GdkWindow *toplevel;
+  GtkWindowPrivate *priv = window->priv;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
 
-  priv = window->priv;
-  widget = GTK_WIDGET (window);
-
   priv->fullscreen_initially = TRUE;
 
-  toplevel = gtk_widget_get_window (widget);
-
-  if (toplevel != NULL)
-    gdk_window_fullscreen (toplevel);
+  if (priv->frame_window != NULL)
+    gdk_window_fullscreen (priv->frame_window);
 }
 
 /**
@@ -9274,21 +9188,14 @@ gtk_window_fullscreen (GtkWindow *window)
 void
 gtk_window_unfullscreen (GtkWindow *window)
 {
-  GtkWidget *widget;
-  GdkWindow *toplevel;
-  GtkWindowPrivate *priv;
+  GtkWindowPrivate *priv = window->priv;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
 
-  priv = window->priv;
-  widget = GTK_WIDGET (window);
-
   priv->fullscreen_initially = FALSE;
 
-  toplevel = gtk_widget_get_window (widget);
-
-  if (toplevel != NULL)
-    gdk_window_unfullscreen (toplevel);
+  if (priv->frame_window != NULL)
+    gdk_window_unfullscreen (priv->frame_window);
 }
 
 /**
@@ -9323,23 +9230,16 @@ void
 gtk_window_set_keep_above (GtkWindow *window,
                           gboolean   setting)
 {
-  GtkWidget *widget;
-  GtkWindowPrivate *priv;
-  GdkWindow *toplevel;
+  GtkWindowPrivate *priv = window->priv;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
 
-  priv = window->priv;
-  widget = GTK_WIDGET (window);
-
   priv->above_initially = setting != FALSE;
   if (setting)
     priv->below_initially = FALSE;
 
-  toplevel = gtk_widget_get_window (widget);
-
-  if (toplevel != NULL)
-    gdk_window_set_keep_above (toplevel, setting);
+  if (priv->frame_window != NULL)
+    gdk_window_set_keep_above (priv->frame_window, setting);
 }
 
 /**
@@ -9374,23 +9274,16 @@ void
 gtk_window_set_keep_below (GtkWindow *window,
                           gboolean   setting)
 {
-  GtkWidget *widget;
-  GtkWindowPrivate *priv;
-  GdkWindow *toplevel;
+  GtkWindowPrivate *priv = window->priv;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
 
-  priv = window->priv;
-  widget = GTK_WIDGET (window);
-
   priv->below_initially = setting != FALSE;
   if (setting)
     priv->above_initially = FALSE;
 
-  toplevel = gtk_widget_get_window (widget);
-
-  if (toplevel != NULL)
-    gdk_window_set_keep_below (toplevel, setting);
+  if (priv->frame_window != NULL)
+    gdk_window_set_keep_below (priv->frame_window, setting);
 }
 
 /**
@@ -9519,15 +9412,13 @@ gtk_window_begin_resize_drag  (GtkWindow    *window,
                                guint32       timestamp)
 {
   GtkWidget *widget;
-  GdkWindow *toplevel;
+  GtkWindowPrivate *priv = window->priv;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
   widget = GTK_WIDGET (window);
   g_return_if_fail (gtk_widget_get_visible (widget));
 
-  toplevel = gtk_widget_get_window (widget);
-
-  gdk_window_begin_resize_drag (toplevel,
+  gdk_window_begin_resize_drag (priv->frame_window,
                                 edge, button,
                                 root_x, root_y,
                                 timestamp);
@@ -9556,16 +9447,14 @@ gtk_window_begin_move_drag  (GtkWindow *window,
                              gint       root_y,
                              guint32    timestamp)
 {
+  GtkWindowPrivate *priv = window->priv;
   GtkWidget *widget;
-  GdkWindow *toplevel;
 
   g_return_if_fail (GTK_IS_WINDOW (window));
   widget = GTK_WIDGET (window);
   g_return_if_fail (gtk_widget_get_visible (widget));
 
-  toplevel = gtk_widget_get_window (widget);
-
-  gdk_window_begin_move_drag (toplevel,
+  gdk_window_begin_move_drag (priv->frame_window,
                               button,
                               root_x, root_y,
                               timestamp);
@@ -9643,17 +9532,15 @@ static void
 gtk_window_set_theme_variant (GtkWindow *window)
 {
 #ifdef GDK_WINDOWING_X11
-  GdkWindow *gdk_window;
+  GtkWindowPrivate *priv = window->priv;
   gboolean   dark_theme_requested;
 
   g_object_get (gtk_settings_get_for_screen (window->priv->screen),
                 "gtk-application-prefer-dark-theme", &dark_theme_requested,
                 NULL);
 
-  gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
-
-  if (GDK_IS_X11_WINDOW (gdk_window))
-    gdk_x11_window_set_theme_variant (gdk_window,
+  if (GDK_IS_X11_WINDOW (priv->frame_window))
+    gdk_x11_window_set_theme_variant (priv->frame_window,
                                       dark_theme_requested ? "dark" : NULL);
 #endif
 }
@@ -11088,12 +10975,10 @@ gtk_window_set_has_user_ref_count (GtkWindow *window,
 static void
 ensure_state_flag_backdrop (GtkWidget *widget)
 {
-  GdkWindow *window;
+  GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
   gboolean window_focused = TRUE;
 
-  window = gtk_widget_get_window (widget);
-
-  window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
+  window_focused = gdk_window_get_state (priv->frame_window) & GDK_WINDOW_STATE_FOCUSED;
 
   if (!window_focused)
     gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]