[gtk/bin-removal: 5/5] window: Derive from GtkWidget



commit 2d337a9a9fdbb468a6d5f3165ff91e99bc898527
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat May 2 15:17:20 2020 -0400

    window: Derive from GtkWidget
    
    We want to remove GtkBin and GtkContainer as they don't
    provide much useful functionality anymore. This requires
    us to move get_request_mode and compute_expand down.
    
    Update the accessible implementation to match, remove
    remnants of container implementations in GtkWindow
    subclasses, and fix livecycle issues around destroy
    vs dispose in GtkAssistant.
    
    After this commit, using gtk_container_add on window
    subclasses is not allowed anymore, but adding childing
    with <child> in ui files still works.
    
    See #2681

 gtk/a11y/gtkwindowaccessible.c |  71 +++++-------------
 gtk/gtkapplicationwindow.c     |  18 -----
 gtk/gtkassistant.c             | 100 ++++---------------------
 gtk/gtkshortcutswindow.c       | 111 ++++++++-------------------
 gtk/gtkwindow.c                | 166 ++++++++++++++++++++---------------------
 gtk/ui/gtkassistant.ui         |   1 -
 6 files changed, 147 insertions(+), 320 deletions(-)
---
diff --git a/gtk/a11y/gtkwindowaccessible.c b/gtk/a11y/gtkwindowaccessible.c
index 742cfd2776..b25eeffb96 100644
--- a/gtk/a11y/gtkwindowaccessible.c
+++ b/gtk/a11y/gtkwindowaccessible.c
@@ -46,7 +46,7 @@ static void atk_window_interface_init (AtkWindowIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (GtkWindowAccessible,
                          gtk_window_accessible,
-                         GTK_TYPE_CONTAINER_ACCESSIBLE,
+                         GTK_TYPE_WIDGET_ACCESSIBLE,
                          G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT,
                                                 atk_component_interface_init)
                          G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW,
@@ -76,33 +76,6 @@ gtk_window_accessible_notify_gtk (GObject    *obj,
     GTK_WIDGET_ACCESSIBLE_CLASS (gtk_window_accessible_parent_class)->notify_gtk (obj, pspec);
 }
 
-static GtkWidget *
-find_label_child (GtkContainer *container)
-{
-  GList *children, *tmp_list;
-  GtkWidget *child;
-
-  children = gtk_container_get_children (container);
-
-  child = NULL;
-  for (tmp_list = children; tmp_list != NULL; tmp_list = tmp_list->next)
-    {
-      if (GTK_IS_LABEL (tmp_list->data))
-        {
-          child = GTK_WIDGET (tmp_list->data);
-          break;
-        }
-      else if (GTK_IS_CONTAINER (tmp_list->data))
-        {
-          child = find_label_child (GTK_CONTAINER (tmp_list->data));
-          if (child)
-            break;
-        }
-   }
-  g_list_free (children);
-  return child;
-}
-
 static const gchar *
 gtk_window_accessible_get_name (AtkObject *accessible)
 {
@@ -236,29 +209,19 @@ gtk_window_accessible_ref_state_set (AtkObject *accessible)
   return state_set;
 }
 
-static void
-count_widget (GtkWidget *widget,
-              gint      *count)
-{
-  (*count)++;
-}
-
-static void
-prepend_widget (GtkWidget  *widget,
-               GList     **list)
-{
-  *list = g_list_prepend (*list, widget);
-}
-
 static gint
 gtk_window_accessible_get_n_children (AtkObject *object)
 {
   GtkWidget *window;
+  GtkWidget *child;
   gint count = 0;
 
   window = gtk_accessible_get_widget (GTK_ACCESSIBLE (object));
-  gtk_container_forall (GTK_CONTAINER (window),
-                       (GtkCallback) count_widget, &count);
+  for (child = gtk_widget_get_first_child (GTK_WIDGET (window));
+       child != NULL;
+       child = gtk_widget_get_next_sibling (child))
+    count++;
+
   return count;
 }
 
@@ -266,19 +229,19 @@ static AtkObject *
 gtk_window_accessible_ref_child (AtkObject *object,
                                  gint       i)
 {
-  GtkWidget *window, *ref_child;
-  GList *children = NULL;
+  GtkWidget *window, *child;
+  int pos;
 
   window = gtk_accessible_get_widget (GTK_ACCESSIBLE (object));
-  gtk_container_forall (GTK_CONTAINER (window),
-                       (GtkCallback) prepend_widget, &children);
-  ref_child = g_list_nth_data (children, i);
-  g_list_free (children);
-
-  if (!ref_child)
-    return NULL;
+  for (child = gtk_widget_get_first_child (GTK_WIDGET (window)), pos = 0;
+       child != NULL;
+       child = gtk_widget_get_next_sibling (child), pos++)
+    {
+      if (pos == i)
+        return g_object_ref (gtk_widget_get_accessible (child));
+    }
 
-  return g_object_ref (gtk_widget_get_accessible (ref_child));
+  return NULL;
 }
 
 static void
diff --git a/gtk/gtkapplicationwindow.c b/gtk/gtkapplicationwindow.c
index 6f17e65f3f..84da2e3bbe 100644
--- a/gtk/gtkapplicationwindow.c
+++ b/gtk/gtkapplicationwindow.c
@@ -668,21 +668,6 @@ gtk_application_window_real_unmap (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_application_window_parent_class)->unmap (widget);
 }
 
-static void
-gtk_application_window_real_forall_internal (GtkContainer *container,
-                                             GtkCallback   callback,
-                                             gpointer      user_data)
-{
-  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (container);
-  GtkApplicationWindowPrivate *priv = gtk_application_window_get_instance_private (window);
-
-  if (priv->menubar)
-    callback (priv->menubar, user_data);
-
-  GTK_CONTAINER_CLASS (gtk_application_window_parent_class)
-    ->forall (container, callback, user_data);
-}
-
 static void
 gtk_application_window_get_property (GObject    *object,
                                      guint       prop_id,
@@ -782,12 +767,9 @@ gtk_application_window_init (GtkApplicationWindow *window)
 static void
 gtk_application_window_class_init (GtkApplicationWindowClass *class)
 {
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
   GObjectClass *object_class = G_OBJECT_CLASS (class);
 
-  container_class->forall = gtk_application_window_real_forall_internal;
-
   widget_class->measure = gtk_application_window_measure;
   widget_class->size_allocate = gtk_application_window_real_size_allocate;
   widget_class->realize = gtk_application_window_real_realize;
diff --git a/gtk/gtkassistant.c b/gtk/gtkassistant.c
index c0b00dbf8f..607f010ca9 100644
--- a/gtk/gtkassistant.c
+++ b/gtk/gtkassistant.c
@@ -159,15 +159,11 @@ struct _GtkAssistantPrivate
   guint committed : 1;
 };
 
-static void     gtk_assistant_destroy            (GtkWidget         *widget);
+static void     gtk_assistant_dispose            (GObject           *object);
 static void     gtk_assistant_map                (GtkWidget         *widget);
 static void     gtk_assistant_unmap              (GtkWidget         *widget);
 static gboolean gtk_assistant_close_request      (GtkWindow         *window);
 
-static void     gtk_assistant_add                (GtkContainer      *container,
-                                                  GtkWidget         *page);
-static void     gtk_assistant_remove             (GtkContainer      *container,
-                                                  GtkWidget         *page);
 static void     gtk_assistant_page_set_property  (GObject           *object,
                                                   guint              property_id,
                                                   const GValue      *value,
@@ -208,10 +204,6 @@ static void     on_assistant_cancel                      (GtkWidget          *wi
                                                           GtkAssistant       *assistant);
 static void     on_assistant_last                        (GtkWidget          *widget,
                                                           GtkAssistant       *assistant);
-static void     assistant_remove_page_cb                 (GtkContainer       *container,
-                                                          GtkWidget          *page,
-                                                          GtkAssistant       *assistant);
-
 
 static int        gtk_assistant_add_page                 (GtkAssistant     *assistant,
                                                           GtkAssistantPage *page_info,
@@ -507,28 +499,23 @@ gtk_assistant_class_init (GtkAssistantClass *class)
 {
   GObjectClass *gobject_class;
   GtkWidgetClass *widget_class;
-  GtkContainerClass *container_class;
   GtkWindowClass *window_class;
 
   gobject_class   = (GObjectClass *) class;
   widget_class    = (GtkWidgetClass *) class;
-  container_class = (GtkContainerClass *) class;
   window_class    = (GtkWindowClass *) class;
 
+  gobject_class->dispose = gtk_assistant_dispose;
   gobject_class->finalize = gtk_assistant_finalize;
   gobject_class->constructed  = gtk_assistant_constructed;
   gobject_class->set_property = gtk_assistant_set_property;
   gobject_class->get_property = gtk_assistant_get_property;
 
-  widget_class->destroy = gtk_assistant_destroy;
   widget_class->map = gtk_assistant_map;
   widget_class->unmap = gtk_assistant_unmap;
 
   gtk_widget_class_set_accessible_type (widget_class, _gtk_assistant_accessible_get_type ());
 
-  container_class->add = gtk_assistant_add;
-  container_class->remove = gtk_assistant_remove;
-
   window_class->close_request = gtk_assistant_close_request;
 
   /**
@@ -665,7 +652,6 @@ gtk_assistant_class_init (GtkAssistantClass *class)
   gtk_widget_class_bind_template_child_private (widget_class, GtkAssistant, button_size_group);
   gtk_widget_class_bind_template_child_private (widget_class, GtkAssistant, title_size_group);
 
-  gtk_widget_class_bind_template_callback (widget_class, assistant_remove_page_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_assistant_close);
   gtk_widget_class_bind_template_callback (widget_class, on_assistant_apply);
   gtk_widget_class_bind_template_callback (widget_class, on_assistant_forward);
@@ -1134,9 +1120,8 @@ on_page_notify (GtkAssistantPage *page,
 }
 
 static void
-assistant_remove_page_cb (GtkContainer *container,
-                          GtkWidget    *page,
-                          GtkAssistant *assistant)
+assistant_remove_page (GtkAssistant *assistant,
+                       GtkWidget    *page)
 {
   GtkAssistantPrivate *priv = gtk_assistant_get_instance_private (assistant);
   GtkAssistantPage *page_info;
@@ -1337,9 +1322,9 @@ gtk_assistant_page_get_property (GObject      *object,
 }
 
 static void
-gtk_assistant_destroy (GtkWidget *widget)
+gtk_assistant_dispose (GObject *object)
 {
-  GtkAssistant *assistant = GTK_ASSISTANT (widget);
+  GtkAssistant *assistant = GTK_ASSISTANT (object);
   GtkAssistantPrivate *priv = gtk_assistant_get_instance_private (assistant);
 
   if (priv->model)
@@ -1352,27 +1337,14 @@ gtk_assistant_destroy (GtkWidget *widget)
 
   if (priv->content)
     {
-      GList *children, *l;
-
-      children = gtk_container_get_children (GTK_CONTAINER (priv->content));
-      for (l = children; l; l = l->next)
-        {
-          GtkWidget *page = l->data;
-          gtk_container_remove (GTK_CONTAINER (priv->content), page);
-        }
-      g_list_free (children);
-
-      /* Our GtkAssistantPage list should be empty now. */
-      g_warn_if_fail (priv->pages == NULL);
+      while (priv->pages)
+        gtk_assistant_remove_page (assistant, 0);
 
       priv->content = NULL;
     }
 
-  if (priv->sidebar)
-    priv->sidebar = NULL;
-
-  if (priv->action_area)
-    priv->action_area = NULL;
+  priv->sidebar = NULL;
+  priv->action_area = NULL;
 
   if (priv->forward_function)
     {
@@ -1391,8 +1363,7 @@ gtk_assistant_destroy (GtkWidget *widget)
       priv->visited_pages = NULL;
     }
 
-  gtk_window_set_titlebar (GTK_WINDOW (widget), NULL);
-  GTK_WIDGET_CLASS (gtk_assistant_parent_class)->destroy (widget);
+  G_OBJECT_CLASS (gtk_assistant_parent_class)->dispose (object);
 }
 
 static GList*
@@ -1478,47 +1449,6 @@ gtk_assistant_close_request (GtkWindow *window)
   return TRUE;
 }
 
-static void
-gtk_assistant_add (GtkContainer *container,
-                   GtkWidget    *page)
-{
-  GtkAssistant *assistant = GTK_ASSISTANT (container);
-  GtkAssistantPrivate *priv = gtk_assistant_get_instance_private (assistant);
-
-  /* A bit tricky here, GtkAssistant doesnt exactly play by 
-   * the rules by allowing gtk_container_add() to insert pages.
-   *
-   * For the first invocation (from the builder template invocation),
-   * let's make sure we add the actual direct container content properly.
-   */
-  if (!priv->constructed)
-    {
-      gtk_widget_set_parent (page, GTK_WIDGET (container));
-      _gtk_bin_set_child (GTK_BIN (container), page);
-      return;
-    }
-
-  gtk_assistant_append_page (GTK_ASSISTANT (container), page);
-}
-
-static void
-gtk_assistant_remove (GtkContainer *container,
-                      GtkWidget    *page)
-{
-  GtkAssistant *assistant = GTK_ASSISTANT (container);
-  GtkAssistantPrivate *priv = gtk_assistant_get_instance_private (assistant);
-
-  /* Forward this removal to the content stack */
-  if (gtk_widget_get_parent (page) == priv->content)
-    {
-      gtk_container_remove (GTK_CONTAINER (priv->content), page);
-    }
-  else
-    {
-      GTK_CONTAINER_CLASS (gtk_assistant_parent_class)->remove (container, page);
-    }
-}
-
 /**
  * gtk_assistant_new:
  *
@@ -1875,9 +1805,8 @@ gtk_assistant_remove_page (GtkAssistant *assistant,
   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
   page = gtk_assistant_get_nth_page (assistant, page_num);
-
   if (page)
-    gtk_container_remove (GTK_CONTAINER (assistant), page);
+    assistant_remove_page (assistant, page);
 
   if (priv->model)
     g_list_model_items_changed (priv->model, page_num, 1, 0);
@@ -2322,6 +2251,7 @@ static void
 gtk_assistant_buildable_interface_init (GtkBuildableIface *iface)
 {
   parent_buildable_iface = g_type_interface_peek_parent (iface);
+
   iface->custom_tag_start = gtk_assistant_buildable_custom_tag_start;
   iface->custom_finished = gtk_assistant_buildable_custom_finished;
   iface->add_child = gtk_assistant_buildable_add_child;
@@ -2342,10 +2272,8 @@ gtk_assistant_buildable_add_child (GtkBuildable *buildable,
       priv->headerbar = GTK_WIDGET (child);
       gtk_window_set_titlebar (GTK_WINDOW (buildable), priv->headerbar);
     }
-  else if (GTK_IS_WIDGET (child))
-    gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
   else
-    g_warning ("Can't add a child of type '%s' to '%s'", G_OBJECT_TYPE_NAME (child), G_OBJECT_TYPE_NAME 
(buildable));
+    parent_buildable_iface->add_child (buildable, builder, child, type);
 }
 
 gboolean
diff --git a/gtk/gtkshortcutswindow.c b/gtk/gtkshortcutswindow.c
index e8aee12510..aa235dd0ca 100644
--- a/gtk/gtkshortcutswindow.c
+++ b/gtk/gtkshortcutswindow.c
@@ -21,6 +21,7 @@
 #include "gtkshortcutswindowprivate.h"
 
 #include "gtkbox.h"
+#include "gtkbuildable.h"
 #include "gtkgrid.h"
 #include "gtkheaderbar.h"
 #include "gtkintl.h"
@@ -133,8 +134,13 @@ typedef struct
   guint              translatable : 1;
 } ViewsParserData;
 
+static void gtk_shortcuts_window_buildable_iface_init (GtkBuildableIface *iface);
 
-G_DEFINE_TYPE_WITH_PRIVATE (GtkShortcutsWindow, gtk_shortcuts_window, GTK_TYPE_WINDOW)
+
+G_DEFINE_TYPE_WITH_CODE (GtkShortcutsWindow, gtk_shortcuts_window, GTK_TYPE_WINDOW,
+                         G_ADD_PRIVATE (GtkShortcutsWindow)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                                gtk_shortcuts_window_buildable_iface_init))
 
 
 enum {
@@ -368,62 +374,27 @@ gtk_shortcuts_window_add_section (GtkShortcutsWindow  *self,
   g_free (title);
 }
 
-static void
-gtk_shortcuts_window_add (GtkContainer *container,
-                          GtkWidget    *widget)
-{
-  GtkShortcutsWindow *self = (GtkShortcutsWindow *)container;
-
-  if (GTK_IS_SHORTCUTS_SECTION (widget))
-    gtk_shortcuts_window_add_section (self, GTK_SHORTCUTS_SECTION (widget));
-  else
-    g_warning ("Can't add children of type %s to %s",
-               G_OBJECT_TYPE_NAME (widget),
-               G_OBJECT_TYPE_NAME (container));
-}
+static GtkBuildableIface *parent_buildable_iface;
 
 static void
-gtk_shortcuts_window_remove (GtkContainer *container,
-                             GtkWidget    *widget)
-{
-  GtkShortcutsWindow *self = (GtkShortcutsWindow *)container;
-  GtkShortcutsWindowPrivate *priv = gtk_shortcuts_window_get_instance_private (self);
-
-  g_signal_handlers_disconnect_by_func (widget, section_notify_cb, self);
-
-  if (widget == (GtkWidget *)priv->header_bar ||
-      widget == (GtkWidget *)priv->main_box)
-    GTK_CONTAINER_CLASS (gtk_shortcuts_window_parent_class)->remove (container, widget);
+gtk_shortcuts_window_buildable_add_child (GtkBuildable *buildable,
+                                          GtkBuilder   *builder,
+                                          GObject      *child,
+                                          const gchar  *type)
+{
+  if (GTK_IS_SHORTCUTS_SECTION (child))
+    gtk_shortcuts_window_add_section (GTK_SHORTCUTS_WINDOW (buildable),
+                                      GTK_SHORTCUTS_SECTION (child));
   else
-    gtk_container_remove (GTK_CONTAINER (priv->stack), widget);
+    parent_buildable_iface->add_child (buildable, builder, child, type);
 }
 
 static void
-gtk_shortcuts_window_forall (GtkContainer *container,
-                             GtkCallback   callback,
-                             gpointer      callback_data)
+gtk_shortcuts_window_buildable_iface_init (GtkBuildableIface *iface)
 {
-  GtkShortcutsWindow *self = (GtkShortcutsWindow *)container;
-  GtkShortcutsWindowPrivate *priv = gtk_shortcuts_window_get_instance_private (self);
-
-  if (priv->stack)
-    {
-      GList *children, *l;
-      GtkWidget *search;
-      GtkWidget *empty;
-
-      search = gtk_stack_get_child_by_name (GTK_STACK (priv->stack), "internal-search");
-      empty = gtk_stack_get_child_by_name (GTK_STACK (priv->stack), "no-search-results");
-      children = gtk_container_get_children (GTK_CONTAINER (priv->stack));
-      for (l = children; l; l = l->next)
-        {
-          GtkWidget *child = l->data;
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
 
-          if (child != search && child != empty)
-            callback (child, callback_data);
-        }
-      g_list_free (children);
-    }
+  iface->add_child = gtk_shortcuts_window_buildable_add_child;
 }
 
 static void
@@ -482,7 +453,14 @@ update_accels_for_actions (GtkShortcutsWindow *self)
   GtkShortcutsWindowPrivate *priv = gtk_shortcuts_window_get_instance_private (self);
 
   if (priv->window)
-    gtk_container_forall (GTK_CONTAINER (self), update_accels_cb, self);
+    {
+      GtkWidget *child;
+
+      for (child = gtk_widget_get_first_child (GTK_WIDGET (self));
+           child != NULL;
+           child = gtk_widget_get_next_sibling (child))
+        update_accels_cb (child, self);
+    }
 }
 
 static void
@@ -672,20 +650,9 @@ gtk_shortcuts_window_dispose (GObject *object)
 
   gtk_shortcuts_window_set_window (self, NULL);
 
-  if (priv->header_bar)
-    {
-      gtk_container_remove (GTK_CONTAINER (self), GTK_WIDGET (priv->header_bar));
-      priv->header_bar = NULL;
-      priv->popover = NULL;
-    }
-
-  if (priv->main_box)
-    {
-      gtk_container_remove (GTK_CONTAINER (self), GTK_WIDGET (priv->main_box));
-      priv->main_box = NULL;
-      priv->stack = NULL;
-      priv->search_bar = NULL;
-    }
+  priv->stack = NULL;
+  priv->search_bar = NULL;
+  priv->main_box = NULL;
 
   G_OBJECT_CLASS (gtk_shortcuts_window_parent_class)->dispose (object);
 }
@@ -761,18 +728,11 @@ gtk_shortcuts_window_unmap (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_shortcuts_window_parent_class)->unmap (widget);
 }
 
-static GType
-gtk_shortcuts_window_child_type (GtkContainer *container)
-{
-  return GTK_TYPE_SHORTCUTS_SECTION;
-}
-
 static void
 gtk_shortcuts_window_class_init (GtkShortcutsWindowClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
 
   object_class->constructed = gtk_shortcuts_window_constructed;
   object_class->finalize = gtk_shortcuts_window_finalize;
@@ -781,10 +741,6 @@ gtk_shortcuts_window_class_init (GtkShortcutsWindowClass *klass)
   object_class->dispose = gtk_shortcuts_window_dispose;
 
   widget_class->unmap = gtk_shortcuts_window_unmap;
-  container_class->add = gtk_shortcuts_window_add;
-  container_class->remove = gtk_shortcuts_window_remove;
-  container_class->child_type = gtk_shortcuts_window_child_type;
-  container_class->forall = gtk_shortcuts_window_forall;
 
   klass->close = gtk_shortcuts_window_close;
   klass->search = gtk_shortcuts_window_search;
@@ -899,10 +855,9 @@ gtk_shortcuts_window_init (GtkShortcutsWindow *self)
   priv->main_box = g_object_new (GTK_TYPE_BOX,
                            "orientation", GTK_ORIENTATION_VERTICAL,
                            NULL);
-  GTK_CONTAINER_CLASS (gtk_shortcuts_window_parent_class)->add (GTK_CONTAINER (self), GTK_WIDGET 
(priv->main_box));
+  gtk_window_set_child (GTK_WINDOW (self), priv->main_box);
 
-  priv->search_bar = g_object_new (GTK_TYPE_SEARCH_BAR,
-                                   NULL);
+  priv->search_bar = g_object_new (GTK_TYPE_SEARCH_BAR, NULL);
   g_object_bind_property (priv->search_bar, "search-mode-enabled",
                           search_button, "active",
                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 0dc421be1a..c686ddc5b2 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -172,6 +172,8 @@
 
 typedef struct
 {
+  GtkWidget             *child;
+
   GtkWidget             *attach_widget;
   GtkWidget             *default_widget;
   GtkWidget             *focus_widget;
@@ -399,11 +401,6 @@ static gboolean surface_event             (GdkSurface         *surface,
                                            GdkEvent           *event,
                                            GtkWidget          *widget);
 
-static void gtk_window_remove             (GtkContainer      *container,
-                                           GtkWidget         *widget);
-static void gtk_window_forall             (GtkContainer   *container,
-                                          GtkCallback     callback,
-                                          gpointer        callback_data);
 static gint gtk_window_focus              (GtkWidget        *widget,
                                           GtkDirectionType  direction);
 static void gtk_window_move_focus         (GtkWidget         *widget,
@@ -542,7 +539,7 @@ static GtkWindowRegion get_active_region_type (GtkWindow   *window,
                                                gint         y);
 
 
-G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
+G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_WIDGET,
                          G_ADD_PRIVATE (GtkWindow)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                gtk_window_buildable_interface_init)
@@ -637,7 +634,7 @@ gtk_window_measure (GtkWidget      *widget,
 {
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
-  GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
+  GtkWidget *child = priv->child;
   gboolean has_size_request = gtk_widget_has_size_request (widget);
   int title_min_size = 0;
   int title_nat_size = 0;
@@ -708,15 +705,35 @@ gtk_window_measure (GtkWidget      *widget,
 }
 
 static void
-gtk_window_add (GtkContainer *container,
-                GtkWidget    *child)
+gtk_window_compute_expand (GtkWidget *widget,
+                           gboolean  *hexpand,
+                           gboolean  *vexpand)
 {
-  /* Insert the child's css node now at the end so the order wrt. decoration_node is correct */
-  gtk_css_node_insert_before (gtk_widget_get_css_node (GTK_WIDGET (container)),
-                              gtk_widget_get_css_node (child),
-                              NULL);
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
 
-  GTK_CONTAINER_CLASS (gtk_window_parent_class)->add (container, child);
+  if (priv->child)
+    {
+      *hexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_HORIZONTAL);
+      *vexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_VERTICAL);
+    }
+  else
+    {
+      *hexpand = FALSE;
+      *vexpand = FALSE;
+    }
+}
+
+static GtkSizeRequestMode
+gtk_window_get_request_mode (GtkWidget *widget)
+{
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+  if (priv->child)
+    return gtk_widget_get_request_mode (priv->child);
+  else
+    return GTK_SIZE_REQUEST_CONSTANT_SIZE;
 }
 
 static void
@@ -724,7 +741,6 @@ gtk_window_class_init (GtkWindowClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
 
   quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
 
@@ -746,17 +762,15 @@ gtk_window_class_init (GtkWindowClass *klass)
   widget_class->realize = gtk_window_realize;
   widget_class->unrealize = gtk_window_unrealize;
   widget_class->size_allocate = gtk_window_size_allocate;
+  widget_class->measure = gtk_window_measure;
+  widget_class->compute_expand = gtk_window_compute_expand;
+  widget_class->get_request_mode = gtk_window_get_request_mode;
   widget_class->focus = gtk_window_focus;
   widget_class->move_focus = gtk_window_move_focus;
-  widget_class->measure = gtk_window_measure;
   widget_class->state_flags_changed = gtk_window_state_flags_changed;
   widget_class->css_changed = gtk_window_css_changed;
   widget_class->snapshot = gtk_window_snapshot;
 
-  container_class->add = gtk_window_add;
-  container_class->remove = gtk_window_remove;
-  container_class->forall = gtk_window_forall;
-
   klass->activate_default = gtk_window_real_activate_default;
   klass->activate_focus = gtk_window_real_activate_focus;
   klass->keys_changed = gtk_window_keys_changed;
@@ -2057,6 +2071,8 @@ gtk_window_buildable_add_child (GtkBuildable *buildable,
 {
   if (type && strcmp (type, "titlebar") == 0)
     gtk_window_set_titlebar (GTK_WINDOW (buildable), GTK_WIDGET (child));
+  else if (GTK_IS_WIDGET (child))
+    gtk_window_set_child (GTK_WINDOW (buildable), GTK_WIDGET (child));
   else
     parent_buildable_iface->add_child (buildable, builder, child, type);
 }
@@ -2637,7 +2653,10 @@ gtk_window_dispose (GObject *object)
   gtk_window_set_default_widget (window, NULL);
   remove_attach_widget (window);
 
+  g_clear_pointer (&priv->child, gtk_widget_unparent);
+
   G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
+
   unset_titlebar (window);
 }
 
@@ -3159,7 +3178,7 @@ gtk_window_set_titlebar (GtkWindow *window,
 
   gtk_window_enable_csd (window);
   priv->title_box = titlebar;
-  /* Same reason as in gtk_window_add */
+  /* Same reason as in gtk_window_set_child */
   gtk_css_node_insert_before (gtk_widget_get_css_node (GTK_WIDGET (window)),
                               gtk_widget_get_css_node (titlebar),
                               NULL);
@@ -4354,13 +4373,12 @@ gtk_window_update_toplevel (GtkWindow *window)
 static void
 gtk_window_map (GtkWidget *widget)
 {
-  GtkWidget *child;
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+  GtkWidget *child = priv->child;
 
   GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
 
-  child = gtk_bin_get_child (GTK_BIN (window));
   if (child != NULL && gtk_widget_get_visible (child))
     gtk_widget_map (child);
 
@@ -4412,7 +4430,7 @@ gtk_window_unmap (GtkWidget *widget)
 {
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
-  GtkWidget *child;
+  GtkWidget *child = priv->child;
   GdkSurfaceState state;
 
   GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
@@ -4432,7 +4450,6 @@ gtk_window_unmap (GtkWidget *widget)
   if (priv->title_box != NULL)
     gtk_widget_unmap (priv->title_box);
 
-  child = gtk_bin_get_child (GTK_BIN (window));
   if (child != NULL)
     gtk_widget_unmap (child);
 }
@@ -4943,9 +4960,11 @@ gtk_window_unrealize (GtkWidget *widget)
   /* Icons */
   gtk_window_unrealize_icon (window);
 
-  gtk_container_forall (GTK_CONTAINER (widget),
-                        (GtkCallback) gtk_widget_unrealize,
-                        NULL);
+  if (priv->title_box)
+    gtk_widget_unrealize (priv->title_box);
+
+  if (priv->child)
+    gtk_widget_unrealize (priv->child);
 
   g_clear_object (&priv->renderer);
 
@@ -5101,12 +5120,12 @@ gtk_window_size_allocate (GtkWidget *widget,
                           int        baseline)
 {
   GtkWindow *window = GTK_WINDOW (widget);
-  GtkWidget *child;
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+  GtkWidget *child = priv->child;
   GtkAllocation child_allocation;
 
   _gtk_window_set_allocation (window, width, height, &child_allocation);
 
-  child = gtk_bin_get_child (GTK_BIN (window));
   if (child && gtk_widget_get_visible (child))
     gtk_widget_size_allocate (child, &child_allocation, -1);
 }
@@ -5467,19 +5486,6 @@ gtk_window_key_released (GtkWidget       *widget,
   return FALSE;
 }
 
-static void
-gtk_window_remove (GtkContainer *container,
-                   GtkWidget     *widget)
-{
-  GtkWindow *window = GTK_WINDOW (container);
-  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
-
-  if (widget == priv->title_box)
-    unset_titlebar (window);
-  else
-    GTK_CONTAINER_CLASS (gtk_window_parent_class)->remove (container, widget);
-}
-
 void
 gtk_window_check_resize (GtkWindow *self)
 {
@@ -5495,39 +5501,16 @@ gtk_window_check_resize (GtkWindow *self)
     gdk_profiler_end_mark (before, "size allocation", "");
 }
 
-static void
-gtk_window_forall (GtkContainer *container,
-                   GtkCallback   callback,
-                   gpointer      callback_data)
-{
-  GtkWindow *window = GTK_WINDOW (container);
-  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
-  GtkWidget *child;
-
-  child = gtk_bin_get_child (GTK_BIN (container));
-  if (child != NULL)
-    (* callback) (child, callback_data);
-
-  if (priv->title_box != NULL &&
-      priv->titlebar == NULL)
-    (* callback) (priv->title_box, callback_data);
-}
-
 static gboolean
 gtk_window_focus (GtkWidget        *widget,
-                 GtkDirectionType  direction)
+                  GtkDirectionType  direction)
 {
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
-  GtkBin *bin;
-  GtkContainer *container;
   GtkWidget *child;
   GtkWidget *old_focus_child;
   GtkWidget *parent;
 
-  container = GTK_CONTAINER (widget);
-  bin = GTK_BIN (widget);
-
   old_focus_child = gtk_widget_get_focus_child (widget);
 
   /* We need a special implementation here to deal properly with wrapping
@@ -5543,22 +5526,22 @@ gtk_window_focus (GtkWidget        *widget,
   if (priv->focus_widget)
     {
       if (direction == GTK_DIR_LEFT ||
-         direction == GTK_DIR_RIGHT ||
-         direction == GTK_DIR_UP ||
-         direction == GTK_DIR_DOWN)
-       {
-         return FALSE;
-       }
-      
+          direction == GTK_DIR_RIGHT ||
+          direction == GTK_DIR_UP ||
+          direction == GTK_DIR_DOWN)
+        {
+          return FALSE;
+        }
+
       /* Wrapped off the end, clear the focus setting for the toplpevel */
       parent = _gtk_widget_get_parent (priv->focus_widget);
       while (parent)
-       {
+        {
           gtk_widget_set_focus_child (parent, NULL);
-         parent = _gtk_widget_get_parent (parent);
-       }
-      
-      gtk_window_set_focus (GTK_WINDOW (container), NULL);
+          parent = _gtk_widget_get_parent (parent);
+        }
+
+      gtk_window_set_focus (window, NULL);
     }
 
   /* Now try to focus the first widget in the window,
@@ -5570,7 +5553,7 @@ gtk_window_focus (GtkWidget        *widget,
       priv->title_box != old_focus_child)
     child = priv->title_box;
   else
-    child = gtk_bin_get_child (bin);
+    child = priv->child;
 
   if (child)
     {
@@ -5581,7 +5564,7 @@ gtk_window_focus (GtkWidget        *widget,
                gtk_widget_child_focus (priv->title_box, direction))
         return TRUE;
       else if (priv->title_box == child &&
-               gtk_widget_child_focus (gtk_bin_get_child (bin), direction))
+               gtk_widget_child_focus (priv->child, direction))
         return TRUE;
     }
 
@@ -8132,10 +8115,25 @@ void
 gtk_window_set_child (GtkWindow *window,
                       GtkWidget *child)
 {
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
   g_return_if_fail (GTK_IS_WINDOW (window));
   g_return_if_fail (child == NULL || GTK_IS_WIDGET (child));
 
-  gtk_window_add (GTK_CONTAINER (window), child);
+  g_clear_pointer (&priv->child, gtk_widget_unparent);
+
+  if (child)
+    {
+      /* Insert the child's css node now at the end so the order wrt.
+       * decoration_node is correct
+       */
+      gtk_css_node_insert_before (gtk_widget_get_css_node (GTK_WIDGET (window)),
+                                  gtk_widget_get_css_node (child),
+                                  NULL);
+      priv->child = child;
+      gtk_widget_set_parent (child, GTK_WIDGET (window));
+    }
+
   g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_CHILD]);
 }
 
@@ -8150,7 +8148,9 @@ gtk_window_set_child (GtkWindow *window,
 GtkWidget *
 gtk_window_get_child (GtkWindow *window)
 {
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
 
-  return gtk_bin_get_child (GTK_BIN (window));
+  return priv->child;
 }
diff --git a/gtk/ui/gtkassistant.ui b/gtk/ui/gtkassistant.ui
index d380d44257..101eb49641 100644
--- a/gtk/ui/gtkassistant.ui
+++ b/gtk/ui/gtkassistant.ui
@@ -21,7 +21,6 @@
             <child>
               <object class="GtkStack" id="content">
                 <property name="vexpand">1</property>
-                <signal name="remove" handler="assistant_remove_page_cb" swapped="no"/>
                 <child type="tab"/>
               </object>
             </child>


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