summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc46
-rw-r--r--chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h3
-rw-r--r--chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc5
3 files changed, 47 insertions, 7 deletions
diff --git a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc
index 0dccb7d..5384ff4 100644
--- a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc
+++ b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc
@@ -30,6 +30,21 @@ void CountVisibleChildren(GtkWidget* child, gpointer userdata) {
++(*reinterpret_cast<int*>(userdata));
}
+void SumChildrenWidthRequisition(GtkWidget* child, gpointer userdata) {
+ if (GTK_WIDGET_VISIBLE(child)) {
+ GtkRequisition req;
+ gtk_widget_get_child_requisition(child, &req);
+ (*reinterpret_cast<int*>(userdata)) += std::max(req.width, 0);
+ }
+}
+
+void ShowInvisibleChildren(GtkWidget* child, gpointer userdata) {
+ if (!GTK_WIDGET_VISIBLE(child)) {
+ gtk_widget_show(child);
+ ++(*reinterpret_cast<int*>(userdata));
+ }
+}
+
void ChildSizeAllocate(GtkWidget* child, gpointer userdata) {
if (!GTK_WIDGET_VISIBLE(child))
return;
@@ -118,6 +133,7 @@ static void gtk_chrome_shrinkable_hbox_class_init(
static void gtk_chrome_shrinkable_hbox_init(GtkChromeShrinkableHBox* box) {
box->hide_child_directly = FALSE;
+ box->children_width_requisition = 0;
}
static void gtk_chrome_shrinkable_hbox_set_property(GObject* object,
@@ -155,13 +171,23 @@ static void gtk_chrome_shrinkable_hbox_get_property(GObject* object,
static void gtk_chrome_shrinkable_hbox_size_allocate(
GtkWidget* widget, GtkAllocation* allocation) {
- // If we are allocated to more width, then we need to show all invisible
- // children before calling parent class's size_allocate method, because the
- // new width may be enough to show those hidden children.
- if (widget->allocation.width < allocation->width) {
- gtk_container_foreach(GTK_CONTAINER(widget),
- reinterpret_cast<GtkCallback>(gtk_widget_show),
- NULL);
+ GtkChromeShrinkableHBox* box = GTK_CHROME_SHRINKABLE_HBOX(widget);
+ gint children_width_requisition = 0;
+ gtk_container_foreach(GTK_CONTAINER(widget), SumChildrenWidthRequisition,
+ &children_width_requisition);
+
+ // If we are allocated to more width or some children are removed or shrunk,
+ // then we need to show all invisible children before calling parent class's
+ // size_allocate method, because the new width may be enough to show those
+ // hidden children.
+ if (widget->allocation.width < allocation->width ||
+ box->children_width_requisition > children_width_requisition) {
+ gint count = 0;
+ gtk_container_foreach(GTK_CONTAINER(widget), ShowInvisibleChildren, &count);
+
+ // If there were any invisible children, showing them will trigger another
+ // allocate, so we can just return here.
+ if (count > 0) return;
}
// Let the parent class do size allocation first. After that all children will
@@ -174,6 +200,7 @@ static void gtk_chrome_shrinkable_hbox_size_allocate(
gtk_chrome_shrinkable_hbox_get_visible_child_count(
GTK_CHROME_SHRINKABLE_HBOX(widget));
+ box->children_width_requisition = 0;
if (visible_children_count == 0)
return;
@@ -190,6 +217,11 @@ static void gtk_chrome_shrinkable_hbox_size_allocate(
// Shrink or hide children if necessary.
gtk_container_foreach(GTK_CONTAINER(widget), ChildSizeAllocate, &data);
+
+ // Record current width requisition of visible children, so we can know if
+ // it's necessary to show invisible children next time.
+ gtk_container_foreach(GTK_CONTAINER(widget), SumChildrenWidthRequisition,
+ &box->children_width_requisition);
}
GtkWidget* gtk_chrome_shrinkable_hbox_new(gboolean hide_child_directly,
diff --git a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h
index 02be55d..08d0b37 100644
--- a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h
+++ b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h
@@ -45,6 +45,9 @@ struct _GtkChromeShrinkableHBox {
GtkHBox hbox;
gboolean hide_child_directly;
+
+ // Private
+ int children_width_requisition;
};
struct _GtkChromeShrinkableHBoxClass {
diff --git a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc
index dd30c2c..db9981f 100644
--- a/chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc
+++ b/chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc
@@ -149,6 +149,10 @@ class GtkChromeShrinkableHBoxTest : public testing::Test {
<< " width = " << width);
allocation.width = width;
+ // Expanding the width may cause some invisible children to be shown,
+ // which will cause queue resize, so it's necessary to do another size
+ // allocation to emulate the queue resize.
+ gtk_widget_size_allocate(box_, &allocation);
gtk_widget_size_allocate(box_, &allocation);
ASSERT_NO_FATAL_FAILURE(Validate(pack_start));
}
@@ -171,6 +175,7 @@ class GtkChromeShrinkableHBoxTest : public testing::Test {
allocation.width = width;
gtk_widget_size_allocate(box_, &allocation);
+ gtk_widget_size_allocate(box_, &allocation);
ASSERT_NO_FATAL_FAILURE(Validate(pack_start));
}
}