summaryrefslogtreecommitdiff
path: root/chromium/components/constrained_window
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/constrained_window')
-rw-r--r--chromium/components/constrained_window/BUILD.gn2
-rw-r--r--chromium/components/constrained_window/DEPS1
-rw-r--r--chromium/components/constrained_window/constrained_window_views.cc16
-rw-r--r--chromium/components/constrained_window/constrained_window_views_client.h4
-rw-r--r--chromium/components/constrained_window/constrained_window_views_unittest.cc38
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