Chromium Code Reviews| 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 #import "chrome/browser/ui/cocoa/framed_browser_window.h" | 5 #import "chrome/browser/ui/cocoa/framed_browser_window.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/mac/sdk_forward_declarations.h" | 8 #include "base/mac/sdk_forward_declarations.h" |
| 9 #include "chrome/browser/global_keyboard_shortcuts_mac.h" | 9 #include "chrome/browser/global_keyboard_shortcuts_mac.h" |
| 10 #include "chrome/browser/profiles/profile_avatar_icon_util.h" | 10 #include "chrome/browser/profiles/profile_avatar_icon_util.h" |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 | 34 |
| 35 } | 35 } |
| 36 | 36 |
| 37 @interface FramedBrowserWindow (Private) | 37 @interface FramedBrowserWindow (Private) |
| 38 | 38 |
| 39 - (void)adjustCloseButton:(NSNotification*)notification; | 39 - (void)adjustCloseButton:(NSNotification*)notification; |
| 40 - (void)adjustMiniaturizeButton:(NSNotification*)notification; | 40 - (void)adjustMiniaturizeButton:(NSNotification*)notification; |
| 41 - (void)adjustZoomButton:(NSNotification*)notification; | 41 - (void)adjustZoomButton:(NSNotification*)notification; |
| 42 - (void)adjustButton:(NSButton*)button | 42 - (void)adjustButton:(NSButton*)button |
| 43 ofKind:(NSWindowButton)kind; | 43 ofKind:(NSWindowButton)kind; |
| 44 - (NSView*)frameView; | |
| 45 | 44 |
| 46 @end | 45 @end |
| 47 | 46 |
| 48 // Undocumented APIs. They are really on NSGrayFrame rather than NSView. Take | 47 // Undocumented APIs. They are really on NSGrayFrame rather than NSView. Take |
| 49 // care to only call them on the NSView passed into | 48 // care to only call them on the NSView passed into |
| 50 // -[NSWindow drawCustomRect:forView:]. | 49 // -[NSWindow drawCustomRect:forView:]. |
| 51 @interface NSView (UndocumentedAPI) | 50 @interface NSView (UndocumentedAPI) |
| 52 | 51 |
| 53 - (float)roundedCornerRadius; | 52 - (float)roundedCornerRadius; |
| 54 - (CGRect)_titlebarTitleRect; | 53 - (CGRect)_titlebarTitleRect; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 104 name:NSViewFrameDidChangeNotification | 103 name:NSViewFrameDidChangeNotification |
| 105 object:closeButton_]; | 104 object:closeButton_]; |
| 106 [center addObserver:self | 105 [center addObserver:self |
| 107 selector:@selector(adjustMiniaturizeButton:) | 106 selector:@selector(adjustMiniaturizeButton:) |
| 108 name:NSViewFrameDidChangeNotification | 107 name:NSViewFrameDidChangeNotification |
| 109 object:miniaturizeButton_]; | 108 object:miniaturizeButton_]; |
| 110 [center addObserver:self | 109 [center addObserver:self |
| 111 selector:@selector(adjustZoomButton:) | 110 selector:@selector(adjustZoomButton:) |
| 112 name:NSViewFrameDidChangeNotification | 111 name:NSViewFrameDidChangeNotification |
| 113 object:zoomButton_]; | 112 object:zoomButton_]; |
| 114 [center addObserver:self | |
| 115 selector:@selector(themeDidChangeNotification:) | |
| 116 name:kBrowserThemeDidChangeNotification | |
| 117 object:nil]; | |
| 118 } | 113 } |
| 119 | 114 |
| 120 return self; | 115 return self; |
| 121 } | 116 } |
| 122 | 117 |
| 123 - (void)dealloc { | 118 - (void)dealloc { |
| 124 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 119 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 125 [super dealloc]; | 120 [super dealloc]; |
| 126 } | 121 } |
| 127 | 122 |
| 128 - (void)adjustCloseButton:(NSNotification*)notification { | 123 - (void)adjustCloseButton:(NSNotification*)notification { |
| 129 [self adjustButton:[notification object] | 124 [self adjustButton:[notification object] |
| 130 ofKind:NSWindowCloseButton]; | 125 ofKind:NSWindowCloseButton]; |
| 131 } | 126 } |
| 132 | 127 |
| 133 - (void)adjustMiniaturizeButton:(NSNotification*)notification { | 128 - (void)adjustMiniaturizeButton:(NSNotification*)notification { |
| 134 [self adjustButton:[notification object] | 129 [self adjustButton:[notification object] |
| 135 ofKind:NSWindowMiniaturizeButton]; | 130 ofKind:NSWindowMiniaturizeButton]; |
| 136 } | 131 } |
| 137 | 132 |
| 138 - (void)adjustZoomButton:(NSNotification*)notification { | 133 - (void)adjustZoomButton:(NSNotification*)notification { |
| 139 [self adjustButton:[notification object] | 134 [self adjustButton:[notification object] |
| 140 ofKind:NSWindowZoomButton]; | 135 ofKind:NSWindowZoomButton]; |
| 141 } | 136 } |
| 142 | 137 |
| 143 - (void)adjustButton:(NSButton*)button | 138 - (void)adjustButton:(NSButton*)button |
| 144 ofKind:(NSWindowButton)kind { | 139 ofKind:(NSWindowButton)kind { |
| 145 NSRect buttonFrame = [button frame]; | 140 NSRect buttonFrame = [button frame]; |
| 146 NSRect frameViewBounds = [[self frameView] bounds]; | |
| 147 | 141 |
| 148 CGFloat xOffset = hasTabStrip_ | 142 CGFloat xOffset = hasTabStrip_ |
| 149 ? kFramedWindowButtonsWithTabStripOffsetFromLeft | 143 ? kFramedWindowButtonsWithTabStripOffsetFromLeft |
| 150 : kFramedWindowButtonsWithoutTabStripOffsetFromLeft; | 144 : kFramedWindowButtonsWithoutTabStripOffsetFromLeft; |
| 151 CGFloat yOffset = hasTabStrip_ | 145 CGFloat yOffset = hasTabStrip_ |
| 152 ? kFramedWindowButtonsWithTabStripOffsetFromTop | 146 ? kFramedWindowButtonsWithTabStripOffsetFromTop |
| 153 : kFramedWindowButtonsWithoutTabStripOffsetFromTop; | 147 : kFramedWindowButtonsWithoutTabStripOffsetFromTop; |
| 154 buttonFrame.origin = | 148 buttonFrame.origin = |
| 155 NSMakePoint(xOffset, (NSHeight(frameViewBounds) - | 149 NSMakePoint(xOffset, (NSHeight([self frame]) - |
| 156 NSHeight(buttonFrame) - yOffset)); | 150 NSHeight(buttonFrame) - yOffset)); |
| 157 | 151 |
| 158 switch (kind) { | 152 switch (kind) { |
| 159 case NSWindowZoomButton: | 153 case NSWindowZoomButton: |
| 160 buttonFrame.origin.x += NSWidth([miniaturizeButton_ frame]); | 154 buttonFrame.origin.x += NSWidth([miniaturizeButton_ frame]); |
| 161 buttonFrame.origin.x += windowButtonsInterButtonSpacing_; | 155 buttonFrame.origin.x += windowButtonsInterButtonSpacing_; |
| 162 // fallthrough | 156 // fallthrough |
| 163 case NSWindowMiniaturizeButton: | 157 case NSWindowMiniaturizeButton: |
| 164 buttonFrame.origin.x += NSWidth([closeButton_ frame]); | 158 buttonFrame.origin.x += NSWidth([closeButton_ frame]); |
| 165 buttonFrame.origin.x += windowButtonsInterButtonSpacing_; | 159 buttonFrame.origin.x += windowButtonsInterButtonSpacing_; |
| 166 // fallthrough | 160 // fallthrough |
| 167 default: | 161 default: |
| 168 break; | 162 break; |
| 169 } | 163 } |
| 170 | 164 |
| 171 BOOL didPost = [button postsBoundsChangedNotifications]; | 165 BOOL didPost = [button postsBoundsChangedNotifications]; |
| 172 [button setPostsFrameChangedNotifications:NO]; | 166 [button setPostsFrameChangedNotifications:NO]; |
| 173 [button setFrame:buttonFrame]; | 167 [button setFrame:buttonFrame]; |
| 174 [button setPostsFrameChangedNotifications:didPost]; | 168 [button setPostsFrameChangedNotifications:didPost]; |
| 175 } | 169 } |
| 176 | 170 |
| 177 - (NSView*)frameView { | |
| 178 return [[self contentView] superview]; | |
| 179 } | |
| 180 | |
| 181 // The tab strip view covers our window buttons. So we add hit testing here | 171 // The tab strip view covers our window buttons. So we add hit testing here |
| 182 // to find them properly and return them to the accessibility system. | 172 // to find them properly and return them to the accessibility system. |
| 183 - (id)accessibilityHitTest:(NSPoint)point { | 173 - (id)accessibilityHitTest:(NSPoint)point { |
| 184 NSPoint windowPoint = [self convertScreenToBase:point]; | 174 NSPoint windowPoint = [self convertScreenToBase:point]; |
| 185 NSControl* controls[] = { closeButton_, zoomButton_, miniaturizeButton_ }; | 175 NSControl* controls[] = { closeButton_, zoomButton_, miniaturizeButton_ }; |
| 186 id value = nil; | 176 id value = nil; |
| 187 for (size_t i = 0; i < sizeof(controls) / sizeof(controls[0]); ++i) { | 177 for (size_t i = 0; i < sizeof(controls) / sizeof(controls[0]); ++i) { |
| 188 if (NSPointInRect(windowPoint, [controls[i] frame])) { | 178 if (NSPointInRect(windowPoint, [controls[i] frame])) { |
| 189 value = [controls[i] accessibilityHitTest:point]; | 179 value = [controls[i] accessibilityHitTest:point]; |
| 190 break; | 180 break; |
| 191 } | 181 } |
| 192 } | 182 } |
| 193 if (!value) { | 183 if (!value) { |
| 194 value = [super accessibilityHitTest:point]; | 184 value = [super accessibilityHitTest:point]; |
| 195 } | 185 } |
| 196 return value; | 186 return value; |
| 197 } | 187 } |
| 198 | 188 |
| 199 - (void)windowMainStatusChanged { | |
| 200 NSView* frameView = [self frameView]; | |
| 201 NSView* contentView = [self contentView]; | |
| 202 NSRect updateRect = [frameView frame]; | |
| 203 NSRect contentRect = [contentView frame]; | |
| 204 CGFloat tabStripHeight = [TabStripController defaultTabHeight]; | |
| 205 updateRect.size.height -= NSHeight(contentRect) - tabStripHeight; | |
| 206 updateRect.origin.y = NSMaxY(contentRect) - tabStripHeight; | |
| 207 [[self frameView] setNeedsDisplayInRect:updateRect]; | |
| 208 } | |
| 209 | |
| 210 - (void)becomeMainWindow { | |
| 211 [self windowMainStatusChanged]; | |
| 212 [super becomeMainWindow]; | |
| 213 } | |
| 214 | |
| 215 - (void)resignMainWindow { | |
| 216 [self windowMainStatusChanged]; | |
| 217 [super resignMainWindow]; | |
| 218 } | |
| 219 | |
| 220 // Called after the current theme has changed. | |
| 221 - (void)themeDidChangeNotification:(NSNotification*)aNotification { | |
| 222 [[self frameView] setNeedsDisplay:YES]; | |
|
erikchen
2015/02/04 23:53:55
It seems like this class was a generic catch-all t
Andre
2015/02/05 01:04:26
This does not trigger redraw of the entire window,
| |
| 223 } | |
| 224 | |
| 225 - (void)sendEvent:(NSEvent*)event { | |
| 226 // For Cocoa windows, clicking on the close and the miniaturize buttons (but | |
| 227 // not the zoom button) while a window is in the background does NOT bring | |
| 228 // that window to the front. We don't get that behavior for free (probably | |
| 229 // because the tab strip view covers those buttons), so we handle it here. | |
| 230 // Zoom buttons do bring the window to the front. Note that Finder windows (in | |
| 231 // Leopard) behave differently in this regard in that zoom buttons don't bring | |
| 232 // the window to the foreground. | |
|
Andre
2015/02/04 23:03:23
This looks like it's no longer a problem.
There wa
| |
| 233 BOOL eventHandled = NO; | |
| 234 if (![self isMainWindow]) { | |
| 235 if ([event type] == NSLeftMouseDown) { | |
| 236 NSView* frameView = [self frameView]; | |
| 237 NSPoint mouse = [frameView convertPoint:[event locationInWindow] | |
| 238 fromView:nil]; | |
| 239 if (NSPointInRect(mouse, [closeButton_ frame])) { | |
| 240 [closeButton_ mouseDown:event]; | |
| 241 eventHandled = YES; | |
| 242 } else if (NSPointInRect(mouse, [miniaturizeButton_ frame])) { | |
| 243 [miniaturizeButton_ mouseDown:event]; | |
| 244 eventHandled = YES; | |
| 245 } | |
| 246 } | |
| 247 } | |
| 248 if (!eventHandled) { | |
| 249 [super sendEvent:event]; | |
| 250 } | |
| 251 } | |
| 252 | |
| 253 - (void)setShouldHideTitle:(BOOL)flag { | 189 - (void)setShouldHideTitle:(BOOL)flag { |
| 254 shouldHideTitle_ = flag; | 190 shouldHideTitle_ = flag; |
| 255 } | 191 } |
| 256 | 192 |
| 257 - (BOOL)_isTitleHidden { | 193 - (BOOL)_isTitleHidden { |
| 258 return shouldHideTitle_; | 194 return shouldHideTitle_; |
| 259 } | 195 } |
| 260 | 196 |
| 261 - (CGFloat)windowButtonsInterButtonSpacing { | 197 - (CGFloat)windowButtonsInterButtonSpacing { |
| 262 return windowButtonsInterButtonSpacing_; | 198 return windowButtonsInterButtonSpacing_; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 NSCompositingOperation operation = NSCompositeCopy; | 297 NSCompositingOperation operation = NSCompositeCopy; |
| 362 if (forceBlackBackground) { | 298 if (forceBlackBackground) { |
| 363 [[NSColor blackColor] set]; | 299 [[NSColor blackColor] set]; |
| 364 NSRectFill(dirtyRect); | 300 NSRectFill(dirtyRect); |
| 365 operation = NSCompositeSourceOver; | 301 operation = NSCompositeSourceOver; |
| 366 } | 302 } |
| 367 | 303 |
| 368 NSPoint position = [[view window] themeImagePositionForAlignment: | 304 NSPoint position = [[view window] themeImagePositionForAlignment: |
| 369 THEME_IMAGE_ALIGN_WITH_FRAME]; | 305 THEME_IMAGE_ALIGN_WITH_FRAME]; |
| 370 | 306 |
| 371 // Align the phase to physical pixels so resizing the window under HiDPI | 307 if ([view respondsToSelector:@selector(convertPointToBacking:)]) { |
| 372 // doesn't cause wiggling of the theme. | 308 // Align the phase to physical pixels so resizing the window under HiDPI |
| 373 NSView* frameView = [[[view window] contentView] superview]; | 309 // doesn't cause wiggling of the theme. |
| 374 position = [frameView convertPointToBase:position]; | 310 position = [view convertPointToBacking:position]; |
|
Andre
2015/02/04 23:03:23
This is deprecated in 10.7, and is not the right t
erikchen
2015/02/04 23:53:55
Shouldn't we have some sort of logic for 10.6?
Andre
2015/02/05 01:04:26
Good point.
Took a deeper look at this, I believe
| |
| 375 position.x = floor(position.x); | 311 position.x = floor(position.x); |
| 376 position.y = floor(position.y); | 312 position.y = floor(position.y); |
| 377 position = [frameView convertPointFromBase:position]; | 313 position = [view convertPointFromBacking:position]; |
| 314 } | |
| 315 | |
| 378 [[NSGraphicsContext currentContext] cr_setPatternPhase:position | 316 [[NSGraphicsContext currentContext] cr_setPatternPhase:position |
| 379 forView:view]; | 317 forView:view]; |
| 380 | 318 |
| 381 [themeImageColor set]; | 319 [themeImageColor set]; |
| 382 NSRectFillUsingOperation(dirtyRect, operation); | 320 NSRectFillUsingOperation(dirtyRect, operation); |
| 383 themed = YES; | 321 themed = YES; |
| 384 } else if (gradient) { | 322 } else if (gradient) { |
| 385 NSPoint startPoint = NSMakePoint(NSMinX(bounds), NSMaxY(bounds)); | 323 NSPoint startPoint = NSMakePoint(NSMinX(bounds), NSMaxY(bounds)); |
| 386 NSPoint endPoint = startPoint; | 324 NSPoint endPoint = startPoint; |
| 387 endPoint.y -= kBrowserFrameViewPaintHeight; | 325 endPoint.y -= kBrowserFrameViewPaintHeight; |
| 388 [gradient drawFromPoint:startPoint toPoint:endPoint options:0]; | 326 [gradient drawFromPoint:startPoint toPoint:endPoint options:0]; |
| 389 themed = YES; | 327 themed = YES; |
| 390 } | 328 } |
| 391 | 329 |
| 392 // Check to see if we have an overlay image. | 330 // Check to see if we have an overlay image. |
| 393 NSImage* overlayImage = nil; | 331 NSImage* overlayImage = nil; |
| 394 if (themeProvider->HasCustomImage(IDR_THEME_FRAME_OVERLAY) && !incognito && | 332 if (themeProvider->HasCustomImage(IDR_THEME_FRAME_OVERLAY) && !incognito && |
| 395 !popup) { | 333 !popup) { |
| 396 overlayImage = themeProvider-> | 334 overlayImage = themeProvider-> |
| 397 GetNSImageNamed(active ? IDR_THEME_FRAME_OVERLAY : | 335 GetNSImageNamed(active ? IDR_THEME_FRAME_OVERLAY : |
| 398 IDR_THEME_FRAME_OVERLAY_INACTIVE); | 336 IDR_THEME_FRAME_OVERLAY_INACTIVE); |
| 399 } | 337 } |
| 400 | 338 |
| 401 if (overlayImage) { | 339 if (overlayImage) { |
| 402 // Anchor to top-left and don't scale. | 340 // Anchor to top-left and don't scale. |
| 403 NSView* frameView = [[[view window] contentView] superview]; | |
| 404 NSPoint position = [[view window] themeImagePositionForAlignment: | 341 NSPoint position = [[view window] themeImagePositionForAlignment: |
| 405 THEME_IMAGE_ALIGN_WITH_FRAME]; | 342 THEME_IMAGE_ALIGN_WITH_FRAME]; |
| 406 position = [view convertPoint:position fromView:frameView]; | 343 position = [view convertPoint:position fromView:nil]; |
| 407 NSSize overlaySize = [overlayImage size]; | 344 NSSize overlaySize = [overlayImage size]; |
| 408 NSRect imageFrame = NSMakeRect(0, 0, overlaySize.width, overlaySize.height); | 345 NSRect imageFrame = NSMakeRect(0, 0, overlaySize.width, overlaySize.height); |
| 409 [overlayImage drawAtPoint:NSMakePoint(position.x, | 346 [overlayImage drawAtPoint:NSMakePoint(position.x, |
| 410 position.y - overlaySize.height) | 347 position.y - overlaySize.height) |
| 411 fromRect:imageFrame | 348 fromRect:imageFrame |
| 412 operation:NSCompositeSourceOver | 349 operation:NSCompositeSourceOver |
| 413 fraction:1.0]; | 350 fraction:1.0]; |
| 414 } | 351 } |
| 415 | 352 |
| 416 return themed; | 353 return themed; |
| 417 } | 354 } |
| 418 | 355 |
| 419 - (NSColor*)titleColor { | 356 - (NSColor*)titleColor { |
| 420 ui::ThemeProvider* themeProvider = [self themeProvider]; | 357 ui::ThemeProvider* themeProvider = [self themeProvider]; |
| 421 if (!themeProvider) | 358 if (!themeProvider) |
| 422 return [NSColor windowFrameTextColor]; | 359 return [NSColor windowFrameTextColor]; |
| 423 | 360 |
| 424 ThemedWindowStyle windowStyle = [self themedWindowStyle]; | 361 ThemedWindowStyle windowStyle = [self themedWindowStyle]; |
| 425 BOOL incognito = windowStyle & THEMED_INCOGNITO; | 362 BOOL incognito = windowStyle & THEMED_INCOGNITO; |
| 426 | 363 |
| 427 if (incognito) | 364 if (incognito) |
| 428 return [NSColor whiteColor]; | 365 return [NSColor whiteColor]; |
| 429 else | 366 else |
| 430 return [NSColor windowFrameTextColor]; | 367 return [NSColor windowFrameTextColor]; |
| 431 } | 368 } |
| 432 | 369 |
| 433 @end | 370 @end |
| OLD | NEW |