| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h" | 5 #include "chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h" |
| 6 | 6 |
| 7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
| 8 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #import "chrome/browser/ui/cocoa/panels/panel_cocoa.h" | 21 #import "chrome/browser/ui/cocoa/panels/panel_cocoa.h" |
| 22 #import "chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.h" | 22 #import "chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.h" |
| 23 #import "chrome/browser/ui/cocoa/panels/panel_utils_cocoa.h" | 23 #import "chrome/browser/ui/cocoa/panels/panel_utils_cocoa.h" |
| 24 #import "chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.h" | 24 #import "chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.h" |
| 25 #import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h" | 25 #import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h" |
| 26 #import "chrome/browser/ui/cocoa/tabs/throbber_view.h" | 26 #import "chrome/browser/ui/cocoa/tabs/throbber_view.h" |
| 27 #include "chrome/browser/ui/panels/panel_bounds_animation.h" | 27 #include "chrome/browser/ui/panels/panel_bounds_animation.h" |
| 28 #include "chrome/browser/ui/panels/panel_collection.h" | 28 #include "chrome/browser/ui/panels/panel_collection.h" |
| 29 #include "chrome/browser/ui/panels/panel_constants.h" | 29 #include "chrome/browser/ui/panels/panel_constants.h" |
| 30 #include "chrome/browser/ui/panels/panel_manager.h" | 30 #include "chrome/browser/ui/panels/panel_manager.h" |
| 31 #include "chrome/browser/ui/panels/stacked_panel_collection.h" | |
| 32 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 31 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 33 #include "chrome/browser/ui/toolbar/encoding_menu_controller.h" | 32 #include "chrome/browser/ui/toolbar/encoding_menu_controller.h" |
| 34 #include "content/public/browser/render_widget_host_view.h" | 33 #include "content/public/browser/render_widget_host_view.h" |
| 35 #include "content/public/browser/web_contents.h" | 34 #include "content/public/browser/web_contents.h" |
| 36 #include "content/public/browser/web_contents_view.h" | 35 #include "content/public/browser/web_contents_view.h" |
| 37 #include "grit/ui_resources.h" | 36 #include "grit/ui_resources.h" |
| 37 #include "third_party/WebKit/public/web/WebCursorInfo.h" |
| 38 #include "ui/base/resource/resource_bundle.h" | 38 #include "ui/base/resource/resource_bundle.h" |
| 39 #include "ui/gfx/image/image.h" | 39 #include "ui/gfx/image/image.h" |
| 40 #include "webkit/common/cursors/webcursor.h" |
| 40 | 41 |
| 41 using content::WebContents; | 42 using content::WebContents; |
| 42 | 43 |
| 43 const int kMinimumWindowSize = 1; | 44 const int kMinimumWindowSize = 1; |
| 44 const double kBoundsAnimationSpeedPixelsPerSecond = 1000; | 45 const double kBoundsAnimationSpeedPixelsPerSecond = 1000; |
| 45 const double kBoundsAnimationMaxDurationSeconds = 0.18; | 46 const double kBoundsAnimationMaxDurationSeconds = 0.18; |
| 46 | 47 |
| 47 // Edge thickness to trigger user resizing via system, in screen pixels. | 48 // Resize edge thickness, in screen pixels. |
| 48 const double kWidthOfMouseResizeArea = 15.0; | 49 const double kWidthOfMouseResizeArea = 4.0; |
| 49 | 50 |
| 50 @interface PanelWindowControllerCocoa (PanelsCanBecomeKey) | 51 @interface PanelWindowControllerCocoa (PanelsCanBecomeKey) |
| 51 // Internal helper method for extracting the total number of panel windows | 52 // Internal helper method for extracting the total number of panel windows |
| 52 // from the panel manager. Used to decide if panel can become the key window. | 53 // from the panel manager. Used to decide if panel can become the key window. |
| 53 - (int)numPanels; | 54 - (int)numPanels; |
| 54 @end | 55 @end |
| 55 | 56 |
| 56 @implementation PanelWindowCocoaImpl | 57 @implementation PanelWindowCocoaImpl |
| 57 // The panels cannot be reduced to 3-px windows on the edge of the screen | 58 // The panels cannot be reduced to 3-px windows on the edge of the screen |
| 58 // active area (above Dock). Default constraining logic makes at least a height | 59 // active area (above Dock). Default constraining logic makes at least a height |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 // Ignore key events if window cannot become key window to fix problem | 101 // Ignore key events if window cannot become key window to fix problem |
| 101 // where keyboard input is still going into a minimized panel even though | 102 // where keyboard input is still going into a minimized panel even though |
| 102 // the app has been deactivated in -[PanelWindowControllerCocoa deactivate:]. | 103 // the app has been deactivated in -[PanelWindowControllerCocoa deactivate:]. |
| 103 - (void)sendEvent:(NSEvent*)anEvent { | 104 - (void)sendEvent:(NSEvent*)anEvent { |
| 104 NSEventType eventType = [anEvent type]; | 105 NSEventType eventType = [anEvent type]; |
| 105 if ((eventType == NSKeyDown || eventType == NSKeyUp) && | 106 if ((eventType == NSKeyDown || eventType == NSKeyUp) && |
| 106 ![self canBecomeKeyWindow]) | 107 ![self canBecomeKeyWindow]) |
| 107 return; | 108 return; |
| 108 [super sendEvent:anEvent]; | 109 [super sendEvent:anEvent]; |
| 109 } | 110 } |
| 110 | |
| 111 - (void)mouseMoved:(NSEvent*)event { | |
| 112 // Cocoa does not support letting the application determine the edges that | |
| 113 // can trigger the user resizing. To work around this, we track the mouse | |
| 114 // location. When it is close to the edge/corner where the user resizing | |
| 115 // is not desired, we force the min and max size of the window to be same | |
| 116 // as current window size. For all other cases, we restore the min and max | |
| 117 // size. | |
| 118 PanelWindowControllerCocoa* controller = | |
| 119 base::mac::ObjCCast<PanelWindowControllerCocoa>([self windowController]); | |
| 120 NSRect frame = [self frame]; | |
| 121 if ([controller canResizeByMouseAtCurrentLocation]) { | |
| 122 // Mac window server limits window sizes to 10000. | |
| 123 NSSize maxSize = NSMakeSize(10000, 10000); | |
| 124 | |
| 125 // If the user is resizing a stacked panel by its bottom edge, make sure its | |
| 126 // height cannot grow more than what the panel below it could offer. This is | |
| 127 // because growing a stacked panel by y amount will shrink the panel below | |
| 128 // it by same amount and we do not want the panel below it being shrunk to | |
| 129 // be smaller than the titlebar. | |
| 130 Panel* panel = [controller panel]; | |
| 131 NSPoint point = [NSEvent mouseLocation]; | |
| 132 if (point.y < NSMinY(frame) + kWidthOfMouseResizeArea && panel->stack()) { | |
| 133 Panel* belowPanel = panel->stack()->GetPanelBelow(panel); | |
| 134 if (belowPanel && !belowPanel->IsMinimized()) { | |
| 135 maxSize.height = panel->GetBounds().height() + | |
| 136 belowPanel->GetBounds().height() - panel::kTitlebarHeight; | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 // Enable the user-resizing by setting both min and max size to the right | |
| 141 // values. | |
| 142 [self setMinSize:NSMakeSize(panel::kPanelMinWidth, | |
| 143 panel::kPanelMinHeight)]; | |
| 144 [self setMaxSize:maxSize]; | |
| 145 } else { | |
| 146 // Disable the user-resizing by setting both min and max size to be same as | |
| 147 // current window size. | |
| 148 [self setMinSize:frame.size]; | |
| 149 [self setMaxSize:frame.size]; | |
| 150 } | |
| 151 | |
| 152 [super mouseMoved:event]; | |
| 153 } | |
| 154 @end | 111 @end |
| 155 | 112 |
| 113 // Transparent view covering the whole panel in order to intercept mouse |
| 114 // messages for custom user resizing. We need custom resizing because panels |
| 115 // use their own constrained layout. |
| 116 @interface PanelResizeByMouseOverlay : NSView <MouseDragControllerClient> { |
| 117 @private |
| 118 Panel* panel_; |
| 119 base::scoped_nsobject<MouseDragController> dragController_; |
| 120 base::scoped_nsobject<NSCursor> dragCursor_; |
| 121 base::scoped_nsobject<NSCursor> eastWestCursor_; |
| 122 base::scoped_nsobject<NSCursor> northSouthCursor_; |
| 123 base::scoped_nsobject<NSCursor> northEastSouthWestCursor_; |
| 124 base::scoped_nsobject<NSCursor> northWestSouthEastCursor_; |
| 125 NSRect leftCursorRect_; |
| 126 NSRect rightCursorRect_; |
| 127 NSRect topCursorRect_; |
| 128 NSRect bottomCursorRect_; |
| 129 NSRect topLeftCursorRect_; |
| 130 NSRect topRightCursorRect_; |
| 131 NSRect bottomLeftCursorRect_; |
| 132 NSRect bottomRightCursorRect_; |
| 133 } |
| 134 @end |
| 135 |
| 136 namespace { |
| 137 NSCursor* LoadWebKitCursor(WebKit::WebCursorInfo::Type type) { |
| 138 return WebCursor(WebCursor::CursorInfo(type)).GetNativeCursor(); |
| 139 } |
| 140 } |
| 141 |
| 142 @implementation PanelResizeByMouseOverlay |
| 143 - (PanelResizeByMouseOverlay*)initWithFrame:(NSRect)frame panel:(Panel*)panel { |
| 144 if ((self = [super initWithFrame:frame])) { |
| 145 panel_ = panel; |
| 146 dragController_.reset([[MouseDragController alloc] initWithClient:self]); |
| 147 |
| 148 eastWestCursor_.reset( |
| 149 [LoadWebKitCursor(WebKit::WebCursorInfo::TypeEastWestResize) retain]); |
| 150 northSouthCursor_.reset( |
| 151 [LoadWebKitCursor(WebKit::WebCursorInfo::TypeNorthSouthResize) retain]); |
| 152 northEastSouthWestCursor_.reset( |
| 153 [LoadWebKitCursor(WebKit::WebCursorInfo::TypeNorthEastSouthWestResize) |
| 154 retain]); |
| 155 northWestSouthEastCursor_.reset( |
| 156 [LoadWebKitCursor(WebKit::WebCursorInfo::TypeNorthWestSouthEastResize) |
| 157 retain]); |
| 158 } |
| 159 return self; |
| 160 } |
| 161 |
| 162 - (BOOL)acceptsFirstMouse:(NSEvent*)event { |
| 163 return YES; |
| 164 } |
| 165 |
| 166 // |pointInWindow| is in window coordinates. |
| 167 - (panel::ResizingSides)edgeHitTest:(NSPoint)pointInWindow { |
| 168 panel::Resizability resizability = panel_->CanResizeByMouse(); |
| 169 DCHECK_NE(panel::NOT_RESIZABLE, resizability); |
| 170 |
| 171 NSPoint point = [self convertPoint:pointInWindow fromView:nil]; |
| 172 BOOL flipped = [self isFlipped]; |
| 173 |
| 174 if ((resizability & panel::RESIZABLE_TOP_LEFT) && |
| 175 NSMouseInRect(point, topLeftCursorRect_, flipped)) { |
| 176 return panel::RESIZE_TOP_LEFT; |
| 177 } |
| 178 if ((resizability & panel::RESIZABLE_TOP_RIGHT) && |
| 179 NSMouseInRect(point, topRightCursorRect_, flipped)) { |
| 180 return panel::RESIZE_TOP_RIGHT; |
| 181 } |
| 182 if ((resizability & panel::RESIZABLE_BOTTOM_LEFT) && |
| 183 NSMouseInRect(point, bottomLeftCursorRect_, flipped)) { |
| 184 return panel::RESIZE_BOTTOM_LEFT; |
| 185 } |
| 186 if ((resizability & panel::RESIZABLE_BOTTOM_RIGHT) && |
| 187 NSMouseInRect(point, bottomRightCursorRect_, flipped)) { |
| 188 return panel::RESIZE_BOTTOM_RIGHT; |
| 189 } |
| 190 |
| 191 if ((resizability & panel::RESIZABLE_LEFT) && |
| 192 NSMouseInRect(point, leftCursorRect_, flipped)) { |
| 193 return panel::RESIZE_LEFT; |
| 194 } |
| 195 if ((resizability & panel::RESIZABLE_RIGHT) && |
| 196 NSMouseInRect(point, rightCursorRect_, flipped)) { |
| 197 return panel::RESIZE_RIGHT; |
| 198 } |
| 199 if ((resizability & panel::RESIZABLE_TOP) && |
| 200 NSMouseInRect(point, topCursorRect_, flipped)) { |
| 201 return panel::RESIZE_TOP; |
| 202 } |
| 203 if ((resizability & panel::RESIZABLE_BOTTOM) && |
| 204 NSMouseInRect(point, bottomCursorRect_, flipped)) { |
| 205 return panel::RESIZE_BOTTOM; |
| 206 } |
| 207 |
| 208 return panel::RESIZE_NONE; |
| 209 } |
| 210 |
| 211 // NSWindow uses this method to figure out if this view is under the mouse |
| 212 // and hence the one to handle the incoming mouse event. |
| 213 // Since this view covers the whole panel, it is asked first. |
| 214 // See if this is the mouse event we are interested in (in the resize areas) |
| 215 // and return 'nil' to let NSWindow find another candidate otherwise. |
| 216 // |point| is in coordinate system of the parent view. |
| 217 - (NSView*)hitTest:(NSPoint)point { |
| 218 // If panel is not resizable, let the mouse events fall through. |
| 219 if (panel::NOT_RESIZABLE == panel_->CanResizeByMouse()) |
| 220 return nil; |
| 221 |
| 222 NSPoint pointInWindow = [[self superview] convertPoint:point toView:nil]; |
| 223 return [self edgeHitTest:pointInWindow] == panel::RESIZE_NONE ? nil : self; |
| 224 } |
| 225 |
| 226 // Delegate these to MouseDragController, it will call back on |
| 227 // MouseDragControllerClient protocol. |
| 228 - (void)mouseDown:(NSEvent*)event { |
| 229 [dragController_ mouseDown:event]; |
| 230 } |
| 231 |
| 232 - (void)mouseDragged:(NSEvent*)event { |
| 233 [dragController_ mouseDragged:event]; |
| 234 } |
| 235 |
| 236 - (void)mouseUp:(NSEvent*)event { |
| 237 [dragController_ mouseUp:event]; |
| 238 } |
| 239 |
| 240 // MouseDragControllerClient protocol. |
| 241 |
| 242 - (void)prepareForDrag { |
| 243 // If the panel is not resizable, hitTest should have failed and no mouse |
| 244 // events should have come here. |
| 245 DCHECK_NE(panel::NOT_RESIZABLE, panel_->CanResizeByMouse()); |
| 246 |
| 247 // Make sure the cursor stays the same during whole resize operation. |
| 248 // The cursor rects normally do not guarantee the same cursor, since the |
| 249 // mouse may temporarily leave the cursor rect area (or even the window) so |
| 250 // the cursor will flicker. Disable cursor rects and grab the current cursor |
| 251 // so we can set it on mouseDragged: events to avoid flicker. |
| 252 [[self window] disableCursorRects]; |
| 253 dragCursor_.reset([[NSCursor currentCursor] retain]); |
| 254 } |
| 255 |
| 256 - (void)cleanupAfterDrag { |
| 257 [[self window] enableCursorRects]; |
| 258 dragCursor_.reset(); |
| 259 } |
| 260 |
| 261 - (void)dragStarted:(NSPoint)initialMouseLocation { |
| 262 NSPoint initialMouseLocationScreen = |
| 263 [[self window] convertBaseToScreen:initialMouseLocation]; |
| 264 |
| 265 panel_->manager()->StartResizingByMouse( |
| 266 panel_, |
| 267 cocoa_utils::ConvertPointFromCocoaCoordinates(initialMouseLocationScreen), |
| 268 [self edgeHitTest:initialMouseLocation]); |
| 269 } |
| 270 |
| 271 - (void)dragProgress:(NSPoint)mouseLocation { |
| 272 NSPoint mouseLocationScreen = |
| 273 [[self window] convertBaseToScreen:mouseLocation]; |
| 274 panel_->manager()->ResizeByMouse( |
| 275 cocoa_utils::ConvertPointFromCocoaCoordinates(mouseLocationScreen)); |
| 276 |
| 277 // Set the resize cursor on every mouse drag event in case the mouse |
| 278 // wandered outside the window and was switched to another one. |
| 279 // This does not produce flicker, seems the real cursor is updated after |
| 280 // mouseDrag is processed. |
| 281 [dragCursor_ set]; |
| 282 } |
| 283 |
| 284 - (void)dragEnded:(BOOL)cancelled { |
| 285 panel_->manager()->EndResizingByMouse(cancelled); |
| 286 } |
| 287 |
| 288 - (void)resetCursorRects { |
| 289 panel::Resizability resizability = panel_->CanResizeByMouse(); |
| 290 if (panel::NOT_RESIZABLE == resizability) |
| 291 return; |
| 292 |
| 293 NSRect bounds = [self bounds]; |
| 294 |
| 295 // Left vertical edge. |
| 296 if (resizability & panel::RESIZABLE_LEFT) { |
| 297 leftCursorRect_ = NSMakeRect( |
| 298 NSMinX(bounds), |
| 299 NSMinY(bounds) + kWidthOfMouseResizeArea, |
| 300 kWidthOfMouseResizeArea, |
| 301 NSHeight(bounds) - 2 * kWidthOfMouseResizeArea); |
| 302 [self addCursorRect:leftCursorRect_ cursor:eastWestCursor_]; |
| 303 } |
| 304 |
| 305 // Right vertical edge. |
| 306 if (resizability & panel::RESIZABLE_RIGHT) { |
| 307 rightCursorRect_ = leftCursorRect_; |
| 308 rightCursorRect_.origin.x = NSMaxX(bounds) - kWidthOfMouseResizeArea; |
| 309 [self addCursorRect:rightCursorRect_ cursor:eastWestCursor_]; |
| 310 } |
| 311 |
| 312 // Top horizontal edge. |
| 313 if (resizability & panel::RESIZABLE_TOP) { |
| 314 topCursorRect_ = NSMakeRect(NSMinX(bounds) + kWidthOfMouseResizeArea, |
| 315 NSMaxY(bounds) - kWidthOfMouseResizeArea, |
| 316 NSWidth(bounds) - 2 * kWidthOfMouseResizeArea, |
| 317 kWidthOfMouseResizeArea); |
| 318 [self addCursorRect:topCursorRect_ cursor:northSouthCursor_]; |
| 319 } |
| 320 |
| 321 // Top left corner. |
| 322 if (resizability & panel::RESIZABLE_TOP_LEFT) { |
| 323 topLeftCursorRect_ = NSMakeRect(NSMinX(bounds), |
| 324 NSMaxY(bounds) - kWidthOfMouseResizeArea, |
| 325 kWidthOfMouseResizeArea, |
| 326 NSMaxY(bounds)); |
| 327 [self addCursorRect:topLeftCursorRect_ cursor:northWestSouthEastCursor_]; |
| 328 } |
| 329 |
| 330 // Top right corner. |
| 331 if (resizability & panel::RESIZABLE_TOP_RIGHT) { |
| 332 topRightCursorRect_ = topLeftCursorRect_; |
| 333 topRightCursorRect_.origin.x = NSMaxX(bounds) - kWidthOfMouseResizeArea; |
| 334 [self addCursorRect:topRightCursorRect_ cursor:northEastSouthWestCursor_]; |
| 335 } |
| 336 |
| 337 // Bottom horizontal edge. |
| 338 if (resizability & panel::RESIZABLE_BOTTOM) { |
| 339 bottomCursorRect_ = topCursorRect_; |
| 340 bottomCursorRect_.origin.y = NSMinY(bounds); |
| 341 [self addCursorRect:bottomCursorRect_ cursor:northSouthCursor_]; |
| 342 } |
| 343 |
| 344 // Bottom right corner. |
| 345 if (resizability & panel::RESIZABLE_BOTTOM_RIGHT) { |
| 346 bottomRightCursorRect_ = topRightCursorRect_; |
| 347 bottomRightCursorRect_.origin.y = NSMinY(bounds); |
| 348 [self addCursorRect:bottomRightCursorRect_ |
| 349 cursor:northWestSouthEastCursor_]; |
| 350 } |
| 351 |
| 352 // Bottom left corner. |
| 353 if (resizability & panel::RESIZABLE_BOTTOM_LEFT) { |
| 354 bottomLeftCursorRect_ = bottomRightCursorRect_; |
| 355 bottomLeftCursorRect_.origin.x = NSMinX(bounds); |
| 356 [self addCursorRect:bottomLeftCursorRect_ cursor:northEastSouthWestCursor_]; |
| 357 } |
| 358 } |
| 359 @end |
| 360 |
| 156 // ChromeEventProcessingWindow expects its controller to implement the | 361 // ChromeEventProcessingWindow expects its controller to implement the |
| 157 // BrowserCommandExecutor protocol. | 362 // BrowserCommandExecutor protocol. |
| 158 @interface PanelWindowControllerCocoa (InternalAPI) <BrowserCommandExecutor> | 363 @interface PanelWindowControllerCocoa (InternalAPI) <BrowserCommandExecutor> |
| 159 | 364 |
| 160 // BrowserCommandExecutor methods. | 365 // BrowserCommandExecutor methods. |
| 161 - (void)executeCommand:(int)command; | 366 - (void)executeCommand:(int)command; |
| 162 | 367 |
| 163 @end | 368 @end |
| 164 | 369 |
| 165 @implementation PanelWindowControllerCocoa (InternalAPI) | 370 @implementation PanelWindowControllerCocoa (InternalAPI) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 177 [base::mac::FrameworkBundle() pathForResource:@"Panel" ofType:@"nib"]; | 382 [base::mac::FrameworkBundle() pathForResource:@"Panel" ofType:@"nib"]; |
| 178 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { | 383 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { |
| 179 windowShim_.reset(window); | 384 windowShim_.reset(window); |
| 180 animateOnBoundsChange_ = YES; | 385 animateOnBoundsChange_ = YES; |
| 181 canBecomeKeyWindow_ = YES; | 386 canBecomeKeyWindow_ = YES; |
| 182 activationRequestedByPanel_ = NO; | 387 activationRequestedByPanel_ = NO; |
| 183 } | 388 } |
| 184 return self; | 389 return self; |
| 185 } | 390 } |
| 186 | 391 |
| 187 - (Panel*)panel { | |
| 188 return windowShim_->panel(); | |
| 189 } | |
| 190 | |
| 191 - (void)awakeFromNib { | 392 - (void)awakeFromNib { |
| 192 NSWindow* window = [self window]; | 393 NSWindow* window = [self window]; |
| 193 | 394 |
| 194 DCHECK(window); | 395 DCHECK(window); |
| 195 DCHECK(titlebar_view_); | 396 DCHECK(titlebar_view_); |
| 196 DCHECK_EQ(self, [window delegate]); | 397 DCHECK_EQ(self, [window delegate]); |
| 197 | 398 |
| 198 [self updateWindowLevel]; | 399 [self updateWindowLevel]; |
| 199 | 400 |
| 200 [self updateWindowCollectionBehavior]; | 401 [self updateWindowCollectionBehavior]; |
| 201 | 402 |
| 202 [titlebar_view_ attach]; | 403 [titlebar_view_ attach]; |
| 203 | 404 |
| 204 // Set initial size of the window to match the size of the panel to give | 405 // Set initial size of the window to match the size of the panel to give |
| 205 // the renderer the proper size to work with earlier, avoiding a resize | 406 // the renderer the proper size to work with earlier, avoiding a resize |
| 206 // after the window is revealed. | 407 // after the window is revealed. |
| 207 gfx::Rect panelBounds = windowShim_->panel()->GetBounds(); | 408 gfx::Rect panelBounds = windowShim_->panel()->GetBounds(); |
| 208 NSRect frame = [window frame]; | 409 NSRect frame = [window frame]; |
| 209 frame.size.width = panelBounds.width(); | 410 frame.size.width = panelBounds.width(); |
| 210 frame.size.height = panelBounds.height(); | 411 frame.size.height = panelBounds.height(); |
| 211 [window setFrame:frame display:NO]; | 412 [window setFrame:frame display:NO]; |
| 212 | 413 |
| 213 // MacOS will turn the user-resizing to the user-dragging if the direction of | 414 // Add a transparent overlay on top of the whole window to process mouse |
| 214 // the dragging is orthogonal to the direction of the arrow cursor. We do not | 415 // events - for example, user-resizing. |
| 215 // want this since it will bypass our dragging logic. The panel window is | 416 NSView* superview = [[window contentView] superview]; |
| 216 // still draggable because we track and handle the dragging in our custom way. | 417 NSRect bounds = [superview bounds]; |
| 217 [[self window] setMovable:NO]; | 418 overlayView_.reset( |
| 218 | 419 [[PanelResizeByMouseOverlay alloc] initWithFrame:bounds |
| 219 [self updateTrackingArea]; | 420 panel:windowShim_->panel()]); |
| 421 // Set autoresizing behavior: glued to edges. |
| 422 [overlayView_ setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)]; |
| 423 [superview addSubview:overlayView_ positioned:NSWindowAbove relativeTo:nil]; |
| 220 } | 424 } |
| 221 | 425 |
| 222 - (void)updateWebContentsViewFrame { | 426 - (void)updateWebContentsViewFrame { |
| 223 content::WebContents* webContents = windowShim_->panel()->GetWebContents(); | 427 content::WebContents* webContents = windowShim_->panel()->GetWebContents(); |
| 224 if (!webContents) | 428 if (!webContents) |
| 225 return; | 429 return; |
| 226 | 430 |
| 227 // Compute the size of the web contents view. Don't assume it's similar to the | 431 // Compute the size of the web contents view. Don't assume it's similar to the |
| 228 // size of the contentView, because the contentView is managed by the Cocoa | 432 // size of the contentView, because the contentView is managed by the Cocoa |
| 229 // to be (window - standard titlebar), while we have taller custom titlebar | 433 // to be (window - standard titlebar), while we have taller custom titlebar |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 - (void)windowDidBecomeKey:(NSNotification*)notification { | 795 - (void)windowDidBecomeKey:(NSNotification*)notification { |
| 592 // We need to activate the controls (in the "WebView"). To do this, get the | 796 // We need to activate the controls (in the "WebView"). To do this, get the |
| 593 // selected WebContents's RenderWidgetHostView and tell it to activate. | 797 // selected WebContents's RenderWidgetHostView and tell it to activate. |
| 594 if (WebContents* contents = windowShim_->panel()->GetWebContents()) { | 798 if (WebContents* contents = windowShim_->panel()->GetWebContents()) { |
| 595 if (content::RenderWidgetHostView* rwhv = | 799 if (content::RenderWidgetHostView* rwhv = |
| 596 contents->GetRenderWidgetHostView()) | 800 contents->GetRenderWidgetHostView()) |
| 597 rwhv->SetActive(true); | 801 rwhv->SetActive(true); |
| 598 } | 802 } |
| 599 | 803 |
| 600 windowShim_->panel()->OnActiveStateChanged(true); | 804 windowShim_->panel()->OnActiveStateChanged(true); |
| 601 | |
| 602 // Make the window user-resizable when it gains the focus. | |
| 603 [[self window] setStyleMask: | |
| 604 [[self window] styleMask] | NSResizableWindowMask]; | |
| 605 } | 805 } |
| 606 | 806 |
| 607 - (void)windowDidResignKey:(NSNotification*)notification { | 807 - (void)windowDidResignKey:(NSNotification*)notification { |
| 608 // If our app is still active and we're still the key window, ignore this | 808 // If our app is still active and we're still the key window, ignore this |
| 609 // message, since it just means that a menu extra (on the "system status bar") | 809 // message, since it just means that a menu extra (on the "system status bar") |
| 610 // was activated; we'll get another |-windowDidResignKey| if we ever really | 810 // was activated; we'll get another |-windowDidResignKey| if we ever really |
| 611 // lose key window status. | 811 // lose key window status. |
| 612 if ([NSApp isActive] && ([NSApp keyWindow] == [self window])) | 812 if ([NSApp isActive] && ([NSApp keyWindow] == [self window])) |
| 613 return; | 813 return; |
| 614 | 814 |
| 615 [self onWindowDidResignKey]; | 815 [self onWindowDidResignKey]; |
| 616 | |
| 617 // Make the window not user-resizable when it loses the focus. This is to | |
| 618 // solve the problem that the bottom edge of the active panel does not | |
| 619 // trigger the user-resizing if this panel stacks with another inactive | |
| 620 // panel at the bottom. | |
| 621 [[self window] setStyleMask: | |
| 622 [[self window] styleMask] & ~NSResizableWindowMask]; | |
| 623 } | |
| 624 | |
| 625 - (void)windowWillStartLiveResize:(NSNotification*)notification { | |
| 626 // Check if the user-resizing is allowed for the triggering edge/corner. | |
| 627 // This is an extra safe guard because we are not able to track the mouse | |
| 628 // movement outside the window and Cocoa could trigger the user-resizing | |
| 629 // when the mouse moves a bit outside the edge/corner. | |
| 630 if (![self canResizeByMouseAtCurrentLocation]) | |
| 631 return; | |
| 632 userResizing_ = YES; | |
| 633 windowShim_->panel()->OnPanelStartUserResizing(); | |
| 634 } | |
| 635 | |
| 636 - (void)windowDidEndLiveResize:(NSNotification*)notification { | |
| 637 if (!userResizing_) | |
| 638 return; | |
| 639 userResizing_ = NO; | |
| 640 | |
| 641 Panel* panel = windowShim_->panel(); | |
| 642 panel->OnPanelEndUserResizing(); | |
| 643 | |
| 644 gfx::Rect newBounds = | |
| 645 cocoa_utils::ConvertRectFromCocoaCoordinates([[self window] frame]); | |
| 646 if (windowShim_->panel()->GetBounds() == newBounds) | |
| 647 return; | |
| 648 windowShim_->set_cached_bounds_directly(newBounds); | |
| 649 | |
| 650 panel->IncreaseMaxSize(newBounds.size()); | |
| 651 panel->set_full_size(newBounds.size()); | |
| 652 | |
| 653 panel->collection()->RefreshLayout(); | |
| 654 } | |
| 655 | |
| 656 - (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)newSize { | |
| 657 // As an extra safe guard, we avoid the user resizing if it is deemed not to | |
| 658 // be allowed (see comment in windowWillStartLiveResize). | |
| 659 if ([[self window] inLiveResize] && !userResizing_) | |
| 660 return [[self window] frame].size; | |
| 661 return newSize; | |
| 662 } | 816 } |
| 663 | 817 |
| 664 - (void)windowDidResize:(NSNotification*)notification { | 818 - (void)windowDidResize:(NSNotification*)notification { |
| 665 Panel* panel = windowShim_->panel(); | 819 Panel* panel = windowShim_->panel(); |
| 666 if (userResizing_) { | |
| 667 panel->collection()->OnPanelResizedByMouse( | |
| 668 panel, | |
| 669 cocoa_utils::ConvertRectFromCocoaCoordinates([[self window] frame])); | |
| 670 } | |
| 671 | |
| 672 [self updateTrackingArea]; | |
| 673 | |
| 674 if (![self isAnimatingBounds] || | 820 if (![self isAnimatingBounds] || |
| 675 panel->collection()->type() != PanelCollection::DOCKED) | 821 panel->collection()->type() != PanelCollection::DOCKED) |
| 676 return; | 822 return; |
| 677 | 823 |
| 678 // Remove the web contents view from the view hierarchy when the panel is not | 824 // Remove the web contents view from the view hierarchy when the panel is not |
| 679 // taller than the titlebar. Put it back when the panel grows taller than | 825 // taller than the titlebar. Put it back when the panel grows taller than |
| 680 // the titlebar. Note that RenderWidgetHostViewMac works for the case that | 826 // the titlebar. Note that RenderWidgetHostViewMac works for the case that |
| 681 // the web contents view does not exist in the view hierarchy (i.e. the tab | 827 // the web contents view does not exist in the view hierarchy (i.e. the tab |
| 682 // is not the main one), but it does not work well, like causing occasional | 828 // is not the main one), but it does not work well, like causing occasional |
| 683 // crashes (http://crbug.com/265932), if the web contents view is made hidden. | 829 // crashes (http://crbug.com/265932), if the web contents view is made hidden. |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 819 - (void)updateWindowCollectionBehavior { | 965 - (void)updateWindowCollectionBehavior { |
| 820 if (![self isWindowLoaded]) | 966 if (![self isWindowLoaded]) |
| 821 return; | 967 return; |
| 822 NSWindowCollectionBehavior collectionBehavior = | 968 NSWindowCollectionBehavior collectionBehavior = |
| 823 NSWindowCollectionBehaviorParticipatesInCycle; | 969 NSWindowCollectionBehaviorParticipatesInCycle; |
| 824 if (windowShim_->panel()->IsAlwaysOnTop()) | 970 if (windowShim_->panel()->IsAlwaysOnTop()) |
| 825 collectionBehavior |= NSWindowCollectionBehaviorCanJoinAllSpaces; | 971 collectionBehavior |= NSWindowCollectionBehaviorCanJoinAllSpaces; |
| 826 [[self window] setCollectionBehavior:collectionBehavior]; | 972 [[self window] setCollectionBehavior:collectionBehavior]; |
| 827 } | 973 } |
| 828 | 974 |
| 829 - (void)updateTrackingArea { | 975 - (void)enableResizeByMouse:(BOOL)enable { |
| 830 NSView* superview = [[[self window] contentView] superview]; | 976 if (![self isWindowLoaded]) |
| 831 | 977 return; |
| 832 if (trackingArea_.get()) | 978 [[self window] invalidateCursorRectsForView:overlayView_]; |
| 833 [superview removeTrackingArea:trackingArea_.get()]; | |
| 834 | |
| 835 trackingArea_.reset( | |
| 836 [[CrTrackingArea alloc] initWithRect:[superview bounds] | |
| 837 options:NSTrackingInVisibleRect | | |
| 838 NSTrackingMouseMoved | | |
| 839 NSTrackingActiveInKeyWindow | |
| 840 owner:superview | |
| 841 userInfo:nil]); | |
| 842 [superview addTrackingArea:trackingArea_.get()]; | |
| 843 } | 979 } |
| 844 | 980 |
| 845 - (void)showShadow:(BOOL)show { | 981 - (void)showShadow:(BOOL)show { |
| 846 if (![self isWindowLoaded]) | 982 if (![self isWindowLoaded]) |
| 847 return; | 983 return; |
| 848 [[self window] setHasShadow:show]; | 984 [[self window] setHasShadow:show]; |
| 849 } | 985 } |
| 850 | 986 |
| 851 - (void)miniaturize { | 987 - (void)miniaturize { |
| 852 [[self window] miniaturize:nil]; | 988 [[self window] miniaturize:nil]; |
| 853 } | 989 } |
| 854 | 990 |
| 855 - (BOOL)isMiniaturized { | 991 - (BOOL)isMiniaturized { |
| 856 return [[self window] isMiniaturized]; | 992 return [[self window] isMiniaturized]; |
| 857 } | 993 } |
| 858 | 994 |
| 859 - (BOOL)canResizeByMouseAtCurrentLocation { | |
| 860 panel::Resizability resizability = windowShim_->panel()->CanResizeByMouse(); | |
| 861 NSRect frame = [[self window] frame]; | |
| 862 NSPoint point = [NSEvent mouseLocation]; | |
| 863 | |
| 864 if (point.y < NSMinY(frame) + kWidthOfMouseResizeArea) { | |
| 865 if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea && | |
| 866 (resizability & panel::RESIZABLE_BOTTOM_LEFT) == 0) { | |
| 867 return NO; | |
| 868 } | |
| 869 if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea && | |
| 870 (resizability & panel::RESIZABLE_BOTTOM_RIGHT) == 0) { | |
| 871 return NO; | |
| 872 } | |
| 873 if ((resizability & panel::RESIZABLE_BOTTOM) == 0) | |
| 874 return NO; | |
| 875 } else if (point.y > NSMaxY(frame) - kWidthOfMouseResizeArea) { | |
| 876 if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea && | |
| 877 (resizability & panel::RESIZABLE_TOP_LEFT) == 0) { | |
| 878 return NO; | |
| 879 } | |
| 880 if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea && | |
| 881 (resizability & panel::RESIZABLE_TOP_RIGHT) == 0) { | |
| 882 return NO; | |
| 883 } | |
| 884 if ((resizability & panel::RESIZABLE_TOP) == 0) | |
| 885 return NO; | |
| 886 } else { | |
| 887 if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea && | |
| 888 (resizability & panel::RESIZABLE_LEFT) == 0) { | |
| 889 return NO; | |
| 890 } | |
| 891 if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea && | |
| 892 (resizability & panel::RESIZABLE_RIGHT) == 0) { | |
| 893 return NO; | |
| 894 } | |
| 895 } | |
| 896 return YES; | |
| 897 } | |
| 898 | |
| 899 // We have custom implementation of these because our titlebar height is custom | 995 // We have custom implementation of these because our titlebar height is custom |
| 900 // and does not match the standard one. | 996 // and does not match the standard one. |
| 901 - (NSRect)frameRectForContentRect:(NSRect)contentRect { | 997 - (NSRect)frameRectForContentRect:(NSRect)contentRect { |
| 902 // contentRect is in contentView coord system. We should add a titlebar on top | 998 // contentRect is in contentView coord system. We should add a titlebar on top |
| 903 // and then convert to the windows coord system. | 999 // and then convert to the windows coord system. |
| 904 contentRect.size.height += panel::kTitlebarHeight; | 1000 contentRect.size.height += panel::kTitlebarHeight; |
| 905 NSRect frameRect = [[[self window] contentView] convertRect:contentRect | 1001 NSRect frameRect = [[[self window] contentView] convertRect:contentRect |
| 906 toView:nil]; | 1002 toView:nil]; |
| 907 return frameRect; | 1003 return frameRect; |
| 908 } | 1004 } |
| 909 | 1005 |
| 910 - (NSRect)contentRectForFrameRect:(NSRect)frameRect { | 1006 - (NSRect)contentRectForFrameRect:(NSRect)frameRect { |
| 911 NSRect contentRect = [[[self window] contentView] convertRect:frameRect | 1007 NSRect contentRect = [[[self window] contentView] convertRect:frameRect |
| 912 fromView:nil]; | 1008 fromView:nil]; |
| 913 contentRect.size.height -= panel::kTitlebarHeight; | 1009 contentRect.size.height -= panel::kTitlebarHeight; |
| 914 if (contentRect.size.height < 0) | 1010 if (contentRect.size.height < 0) |
| 915 contentRect.size.height = 0; | 1011 contentRect.size.height = 0; |
| 916 return contentRect; | 1012 return contentRect; |
| 917 } | 1013 } |
| 918 | 1014 |
| 919 @end | 1015 @end |
| OLD | NEW |