summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/views/html_dialog_view_browsertest.cc204
-rw-r--r--chrome/browser/views/tab_contents/tab_contents_view_gtk.cc11
-rw-r--r--chrome/browser/views/tabs/dragged_tab_view.cc3
-rw-r--r--chrome/chrome_tests.gypi2
-rw-r--r--views/controls/native/native_view_host_gtk.cc14
-rw-r--r--views/controls/tabbed_pane/tabbed_pane_unittest.cc5
-rw-r--r--views/widget/gtk_views_fixed.cc37
-rw-r--r--views/widget/gtk_views_fixed.h16
-rw-r--r--views/widget/widget_gtk.cc18
-rw-r--r--views/widget/widget_gtk.h5
10 files changed, 287 insertions, 28 deletions
diff --git a/chrome/browser/views/html_dialog_view_browsertest.cc b/chrome/browser/views/html_dialog_view_browsertest.cc
new file mode 100644
index 0000000..7bb9977
--- /dev/null
+++ b/chrome/browser/views/html_dialog_view_browsertest.cc
@@ -0,0 +1,204 @@
+// Copyright (c) 2010 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/test/ui/ui_test.h"
+
+#include "base/file_path.h"
+#include "base/message_loop.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/views/html_dialog_view.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "views/widget/widget.h"
+#include "views/window/window.h"
+
+using testing::Eq;
+
+namespace {
+
+// Window non-client-area means that the minimum size for the window
+// won't be the actual minimum size - our layout and resizing code
+// makes sure the chrome is always visible.
+const int kMinimumWidthToTestFor = 20;
+const int kMinimumHeightToTestFor = 30;
+
+class TestHtmlDialogUIDelegate : public HtmlDialogUIDelegate {
+ public:
+ TestHtmlDialogUIDelegate() {}
+ virtual ~TestHtmlDialogUIDelegate() {}
+
+ // HTMLDialogUIDelegate implementation:
+ virtual bool IsDialogModal() const {
+ return true;
+ }
+ virtual std::wstring GetDialogTitle() const {
+ return std::wstring(L"Test");
+ }
+ virtual GURL GetDialogContentURL() const {
+ return GURL(chrome::kAboutBlankURL);
+ }
+ virtual void GetDOMMessageHandlers(
+ std::vector<DOMMessageHandler*>* handlers) const { }
+ virtual void GetDialogSize(gfx::Size* size) const {
+ size->set_width(40);
+ size->set_height(40);
+ }
+ virtual std::string GetDialogArgs() const {
+ return std::string();
+ }
+ virtual void OnDialogClosed(const std::string& json_retval) { }
+ virtual void OnCloseContents(TabContents* source, bool* out_close_dialog) {
+ if (out_close_dialog)
+ *out_close_dialog = true;
+ }
+};
+
+} // namespace
+
+class HtmlDialogBrowserTest : public InProcessBrowserTest {
+ public:
+ HtmlDialogBrowserTest() {}
+
+#if defined(OS_WIN)
+ class WindowChangedObserver : public base::MessagePumpForUI::Observer {
+ public:
+ WindowChangedObserver() {}
+
+ static WindowChangedObserver* Get() {
+ return Singleton<WindowChangedObserver>::get();
+ }
+
+ // This method is called before processing a message.
+ virtual void WillProcessMessage(const MSG& msg) {}
+
+ // This method is called after processing a message.
+ virtual void DidProcessMessage(const MSG& msg) {
+ // Either WM_PAINT or WM_TIMER indicates the actual work of
+ // pushing through the window resizing messages is done since
+ // they are lower priority (we don't get to see the
+ // WM_WINDOWPOSCHANGED message here).
+ if (msg.message == WM_PAINT || msg.message == WM_TIMER)
+ MessageLoop::current()->Quit();
+ }
+ };
+#elif !defined(OS_MACOSX)
+ class WindowChangedObserver : public base::MessagePumpForUI::Observer {
+ public:
+ WindowChangedObserver() {}
+
+ static WindowChangedObserver* Get() {
+ return Singleton<WindowChangedObserver>::get();
+ }
+
+ // This method is called before processing a message.
+ virtual void WillProcessEvent(GdkEvent* event) {}
+
+ // This method is called after processing a message.
+ virtual void DidProcessEvent(GdkEvent* event) {
+ // Quit once the GDK_CONFIGURE event has been processed - seeing
+ // this means the window sizing request that was made actually
+ // happened.
+ if (event->type == GDK_CONFIGURE)
+ MessageLoop::current()->Quit();
+ }
+ };
+#endif
+};
+
+#if defined(OS_LINUX)
+#define MAYBE_SizeWindow SizeWindow
+#else
+// http://code.google.com/p/chromium/issues/detail?id=52602
+// Windows has some issues resizing windows- an off by one problem,
+// and a minimum size that seems too big. This file isn't included in
+// Mac builds yet.
+#define MAYBE_SizeWindow DISABLED_SizeWindow
+#endif
+
+IN_PROC_BROWSER_TEST_F(HtmlDialogBrowserTest, MAYBE_SizeWindow) {
+ HtmlDialogUIDelegate* delegate = new TestHtmlDialogUIDelegate();
+
+ HtmlDialogView* html_view =
+ new HtmlDialogView(browser()->profile(), delegate);
+ TabContents* tab_contents = browser()->GetSelectedTabContents();
+ ASSERT_TRUE(tab_contents != NULL);
+ views::Window::CreateChromeWindow(tab_contents->GetMessageBoxRootWindow(),
+ gfx::Rect(), html_view);
+ html_view->InitDialog();
+ html_view->window()->Show();
+
+ MessageLoopForUI::current()->AddObserver(WindowChangedObserver::Get());
+
+ gfx::Rect bounds;
+ html_view->GetWidget()->GetBounds(&bounds, false);
+
+ gfx::Rect set_bounds = bounds;
+ gfx::Rect actual_bounds, rwhv_bounds;
+
+ // Bigger than the default in both dimensions.
+ set_bounds.set_width(400);
+ set_bounds.set_height(300);
+
+ html_view->MoveContents(tab_contents, set_bounds);
+ ui_test_utils::RunMessageLoop();
+ html_view->GetWidget()->GetBounds(&actual_bounds, false);
+ EXPECT_EQ(set_bounds, actual_bounds);
+
+ rwhv_bounds =
+ html_view->tab_contents()->GetRenderWidgetHostView()->GetViewBounds();
+ EXPECT_LT(0, rwhv_bounds.width());
+ EXPECT_LT(0, rwhv_bounds.height());
+ EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
+ EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
+
+ // Larger in one dimension and smaller in the other.
+ set_bounds.set_width(550);
+ set_bounds.set_height(250);
+
+ html_view->MoveContents(tab_contents, set_bounds);
+ ui_test_utils::RunMessageLoop();
+ html_view->GetWidget()->GetBounds(&actual_bounds, false);
+ EXPECT_EQ(set_bounds, actual_bounds);
+
+ rwhv_bounds =
+ html_view->tab_contents()->GetRenderWidgetHostView()->GetViewBounds();
+ EXPECT_LT(0, rwhv_bounds.width());
+ EXPECT_LT(0, rwhv_bounds.height());
+ EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
+ EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
+
+ // Get very small.
+ set_bounds.set_width(kMinimumWidthToTestFor);
+ set_bounds.set_height(kMinimumHeightToTestFor);
+
+ html_view->MoveContents(tab_contents, set_bounds);
+ ui_test_utils::RunMessageLoop();
+ html_view->GetWidget()->GetBounds(&actual_bounds, false);
+ EXPECT_EQ(set_bounds, actual_bounds);
+
+ rwhv_bounds =
+ html_view->tab_contents()->GetRenderWidgetHostView()->GetViewBounds();
+ EXPECT_LT(0, rwhv_bounds.width());
+ EXPECT_LT(0, rwhv_bounds.height());
+ EXPECT_GE(set_bounds.width(), rwhv_bounds.width());
+ EXPECT_GE(set_bounds.height(), rwhv_bounds.height());
+
+ // Check to make sure we can't get to 0x0
+ set_bounds.set_width(0);
+ set_bounds.set_height(0);
+
+ html_view->MoveContents(tab_contents, set_bounds);
+ ui_test_utils::RunMessageLoop();
+ html_view->GetWidget()->GetBounds(&actual_bounds, false);
+ EXPECT_LT(0, actual_bounds.width());
+ EXPECT_LT(0, actual_bounds.height());
+
+ MessageLoopForUI::current()->RemoveObserver(WindowChangedObserver::Get());
+}
diff --git a/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc
index e8265cb..c261600 100644
--- a/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc
+++ b/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc
@@ -213,14 +213,13 @@ gfx::NativeWindow TabContentsViewGtk::GetTopLevelNativeWindow() const {
}
void TabContentsViewGtk::GetContainerBounds(gfx::Rect* out) const {
- GetBounds(out, false);
-
// Callers expect the requested bounds not the actual bounds. For example,
// during init callers expect 0x0, but Gtk layout enforces a min size of 1x1.
- GtkRequisition requisition;
- gtk_widget_get_child_requisition(GetNativeView(), &requisition);
- out->set_width(requisition.width);
- out->set_height(requisition.height);
+ GetBounds(out, false);
+
+ gfx::Size size;
+ WidgetGtk::GetRequestedSize(&size);
+ out->set_size(size);
}
void TabContentsViewGtk::StartDragging(const WebDropData& drop_data,
diff --git a/chrome/browser/views/tabs/dragged_tab_view.cc b/chrome/browser/views/tabs/dragged_tab_view.cc
index 5ee2626..8f77a87 100644
--- a/chrome/browser/views/tabs/dragged_tab_view.cc
+++ b/chrome/browser/views/tabs/dragged_tab_view.cc
@@ -163,8 +163,7 @@ void DraggedTabView::PaintDetachedView(gfx::Canvas* canvas) {
int image_x = kDragFrameBorderSize;
int image_y = tab_size_.height();
int image_w = ps.width() - kTwiceDragFrameBorderSize;
- int image_h =
- ps.height() - kTwiceDragFrameBorderSize - tab_size_.height();
+ int image_h = contents_size_.height();
scale_canvas.FillRectInt(SK_ColorBLACK, image_x, image_y, image_w, image_h);
photobooth_->PaintScreenshotIntoCanvas(
&scale_canvas,
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 1f60543..6323db8 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1764,6 +1764,7 @@
'browser/ssl/ssl_browser_tests.cc',
'browser/task_manager_browsertest.cc',
'browser/views/browser_actions_container_browsertest.cc',
+ 'browser/views/html_dialog_view_browsertest.cc',
'renderer/form_autocomplete_browsertest.cc',
'renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc',
'test/automation/dom_automation_browsertest.cc',
@@ -1897,6 +1898,7 @@
'sources!': [
'browser/extensions/browser_action_test_util_views.cc',
'browser/views/browser_actions_container_browsertest.cc',
+ 'browser/views/html_dialog_view_browsertest.cc',
],
}],
], # conditions
diff --git a/views/controls/native/native_view_host_gtk.cc b/views/controls/native/native_view_host_gtk.cc
index 79a144d..2ba10b8 100644
--- a/views/controls/native/native_view_host_gtk.cc
+++ b/views/controls/native/native_view_host_gtk.cc
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "views/controls/native/native_view_host.h"
#include "views/focus/focus_manager.h"
+#include "views/widget/gtk_views_fixed.h"
#include "views/widget/widget_gtk.h"
namespace views {
@@ -228,13 +229,16 @@ void NativeViewHostGtk::ShowWidget(int x, int y, int w, int h) {
fixed_h = std::min(installed_clip_bounds_.height(), h);
}
+ // Don't call gtk_widget_size_allocate now, as we're possibly in the
+ // middle of a re-size, and it kicks off another re-size, and you
+ // get flashing. Instead, we'll set the desired size as properties
+ // on the widget and queue the re-size.
+ gtk_views_fixed_set_widget_size(host_->native_view(), child_w, child_h);
+ gtk_fixed_move(GTK_FIXED(fixed_), host_->native_view(), child_x, child_y);
+
// Size and place the fixed_.
GetHostWidget()->PositionChild(fixed_, fixed_x, fixed_y, fixed_w, fixed_h);
- // Size and place the hosted NativeView.
- gtk_widget_set_size_request(host_->native_view(), child_w, child_h);
- gtk_fixed_move(GTK_FIXED(fixed_), host_->native_view(), child_x, child_y);
-
gtk_widget_show(fixed_);
gtk_widget_show(host_->native_view());
}
@@ -272,7 +276,7 @@ void NativeViewHostGtk::CreateFixed(bool needs_window) {
DestroyFixed();
- fixed_ = gtk_fixed_new();
+ fixed_ = gtk_views_fixed_new();
gtk_widget_set_name(fixed_, "views-native-view-host-fixed");
gtk_fixed_set_has_window(GTK_FIXED(fixed_), needs_window);
// Defeat refcounting. We need to own the fixed.
diff --git a/views/controls/tabbed_pane/tabbed_pane_unittest.cc b/views/controls/tabbed_pane/tabbed_pane_unittest.cc
index 51a4acb..1ceef86 100644
--- a/views/controls/tabbed_pane/tabbed_pane_unittest.cc
+++ b/views/controls/tabbed_pane/tabbed_pane_unittest.cc
@@ -32,6 +32,10 @@ class TabbedPaneTest : public testing::Test, WindowDelegate {
TabbedPane* tabbed_pane_;
+ void RunAllPending() {
+ message_loop_.RunAllPending();
+ }
+
private:
virtual void SetUp() {
tabbed_pane_ = new TabbedPane();
@@ -69,6 +73,7 @@ TEST_F(TabbedPaneTest, SizeAndLayout) {
// The bounds of our children should be smaller than the tabbed pane's bounds.
tabbed_pane_->SetBounds(0, 0, 100, 200);
+ RunAllPending();
gfx::Rect bounds(child1->bounds());
EXPECT_GT(bounds.width(), 0);
EXPECT_LT(bounds.width(), 100);
diff --git a/views/widget/gtk_views_fixed.cc b/views/widget/gtk_views_fixed.cc
index 0b322bb..a2a3f2f 100644
--- a/views/widget/gtk_views_fixed.cc
+++ b/views/widget/gtk_views_fixed.cc
@@ -4,12 +4,16 @@
#include "views/widget/gtk_views_fixed.h"
+#include "base/logging.h"
+
// We store whether we use the widget's allocated size as a property. Ideally
// we would stash this in GtkFixedChild, but GtkFixed doesn't allow subclassing
// gtk_fixed_put. Alternatively we could subclass GtkContainer and use our own
// API (effectively duplicating GtkFixed), but that means folks could no longer
// use the GtkFixed API else where in Chrome. For now I'm going with this route.
static const char* kUseAllocatedSize = "__VIEWS_USE_ALLOCATED_SIZE__";
+static const char* kRequisitionWidth = "__VIEWS_REQUISITION_WIDTH__";
+static const char* kRequisitionHeight = "__VIEWS_REQUISITION_HEIGHT__";
G_BEGIN_DECLS
@@ -32,13 +36,14 @@ static void gtk_views_fixed_size_allocate(GtkWidget* widget,
if (GTK_WIDGET_VISIBLE(child->widget)) {
GtkAllocation child_allocation;
- gpointer use_allocated_size = g_object_get_data(G_OBJECT(child->widget),
- kUseAllocatedSize);
+ int width, height;
+ bool use_allocated_size =
+ gtk_views_fixed_get_widget_size(child->widget, &width, &height);
if (use_allocated_size) {
// NOTE: even though the size isn't changing, we have to call
// size_allocate, otherwise things like buttons won't repaint.
- child_allocation.width = child->widget->allocation.width;
- child_allocation.height = child->widget->allocation.height;
+ child_allocation.width = width;
+ child_allocation.height = height;
} else {
GtkRequisition child_requisition;
gtk_widget_get_child_requisition(child->widget, &child_requisition);
@@ -71,9 +76,29 @@ GtkWidget* gtk_views_fixed_new(void) {
return GTK_WIDGET(g_object_new(GTK_TYPE_VIEWS_FIXED, NULL));
}
-void gtk_views_fixed_set_use_allocated_size(GtkWidget* widget, bool value) {
+void gtk_views_fixed_set_widget_size(GtkWidget* widget,
+ int width, int height) {
+ // Remember the allocation request, and set this widget up to use it.
+ bool use_requested_size = (width != 0 && height != 0);
g_object_set_data(G_OBJECT(widget), kUseAllocatedSize,
- reinterpret_cast<gpointer>(value ? 1 : 0));
+ reinterpret_cast<gpointer>(use_requested_size ? 1 : 0));
+ g_object_set_data(G_OBJECT(widget), kRequisitionWidth,
+ reinterpret_cast<gpointer>(width));
+ g_object_set_data(G_OBJECT(widget), kRequisitionHeight,
+ reinterpret_cast<gpointer>(height));
+
+ gtk_widget_queue_resize(widget);
+}
+
+bool gtk_views_fixed_get_widget_size(GtkWidget* widget,
+ int* width, int* height) {
+ DCHECK(width);
+ DCHECK(height);
+ *width = reinterpret_cast<glong>(g_object_get_data(G_OBJECT(widget),
+ kRequisitionWidth));
+ *height = reinterpret_cast<glong>(g_object_get_data(G_OBJECT(widget),
+ kRequisitionHeight));
+ return (g_object_get_data(G_OBJECT(widget), kUseAllocatedSize) != 0);
}
G_END_DECLS
diff --git a/views/widget/gtk_views_fixed.h b/views/widget/gtk_views_fixed.h
index a03c67b..e9f3fe7 100644
--- a/views/widget/gtk_views_fixed.h
+++ b/views/widget/gtk_views_fixed.h
@@ -9,10 +9,11 @@
#include <gdk/gdk.h>
#include <gtk/gtkfixed.h>
-// GtkViewsFixed is a subclass of GtkFixed that can give child widgets their
-// current size rather than their requested size. This behavior is controlled
-// by gtk_views_fixed_set_use_allocated_size; the default is to use the
-// Widget's requested size.
+// GtkViewsFixed is a subclass of GtkFixed that can give child widgets
+// a set size rather than their requisitioned size (which is actually
+// a minimum size, and that can cause issues). This behavior is
+// controlled by gtk_views_fixed_set_widget_size; the default is to
+// use the Widget's requisitioned size.
G_BEGIN_DECLS
@@ -43,7 +44,12 @@ GtkWidget* gtk_views_fixed_new();
GType gtk_views_fixed_get_type();
-void gtk_views_fixed_set_use_allocated_size(GtkWidget* widget, bool value);
+// If width and height are 0, go back to using the requisitioned size.
+// Queues up a re-size on the widget.
+void gtk_views_fixed_set_widget_size(GtkWidget* widget, int width, int height);
+
+bool gtk_views_fixed_get_widget_size(GtkWidget* widget,
+ int* width, int* height);
G_END_DECLS
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc
index 1f7afb2..f74eef13 100644
--- a/views/widget/widget_gtk.cc
+++ b/views/widget/widget_gtk.cc
@@ -331,7 +331,7 @@ void WidgetGtk::RemoveChild(GtkWidget* child) {
// closed.
if (GTK_IS_CONTAINER(window_contents_)) {
gtk_container_remove(GTK_CONTAINER(window_contents_), child);
- gtk_views_fixed_set_use_allocated_size(child, false);
+ gtk_views_fixed_set_widget_size(child, 0, 0);
}
}
@@ -340,9 +340,7 @@ void WidgetGtk::ReparentChild(GtkWidget* child) {
}
void WidgetGtk::PositionChild(GtkWidget* child, int x, int y, int w, int h) {
- GtkAllocation alloc = { x, y, w, h };
- gtk_widget_size_allocate(child, &alloc);
- gtk_views_fixed_set_use_allocated_size(child, true);
+ gtk_views_fixed_set_widget_size(child, w, h);
gtk_fixed_move(GTK_FIXED(window_contents_), child, x, y);
}
@@ -429,6 +427,18 @@ RootView* WidgetGtk::GetRootViewForWidget(GtkWidget* widget) {
return static_cast<RootView*>(user_data);
}
+void WidgetGtk::GetRequestedSize(gfx::Size* out) const {
+ int width, height;
+ if (GTK_IS_VIEWS_FIXED(widget_) &&
+ gtk_views_fixed_get_widget_size(GetNativeView(), &width, &height)) {
+ out->SetSize(width, height);
+ } else {
+ GtkRequisition requisition;
+ gtk_widget_get_child_requisition(GetNativeView(), &requisition);
+ out->SetSize(requisition.width, requisition.height);
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// WidgetGtk, ActiveWindowWatcherX::Observer implementation:
diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h
index 7e1bdd1..7a2820e 100644
--- a/views/widget/widget_gtk.h
+++ b/views/widget/widget_gtk.h
@@ -149,6 +149,11 @@ class WidgetGtk
// Returns the RootView for |widget|.
static RootView* GetRootViewForWidget(GtkWidget* widget);
+ // Gets the requested size of the widget. This can be the size
+ // stored in properties for a GtkViewsFixed, or in the requisitioned
+ // size of other kinds of widgets.
+ void GetRequestedSize(gfx::Size* out) const;
+
// Overriden from ActiveWindowWatcherX::Observer.
virtual void ActiveWindowChanged(GdkWindow* active_window);