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