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.
5 #include "chrome/browser/ui/app_list/app_list_positioner.h"
9 #include "base/logging.h"
10 #include "ui/gfx/point.h"
11 #include "ui/gfx/rect.h"
13 AppListPositioner::AppListPositioner(const gfx::Display
& display
,
14 const gfx::Size
& window_size
,
15 int min_distance_from_edge
)
17 window_size_(window_size
),
18 min_distance_from_edge_(min_distance_from_edge
) {}
20 void AppListPositioner::WorkAreaSubtract(const gfx::Rect
& rect
) {
21 gfx::Rect work_area
= display_
.work_area();
22 work_area
.Subtract(rect
);
23 display_
.set_work_area(work_area
);
26 void AppListPositioner::WorkAreaInset(int left
,
30 gfx::Rect work_area
= display_
.work_area();
31 work_area
.Inset(left
, top
, right
, bottom
);
32 display_
.set_work_area(work_area
);
35 gfx::Point
AppListPositioner::GetAnchorPointForScreenCorner(
36 ScreenCorner corner
) const {
37 const gfx::Rect
& screen_rect
= display_
.bounds();
40 case SCREEN_CORNER_TOP_LEFT
:
41 anchor
= screen_rect
.origin();
43 case SCREEN_CORNER_TOP_RIGHT
:
44 anchor
= screen_rect
.top_right();
46 case SCREEN_CORNER_BOTTOM_LEFT
:
47 anchor
= screen_rect
.bottom_left();
49 case SCREEN_CORNER_BOTTOM_RIGHT
:
50 anchor
= screen_rect
.bottom_right();
54 anchor
= gfx::Point();
56 return ClampAnchorPoint(anchor
);
59 gfx::Point
AppListPositioner::GetAnchorPointForShelfCorner(
60 ScreenEdge shelf_edge
) const {
61 const gfx::Rect
& screen_rect
= display_
.bounds();
62 const gfx::Rect
& work_area
= display_
.work_area();
65 case SCREEN_EDGE_LEFT
:
66 anchor
= gfx::Point(work_area
.x(), screen_rect
.y());
68 case SCREEN_EDGE_RIGHT
:
69 anchor
= gfx::Point(work_area
.right(), screen_rect
.y());
72 anchor
= gfx::Point(screen_rect
.x(), work_area
.y());
74 case SCREEN_EDGE_BOTTOM
:
75 anchor
= gfx::Point(screen_rect
.x(), work_area
.bottom());
79 anchor
= gfx::Point();
81 return ClampAnchorPoint(anchor
);
84 gfx::Point
AppListPositioner::GetAnchorPointForShelfCenter(
85 ScreenEdge shelf_edge
) const {
86 const gfx::Rect
& work_area
= display_
.work_area();
89 case SCREEN_EDGE_LEFT
:
91 gfx::Point(work_area
.x(), work_area
.y() + work_area
.height() / 2);
93 case SCREEN_EDGE_RIGHT
:
95 gfx::Point(work_area
.right(), work_area
.y() + work_area
.height() / 2);
98 anchor
= gfx::Point(work_area
.x() + work_area
.width() / 2, work_area
.y());
100 case SCREEN_EDGE_BOTTOM
:
102 gfx::Point(work_area
.x() + work_area
.width() / 2, work_area
.bottom());
106 anchor
= gfx::Point();
108 return ClampAnchorPoint(anchor
);
111 gfx::Point
AppListPositioner::GetAnchorPointForShelfCursor(
112 ScreenEdge shelf_edge
,
113 const gfx::Point
& cursor
) const {
114 const gfx::Rect
& work_area
= display_
.work_area();
116 switch (shelf_edge
) {
117 case SCREEN_EDGE_LEFT
:
118 anchor
= gfx::Point(work_area
.x(), cursor
.y());
120 case SCREEN_EDGE_RIGHT
:
121 anchor
= gfx::Point(work_area
.right(), cursor
.y());
123 case SCREEN_EDGE_TOP
:
124 anchor
= gfx::Point(cursor
.x(), work_area
.y());
126 case SCREEN_EDGE_BOTTOM
:
127 anchor
= gfx::Point(cursor
.x(), work_area
.bottom());
131 anchor
= gfx::Point();
133 return ClampAnchorPoint(anchor
);
136 AppListPositioner::ScreenEdge
AppListPositioner::GetShelfEdge(
137 const gfx::Rect
& shelf_rect
) const {
138 const gfx::Rect
& screen_rect
= display_
.bounds();
139 const gfx::Rect
& work_area
= display_
.work_area();
141 // If we can't find the shelf, return SCREEN_EDGE_UNKNOWN. If the display
142 // size is the same as the work area, and does not contain the shelf, either
143 // the shelf is hidden or on another monitor.
144 if (work_area
== screen_rect
&& !work_area
.Contains(shelf_rect
))
145 return SCREEN_EDGE_UNKNOWN
;
147 // Note: On Windows 8 the work area won't include split windows on the left or
148 // right, and neither will |shelf_rect|.
149 if (shelf_rect
.x() == work_area
.x() &&
150 shelf_rect
.width() == work_area
.width()) {
151 // Shelf is horizontal.
152 if (shelf_rect
.bottom() == screen_rect
.bottom())
153 return SCREEN_EDGE_BOTTOM
;
154 else if (shelf_rect
.y() == screen_rect
.y())
155 return SCREEN_EDGE_TOP
;
156 } else if (shelf_rect
.y() == work_area
.y() &&
157 shelf_rect
.height() == work_area
.height()) {
158 // Shelf is vertical.
159 if (shelf_rect
.x() == screen_rect
.x())
160 return SCREEN_EDGE_LEFT
;
161 else if (shelf_rect
.right() == screen_rect
.right())
162 return SCREEN_EDGE_RIGHT
;
165 return SCREEN_EDGE_UNKNOWN
;
168 int AppListPositioner::GetCursorDistanceFromShelf(
169 ScreenEdge shelf_edge
,
170 const gfx::Point
& cursor
) const {
171 const gfx::Rect
& work_area
= display_
.work_area();
172 switch (shelf_edge
) {
173 case SCREEN_EDGE_UNKNOWN
:
175 case SCREEN_EDGE_LEFT
:
176 return std::max(0, cursor
.x() - work_area
.x());
177 case SCREEN_EDGE_RIGHT
:
178 return std::max(0, work_area
.right() - cursor
.x());
179 case SCREEN_EDGE_TOP
:
180 return std::max(0, cursor
.y() - work_area
.y());
181 case SCREEN_EDGE_BOTTOM
:
182 return std::max(0, work_area
.bottom() - cursor
.y());
189 gfx::Point
AppListPositioner::ClampAnchorPoint(gfx::Point anchor
) const {
190 gfx::Rect
bounds_rect(display_
.work_area());
192 // Anchor the center of the window in a region that prevents the window
193 // showing outside of the work area.
194 bounds_rect
.Inset(window_size_
.width() / 2 + min_distance_from_edge_
,
195 window_size_
.height() / 2 + min_distance_from_edge_
);
197 anchor
.SetToMax(bounds_rect
.origin());
198 anchor
.SetToMin(bounds_rect
.bottom_right());