[gtk/global-coords: 18/24] menu: Use a box
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/global-coords: 18/24] menu: Use a box
- Date: Fri, 31 May 2019 23:38:04 +0000 (UTC)
commit ae1ba79f63168c4ad53b459a8bb8ef6a435c045f
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]