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