OLD | NEW |
| (Empty) |
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 "chrome/browser/ui/app_list/app_list_positioner.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/logging.h" | |
10 #include "ui/gfx/geometry/point.h" | |
11 #include "ui/gfx/geometry/rect.h" | |
12 | |
13 AppListPositioner::AppListPositioner(const display::Display& display, | |
14 const gfx::Size& window_size, | |
15 int min_distance_from_edge) | |
16 : display_(display), | |
17 window_size_(window_size), | |
18 min_distance_from_edge_(min_distance_from_edge) {} | |
19 | |
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); | |
24 } | |
25 | |
26 void AppListPositioner::WorkAreaInset(int left, | |
27 int top, | |
28 int right, | |
29 int bottom) { | |
30 gfx::Rect work_area = display_.work_area(); | |
31 work_area.Inset(left, top, right, bottom); | |
32 display_.set_work_area(work_area); | |
33 } | |
34 | |
35 gfx::Point AppListPositioner::GetAnchorPointForScreenCenter() const { | |
36 return display_.bounds().CenterPoint(); | |
37 } | |
38 | |
39 gfx::Point AppListPositioner::GetAnchorPointForScreenCorner( | |
40 ScreenCorner corner) const { | |
41 const gfx::Rect& screen_rect = display_.bounds(); | |
42 gfx::Point anchor; | |
43 switch (corner) { | |
44 case SCREEN_CORNER_TOP_LEFT: | |
45 anchor = screen_rect.origin(); | |
46 break; | |
47 case SCREEN_CORNER_TOP_RIGHT: | |
48 anchor = screen_rect.top_right(); | |
49 break; | |
50 case SCREEN_CORNER_BOTTOM_LEFT: | |
51 anchor = screen_rect.bottom_left(); | |
52 break; | |
53 case SCREEN_CORNER_BOTTOM_RIGHT: | |
54 anchor = screen_rect.bottom_right(); | |
55 break; | |
56 default: | |
57 NOTREACHED(); | |
58 anchor = gfx::Point(); | |
59 } | |
60 return ClampAnchorPoint(anchor); | |
61 } | |
62 | |
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(); | |
67 gfx::Point anchor; | |
68 switch (shelf_edge) { | |
69 case SCREEN_EDGE_LEFT: | |
70 anchor = gfx::Point(work_area.x(), screen_rect.y()); | |
71 break; | |
72 case SCREEN_EDGE_RIGHT: | |
73 anchor = gfx::Point(work_area.right(), screen_rect.y()); | |
74 break; | |
75 case SCREEN_EDGE_TOP: | |
76 anchor = gfx::Point(screen_rect.x(), work_area.y()); | |
77 break; | |
78 case SCREEN_EDGE_BOTTOM: | |
79 anchor = gfx::Point(screen_rect.x(), work_area.bottom()); | |
80 break; | |
81 default: | |
82 NOTREACHED(); | |
83 anchor = gfx::Point(); | |
84 } | |
85 return ClampAnchorPoint(anchor); | |
86 } | |
87 | |
88 gfx::Point AppListPositioner::GetAnchorPointForShelfCenter( | |
89 ScreenEdge shelf_edge) const { | |
90 const gfx::Rect& work_area = display_.work_area(); | |
91 gfx::Point anchor; | |
92 switch (shelf_edge) { | |
93 case SCREEN_EDGE_LEFT: | |
94 anchor = | |
95 gfx::Point(work_area.x(), work_area.y() + work_area.height() / 2); | |
96 break; | |
97 case SCREEN_EDGE_RIGHT: | |
98 anchor = | |
99 gfx::Point(work_area.right(), work_area.y() + work_area.height() / 2); | |
100 break; | |
101 case SCREEN_EDGE_TOP: | |
102 anchor = gfx::Point(work_area.x() + work_area.width() / 2, work_area.y()); | |
103 break; | |
104 case SCREEN_EDGE_BOTTOM: | |
105 anchor = | |
106 gfx::Point(work_area.x() + work_area.width() / 2, work_area.bottom()); | |
107 break; | |
108 default: | |
109 NOTREACHED(); | |
110 anchor = gfx::Point(); | |
111 } | |
112 return ClampAnchorPoint(anchor); | |
113 } | |
114 | |
115 gfx::Point AppListPositioner::GetAnchorPointForShelfCursor( | |
116 ScreenEdge shelf_edge, | |
117 const gfx::Point& cursor) const { | |
118 const gfx::Rect& work_area = display_.work_area(); | |
119 gfx::Point anchor; | |
120 switch (shelf_edge) { | |
121 case SCREEN_EDGE_LEFT: | |
122 anchor = gfx::Point(work_area.x(), cursor.y()); | |
123 break; | |
124 case SCREEN_EDGE_RIGHT: | |
125 anchor = gfx::Point(work_area.right(), cursor.y()); | |
126 break; | |
127 case SCREEN_EDGE_TOP: | |
128 anchor = gfx::Point(cursor.x(), work_area.y()); | |
129 break; | |
130 case SCREEN_EDGE_BOTTOM: | |
131 anchor = gfx::Point(cursor.x(), work_area.bottom()); | |
132 break; | |
133 default: | |
134 NOTREACHED(); | |
135 anchor = gfx::Point(); | |
136 } | |
137 return ClampAnchorPoint(anchor); | |
138 } | |
139 | |
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(); | |
144 | |
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; | |
150 | |
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; | |
167 } | |
168 | |
169 return SCREEN_EDGE_UNKNOWN; | |
170 } | |
171 | |
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: | |
178 return 0; | |
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()); | |
187 default: | |
188 NOTREACHED(); | |
189 return 0; | |
190 } | |
191 } | |
192 | |
193 gfx::Point AppListPositioner::ClampAnchorPoint(gfx::Point anchor) const { | |
194 gfx::Rect bounds_rect(display_.work_area()); | |
195 | |
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_); | |
200 | |
201 anchor.SetToMax(bounds_rect.origin()); | |
202 anchor.SetToMin(bounds_rect.bottom_right()); | |
203 return anchor; | |
204 } | |
OLD | NEW |