[gtk/global-coords: 27/28] menu: Use a box



commit b99e853958e492379ca4b7197d0b38b9a2e69322
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu May 30 20:10:03 2019 +0000

    menu: Use a box
    
    This makes some of the GtkMenuShell api
    no longer work, since we don't let the
    menu shell code maintain the list of
    children anymore.

 gtk/gtkmenu.c        | 369 ++++++++-------------------------------------------
 gtk/gtkmenuprivate.h |   1 +
 2 files changed, 55 insertions(+), 315 deletions(-)
---
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index fc9279c01d..7b78615c77 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -121,16 +121,8 @@
 #include <gobject/gvaluecollector.h>
 #include <string.h>
 
-
-#define MENU_SCROLL_STEP1      8
-#define MENU_SCROLL_STEP2     15
-#define MENU_SCROLL_FAST_ZONE  8
-#define MENU_SCROLL_TIMEOUT1  50
-#define MENU_SCROLL_TIMEOUT2  20
-
 #define MENU_POPUP_DELAY     225
 
-#define ATTACH_INFO_KEY "gtk-menu-child-attach-info-key"
 #define ATTACHED_MENUS "gtk-attached-menus"
 
 typedef struct _GtkMenuAttachData  GtkMenuAttachData;
@@ -148,13 +140,7 @@ struct _GtkMenuPopdownData
   GdkDevice *device;
 };
 
-typedef struct
-{
-  gint effective_top_attach;
-} AttachInfo;
-
 enum {
-  MOVE_SCROLL,
   POPPED_UP,
   LAST_SIGNAL
 };
@@ -252,96 +238,6 @@ menu_queue_resize (GtkMenu *menu)
   gtk_widget_queue_resize (GTK_WIDGET (menu));
 }
 
-static void
-attach_info_free (AttachInfo *info)
-{
-  g_slice_free (AttachInfo, info);
-}
-
-static AttachInfo *
-get_attach_info (GtkWidget *child)
-{
-  GObject *object = G_OBJECT (child);
-  AttachInfo *ai = g_object_get_data (object, ATTACH_INFO_KEY);
-
-  if (!ai)
-    {
-      ai = g_slice_new0 (AttachInfo);
-      g_object_set_data_full (object, I_(ATTACH_INFO_KEY), ai,
-                              (GDestroyNotify) attach_info_free);
-    }
-
-  return ai;
-}
-
-static void
-menu_ensure_layout (GtkMenu *menu)
-{
-  GtkMenuPrivate *priv = menu->priv;
-
-  if (!priv->have_layout)
-    {
-      GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu);
-      GList *l;
-      gchar *row_occupied;
-      gint current_row;
-      gint max_bottom_attach;
-
-      /* Find extents of gridded portion
-       */
-      max_bottom_attach = 0;
-
-      /* Find empty rows */
-      row_occupied = g_malloc0 (max_bottom_attach);
-
-      /* Lay non-grid-items out in those rows
-       */
-      current_row = 0;
-      for (l = menu_shell->priv->children; l; l = l->next)
-        {
-          GtkWidget *child = l->data;
-          AttachInfo *ai = get_attach_info (child);
-
-          while (current_row < max_bottom_attach && row_occupied[current_row])
-            current_row++;
-
-          ai->effective_top_attach = current_row;
-
-          current_row++;
-        }
-
-      g_free (row_occupied);
-
-      priv->n_rows = MAX (current_row, max_bottom_attach);
-      priv->have_layout = TRUE;
-    }
-}
-
-static gint
-gtk_menu_get_n_rows (GtkMenu *menu)
-{
-  GtkMenuPrivate *priv = menu->priv;
-
-  menu_ensure_layout (menu);
-
-  return priv->n_rows;
-}
-
-static void
-get_effective_child_attach (GtkWidget *child,
-                            int       *t)
-{
-  GtkMenu *menu = GTK_MENU (gtk_widget_get_parent (child));
-  AttachInfo *ai;
-  
-  menu_ensure_layout (menu);
-
-  ai = get_attach_info (child);
-
-  if (t)
-    *t = ai->effective_top_attach;
-}
-
 static void
 gtk_menu_class_init (GtkMenuClass *class)
 {
@@ -792,6 +688,7 @@ gtk_menu_init (GtkMenu *menu)
   priv->toplevel = gtk_window_new (GTK_WINDOW_POPUP);
   gtk_container_add (GTK_CONTAINER (priv->toplevel), GTK_WIDGET (menu));
   g_signal_connect (priv->toplevel, "destroy", G_CALLBACK (gtk_widget_destroyed), &priv->toplevel);
+
   gtk_window_set_resizable (GTK_WINDOW (priv->toplevel), FALSE);
   gtk_window_set_mnemonic_modifier (GTK_WINDOW (priv->toplevel), 0);
 
@@ -805,6 +702,9 @@ gtk_menu_init (GtkMenu *menu)
   g_object_force_floating (G_OBJECT (menu));
   priv->needs_destruction_ref = TRUE;
 
+  priv->box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_widget_set_parent (priv->box, GTK_WIDGET (menu));
+
   priv->monitor_num = -1;
 
   priv->anchor_hints = GDK_ANCHOR_FLIP | GDK_ANCHOR_SLIDE | GDK_ANCHOR_RESIZE;
@@ -878,6 +778,11 @@ gtk_menu_destroy (GtkWidget *widget)
 static void
 gtk_menu_finalize (GObject *object)
 {
+  GtkMenu *menu = GTK_MENU (object);
+  GtkMenuPrivate *priv = menu->priv;
+
+  g_clear_pointer (&priv->box, gtk_widget_unparent);
+
   G_OBJECT_CLASS (gtk_menu_parent_class)->finalize (object);
 }
 
@@ -1073,9 +978,7 @@ gtk_menu_remove (GtkContainer *container,
   if (priv->old_active_menu_item == widget)
     g_clear_object (&priv->old_active_menu_item);
 
-  GTK_CONTAINER_CLASS (gtk_menu_parent_class)->remove (container, widget);
-
-  g_object_set_data (G_OBJECT (widget), I_(ATTACH_INFO_KEY), NULL);
+  gtk_container_remove (GTK_CONTAINER (priv->box), widget);
 
   menu_queue_resize (menu);
 }
@@ -1099,10 +1002,9 @@ gtk_menu_real_insert (GtkMenuShell *menu_shell,
                       gint          position)
 {
   GtkMenu *menu = GTK_MENU (menu_shell);
+  GtkMenuPrivate *priv = menu->priv;
 
-  gtk_widget_insert_before (child, GTK_WIDGET (menu), NULL);
-
-  GTK_MENU_SHELL_CLASS (gtk_menu_parent_class)->insert (menu_shell, child, position);
+  gtk_container_add (GTK_CONTAINER (priv->box), child);
 
   menu_queue_resize (menu);
 }
@@ -2034,135 +1936,30 @@ gtk_menu_unrealize (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_menu_parent_class)->unrealize (widget);
 }
 
-static gint
-calculate_line_heights (GtkMenu *menu,
-                        gint     for_width,
-                        guint  **ret_min_heights,
-                        guint  **ret_nat_heights)
-{
-  GtkMenuPrivate *priv;
-  GtkMenuShell   *menu_shell;
-  GtkWidget      *child, *widget;
-  GList          *children;
-  gint            n_heights;
-  guint          *min_heights;
-  guint          *nat_heights;
-  gint            avail_width;
-
-  priv         = menu->priv;
-  widget       = GTK_WIDGET (menu);
-  menu_shell   = GTK_MENU_SHELL (widget);
-
-  min_heights  = g_new0 (guint, gtk_menu_get_n_rows (menu));
-  nat_heights  = g_new0 (guint, gtk_menu_get_n_rows (menu));
-  n_heights    = gtk_menu_get_n_rows (menu);
-  avail_width  = for_width - (2 * priv->toggle_size + priv->accel_size);
-
-  for (children = menu_shell->priv->children; children; children = children->next)
-    {
-      gint part;
-      gint toggle_size;
-      gint t;
-      gint child_min, child_nat;
-
-      child = children->data;
-
-      if (!gtk_widget_get_visible (child))
-        continue;
-
-      get_effective_child_attach (child, &t);
-
-      gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL,
-                          avail_width,
-                          &child_min, &child_nat,
-                          NULL, NULL);
-
-      gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), &toggle_size);
-
-      part = MAX (child_min, toggle_size);
-      min_heights[t] = MAX (min_heights[t], part);
-
-      part = MAX (child_nat, toggle_size);
-      nat_heights[t] = MAX (nat_heights[t], part);
-    }
-
-  if (ret_min_heights)
-    *ret_min_heights = min_heights;
-  else
-    g_free (min_heights);
-
-  if (ret_nat_heights)
-    *ret_nat_heights = nat_heights;
-  else
-    g_free (nat_heights);
-
-  return n_heights;
-}
-
 static void
 gtk_menu_size_allocate (GtkWidget *widget,
-                        int        widget_width,
-                        int        widget_height,
+                        int        width,
+                        int        height,
                         int        baseline)
 {
-  GtkMenu *menu;
-  GtkMenuPrivate *priv;
-  GtkMenuShell *menu_shell;
-  GtkWidget *child;
-  GtkAllocation child_allocation;
-  GList *children;
-  gint i;
-  int base_width;
-
-  g_return_if_fail (GTK_IS_MENU (widget));
-
-  menu = GTK_MENU (widget);
-  menu_shell = GTK_MENU_SHELL (widget);
-  priv = menu->priv;
-
-  g_free (priv->heights);
-  priv->heights_length = calculate_line_heights (menu,
-                                                 widget_width,
-                                                 &priv->heights,
-                                                 NULL);
-
-  /* refresh our cached height request */
-  priv->requested_height = 0;
-  for (i = 0; i < priv->heights_length; i++)
-    priv->requested_height += priv->heights[i];
+  GtkMenu *menu = GTK_MENU (widget);
+  GtkMenuPrivate *priv = menu->priv;
+  GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
+  GList *children, *l;
 
-  base_width = widget_width;
-  children = menu_shell->priv->children;
-  while (children)
+  children = gtk_container_get_children (GTK_CONTAINER (priv->box));
+  for (l = children; l; l = l->next)
     {
-      child = children->data;
-      children = children->next;
-
-      if (gtk_widget_get_visible (child))
-        {
-          gint t;
+      GtkWidget *child = l->data;
 
-          get_effective_child_attach (child, &t);
-
-          child_allocation.width = base_width;
-          child_allocation.height = 0;
-          child_allocation.x = 0;
-          child_allocation.y = 0;
-
-          for (i = 0; i < t + 1; i++)
-            {
-              if (i < t)
-                child_allocation.y += priv->heights[i];
-              else
-                child_allocation.height += priv->heights[i];
-            }
-
-          gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child),
-                                              priv->toggle_size);
-
-          gtk_widget_size_allocate (child, &child_allocation, -1);
-        }
+      gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child),
+                                          priv->toggle_size);
     }
+  g_list_free (children);
+
+  gtk_widget_size_allocate (priv->box,
+                            &(GtkAllocation) { 0, 0, width, height },
+                            baseline);
 }
 
 static void
@@ -2175,59 +1972,50 @@ gtk_menu_show (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_menu_parent_class)->show (widget);
 }
 
-static void gtk_menu_measure (GtkWidget      *widget,
-                              GtkOrientation  orientation,
-                              int             for_size,
-                              int            *minimum,
-                              int            *natural,
-                              int            *minimum_baseline,
-                              int            *natural_baseline)
+static void
+gtk_menu_measure (GtkWidget      *widget,
+                  GtkOrientation  orientation,
+                  int             for_size,
+                  int            *minimum,
+                  int            *natural,
+                  int            *minimum_baseline,
+                  int            *natural_baseline)
 {
   GtkMenu *menu = GTK_MENU (widget);
-  GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
   GtkMenuPrivate *priv = gtk_menu_get_instance_private (menu);
-  GtkWidget *child;
+  GtkMenuShell *menu_shell = GTK_MENU_SHELL (widget);
+
+
+  gtk_widget_measure (priv->box,
+                      orientation,
+                      for_size,
+                      minimum, natural,
+                      minimum_baseline, natural_baseline);
 
   if (orientation == GTK_ORIENTATION_HORIZONTAL)
     {
-      GList          *children;
-      guint           max_toggle_size;
-      guint           max_accel_width;
-      gint            child_min, child_nat;
-      gint            min_width, nat_width;
-
-      min_width = nat_width = 0;
+      GList *children, *l;
+      guint max_toggle_size;
+      guint max_accel_width;
 
       max_toggle_size = 0;
       max_accel_width = 0;
 
-      children = menu_shell->priv->children;
-      while (children)
+      children = gtk_container_get_children (GTK_CONTAINER (priv->box));
+      for (l = children; l; l = l->next)
         {
+          GtkWidget *child = l->data;
           gint toggle_size;
 
-          child = children->data;
-          children = children->next;
-
-          if (! gtk_widget_get_visible (child))
+          if (!gtk_widget_get_visible (child))
             continue;
 
-          /* It's important to size_request the child
-           * before doing the toggle size request, in
-           * case the toggle size request depends on the size
-           * request of a child of the child (e.g. for ImageMenuItem)
-           */
-           gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL,
-                               -1, &child_min, &child_nat, NULL, NULL);
-
            gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), &toggle_size);
            max_toggle_size = MAX (max_toggle_size, toggle_size);
            max_accel_width = MAX (max_accel_width,
                                   GTK_MENU_ITEM (child)->priv->accelerator_width);
-
-           min_width = MAX (min_width, child_min);
-           nat_width = MAX (nat_width, child_min);
         }
+      g_list_free (children);
 
       /* If the menu doesn't include any images or check items
        * reserve the space so that all menus are consistent.
@@ -2256,60 +2044,11 @@ static void gtk_menu_measure (GtkWidget      *widget,
           g_object_unref (menu_item);
         }
 
-      min_width += 2 * max_toggle_size + max_accel_width;
-      nat_width += 2 * max_toggle_size + max_accel_width;
-
       priv->toggle_size = max_toggle_size;
       priv->accel_size  = max_accel_width;
 
-      *minimum = min_width;
-      *natural = nat_width;
-
-    }
-  else /* VERTICAL */
-    {
-      if (for_size < 0)
-        {
-          gint min_width, nat_width;
-
-          /* Menus are height-for-width only, just return the height
-           * for the minimum width
-           */
-          GTK_WIDGET_GET_CLASS (widget)->measure (widget, GTK_ORIENTATION_HORIZONTAL, -1,
-                                                  &min_width, &nat_width, NULL, NULL);
-          GTK_WIDGET_GET_CLASS (widget)->measure (widget, GTK_ORIENTATION_VERTICAL, min_width,
-                                                  minimum, natural,
-                                                  minimum_baseline, natural_baseline);
-        }
-      else
-        {
-          guint          *min_heights, *nat_heights;
-          gint            n_heights, i;
-          gint            min_height, single_height, nat_height;
-
-          min_height = nat_height = 0;
-          single_height = 0;
-
-          n_heights =
-            calculate_line_heights (menu, for_size, &min_heights, &nat_heights);
-
-          for (i = 0; i < n_heights; i++)
-            {
-              min_height += min_heights[i];
-              single_height = MAX (single_height, min_heights[i]);
-              nat_height += nat_heights[i];
-            }
-
-          min_height = MIN (min_height, single_height);
-
-          *minimum = min_height;
-          *natural = nat_height;
-
-          g_free (min_heights);
-          g_free (nat_heights);
-
-
-        }
+      *minimum += 2 * max_toggle_size + max_accel_width;
+      *natural += 2 * max_toggle_size + max_accel_width;
     }
 }
 
diff --git a/gtk/gtkmenuprivate.h b/gtk/gtkmenuprivate.h
index 02bff97776..62e8da8cba 100644
--- a/gtk/gtkmenuprivate.h
+++ b/gtk/gtkmenuprivate.h
@@ -75,6 +75,7 @@ struct _GtkMenuPrivate
    * before operating on these widgets
    */
   GtkWidget *toplevel;
+  GtkWidget *box;
 
   guint needs_destruction_ref : 1;
 


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