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