• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/tabs/dock_info.h"
6 
7 #include "base/logging.h"
8 #if defined(TOOLKIT_VIEWS)
9 #include "chrome/browser/ui/views/tabs/tab.h"
10 #else
11 #include "chrome/browser/ui/gtk/tabs/tab_gtk.h"
12 #endif
13 
14 namespace {
15 
16 // Distance in pixels between the hotspot and when the hint should be shown.
17 const int kHotSpotDeltaX = 120;
18 const int kHotSpotDeltaY = 120;
19 
20 // Size of the popup window.
21 const int kPopupWidth = 70;
22 const int kPopupHeight = 70;
23 
24 }  // namespace
25 
26 // static
27 DockInfo::Factory* DockInfo::factory_ = NULL;
28 
29 // static
IsCloseToPoint(const gfx::Point & screen_loc,int x,int y,bool * in_enable_area)30 bool DockInfo::IsCloseToPoint(const gfx::Point& screen_loc,
31                               int x,
32                               int y,
33                               bool* in_enable_area) {
34   int delta_x = abs(x - screen_loc.x());
35   int delta_y = abs(y - screen_loc.y());
36   *in_enable_area = (delta_x < kPopupWidth / 2 && delta_y < kPopupHeight / 2);
37   return *in_enable_area || (delta_x < kHotSpotDeltaX &&
38                              delta_y < kHotSpotDeltaY);
39 }
40 
41 // static
IsCloseToMonitorPoint(const gfx::Point & screen_loc,int x,int y,DockInfo::Type type,bool * in_enable_area)42 bool DockInfo::IsCloseToMonitorPoint(const gfx::Point& screen_loc,
43                                      int x,
44                                      int y,
45                                      DockInfo::Type type,
46                                      bool* in_enable_area) {
47   // Because the monitor relative positions are aligned with the edge of the
48   // monitor these need to be handled differently.
49   int delta_x = abs(x - screen_loc.x());
50   int delta_y = abs(y - screen_loc.y());
51 
52   int enable_delta_x = kPopupWidth / 2;
53   int enable_delta_y = kPopupHeight / 2;
54   int hot_spot_delta_x = kHotSpotDeltaX;
55   int hot_spot_delta_y = kHotSpotDeltaY;
56 
57   switch (type) {
58     case DockInfo::LEFT_HALF:
59     case DockInfo::RIGHT_HALF:
60       enable_delta_x += enable_delta_x;
61       hot_spot_delta_x += hot_spot_delta_x;
62       break;
63 
64 
65     case DockInfo::MAXIMIZE: {
66       // Make the maximize height smaller than the tab height to avoid showing
67       // the dock indicator when close to maximized browser.
68 #if defined(TOOLKIT_VIEWS)
69       hot_spot_delta_y = Tab::GetMinimumUnselectedSize().height() - 1;
70 #else
71       hot_spot_delta_y = TabGtk::GetMinimumUnselectedSize().height() - 1;
72 #endif
73       enable_delta_y = hot_spot_delta_y / 2;
74       break;
75     }
76     case DockInfo::BOTTOM_HALF:
77       enable_delta_y += enable_delta_y;
78       hot_spot_delta_y += hot_spot_delta_y;
79       break;
80 
81     default:
82       NOTREACHED();
83       return false;
84   }
85   *in_enable_area = (delta_x < enable_delta_x && delta_y < enable_delta_y);
86   bool result = (*in_enable_area || (delta_x < hot_spot_delta_x &&
87                                      delta_y < hot_spot_delta_y));
88   if (type != DockInfo::MAXIMIZE)
89     return result;
90 
91   // Make the hot spot/enable spot for maximized windows the whole top of the
92   // monitor.
93   int max_delta_y = abs(screen_loc.y() - y);
94   *in_enable_area = (*in_enable_area || (max_delta_y < enable_delta_y));
95   return *in_enable_area || (max_delta_y < hot_spot_delta_y);
96 }
97 
98 // static
popup_width()99 int DockInfo::popup_width() {
100   return kPopupWidth;
101 }
102 
103 // static
popup_height()104 int DockInfo::popup_height() {
105   return kPopupHeight;
106 }
107 
IsValidForPoint(const gfx::Point & screen_point)108 bool DockInfo::IsValidForPoint(const gfx::Point& screen_point) {
109   if (type_ == NONE)
110     return false;
111 
112   if (window_) {
113     return IsCloseToPoint(screen_point, hot_spot_.x(), hot_spot_.y(),
114                           &in_enable_area_);
115   }
116 
117   return monitor_bounds_.Contains(screen_point) &&
118           IsCloseToMonitorPoint(screen_point, hot_spot_.x(),
119                                 hot_spot_.y(), type_, &in_enable_area_);
120 }
121 
GetNewWindowBounds(gfx::Rect * new_window_bounds,bool * maximize_new_window) const122 bool DockInfo::GetNewWindowBounds(gfx::Rect* new_window_bounds,
123                                   bool* maximize_new_window) const {
124   if (type_ == NONE || !in_enable_area_)
125     return false;
126 
127   gfx::Rect window_bounds;
128   if (window_ && !GetWindowBounds(&window_bounds))
129     return false;
130 
131   int half_m_width = (monitor_bounds_.right() - monitor_bounds_.x()) / 2;
132   int half_m_height = (monitor_bounds_.bottom() - monitor_bounds_.y()) / 2;
133 
134   *maximize_new_window = false;
135 
136   switch (type_) {
137     case LEFT_OF_WINDOW:
138       new_window_bounds->SetRect(monitor_bounds_.x(), window_bounds.y(),
139                                  half_m_width, window_bounds.height());
140       break;
141 
142     case RIGHT_OF_WINDOW:
143       new_window_bounds->SetRect(monitor_bounds_.x() + half_m_width,
144                                  window_bounds.y(), half_m_width,
145                                  window_bounds.height());
146       break;
147 
148     case TOP_OF_WINDOW:
149       new_window_bounds->SetRect(window_bounds.x(), monitor_bounds_.y(),
150                                  window_bounds.width(), half_m_height);
151       break;
152 
153     case BOTTOM_OF_WINDOW:
154       new_window_bounds->SetRect(window_bounds.x(),
155                                  monitor_bounds_.y() + half_m_height,
156                                  window_bounds.width(), half_m_height);
157       break;
158 
159     case LEFT_HALF:
160       new_window_bounds->SetRect(monitor_bounds_.x(), monitor_bounds_.y(),
161                                  half_m_width, monitor_bounds_.height());
162       break;
163 
164     case RIGHT_HALF:
165       new_window_bounds->SetRect(monitor_bounds_.right() - half_m_width,
166           monitor_bounds_.y(), half_m_width, monitor_bounds_.height());
167       break;
168 
169     case BOTTOM_HALF:
170       new_window_bounds->SetRect(monitor_bounds_.x(),
171                                  monitor_bounds_.y() + half_m_height,
172                                  monitor_bounds_.width(), half_m_height);
173       break;
174 
175     case MAXIMIZE:
176       *maximize_new_window = true;
177       break;
178 
179     default:
180       NOTREACHED();
181   }
182   return true;
183 }
184 
AdjustOtherWindowBounds() const185 void DockInfo::AdjustOtherWindowBounds() const {
186   if (!in_enable_area_)
187     return;
188 
189   gfx::Rect window_bounds;
190   if (!window_ || !GetWindowBounds(&window_bounds))
191     return;
192 
193   gfx::Rect other_window_bounds;
194   int half_m_width = (monitor_bounds_.right() - monitor_bounds_.x()) / 2;
195   int half_m_height = (monitor_bounds_.bottom() - monitor_bounds_.y()) / 2;
196 
197   switch (type_) {
198     case LEFT_OF_WINDOW:
199       other_window_bounds.SetRect(monitor_bounds_.x() + half_m_width,
200                                   window_bounds.y(), half_m_width,
201                                   window_bounds.height());
202       break;
203 
204     case RIGHT_OF_WINDOW:
205       other_window_bounds.SetRect(monitor_bounds_.x(), window_bounds.y(),
206                                   half_m_width, window_bounds.height());
207       break;
208 
209     case TOP_OF_WINDOW:
210       other_window_bounds.SetRect(window_bounds.x(),
211                                   monitor_bounds_.y() + half_m_height,
212                                   window_bounds.width(), half_m_height);
213       break;
214 
215     case BOTTOM_OF_WINDOW:
216       other_window_bounds.SetRect(window_bounds.x(), monitor_bounds_.y(),
217                                   window_bounds.width(), half_m_height);
218       break;
219 
220     default:
221       return;
222   }
223 
224   SizeOtherWindowTo(other_window_bounds);
225 }
226 
GetPopupRect() const227 gfx::Rect DockInfo::GetPopupRect() const {
228   int x = hot_spot_.x() - popup_width() / 2;
229   int y = hot_spot_.y() - popup_height() / 2;
230   switch (type_) {
231     case LEFT_OF_WINDOW:
232     case RIGHT_OF_WINDOW:
233     case TOP_OF_WINDOW:
234     case BOTTOM_OF_WINDOW: {
235       // Constrain the popup to the monitor's bounds.
236       gfx::Rect ideal_bounds(x, y, popup_width(), popup_height());
237       ideal_bounds = ideal_bounds.AdjustToFit(monitor_bounds_);
238       return ideal_bounds;
239     }
240     case DockInfo::MAXIMIZE:
241       y += popup_height() / 2;
242       break;
243     case DockInfo::LEFT_HALF:
244       x += popup_width() / 2;
245       break;
246     case DockInfo::RIGHT_HALF:
247       x -= popup_width() / 2;
248       break;
249     case DockInfo::BOTTOM_HALF:
250       y -= popup_height() / 2;
251       break;
252 
253     default:
254       NOTREACHED();
255   }
256   return gfx::Rect(x, y, popup_width(), popup_height());
257 }
258 
CheckMonitorPoint(const gfx::Point & screen_loc,int x,int y,Type type)259 bool DockInfo::CheckMonitorPoint(const gfx::Point& screen_loc,
260                                  int x,
261                                  int y,
262                                  Type type) {
263   if (IsCloseToMonitorPoint(screen_loc, x, y, type, &in_enable_area_)) {
264     hot_spot_.SetPoint(x, y);
265     type_ = type;
266     return true;
267   }
268   return false;
269 }
270