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