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 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 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 99 int DockInfo::popup_width() { 100 return kPopupWidth; 101 } 102 103 // static 104 int DockInfo::popup_height() { 105 return kPopupHeight; 106 } 107 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 122 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 185 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 227 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 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