1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/display/display.h"
6 #include "ui/display/screen.h"
7 #include "ui/views/test/native_widget_factory.h"
8 #include "ui/views/test/widget_test.h"
9 #include "ui/views/widget/widget.h"
10 #include "ui/views/window/dialog_delegate.h"
11 
12 namespace views {
13 
14 using DesktopScreenPositionClientTest = test::DesktopWidgetTest;
15 
16 // Verifies setting the bounds of a dialog parented to a Widget with a
17 // PlatformDesktopNativeWidget is positioned correctly.
TEST_F(DesktopScreenPositionClientTest,PositionDialog)18 TEST_F(DesktopScreenPositionClientTest, PositionDialog) {
19   Widget parent_widget;
20   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
21   params.bounds = gfx::Rect(10, 11, 200, 200);
22   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
23   parent_widget.Init(std::move(params));
24 
25   // Owned by |dialog|.
26   DialogDelegateView* dialog_delegate_view = new DialogDelegateView;
27   // Owned by |parent_widget|.
28   Widget* dialog = DialogDelegate::CreateDialogWidget(
29       dialog_delegate_view, nullptr, parent_widget.GetNativeView());
30   dialog->SetBounds(gfx::Rect(11, 12, 200, 200));
31   EXPECT_EQ(gfx::Point(11, 12), dialog->GetWindowBoundsInScreen().origin());
32 }
33 
34 // Verifies that setting the bounds of a control parented to something other
35 // than the root window is positioned correctly.
TEST_F(DesktopScreenPositionClientTest,PositionControlWithNonRootParent)36 TEST_F(DesktopScreenPositionClientTest, PositionControlWithNonRootParent) {
37   Widget widget1;
38   Widget widget2;
39   Widget widget3;
40   gfx::Point origin = gfx::Point(16, 16);
41   gfx::Rect work_area =
42       display::Screen::GetScreen()->GetDisplayNearestPoint(origin).work_area();
43 
44   // Use a custom frame type.  By default we will choose a native frame when
45   // aero glass is enabled, and this complicates the logic surrounding origin
46   // computation, making it difficult to compute the expected origin location.
47   widget1.set_frame_type(Widget::FrameType::kForceCustom);
48   widget2.set_frame_type(Widget::FrameType::kForceCustom);
49   widget3.set_frame_type(Widget::FrameType::kForceCustom);
50 
51   // Create 3 windows.  A root window, an arbitrary window parented to the root
52   // but NOT positioned at (0,0) relative to the root, and then a third window
53   // parented to the second, also not positioned at (0,0).
54   Widget::InitParams params1 = CreateParams(Widget::InitParams::TYPE_WINDOW);
55   params1.bounds = gfx::Rect(
56       origin + work_area.OffsetFromOrigin(),
57       gfx::Size(700, work_area.height() - origin.y() - work_area.y()));
58   params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
59   widget1.Init(std::move(params1));
60 
61   Widget::InitParams params2 = CreateParams(Widget::InitParams::TYPE_WINDOW);
62   params2.bounds = gfx::Rect(origin, gfx::Size(600, work_area.height() - 100));
63   params2.parent = widget1.GetNativeView();
64   params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
65   params2.child = true;
66   params2.native_widget = test::CreatePlatformNativeWidgetImpl(
67       params2, &widget2, test::kStubCapture, nullptr);
68   widget2.Init(std::move(params2));
69 
70   Widget::InitParams params3 = CreateParams(Widget::InitParams::TYPE_CONTROL);
71   params3.parent = widget2.GetNativeView();
72   params3.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
73   params3.child = true;
74   params3.bounds = gfx::Rect(origin, gfx::Size(500, work_area.height() - 200));
75   params3.native_widget = test::CreatePlatformNativeWidgetImpl(
76       params3, &widget3, test::kStubCapture, nullptr);
77   widget3.Init(std::move(params3));
78 
79   // The origin of the 3rd window should be the sum of all parent origins.
80   gfx::Point expected_origin(origin.x() * 3 + work_area.x(),
81                              origin.y() * 3 + work_area.y());
82   gfx::Rect expected_bounds(expected_origin,
83                             gfx::Size(500, work_area.height() - 200));
84   gfx::Rect actual_bounds(widget3.GetWindowBoundsInScreen());
85   EXPECT_EQ(expected_bounds, actual_bounds);
86 }
87 
88 // Verifies that the initial bounds of the widget is fully on the screen.
TEST_F(DesktopScreenPositionClientTest,InitialBoundsConstrainedToDesktop)89 TEST_F(DesktopScreenPositionClientTest, InitialBoundsConstrainedToDesktop) {
90   Widget widget;
91   // Use the primary display for this test.
92   gfx::Rect work_area =
93       display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
94   // Make the origin start at 75% of the width and height.
95   gfx::Point origin =
96       gfx::Point(work_area.width() * 3 / 4, work_area.height() * 3 / 4);
97 
98   // Use a custom frame type. See above for further explanation.
99   widget.set_frame_type(Widget::FrameType::kForceCustom);
100 
101   // Create a window that is intentionally positioned so that it is off screen.
102   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
103   params.bounds = gfx::Rect(
104       origin, gfx::Size(work_area.width() / 2, work_area.height() / 2));
105   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
106   widget.Init(std::move(params));
107 
108   // The bounds of the window should be fully on the primary display.
109   gfx::Point expected_origin(work_area.right() - work_area.width() / 2,
110                              work_area.bottom() - work_area.height() / 2);
111   gfx::Rect expected_bounds(expected_origin, gfx::Size(work_area.width() / 2,
112                                                        work_area.height() / 2));
113   gfx::Rect actual_bounds(widget.GetWindowBoundsInScreen());
114   EXPECT_EQ(expected_bounds, actual_bounds);
115 }
116 
117 // Verifies that the initial bounds of the widget is fully within the bounds of
118 // the parent.
TEST_F(DesktopScreenPositionClientTest,InitialBoundsConstrainedToParent)119 TEST_F(DesktopScreenPositionClientTest, InitialBoundsConstrainedToParent) {
120   Widget widget1;
121   Widget widget2;
122   // Use the primary display for this test.
123   gfx::Rect work_area =
124       display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
125   gfx::Point origin = gfx::Point(work_area.x() + work_area.width() / 4,
126                                  work_area.y() + work_area.height() / 4);
127 
128   // Use a custom frame type.  See above for further explanation
129   widget1.set_frame_type(Widget::FrameType::kForceCustom);
130   widget2.set_frame_type(Widget::FrameType::kForceCustom);
131 
132   // Create 2 windows.  A root window, and an arbitrary window parented to the
133   // root and positioned such that it extends beyond the bounds of the root.
134   Widget::InitParams params1 = CreateParams(Widget::InitParams::TYPE_WINDOW);
135   params1.bounds = gfx::Rect(
136       origin, gfx::Size(work_area.width() / 2, work_area.height() / 2));
137   params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
138   widget1.Init(std::move(params1));
139 
140   gfx::Rect widget_bounds(widget1.GetWindowBoundsInScreen());
141 
142   Widget::InitParams params2 = CreateParams(Widget::InitParams::TYPE_WINDOW);
143   params2.bounds =
144       gfx::Rect(widget_bounds.width() * 3 / 4, widget_bounds.height() * 3 / 4,
145                 widget_bounds.width() / 2, widget_bounds.height() / 2);
146   params2.parent = widget1.GetNativeView();
147   params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
148   params2.child = true;
149   params2.native_widget = test::CreatePlatformNativeWidgetImpl(
150       params2, &widget2, test::kStubCapture, nullptr);
151   widget2.Init(std::move(params2));
152 
153   // The bounds of the child window should be fully in the parent.
154   gfx::Point expected_origin(
155       widget_bounds.right() - widget_bounds.width() / 2,
156       widget_bounds.bottom() - widget_bounds.height() / 2);
157   gfx::Rect expected_bounds(
158       expected_origin,
159       gfx::Size(widget_bounds.width() / 2, widget_bounds.height() / 2));
160   gfx::Rect actual_bounds(widget2.GetWindowBoundsInScreen());
161   EXPECT_EQ(expected_bounds, actual_bounds);
162 }
163 
164 }  // namespace views
165