diff options
Diffstat (limited to 'chromium/components/constrained_window')
5 files changed, 56 insertions, 5 deletions
diff --git a/chromium/components/constrained_window/BUILD.gn b/chromium/components/constrained_window/BUILD.gn index 8cff9755f0c..cc02308279a 100644 --- a/chromium/components/constrained_window/BUILD.gn +++ b/chromium/components/constrained_window/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/ui.gni") +import("//ui/base/ui_features.gni") static_library("constrained_window") { sources = [ @@ -24,6 +25,7 @@ static_library("constrained_window") { "//components/guest_view/browser", "//components/web_modal", "//content/public/browser", + "//ui/display", "//ui/views", ] public_deps = [ diff --git a/chromium/components/constrained_window/DEPS b/chromium/components/constrained_window/DEPS index 4950d97c958..b4fd76f3ab4 100644 --- a/chromium/components/constrained_window/DEPS +++ b/chromium/components/constrained_window/DEPS @@ -4,6 +4,7 @@ include_rules = [ "+content/public/browser", "+ui/aura", "+ui/base", + "+ui/display", "+ui/gfx", "+ui/views", "+ui/wm", diff --git a/chromium/components/constrained_window/constrained_window_views.cc b/chromium/components/constrained_window/constrained_window_views.cc index 3ed86ce0685..e493eaa7085 100644 --- a/chromium/components/constrained_window/constrained_window_views.cc +++ b/chromium/components/constrained_window/constrained_window_views.cc @@ -13,6 +13,8 @@ #include "components/web_modal/web_contents_modal_dialog_host.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" #include "ui/views/border.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_observer.h" @@ -108,8 +110,20 @@ void UpdateModalDialogPosition(views::Widget* widget, position.set_y(position.y() - border->GetInsets().top()); } - if (widget->is_top_level()) + if (widget->is_top_level()) { position += host_widget->GetClientAreaBoundsInScreen().OffsetFromOrigin(); + // If the dialog extends partially off any display, clamp its position to + // be fully visible within that display. If the dialog doesn't intersect + // with any display clamp its position to be fully on the nearest display. + gfx::Rect display_rect = gfx::Rect(position, size); + const display::Display display = + display::Screen::GetScreen()->GetDisplayNearestWindow( + dialog_host->GetHostView()); + const gfx::Rect work_area = display.work_area(); + if (!work_area.Contains(display_rect)) + display_rect.AdjustToFit(work_area); + position = display_rect.origin(); + } widget->SetBounds(gfx::Rect(position, size)); } diff --git a/chromium/components/constrained_window/constrained_window_views_client.h b/chromium/components/constrained_window/constrained_window_views_client.h index de58b2cb0f4..739f7aaadf6 100644 --- a/chromium/components/constrained_window/constrained_window_views_client.h +++ b/chromium/components/constrained_window/constrained_window_views_client.h @@ -7,10 +7,6 @@ #include "ui/gfx/native_widget_types.h" -namespace content { -class WebContents; -} - namespace web_modal { class ModalDialogHost; } diff --git a/chromium/components/constrained_window/constrained_window_views_unittest.cc b/chromium/components/constrained_window/constrained_window_views_unittest.cc index a0dd9dfddc3..26a4b6a21b7 100644 --- a/chromium/components/constrained_window/constrained_window_views_unittest.cc +++ b/chromium/components/constrained_window/constrained_window_views_unittest.cc @@ -5,10 +5,14 @@ #include "components/constrained_window/constrained_window_views.h" #include <memory> +#include <vector> #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "components/constrained_window/constrained_window_views_client.h" #include "components/web_modal/test_web_contents_modal_dialog_host.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -228,4 +232,38 @@ TEST_F(ConstrainedWindowViewsTest, NullModalParent) { widget->CloseNow(); } +// Make sure dialogs presented off-screen are properly clamped to the nearest +// screen. +TEST_F(ConstrainedWindowViewsTest, ClampDialogToNearestDisplay) { + // Make sure the dialog will fit fully on the display + contents()->set_preferred_size(gfx::Size(200, 100)); + + // First, make sure the host and dialog are sized and positioned. + UpdateWebContentsModalDialogPosition(dialog(), dialog_host()); + + const display::Screen* screen = display::Screen::GetScreen(); + const display::Display display = screen->GetPrimaryDisplay(); + // Within the tests there is only 1 display. Error if that ever changes. + EXPECT_EQ(screen->GetNumDisplays(), 1); + const gfx::Rect extents = display.work_area(); + + // Move the host completely off the screen. + views::Widget* host_widget = + views::Widget::GetWidgetForNativeView(dialog_host()->GetHostView()); + gfx::Rect host_bounds = host_widget->GetWindowBoundsInScreen(); + host_bounds.set_origin(gfx::Point(extents.right(), extents.bottom())); + host_widget->SetBounds(host_bounds); + + // Make sure the host is fully off the screen. + EXPECT_FALSE(extents.Intersects(host_widget->GetWindowBoundsInScreen())); + + // Now reposition the modal dialog into the display. + UpdateWebContentsModalDialogPosition(dialog(), dialog_host()); + + const gfx::Rect dialog_bounds = dialog()->GetRootView()->GetBoundsInScreen(); + + // The dialog should now be fully on the display. + EXPECT_TRUE(extents.Contains(dialog_bounds)); +} + } // namespace constrained_window |
