summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorsuzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-03 20:37:45 +0000
committersuzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-03 20:37:45 +0000
commitef3e7220440a9810be9d5ed99a0a109ea044691b (patch)
tree0e1e3ac9af0254b2063888494b99fb4e04314b5f /chrome/browser
parent45dd12ae7eb2213b04831c987bc8521b4a0bfea6 (diff)
downloadchromium_src-ef3e7220440a9810be9d5ed99a0a109ea044691b.zip
chromium_src-ef3e7220440a9810be9d5ed99a0a109ea044691b.tar.gz
chromium_src-ef3e7220440a9810be9d5ed99a0a109ea044691b.tar.bz2
Fix issue 42379
Improve GtkChromeShrinkableHBox to show invisible children properly when some children are removed or shrunk. BUG=42379 gtk_chrome_shrinkable_hbox does not always show children that should be visisble TEST=See bug report. Review URL: http://codereview.chromium.org/1703024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46270 0039d316-1c4b-4281-b951-d872f2087c98
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));
}
}