Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / app_list / app_list_positioner.cc
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/point.h"
11 #include "ui/gfx/rect.h"
12
13 AppListPositioner::AppListPositioner(const gfx::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 }