diff options
author | suzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-21 05:59:08 +0000 |
---|---|---|
committer | suzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-21 05:59:08 +0000 |
commit | 623630cfea007bcacf01950c44d46c412d9ced8b (patch) | |
tree | 78bdd9d97037a04e13d400e05b9a43b66b7170f2 | |
parent | 53d3f3046205f2d6151f61b8ef835ad708215761 (diff) | |
download | chromium_src-623630cfea007bcacf01950c44d46c412d9ced8b.zip chromium_src-623630cfea007bcacf01950c44d46c412d9ced8b.tar.gz chromium_src-623630cfea007bcacf01950c44d46c412d9ced8b.tar.bz2 |
Re-land http://codereview.chromium.org/507022.
Fix failed Linux Views and ChromeOS build.
BUG=11258
TEST=See bug report.
Review URL: http://codereview.chromium.org/503065
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35079 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.cc | 8 | ||||
-rw-r--r-- | chrome/browser/gtk/download_shelf_gtk.cc | 4 | ||||
-rw-r--r-- | chrome/browser/gtk/gtk_expanded_container.cc | 192 | ||||
-rw-r--r-- | chrome/browser/gtk/gtk_expanded_container.h | 70 | ||||
-rw-r--r-- | chrome/browser/gtk/gtk_expanded_container_unittest.cc | 159 | ||||
-rw-r--r-- | chrome/browser/gtk/infobar_gtk.cc | 23 | ||||
-rw-r--r-- | chrome/browser/gtk/slide_animator_gtk.cc | 43 | ||||
-rw-r--r-- | chrome/browser/gtk/tab_contents_container_gtk.cc | 46 | ||||
-rw-r--r-- | chrome/browser/gtk/tab_contents_container_gtk.h | 19 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/tab_strip_gtk.cc | 4 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents_view_gtk.cc | 50 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents_view_gtk.h | 24 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 2 | ||||
-rwxr-xr-x | chrome/chrome_tests.gypi | 2 |
14 files changed, 528 insertions, 118 deletions
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index 1279dac..83c4d52 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -1583,14 +1583,6 @@ void BrowserWindowGtk::BookmarkBarIsFloating(bool is_floating) { } void BrowserWindowGtk::SetGeometryHints() { - // Do not allow the user to resize us arbitrarily small. When using the - // custom frame, the window can disappear entirely while resizing, or get - // to a size that's very hard to resize. - GdkGeometry geometry; - geometry.min_width = 100; - geometry.min_height = 100; - gtk_window_set_geometry_hints(window_, NULL, &geometry, GDK_HINT_MIN_SIZE); - // If we call gtk_window_maximize followed by gtk_window_present, compiz gets // confused and maximizes the window, but doesn't set the // GDK_WINDOW_STATE_MAXIMIZED bit. So instead, we keep track of whether to diff --git a/chrome/browser/gtk/download_shelf_gtk.cc b/chrome/browser/gtk/download_shelf_gtk.cc index 6d94b9f..0aa3c23 100644 --- a/chrome/browser/gtk/download_shelf_gtk.cc +++ b/chrome/browser/gtk/download_shelf_gtk.cc @@ -62,7 +62,9 @@ DownloadShelfGtk::DownloadShelfGtk(Browser* browser, GtkWidget* parent) // Create |hbox_|. hbox_.Own(gtk_hbox_new(FALSE, kDownloadItemPadding)); - gtk_widget_set_size_request(hbox_.get(), -1, kDownloadItemHeight); + // We want the download shelf to be horizontally shrinkable, so that the + // Chrome window can be resized freely even with many download items. + gtk_widget_set_size_request(hbox_.get(), 0, kDownloadItemHeight); // Get the padding and background color for |hbox_| right. GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1); diff --git a/chrome/browser/gtk/gtk_expanded_container.cc b/chrome/browser/gtk/gtk_expanded_container.cc new file mode 100644 index 0000000..dbcb15e --- /dev/null +++ b/chrome/browser/gtk/gtk_expanded_container.cc @@ -0,0 +1,192 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/gtk/gtk_expanded_container.h" + +#include <gtk/gtk.h> +#include <algorithm> + +namespace { + +enum { + CHILD_SIZE_REQUEST, + LAST_SIGNAL +}; + +guint expanded_container_signals[LAST_SIGNAL] = { 0 }; + +struct SizeAllocateData { + GtkWidget* container; + GtkAllocation* allocation; + int border_width; +}; + +void GetChildPosition(GtkWidget* container, GtkWidget* child, int* x, int* y) { + GValue v = { 0 }; + g_value_init(&v, G_TYPE_INT); + gtk_container_child_get_property(GTK_CONTAINER(container), child, "x", &v); + *x = g_value_get_int(&v); + gtk_container_child_get_property(GTK_CONTAINER(container), child, "y", &v); + *y = g_value_get_int(&v); + g_value_unset(&v); +} + +void ChildSizeAllocate(GtkWidget* child, gpointer userdata) { + if (!GTK_WIDGET_VISIBLE(child)) + return; + + SizeAllocateData* data = reinterpret_cast<SizeAllocateData*>(userdata); + + GtkRequisition child_requisition; + child_requisition.width = data->allocation->width - data->border_width * 2; + child_requisition.height = data->allocation->height - data->border_width * 2; + + // We need to give whoever is pulling our strings a chance to adjust the + // size of our children. + g_signal_emit(data->container, + expanded_container_signals[CHILD_SIZE_REQUEST], 0, + child, &child_requisition); + + GtkAllocation child_allocation; + child_allocation.width = child_requisition.width; + child_allocation.height = child_requisition.height; + if (child_allocation.width < 0 || child_allocation.height < 0) { + gtk_widget_get_child_requisition(child, &child_requisition); + if (child_allocation.width < 0) + child_allocation.width = child_requisition.width; + if (child_allocation.height < 0) + child_allocation.height = child_requisition.height; + } + + int x, y; + GetChildPosition(data->container, child, &x, &y); + + child_allocation.x = x + data->border_width; + child_allocation.y = y + data->border_width; + + if (GTK_WIDGET_NO_WINDOW(data->container)) { + child_allocation.x += data->allocation->x; + child_allocation.y += data->allocation->y; + } + gtk_widget_size_allocate(child, &child_allocation); +} + +void Marshal_VOID__OBJECT_BOXED(GClosure* closure, + GValue* return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue* param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) { + typedef void (*GMarshalFunc_VOID__OBJECT_BOXED) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__OBJECT_BOXED callback; + register GCClosure *cc = reinterpret_cast<GCClosure*>(closure); + register gpointer data1, data2; + + g_return_if_fail(n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA(closure)) { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } else { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + + callback = reinterpret_cast<GMarshalFunc_VOID__OBJECT_BOXED>( + marshal_data ? marshal_data : cc->callback); + + callback(data1, + g_value_get_object(param_values + 1), + g_value_get_boxed(param_values + 2), + data2); +} + +} // namespace + +G_BEGIN_DECLS + +static void gtk_expanded_container_size_allocate(GtkWidget* widget, + GtkAllocation* allocation); + +G_DEFINE_TYPE(GtkExpandedContainer, gtk_expanded_container, GTK_TYPE_FIXED) + +static void gtk_expanded_container_class_init( + GtkExpandedContainerClass *klass) { + GtkObjectClass* object_class = + reinterpret_cast<GtkObjectClass*>(klass); + + GtkWidgetClass* widget_class = + reinterpret_cast<GtkWidgetClass*>(klass); + widget_class->size_allocate = gtk_expanded_container_size_allocate; + + expanded_container_signals[CHILD_SIZE_REQUEST] = + g_signal_new("child-size-request", + G_OBJECT_CLASS_TYPE(object_class), + static_cast<GSignalFlags>(G_SIGNAL_RUN_FIRST), + NULL, + NULL, NULL, + Marshal_VOID__OBJECT_BOXED, + G_TYPE_NONE, 2, + GTK_TYPE_WIDGET, + GTK_TYPE_REQUISITION | G_SIGNAL_TYPE_STATIC_SCOPE); +} + +static void gtk_expanded_container_init(GtkExpandedContainer* container) { +} + +static void gtk_expanded_container_size_allocate(GtkWidget* widget, + GtkAllocation* allocation) { + widget->allocation = *allocation; + + if (!GTK_WIDGET_NO_WINDOW(widget) && GTK_WIDGET_REALIZED(widget)) { + gdk_window_move_resize(widget->window, + allocation->x, + allocation->y, + allocation->width, + allocation->height); + } + + SizeAllocateData data; + data.container = widget; + data.allocation = allocation; + data.border_width = gtk_container_get_border_width(GTK_CONTAINER(widget)); + + gtk_container_foreach(GTK_CONTAINER(widget), ChildSizeAllocate, &data); +} + +GtkWidget* gtk_expanded_container_new() { + return GTK_WIDGET(g_object_new(GTK_TYPE_EXPANDED_CONTAINER, NULL)); +} + +void gtk_expanded_container_put(GtkExpandedContainer* container, + GtkWidget* widget, gint x, gint y) { + g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container)); + g_return_if_fail(GTK_IS_WIDGET(widget)); + gtk_fixed_put(GTK_FIXED(container), widget, x, y); +} + +void gtk_expanded_container_move(GtkExpandedContainer* container, + GtkWidget* widget, gint x, gint y) { + g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container)); + g_return_if_fail(GTK_IS_WIDGET(widget)); + gtk_fixed_move(GTK_FIXED(container), widget, x, y); +} + +void gtk_expanded_container_set_has_window(GtkExpandedContainer* container, + gboolean has_window) { + g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container)); + g_return_if_fail(!GTK_WIDGET_REALIZED(container)); + gtk_fixed_set_has_window(GTK_FIXED(container), has_window); +} + +gboolean gtk_expanded_container_get_has_window( + GtkExpandedContainer* container) { + g_return_val_if_fail(GTK_IS_EXPANDED_CONTAINER(container), FALSE); + return gtk_fixed_get_has_window(GTK_FIXED(container)); +} + +G_END_DECLS diff --git a/chrome/browser/gtk/gtk_expanded_container.h b/chrome/browser/gtk/gtk_expanded_container.h new file mode 100644 index 0000000..396177e --- /dev/null +++ b/chrome/browser/gtk/gtk_expanded_container.h @@ -0,0 +1,70 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_GTK_GTK_EXPANDED_CONTAINER_H_ +#define CHROME_BROWSER_GTK_GTK_EXPANDED_CONTAINER_H_ + +#include <gdk/gdk.h> +#include <gtk/gtk.h> + +// A specialized container derived from GtkFixed, which expands the size of its +// children to fill the container, in one or both directions. The usage of this +// container is similar to GtkFixed. +// +// The "child-size-request" signal is optional, if you want to expand child +// widgets to customized size other than the container's size. It should have +// the following signature: +// +// void (*child_size_request)(GtkExpandedContainer* container, +// GtkWidget* child, +// GtkRequisition* requisition); +// +// This signal is emitted for each child with the requisition set to the size of +// the container. Your handler may adjust the value of the requisition. If the +// width or height is set to -1, then that direction will not be expanded, and +// the original size request of the child will be used. + +G_BEGIN_DECLS + +#define GTK_TYPE_EXPANDED_CONTAINER \ + (gtk_expanded_container_get_type()) +#define GTK_EXPANDED_CONTAINER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_EXPANDED_CONTAINER, \ + GtkExpandedContainer)) +#define GTK_EXPANDED_CONTAINER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_EXPANDED_CONTAINER, \ + GtkExpandedContainerClass)) +#define GTK_IS_EXPANDED_CONTAINER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_EXPANDED_CONTAINER)) +#define GTK_IS_EXPANDED_CONTAINER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_EXPANDED_CONTAINER)) +#define GTK_EXPANDED_CONTAINER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_EXPANDED_CONTAINER, \ + GtkExpandedContainerClass)) + +typedef struct _GtkExpandedContainer GtkExpandedContainer; +typedef struct _GtkExpandedContainerClass GtkExpandedContainerClass; + +struct _GtkExpandedContainer { + // Parent class. + GtkFixed fixed; +}; + +struct _GtkExpandedContainerClass { + GtkFixedClass parent_class; +}; + +GType gtk_expanded_container_get_type() G_GNUC_CONST; +GtkWidget* gtk_expanded_container_new(); +void gtk_expanded_container_put(GtkExpandedContainer* container, + GtkWidget* widget, gint x, gint y); +void gtk_expanded_container_move(GtkExpandedContainer* container, + GtkWidget* widget, gint x, gint y); +void gtk_expanded_container_set_has_window(GtkExpandedContainer* container, + gboolean has_window); +gboolean gtk_expanded_container_get_has_window(GtkExpandedContainer* container); + +G_END_DECLS + +#endif // CHROME_BROWSER_GTK_GTK_EXPANDED_CONTAINER_H_ diff --git a/chrome/browser/gtk/gtk_expanded_container_unittest.cc b/chrome/browser/gtk/gtk_expanded_container_unittest.cc new file mode 100644 index 0000000..d400bb1 --- /dev/null +++ b/chrome/browser/gtk/gtk_expanded_container_unittest.cc @@ -0,0 +1,159 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/gtk/gtk_expanded_container.h" + +#include "testing/gtest/include/gtest/gtest.h" + +class GtkExpandedContainerTest : public testing::Test { + protected: + GtkExpandedContainerTest() + : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)), + expanded_(gtk_expanded_container_new()) { + gtk_window_set_default_size(GTK_WINDOW(window_), 200, 200); + gtk_container_add(GTK_CONTAINER(window_), expanded_); + } + ~GtkExpandedContainerTest() { + gtk_widget_destroy(window_); + } + + bool FindChild(GtkWidget* widget) { + GList* children = gtk_container_get_children(GTK_CONTAINER(expanded_)); + for (GList* child = children; child; child = child->next) { + if (GTK_WIDGET(child->data) == widget) { + g_list_free(children); + return true; + } + } + g_list_free(children); + return false; + } + + int GetChildX(GtkWidget* widget) { + GValue x = { 0 }; + g_value_init(&x, G_TYPE_INT); + gtk_container_child_get_property(GTK_CONTAINER(expanded_), widget, "x", &x); + return g_value_get_int(&x); + } + + int GetChildY(GtkWidget* widget) { + GValue y = { 0 }; + g_value_init(&y, G_TYPE_INT); + gtk_container_child_get_property(GTK_CONTAINER(expanded_), widget, "y", &y); + return g_value_get_int(&y); + } + + protected: + GtkWidget* window_; + GtkWidget* expanded_; +}; + +TEST_F(GtkExpandedContainerTest, AddRemove) { + GtkWidget* child1 = gtk_fixed_new(); + GtkWidget* child2 = gtk_fixed_new(); + gtk_container_add(GTK_CONTAINER(expanded_), child1); + ASSERT_TRUE(FindChild(child1)); + + gtk_container_add(GTK_CONTAINER(expanded_), child2); + ASSERT_TRUE(FindChild(child2)); + ASSERT_TRUE(FindChild(child1)); + + gtk_container_remove(GTK_CONTAINER(expanded_), child1); + ASSERT_FALSE(FindChild(child1)); + ASSERT_TRUE(FindChild(child2)); + + gtk_container_remove(GTK_CONTAINER(expanded_), child2); + ASSERT_FALSE(FindChild(child2)); +} + +TEST_F(GtkExpandedContainerTest, Expand) { + GtkWidget* child1 = gtk_fixed_new(); + GtkWidget* child2 = gtk_fixed_new(); + gtk_container_add(GTK_CONTAINER(expanded_), child1); + gtk_expanded_container_put(GTK_EXPANDED_CONTAINER(expanded_), + child2, 10, 20); + gtk_widget_show_all(window_); + + GtkAllocation allocation = { 0, 0, 50, 100 }; + gtk_widget_size_allocate(expanded_, &allocation); + + EXPECT_EQ(0, child1->allocation.x); + EXPECT_EQ(0, child1->allocation.y); + EXPECT_EQ(50, child1->allocation.width); + EXPECT_EQ(100, child1->allocation.height); + + EXPECT_EQ(10, child2->allocation.x); + EXPECT_EQ(20, child2->allocation.y); + EXPECT_EQ(50, child2->allocation.width); + EXPECT_EQ(100, child2->allocation.height); + + allocation.x = 10; + allocation.y = 20; + gtk_widget_size_allocate(expanded_, &allocation); + + EXPECT_EQ(10, child1->allocation.x); + EXPECT_EQ(20, child1->allocation.y); + EXPECT_EQ(20, child2->allocation.x); + EXPECT_EQ(40, child2->allocation.y); +} + +// Test if the size allocation for children still works when using own +// GdkWindow. In this case, the children's origin starts from (0, 0) rather +// than the container's origin. +TEST_F(GtkExpandedContainerTest, HasWindow) { + GtkWidget* child = gtk_fixed_new(); + gtk_container_add(GTK_CONTAINER(expanded_), child); + gtk_expanded_container_set_has_window(GTK_EXPANDED_CONTAINER(expanded_), + TRUE); + gtk_widget_show_all(window_); + + GtkAllocation allocation = { 10, 10, 50, 100 }; + gtk_widget_size_allocate(expanded_, &allocation); + + EXPECT_EQ(0, child->allocation.x); + EXPECT_EQ(0, child->allocation.y); + EXPECT_EQ(50, child->allocation.width); + EXPECT_EQ(100, child->allocation.height); +} + +static void OnChildSizeRequest(GtkExpandedContainer* container, + GtkWidget* child, + GtkRequisition* requisition, + gpointer userdata) { + ASSERT_EQ(child, GTK_WIDGET(userdata)); + requisition->width = 250; + requisition->height = -1; +} + +TEST_F(GtkExpandedContainerTest, ChildSizeRequest) { + GtkWidget* child = gtk_fixed_new(); + gtk_widget_set_size_request(child, 10, 25); + g_signal_connect(expanded_, "child-size-request", + G_CALLBACK(OnChildSizeRequest), child); + gtk_container_add(GTK_CONTAINER(expanded_), child); + gtk_widget_show_all(window_); + + GtkAllocation allocation = { 0, 0, 300, 100 }; + gtk_widget_size_allocate(expanded_, &allocation); + + EXPECT_EQ(0, child->allocation.x); + EXPECT_EQ(0, child->allocation.y); + EXPECT_EQ(250, child->allocation.width); + EXPECT_EQ(25, child->allocation.height); +} + +TEST_F(GtkExpandedContainerTest, ChildPosition) { + GtkWidget* child = gtk_fixed_new(); + gtk_expanded_container_put(GTK_EXPANDED_CONTAINER(expanded_), + child, 10, 20); + gtk_widget_show_all(window_); + + EXPECT_EQ(10, GetChildX(child)); + EXPECT_EQ(20, GetChildY(child)); + + gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(expanded_), + child, 40, 50); + EXPECT_EQ(40, GetChildX(child)); + EXPECT_EQ(50, GetChildY(child)); +} diff --git a/chrome/browser/gtk/infobar_gtk.cc b/chrome/browser/gtk/infobar_gtk.cc index 6562bbc..c360aef 100644 --- a/chrome/browser/gtk/infobar_gtk.cc +++ b/chrome/browser/gtk/infobar_gtk.cc @@ -188,8 +188,13 @@ class AlertInfoBar : public InfoBar { : InfoBar(delegate) { std::wstring text = delegate->GetMessageText(); GtkWidget* label = gtk_label_new(WideToUTF8(text).c_str()); + // We want the label to be horizontally shrinkable, so that the Chrome + // window can be resized freely even with a very long message. + gtk_widget_set_size_request(label, 0, -1); + gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gfx::kGdkBlack); - gtk_box_pack_start(GTK_BOX(hbox_), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox_), label, TRUE, TRUE, 0); gtk_widget_show_all(border_bin_.get()); } @@ -215,13 +220,23 @@ class LinkInfoBar : public InfoBar { G_CALLBACK(OnLinkClick), this); gtk_util::SetButtonTriggersNavigation(link_button); + GtkWidget* hbox = gtk_hbox_new(FALSE, 0); + // We want the link to be horizontally shrinkable, so that the Chrome + // window can be resized freely even with a very long link. + gtk_widget_set_size_request(hbox, 0, -1); + gtk_box_pack_start(GTK_BOX(hbox_), hbox, TRUE, TRUE, 0); // If link_offset is npos, we right-align the link instead of embedding it // in the text. if (link_offset == std::wstring::npos) { - gtk_box_pack_end(GTK_BOX(hbox_), link_button, FALSE, FALSE, 0); + gtk_box_pack_end(GTK_BOX(hbox), link_button, FALSE, FALSE, 0); GtkWidget* label = gtk_label_new(WideToUTF8(display_text).c_str()); + // In order to avoid the link_button and the label overlapping with each + // other, we make the label shrinkable. + gtk_widget_set_size_request(label, 0, -1); + gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gfx::kGdkBlack); - gtk_box_pack_start(GTK_BOX(hbox_), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); } else { GtkWidget* initial_label = gtk_label_new( WideToUTF8(display_text.substr(0, link_offset)).c_str()); @@ -233,11 +248,9 @@ class LinkInfoBar : public InfoBar { // We don't want any spacing between the elements, so we pack them into // this hbox that doesn't use kElementPadding. - GtkWidget* hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), initial_label, FALSE, FALSE, 0); gtk_util::CenterWidgetInHBox(hbox, link_button, false, 0); gtk_box_pack_start(GTK_BOX(hbox), trailing_label, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox_), hbox, FALSE, FALSE, 0); } gtk_widget_show_all(border_bin_.get()); diff --git a/chrome/browser/gtk/slide_animator_gtk.cc b/chrome/browser/gtk/slide_animator_gtk.cc index 329aaa4..ba48e46 100644 --- a/chrome/browser/gtk/slide_animator_gtk.cc +++ b/chrome/browser/gtk/slide_animator_gtk.cc @@ -8,14 +8,20 @@ #include "app/slide_animation.h" #include "base/logging.h" +#include "chrome/browser/gtk/gtk_expanded_container.h" + namespace { -void OnFixedSizeAllocate(GtkWidget* fixed, - GtkAllocation* allocation, - GtkWidget* child) { - // The size of the GtkFixed has changed. We want |child_| to match widths, - // but the height should not change. - gtk_widget_set_size_request(child, allocation->width, -1); +void OnChildSizeRequest(GtkWidget* expanded, + GtkWidget* child, + GtkRequisition* requisition, + gpointer control_child_size) { + // If |control_child_size| is true, then we want |child_| to match the width + // of the |widget_|, but the height of |child_| should not change. + if (!GPOINTER_TO_INT(control_child_size)) { + requisition->width = -1; + } + requisition->height = -1; } } // namespace @@ -29,16 +35,16 @@ SlideAnimatorGtk::SlideAnimatorGtk(GtkWidget* child, : child_(child), direction_(direction), delegate_(delegate) { - widget_.Own(gtk_fixed_new()); - gtk_fixed_put(GTK_FIXED(widget_.get()), child, 0, 0); + widget_.Own(gtk_expanded_container_new()); + gtk_container_add(GTK_CONTAINER(widget_.get()), child); gtk_widget_set_size_request(widget_.get(), -1, 0); - if (control_child_size) { - // If the child requests it, we will manually set the size request for - // |child_| every time the GtkFixed changes sizes. This is mainly useful - // for bars, where we want the child to expand to fill all available space. - g_signal_connect(widget_.get(), "size-allocate", - G_CALLBACK(OnFixedSizeAllocate), child_); - } + + // If the child requests it, we will manually set the size request for + // |child_| every time the |widget_| changes sizes. This is mainly useful + // for bars, where we want the child to expand to fill all available space. + g_signal_connect(widget_.get(), "child-size-request", + G_CALLBACK(OnChildSizeRequest), + GINT_TO_POINTER(control_child_size)); // We connect to this signal to set an initial position for our child widget. // The reason we connect to this signal rather than setting the initial @@ -106,8 +112,8 @@ void SlideAnimatorGtk::AnimationProgressed(const Animation* animation) { int showing_height = static_cast<int>(req.height * animation_->GetCurrentValue()); if (direction_ == DOWN) { - gtk_fixed_move(GTK_FIXED(widget_.get()), child_, 0, - showing_height - req.height); + gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(widget_.get()), + child_, 0, showing_height - req.height); child_needs_move_ = false; } gtk_widget_set_size_request(widget_.get(), -1, showing_height); @@ -126,7 +132,8 @@ void SlideAnimatorGtk::OnChildSizeAllocate(GtkWidget* child, GtkAllocation* allocation, SlideAnimatorGtk* slider) { if (slider->child_needs_move_) { - gtk_fixed_move(GTK_FIXED(slider->widget()), child, 0, -allocation->height); + gtk_expanded_container_move(GTK_EXPANDED_CONTAINER(slider->widget()), + child, 0, -allocation->height); slider->child_needs_move_ = false; } } diff --git a/chrome/browser/gtk/tab_contents_container_gtk.cc b/chrome/browser/gtk/tab_contents_container_gtk.cc index a4fe973..fcf6a3d 100644 --- a/chrome/browser/gtk/tab_contents_container_gtk.cc +++ b/chrome/browser/gtk/tab_contents_container_gtk.cc @@ -6,30 +6,13 @@ #include "app/gfx/native_widget_types.h" #include "app/l10n_util.h" +#include "chrome/browser/gtk/gtk_expanded_container.h" #include "chrome/browser/gtk/gtk_floating_container.h" #include "chrome/browser/gtk/status_bubble_gtk.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" #include "chrome/common/notification_service.h" -namespace { - -// Allocates all normal tab contents views to the size of the passed in -// |allocation|. -void ResizeChildren(GtkWidget* widget, void* param) { - GtkAllocation* allocation = reinterpret_cast<GtkAllocation*>(param); - if (!GTK_WIDGET_VISIBLE(widget)) - return; - - if (widget->allocation.width != allocation->width || - widget->allocation.height != allocation->height) { - gtk_widget_set_size_request(widget, allocation->width, - allocation->height); - } -} - -} // namespace - TabContentsContainerGtk::TabContentsContainerGtk(StatusBubbleGtk* status_bubble) : tab_contents_(NULL), status_bubble_(status_bubble) { @@ -44,7 +27,7 @@ void TabContentsContainerGtk::Init() { // A high level overview of the TabContentsContainer: // // +- GtkFloatingContainer |floating_| -------------------------------+ - // |+- GtkFixedContainer |fixed_| -----------------------------------+| + // |+- GtkExpandedContainer |expanded_| -----------------------------+| // || || // || || // || || @@ -57,10 +40,8 @@ void TabContentsContainerGtk::Init() { floating_.Own(gtk_floating_container_new()); gtk_widget_set_name(floating_.get(), "chrome-tab-contents-container"); - fixed_ = gtk_fixed_new(); - g_signal_connect(fixed_, "size-allocate", - G_CALLBACK(OnFixedSizeAllocate), this); - gtk_container_add(GTK_CONTAINER(floating_.get()), fixed_); + expanded_ = gtk_expanded_container_new(); + gtk_container_add(GTK_CONTAINER(floating_.get()), expanded_); if (status_bubble_) { gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(floating_.get()), @@ -69,7 +50,7 @@ void TabContentsContainerGtk::Init() { G_CALLBACK(OnSetFloatingPosition), this); } - gtk_widget_show(fixed_); + gtk_widget_show(expanded_); gtk_widget_show(floating_.get()); ViewIDUtil::SetDelegateForWidget(widget(), this); @@ -105,8 +86,8 @@ void TabContentsContainerGtk::SetTabContents(TabContents* tab_contents) { gfx::NativeView widget = tab_contents_->GetNativeView(); if (widget) { - if (widget->parent != fixed_) - gtk_fixed_put(GTK_FIXED(fixed_), widget, 0, 0); + if (widget->parent != expanded_) + gtk_container_add(GTK_CONTAINER(expanded_), widget); gtk_widget_show(widget); } @@ -127,8 +108,8 @@ void TabContentsContainerGtk::DetachTabContents(TabContents* tab_contents) { // It is possible to detach an unrealized, unparented TabContents if you // slow things down enough in valgrind. Might happen in the real world, too. if (widget && widget->parent) { - DCHECK_EQ(widget->parent, fixed_); - gtk_container_remove(GTK_CONTAINER(fixed_), widget); + DCHECK_EQ(widget->parent, expanded_); + gtk_container_remove(GTK_CONTAINER(expanded_), widget); } } @@ -176,15 +157,6 @@ GtkWidget* TabContentsContainerGtk::GetWidgetForViewID(ViewID view_id) { // ----------------------------------------------------------------------------- // static -void TabContentsContainerGtk::OnFixedSizeAllocate( - GtkWidget* fixed, - GtkAllocation* allocation, - TabContentsContainerGtk* container) { - // Set all the tab contents GtkWidgets to the size of the allocation. - gtk_container_foreach(GTK_CONTAINER(fixed), ResizeChildren, allocation); -} - -// static void TabContentsContainerGtk::OnSetFloatingPosition( GtkFloatingContainer* floating_container, GtkAllocation* allocation, TabContentsContainerGtk* tab_contents_container) { diff --git a/chrome/browser/gtk/tab_contents_container_gtk.h b/chrome/browser/gtk/tab_contents_container_gtk.h index 8a7a8c7..91c2301 100644 --- a/chrome/browser/gtk/tab_contents_container_gtk.h +++ b/chrome/browser/gtk/tab_contents_container_gtk.h @@ -58,15 +58,6 @@ class TabContentsContainerGtk : public NotificationObserver, // get notified. void TabContentsDestroyed(TabContents* contents); - // Implements our hack around a GtkFixed. The entire size of the GtkFixed is - // allocated to normal tab contents views, while the status bubble is - // informed of its parent and its parent's allocation (it makes a decision - // about layout later.) - static void OnFixedSizeAllocate( - GtkWidget* fixed, - GtkAllocation* allocation, - TabContentsContainerGtk* container); - // Handler for |floating_|'s "set-floating-position" signal. During this // callback, we manually set the position of the status bubble. static void OnSetFloatingPosition( @@ -82,16 +73,16 @@ class TabContentsContainerGtk : public NotificationObserver, StatusBubbleGtk* status_bubble_; // Top of the TabContentsContainerGtk widget hierarchy. A cross between a - // GtkBin and a GtkFixed, |floating_| has |fixed_| as its one "real" child, + // GtkBin and a GtkFixed, |floating_| has |expanded_| as its one "real" child, // and the various things that hang off the bottom (status bubble, etc) have // their positions manually set in OnSetFloatingPosition. OwnedWidgetGtk floating_; - // We insert and remove TabContents GtkWidgets into this fixed_. This should - // not be a GtkVBox since there were errors with timing where the vbox was - // horizontally split with the top half displaying the current TabContents + // We insert and remove TabContents GtkWidgets into this expanded_. This + // should not be a GtkVBox since there were errors with timing where the vbox + // was horizontally split with the top half displaying the current TabContents // and bottom half displaying the loading page. - GtkWidget* fixed_; + GtkWidget* expanded_; DISALLOW_COPY_AND_ASSIGN(TabContentsContainerGtk); }; diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc index 0993372..2f2aa0e 100644 --- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc @@ -711,7 +711,9 @@ void TabStripGtk::Init() { tabstrip_.Own(gtk_fixed_new()); ViewIDUtil::SetID(tabstrip_.get(), VIEW_ID_TAB_STRIP); - gtk_widget_set_size_request(tabstrip_.get(), -1, + // We want the tab strip to be horizontally shrinkable, so that the Chrome + // window can be resized freely. + gtk_widget_set_size_request(tabstrip_.get(), 0, TabGtk::GetMinimumUnselectedSize().height()); gtk_widget_set_app_paintable(tabstrip_.get(), TRUE); gtk_drag_dest_set(tabstrip_.get(), GTK_DEST_DEFAULT_ALL, diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc index f37e3e6..2c94b7d 100644 --- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc +++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc @@ -19,6 +19,7 @@ #include "chrome/browser/gtk/blocked_popup_container_view_gtk.h" #include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/constrained_window_gtk.h" +#include "chrome/browser/gtk/gtk_expanded_container.h" #include "chrome/browser/gtk/gtk_floating_container.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/sad_tab_gtk.h" @@ -100,16 +101,6 @@ gboolean OnMouseScroll(GtkWidget* widget, GdkEventScroll* event, return FALSE; } -// Used with gtk_container_foreach to change the sizes of the children of -// |fixed_|. -void SetSizeRequest(GtkWidget* widget, gpointer userdata) { - gfx::Size* size = static_cast<gfx::Size*>(userdata); - if (widget->allocation.width != size->width() || - widget->allocation.height != size->height()) { - gtk_widget_set_size_request(widget, size->width(), size->height()); - } -} - } // namespace // static @@ -120,16 +111,18 @@ TabContentsView* TabContentsView::Create(TabContents* tab_contents) { TabContentsViewGtk::TabContentsViewGtk(TabContents* tab_contents) : TabContentsView(tab_contents), floating_(gtk_floating_container_new()), - fixed_(gtk_fixed_new()), + expanded_(gtk_expanded_container_new()), popup_view_(NULL) { - gtk_widget_set_name(fixed_, "chrome-tab-contents-view"); - g_signal_connect(fixed_, "size-allocate", + gtk_widget_set_name(expanded_, "chrome-tab-contents-view"); + g_signal_connect(expanded_, "size-allocate", G_CALLBACK(OnSizeAllocate), this); + g_signal_connect(expanded_, "child-size-request", + G_CALLBACK(OnChildSizeRequest), this); g_signal_connect(floating_.get(), "set-floating-position", G_CALLBACK(OnSetFloatingPosition), this); - gtk_container_add(GTK_CONTAINER(floating_.get()), fixed_); - gtk_widget_show(fixed_); + gtk_container_add(GTK_CONTAINER(floating_.get()), expanded_); + gtk_widget_show(expanded_); gtk_widget_show(floating_.get()); registrar_.Add(this, NotificationType::TAB_CONTENTS_CONNECTED, Source<TabContents>(tab_contents)); @@ -179,8 +172,6 @@ void TabContentsViewGtk::RemoveConstrainedWindow( void TabContentsViewGtk::CreateView(const gfx::Size& initial_size) { requested_size_ = initial_size; - gtk_widget_set_size_request(fixed_, requested_size_.width(), - requested_size_.height()); } RenderWidgetHostView* TabContentsViewGtk::CreateViewForWidget( @@ -241,9 +232,9 @@ void TabContentsViewGtk::GetContainerBounds(gfx::Rect* out) const { // animation. int x = 0; int y = 0; - if (fixed_->window) - gdk_window_get_origin(fixed_->window, &x, &y); - out->SetRect(x + fixed_->allocation.x, y + fixed_->allocation.y, + if (expanded_->window) + gdk_window_get_origin(expanded_->window, &x, &y); + out->SetRect(x + expanded_->allocation.x, y + expanded_->allocation.y, requested_size_.width(), requested_size_.height()); } @@ -360,7 +351,7 @@ void TabContentsViewGtk::StartDragging(const WebDropData& drop_data, // ----------------------------------------------------------------------------- void TabContentsViewGtk::InsertIntoContentArea(GtkWidget* widget) { - gtk_fixed_put(GTK_FIXED(fixed_), widget, 0, 0); + gtk_container_add(GTK_CONTAINER(expanded_), widget); } gboolean TabContentsViewGtk::OnMouseDown(GtkWidget* widget, @@ -369,9 +360,19 @@ gboolean TabContentsViewGtk::OnMouseDown(GtkWidget* widget, return FALSE; } -gboolean TabContentsViewGtk::OnSizeAllocate(GtkWidget* widget, - GtkAllocation* allocation, +void TabContentsViewGtk::OnChildSizeRequest(GtkWidget* widget, + GtkWidget* child, + GtkRequisition* requisition, TabContentsViewGtk* view) { + if (view->tab_contents()->delegate()) { + requisition->height += + view->tab_contents()->delegate()->GetExtraRenderViewHeight(); + } +} + +void TabContentsViewGtk::OnSizeAllocate(GtkWidget* widget, + GtkAllocation* allocation, + TabContentsViewGtk* view) { int width = allocation->width; int height = allocation->height; // |delegate()| can be NULL here during browser teardown. @@ -379,7 +380,6 @@ gboolean TabContentsViewGtk::OnSizeAllocate(GtkWidget* widget, height += view->tab_contents()->delegate()->GetExtraRenderViewHeight(); gfx::Size size(width, height); view->requested_size_ = size; - gtk_container_foreach(GTK_CONTAINER(widget), SetSizeRequest, &size); // We manually tell our RWHV to resize the renderer content. This avoids // spurious resizes from GTK+. @@ -387,8 +387,6 @@ gboolean TabContentsViewGtk::OnSizeAllocate(GtkWidget* widget, view->tab_contents()->render_widget_host_view()->SetSize(size); if (view->tab_contents()->interstitial_page()) view->tab_contents()->interstitial_page()->SetSize(size); - - return FALSE; } // static diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.h b/chrome/browser/tab_contents/tab_contents_view_gtk.h index 61e5e21..5b1d820 100644 --- a/chrome/browser/tab_contents/tab_contents_view_gtk.h +++ b/chrome/browser/tab_contents/tab_contents_view_gtk.h @@ -89,22 +89,30 @@ class TabContentsViewGtk : public TabContentsView, static gboolean OnMouseDown(GtkWidget* widget, GdkEventButton* event, TabContentsViewGtk* view); - // Used to propagate size changes on |fixed_| to its children. - static gboolean OnSizeAllocate(GtkWidget* widget, - GtkAllocation* config, + // Used to adjust the size of its children when the size of |expanded_| is + // changed. + static void OnChildSizeRequest(GtkWidget* widget, + GtkWidget* child, + GtkRequisition* requisition, TabContentsViewGtk* view); + // Used to propagate the size change of |expanded_| to our RWHV to resize the + // renderer content. + static void OnSizeAllocate(GtkWidget* widget, + GtkAllocation* allocation, + TabContentsViewGtk* view); + static void OnSetFloatingPosition( GtkFloatingContainer* floating_container, GtkAllocation* allocation, TabContentsViewGtk* tab_contents_view); - // Contains |fixed_| as its GtkBin member and a possible floating widget from - // |popup_view_|. + // Contains |expanded_| as its GtkBin member and a possible floating widget + // from |popup_view_|. OwnedWidgetGtk floating_; - // This container holds the tab's web page views. It is a GtkFixed so that we - // can control the size of the web pages. - GtkWidget* fixed_; + // This container holds the tab's web page views. It is a GtkExpandedContainer + // so that we can control the size of the web pages. + GtkWidget* expanded_; // The context menu is reset every time we show it, but we keep a pointer to // between uses so that it won't go out of scope before we're done with it. diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 1214947..baf2cdd 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -860,6 +860,8 @@ 'browser/gtk/gtk_chrome_button.h', 'browser/gtk/gtk_chrome_link_button.cc', 'browser/gtk/gtk_chrome_link_button.h', + 'browser/gtk/gtk_expanded_container.cc', + 'browser/gtk/gtk_expanded_container.h', 'browser/gtk/gtk_floating_container.cc', 'browser/gtk/gtk_floating_container.h', 'browser/gtk/gtk_theme_provider.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index aad10e6..b46f985 100755 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -686,6 +686,7 @@ 'browser/google_update_settings_posix_unittest.cc', 'browser/gtk/bookmark_bar_gtk_unittest.cc', 'browser/gtk/bookmark_editor_gtk_unittest.cc', + 'browser/gtk/gtk_expanded_container_unittest.cc', 'browser/gtk/gtk_theme_provider_unittest.cc', 'browser/gtk/go_button_gtk_unittest.cc', 'browser/gtk/keyword_editor_view_unittest.cc', @@ -902,6 +903,7 @@ ['exclude', 'browser/gtk/bookmark_bar_gtk_unittest\\.cc$'], ['exclude', 'browser/gtk/bookmark_editor_gtk_unittest\\.cc$'], ['exclude', 'browser/gtk/go_button_gtk_unittest\\.cc$'], + ['exclude', 'browser/gtk/gtk_expanded_container_unittest\\.cc$'], ['exclude', 'browser/gtk/tabs/tab_renderer_gtk_unittest\\.cc$'], ['exclude', 'browser/gtk/options/cookies_view_unittest\\.cc$'], ['exclude', 'browser/gtk/options/languages_page_gtk_unittest\\.cc$'], |