Commit 0026387d authored by rfevang@chromium.org's avatar rfevang@chromium.org

Limit constrained windows to the size of the parent view.

Constrained windows would get drawn partially outside the browser
window, obscuring some of the contents. This CL limits their size so
everything is in view. This mimics the behavior of the old style
dialogs.

This CL also changes the size request to use the current preferred size
of the view, instead of reusing the existing size. Some dialogs (like
the print preview) changes their size preferences when the browser
window size changes, so the old size might not be optimal any more.

Additionally, added a GetMinimumSize to the bubble frame view, as
previously GetPreferredSize would get used, effectively undoing the
additional restrictions placed based on Window sizes.

BUG=272760,274236,276150

Review URL: https://chromiumcodereview.appspot.com/22903022

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221573 0039d316-1c4b-4281-b951-d872f2087c98
parent 4e7cca28
......@@ -230,6 +230,10 @@ gfx::Point WebUILoginView::GetDialogPosition(const gfx::Size& size) {
widget_size.height() / 2 - size.height() / 2);
}
gfx::Size WebUILoginView::GetMaximumDialogSize() {
return GetWidget()->GetWindowBoundsInScreen().size();
}
void WebUILoginView::AddObserver(
web_modal::WebContentsModalDialogHostObserver* observer) {
if (observer && !observer_list_.HasObserver(observer))
......
......@@ -63,6 +63,7 @@ class WebUILoginView : public views::View,
// Overridden from web_modal::WebContentsModalDialogHost:
virtual gfx::NativeView GetHostView() const OVERRIDE;
virtual gfx::Point GetDialogPosition(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetMaximumDialogSize() OVERRIDE;
virtual void AddObserver(
web_modal::WebContentsModalDialogHostObserver* observer) OVERRIDE;
virtual void RemoveObserver(
......
......@@ -311,6 +311,12 @@ gfx::Point ExtensionHost::GetDialogPosition(const gfx::Size& size) {
std::max(0, (bounds.height() - size.height()) / 2));
}
gfx::Size ExtensionHost::GetMaximumDialogSize() {
if (!GetVisibleWebContents())
return gfx::Size();
return GetVisibleWebContents()->GetView()->GetViewBounds().size();
}
void ExtensionHost::AddObserver(
web_modal::WebContentsModalDialogHostObserver* observer) {
}
......
......@@ -208,6 +208,7 @@ class ExtensionHost : public content::WebContentsDelegate,
// web_modal::WebContentsModalDialogHost
virtual gfx::NativeView GetHostView() const OVERRIDE;
virtual gfx::Point GetDialogPosition(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetMaximumDialogSize() OVERRIDE;
virtual void AddObserver(
web_modal::WebContentsModalDialogHostObserver* observer) OVERRIDE;
virtual void RemoveObserver(
......
......@@ -46,6 +46,10 @@ class PrintPreviewTestBrowserWindow
return gfx::Point();
}
virtual gfx::Size GetMaximumDialogSize() OVERRIDE {
return gfx::Size();
}
virtual void AddObserver(
WebContentsModalDialogHostObserver* observer) OVERRIDE {}
virtual void RemoveObserver(
......
......@@ -129,6 +129,7 @@ class NativeAppWindowCocoa : public apps::NativeAppWindow {
// WebContentsModalDialogHost implementation.
virtual gfx::NativeView GetHostView() const OVERRIDE;
virtual gfx::Point GetDialogPosition(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetMaximumDialogSize() OVERRIDE;
virtual void AddObserver(
web_modal::WebContentsModalDialogHostObserver* observer) OVERRIDE;
virtual void RemoveObserver(
......
......@@ -794,6 +794,11 @@ gfx::Point NativeAppWindowCocoa::GetDialogPosition(const gfx::Size& size) {
return gfx::Point();
}
gfx::Size NativeAppWindowCocoa::GetMaximumDialogSize() {
NOTIMPLEMENTED();
return gfx::Size();
}
void NativeAppWindowCocoa::AddObserver(
web_modal::WebContentsModalDialogHostObserver* observer) {
NOTIMPLEMENTED();
......
......@@ -384,6 +384,13 @@ gfx::Point NativeAppWindowGtk::GetDialogPosition(const gfx::Size& size) {
current_height / 2 - size.height() / 2);
}
gfx::Size NativeAppWindowGtk::GetMaximumDialogSize() {
gint current_width = 0;
gint current_height = 0;
gtk_window_get_size(window_, &current_width, &current_height);
return gfx::Size(current_width, current_height);
}
void NativeAppWindowGtk::AddObserver(
web_modal::WebContentsModalDialogHostObserver* observer) {
observer_list_.AddObserver(observer);
......
......@@ -77,6 +77,7 @@ class NativeAppWindowGtk : public apps::NativeAppWindow,
// web_modal::WebContentsModalDialogHost implementation.
virtual gfx::NativeView GetHostView() const OVERRIDE;
virtual gfx::Point GetDialogPosition(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetMaximumDialogSize() OVERRIDE;
virtual void AddObserver(
web_modal::WebContentsModalDialogHostObserver* observer) OVERRIDE;
virtual void RemoveObserver(
......
......@@ -449,6 +449,10 @@ gfx::Point NativeAppWindowViews::GetDialogPosition(const gfx::Size& size) {
shell_window_size.height() / 2 - size.height() / 2);
}
gfx::Size NativeAppWindowViews::GetMaximumDialogSize() {
return window_->GetWindowBoundsInScreen().size();
}
void NativeAppWindowViews::AddObserver(
web_modal::WebContentsModalDialogHostObserver* observer) {
observer_list_.AddObserver(observer);
......
......@@ -148,6 +148,7 @@ class NativeAppWindowViews : public apps::NativeAppWindow,
// web_modal::WebContentsModalDialogHost implementation.
virtual gfx::NativeView GetHostView() const OVERRIDE;
virtual gfx::Point GetDialogPosition(const gfx::Size& size) OVERRIDE;
virtual gfx::Size GetMaximumDialogSize() OVERRIDE;
virtual void AddObserver(
web_modal::WebContentsModalDialogHostObserver* observer) OVERRIDE;
virtual void RemoveObserver(
......
......@@ -570,11 +570,19 @@ void ConstrainedWindowFrameView::InitClass() {
void UpdateWebContentsModalDialogPosition(
views::Widget* widget,
web_modal::WebContentsModalDialogHost* dialog_host) {
gfx::Size size = widget->GetWindowBoundsInScreen().size();
gfx::Point position = dialog_host->GetDialogPosition(size);
gfx::Size size = widget->GetRootView()->GetPreferredSize();
views::Border* border =
widget->non_client_view()->frame_view()->border();
gfx::Size max_size = dialog_host->GetMaximumDialogSize();
// Enlarge the max size by the top border, as the dialog will be shifted
// outside the area specified by the dialog host by this amount later in the
// function.
// Border may be null during widget initialization.
if (border)
max_size.Enlarge(0, border->GetInsets().top());
size.SetToMin(max_size);
gfx::Point position = dialog_host->GetDialogPosition(size);
if (border) {
// Align the first row of pixels inside the border. This is the apparent
// top of the dialog.
......
// Copyright 2013 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/ui/views/constrained_window_views.h"
#include "components/web_modal/web_contents_modal_dialog_host.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_delegate.h"
namespace web_modal {
class WebContentsModalDialogHostObserver;
}
namespace views {
class DialogContents : public DialogDelegateView {
public:
DialogContents() {}
virtual ~DialogContents() {}
void set_preferred_size(const gfx::Size& preferred_size) {
preferred_size_ = preferred_size;
}
// Overriden from DialogDelegateView:
virtual View* GetContentsView() OVERRIDE { return this; }
virtual gfx::Size GetPreferredSize() OVERRIDE { return preferred_size_; }
virtual gfx::Size GetMinimumSize() OVERRIDE { return gfx::Size(); }
private:
gfx::Size preferred_size_;
DISALLOW_COPY_AND_ASSIGN(DialogContents);
};
class DialogHost : public web_modal::WebContentsModalDialogHost {
public:
explicit DialogHost(gfx::NativeView host_view)
: host_view_(host_view),
max_dialog_size_(5000, 5000) {
}
virtual ~DialogHost() {}
void set_max_dialog_size(const gfx::Size& max_dialog_size) {
max_dialog_size_ = max_dialog_size;
}
// Overridden from WebContentsModalDialogHost:
virtual gfx::NativeView GetHostView() const OVERRIDE { return host_view_; }
virtual gfx::Point GetDialogPosition(const gfx::Size& size) OVERRIDE {
return gfx::Point();
}
virtual gfx::Size GetMaximumDialogSize() OVERRIDE { return max_dialog_size_; }
virtual void AddObserver(
web_modal::WebContentsModalDialogHostObserver* observer) OVERRIDE {};
virtual void RemoveObserver(
web_modal::WebContentsModalDialogHostObserver* observer) OVERRIDE {};
private:
gfx::NativeView host_view_;
gfx::Size max_dialog_size_;
DISALLOW_COPY_AND_ASSIGN(DialogHost);
};
typedef ViewsTestBase ConstrainedWindowViewsTest;
TEST_F(ConstrainedWindowViewsTest, UpdateDialogPosition) {
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
Widget parent;
parent.Init(params);
DialogContents* contents = new DialogContents;
Widget* dialog =
CreateBrowserModalDialogViews(contents, parent.GetNativeWindow());
DialogHost dialog_host(parent.GetNativeView());
UpdateWebContentsModalDialogPosition(dialog, &dialog_host);
// Set the preferred size to something larger than the size of a dialog with
// no content.
gfx::Size preferred_size = dialog->GetClientAreaBoundsInScreen().size();
preferred_size.Enlarge(50, 50);
contents->set_preferred_size(preferred_size);
UpdateWebContentsModalDialogPosition(dialog, &dialog_host);
// Now increase the preferred content area and make sure the dialog grows by
// the same amount after the position is updated.
gfx::Size expected_size = dialog->GetClientAreaBoundsInScreen().size();
expected_size.Enlarge(200, 200);
preferred_size.Enlarge(200, 200);
contents->set_preferred_size(preferred_size);
UpdateWebContentsModalDialogPosition(dialog, &dialog_host);
EXPECT_EQ(expected_size, dialog->GetClientAreaBoundsInScreen().size());
// Make sure the dialog shrinks when the preferred content area shrinks.
expected_size.Enlarge(-200, -200);
preferred_size.Enlarge(-200, -200);
contents->set_preferred_size(preferred_size);
UpdateWebContentsModalDialogPosition(dialog, &dialog_host);
EXPECT_EQ(expected_size, dialog->GetClientAreaBoundsInScreen().size());
// Make sure the dialog is never larger than the max dialog size the dialog
// host can handle.
gfx::Size full_dialog_size = dialog->GetClientAreaBoundsInScreen().size();
gfx::Size max_dialog_size = full_dialog_size;
max_dialog_size.Enlarge(-100, -100);
dialog_host.set_max_dialog_size(max_dialog_size);
UpdateWebContentsModalDialogPosition(dialog, &dialog_host);
// The top border of the dialog is intentionally drawn outside the area
// specified by the dialog host, so add it to the size the dialog is expected
// to occupy.
expected_size = max_dialog_size;
Border* border = dialog->non_client_view()->frame_view()->border();
if (border)
expected_size.Enlarge(0, border->GetInsets().top());
EXPECT_EQ(expected_size,
dialog->non_client_view()->GetBoundsInScreen().size());
// Enlarge the max area again and make sure the dialog again uses its
// preferred size.
dialog_host.set_max_dialog_size(gfx::Size(5000, 5000));
UpdateWebContentsModalDialogPosition(dialog, &dialog_host);
EXPECT_EQ(full_dialog_size, dialog->GetClientAreaBoundsInScreen().size());
}
} // namespace views
......@@ -99,6 +99,20 @@ class BrowserViewLayout::WebContentsModalDialogHostViews
return gfx::Point(middle_x - size.width() / 2, top_y);
}
virtual gfx::Size GetMaximumDialogSize() OVERRIDE {
gfx::Rect content_area =
browser_view_layout_->contents_container_->ConvertRectToWidget(
browser_view_layout_->contents_container_->GetLocalBounds());
gfx::Size max_dialog_size = content_area.size();
// Adjust for difference in alignment between the dialog top and the top of
// the content area.
int height_offset = content_area.y() -
browser_view_layout_->web_contents_modal_dialog_top_y_;
max_dialog_size.Enlarge(0, height_offset);
return max_dialog_size;
}
// Add/remove observer.
virtual void AddObserver(
WebContentsModalDialogHostObserver* observer) OVERRIDE {
......
......@@ -1641,6 +1641,7 @@
'browser/ui/views/bookmarks/bookmark_bubble_view_unittest.cc',
'browser/ui/views/bookmarks/bookmark_sync_promo_view_unittest.cc',
'browser/ui/views/confirm_bubble_views_unittest.cc',
'browser/ui/views/constrained_window_views_unittest.cc',
'browser/ui/views/crypto_module_password_dialog_view_unittest.cc',
'browser/ui/views/extensions/browser_action_drag_data_unittest.cc',
'browser/ui/views/first_run_bubble_unittest.cc',
......
......@@ -6,8 +6,11 @@
#define COMPONENTS_WEB_MODAL_WEB_CONTENTS_MODAL_DIALOG_HOST_H_
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/point.h"
#include "ui/gfx/size.h"
namespace gfx {
class Point;
class Size;
}
namespace web_modal {
......@@ -39,6 +42,9 @@ class WebContentsModalDialogHost {
// view.
virtual gfx::Point GetDialogPosition(const gfx::Size& size) = 0;
// Returns the maximum dimensions a dialog can have.
virtual gfx::Size GetMaximumDialogSize() = 0;
// Add/remove observer.
virtual void AddObserver(WebContentsModalDialogHostObserver* observer) = 0;
virtual void RemoveObserver(WebContentsModalDialogHostObserver* observer) = 0;
......
......@@ -168,18 +168,11 @@ gfx::Insets BubbleFrameView::GetInsets() const {
}
gfx::Size BubbleFrameView::GetPreferredSize() {
const gfx::Size client(GetWidget()->client_view()->GetPreferredSize());
gfx::Size size(GetUpdatedWindowBounds(gfx::Rect(), client, false).size());
// Accommodate the width of the title bar elements.
int title_bar_width = GetInsets().width() + border()->GetInsets().width();
if (!title_->text().empty())
title_bar_width += kTitleLeftInset + title_->GetPreferredSize().width();
if (close_->visible())
title_bar_width += close_->width() + 1;
if (titlebar_extra_view_ != NULL)
title_bar_width += titlebar_extra_view_->GetPreferredSize().width();
size.SetToMax(gfx::Size(title_bar_width, 0));
return size;
return GetSizeForClientSize(GetWidget()->client_view()->GetPreferredSize());
}
gfx::Size BubbleFrameView::GetMinimumSize() {
return GetSizeForClientSize(GetWidget()->client_view()->GetMinimumSize());
}
void BubbleFrameView::Layout() {
......@@ -334,4 +327,19 @@ void BubbleFrameView::OffsetArrowIfOffScreen(const gfx::Rect& anchor_rect,
SchedulePaint();
}
gfx::Size BubbleFrameView::GetSizeForClientSize(const gfx::Size& client_size) {
gfx::Size size(
GetUpdatedWindowBounds(gfx::Rect(), client_size, false).size());
// Accommodate the width of the title bar elements.
int title_bar_width = GetInsets().width() + border()->GetInsets().width();
if (!title_->text().empty())
title_bar_width += kTitleLeftInset + title_->GetPreferredSize().width();
if (close_->visible())
title_bar_width += close_->width() + 1;
if (titlebar_extra_view_ != NULL)
title_bar_width += titlebar_extra_view_->GetPreferredSize().width();
size.SetToMax(gfx::Size(title_bar_width, 0));
return size;
}
} // namespace views
......@@ -46,6 +46,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
// View overrides:
virtual gfx::Insets GetInsets() const OVERRIDE;
virtual gfx::Size GetPreferredSize() OVERRIDE;
virtual gfx::Size GetMinimumSize() OVERRIDE;
virtual void Layout() OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
virtual void ChildPreferredSizeChanged(View* child) OVERRIDE;
......@@ -87,6 +88,9 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
void OffsetArrowIfOffScreen(const gfx::Rect& anchor_rect,
const gfx::Size& client_size);
// Calculates the size needed to accommodate the given client area.
gfx::Size GetSizeForClientSize(const gfx::Size& client_size);
// The bubble border.
BubbleBorder* bubble_border_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment