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/geometry/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::GetAnchorPointForScreenCenter() const {
36 return display_
.bounds().CenterPoint();
39 gfx::Point
AppListPositioner::GetAnchorPointForScreenCorner(
40 ScreenCorner corner
) const {
41 const gfx::Rect
& screen_rect
= display_
.bounds();
44 case SCREEN_CORNER_TOP_LEFT
:
45 anchor
= screen_rect
.origin();
47 case SCREEN_CORNER_TOP_RIGHT
:
48 anchor
= screen_rect
.top_right();
50 case SCREEN_CORNER_BOTTOM_LEFT
:
51 anchor
= screen_rect
.bottom_left();
53 case SCREEN_CORNER_BOTTOM_RIGHT
:
54 anchor
= screen_rect
.bottom_right();
58 anchor
= gfx::Point();
60 return ClampAnchorPoint(anchor
);
63 gfx::Point
AppListPositioner::GetAnchorPointForShelfCorner(
64 ScreenEdge shelf_edge
) const {
65 const gfx::Rect
& screen_rect
= display_
.bounds();
66 const gfx::Rect
& work_area
= display_
.work_area();
69 case SCREEN_EDGE_LEFT
:
70 anchor
= gfx::Point(work_area
.x(), screen_rect
.y());
72 case SCREEN_EDGE_RIGHT
:
73 anchor
= gfx::Point(work_area
.right(), screen_rect
.y());
76 anchor
= gfx::Point(screen_rect
.x(), work_area
.y());
78 case SCREEN_EDGE_BOTTOM
:
79 anchor
= gfx::Point(screen_rect
.x(), work_area
.bottom());
83 anchor
= gfx::Point();
85 return ClampAnchorPoint(anchor
);
88 gfx::Point
AppListPositioner::GetAnchorPointForShelfCenter(
89 ScreenEdge shelf_edge
) const {
90 const gfx::Rect
& work_area
= display_
.work_area();
93 case SCREEN_EDGE_LEFT
:
95 gfx::Point(work_area
.x(), work_area
.y() + work_area
.height() / 2);
97 case SCREEN_EDGE_RIGHT
:
99 gfx::Point(work_area
.right(), work_area
.y() + work_area
.height() / 2);
101 case SCREEN_EDGE_TOP
:
102 anchor
= gfx::Point(work_area
.x() + work_area
.width() / 2, work_area
.y());
104 case SCREEN_EDGE_BOTTOM
:
106 gfx::Point(work_area
.x() + work_area
.width() / 2, work_area
.bottom());
110 anchor
= gfx::Point();
112 return ClampAnchorPoint(anchor
);
115 gfx::Point
AppListPositioner::GetAnchorPointForShelfCursor(
116 ScreenEdge shelf_edge
,
117 const gfx::Point
& cursor
) const {
118 const gfx::Rect
& work_area
= display_
.work_area();
120 switch (shelf_edge
) {
121 case SCREEN_EDGE_LEFT
:
122 anchor
= gfx::Point(work_area
.x(), cursor
.y());
124 case SCREEN_EDGE_RIGHT
:
125 anchor
= gfx::Point(work_area
.right(), cursor
.y());
127 case SCREEN_EDGE_TOP
:
128 anchor
= gfx::Point(cursor
.x(), work_area
.y());
130 case SCREEN_EDGE_BOTTOM
:
131 anchor
= gfx::Point(cursor
.x(), work_area
.bottom());
135 anchor
= gfx::Point();
137 return ClampAnchorPoint(anchor
);
140 AppListPositioner::ScreenEdge
AppListPositioner::GetShelfEdge(
141 const gfx::Rect
& shelf_rect
) const {
142 const gfx::Rect
& screen_rect
= display_
.bounds();
143 const gfx::Rect
& work_area
= display_
.work_area();
145 // If we can't find the shelf, return SCREEN_EDGE_UNKNOWN. If the display
146 // size is the same as the work area, and does not contain the shelf, either
147 // the shelf is hidden or on another monitor.
148 if (work_area
== screen_rect
&& !work_area
.Contains(shelf_rect
))
149 return SCREEN_EDGE_UNKNOWN
;
151 // Note: On Windows 8 the work area won't include split windows on the left or
152 // right, and neither will |shelf_rect|.
153 if (shelf_rect
.x() == work_area
.x() &&
154 shelf_rect
.width() == work_area
.width()) {
155 // Shelf is horizontal.
156 if (shelf_rect
.bottom() == screen_rect
.bottom())
157 return SCREEN_EDGE_BOTTOM
;
158 else if (shelf_rect
.y() == screen_rect
.y())
159 return SCREEN_EDGE_TOP
;
160 } else if (shelf_rect
.y() == work_area
.y() &&
161 shelf_rect
.height() == work_area
.height()) {
162 // Shelf is vertical.
163 if (shelf_rect
.x() == screen_rect
.x())
164 return SCREEN_EDGE_LEFT
;
165 else if (shelf_rect
.right() == screen_rect
.right())
166 return SCREEN_EDGE_RIGHT
;
169 return SCREEN_EDGE_UNKNOWN
;
172 int AppListPositioner::GetCursorDistanceFromShelf(
173 ScreenEdge shelf_edge
,
174 const gfx::Point
& cursor
) const {
175 const gfx::Rect
& work_area
= display_
.work_area();
176 switch (shelf_edge
) {
177 case SCREEN_EDGE_UNKNOWN
:
179 case SCREEN_EDGE_LEFT
:
180 return std::max(0, cursor
.x() - work_area
.x());
181 case SCREEN_EDGE_RIGHT
:
182 return std::max(0, work_area
.right() - cursor
.x());
183 case SCREEN_EDGE_TOP
:
184 return std::max(0, cursor
.y() - work_area
.y());
185 case SCREEN_EDGE_BOTTOM
:
186 return std::max(0, work_area
.bottom() - cursor
.y());
193 gfx::Point
AppListPositioner::ClampAnchorPoint(gfx::Point anchor
) const {
194 gfx::Rect
bounds_rect(display_
.work_area());
196 // Anchor the center of the window in a region that prevents the window
197 // showing outside of the work area.
198 bounds_rect
.Inset(window_size_
.width() / 2 + min_distance_from_edge_
,
199 window_size_
.height() / 2 + min_distance_from_edge_
);
201 anchor
.SetToMax(bounds_rect
.origin());
202 anchor
.SetToMin(bounds_rect
.bottom_right());