| 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/tabs/tab_strip_view.h" | 5 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h" |
| 6 | 6 |
| 7 #include <cmath> // floor | 7 #include <cmath> // floor |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/mac/foundation_util.h" | 10 #include "base/mac/foundation_util.h" |
| 11 #include "base/mac/mac_util.h" | 11 #include "base/mac/mac_util.h" |
| 12 #include "base/mac/sdk_forward_declarations.h" | 12 #include "base/mac/sdk_forward_declarations.h" |
| 13 #include "chrome/browser/themes/theme_properties.h" | 13 #include "chrome/browser/themes/theme_properties.h" |
| 14 #include "chrome/browser/themes/theme_service.h" | 14 #include "chrome/browser/themes/theme_service.h" |
| 15 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 16 #import "chrome/browser/ui/cocoa/browser_window_layout.h" |
| 15 #import "chrome/browser/ui/cocoa/new_tab_button.h" | 17 #import "chrome/browser/ui/cocoa/new_tab_button.h" |
| 16 #import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h" | 18 #import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h" |
| 17 #import "chrome/browser/ui/cocoa/tabs/tab_view.h" | 19 #import "chrome/browser/ui/cocoa/tabs/tab_view.h" |
| 18 #import "chrome/browser/ui/cocoa/view_id_util.h" | 20 #import "chrome/browser/ui/cocoa/view_id_util.h" |
| 19 #include "chrome/grit/generated_resources.h" | 21 #include "chrome/grit/generated_resources.h" |
| 20 #include "chrome/grit/theme_resources.h" | 22 #include "chrome/grit/theme_resources.h" |
| 21 #import "ui/base/cocoa/appkit_utils.h" | 23 #import "ui/base/cocoa/appkit_utils.h" |
| 22 #import "ui/base/cocoa/nsgraphics_context_additions.h" | 24 #import "ui/base/cocoa/nsgraphics_context_additions.h" |
| 23 #import "ui/base/cocoa/nsview_additions.h" | 25 #import "ui/base/cocoa/nsview_additions.h" |
| 24 #include "ui/base/l10n/l10n_util_mac.h" | 26 #include "ui/base/l10n/l10n_util_mac.h" |
| 25 #include "ui/base/material_design/material_design_controller.h" | 27 #include "ui/base/material_design/material_design_controller.h" |
| 26 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" | 28 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" |
| 27 | 29 |
| 28 @implementation TabStripView | 30 @implementation TabStripView |
| 29 | 31 |
| 30 @synthesize controller = controller_; | |
| 31 @synthesize dropArrowShown = dropArrowShown_; | 32 @synthesize dropArrowShown = dropArrowShown_; |
| 32 @synthesize dropArrowPosition = dropArrowPosition_; | 33 @synthesize dropArrowPosition = dropArrowPosition_; |
| 34 @synthesize inATabDraggingOverlayWindow = inATabDraggingOverlayWindow_; |
| 33 | 35 |
| 34 - (id)initWithFrame:(NSRect)frame { | 36 - (id)initWithFrame:(NSRect)frame { |
| 35 self = [super initWithFrame:frame]; | 37 self = [super initWithFrame:frame]; |
| 36 if (self) { | 38 if (self) { |
| 37 newTabButton_.reset([[NewTabButton alloc] initWithFrame: | 39 newTabButton_.reset([[NewTabButton alloc] initWithFrame: |
| 38 NSMakeRect(295, 0, 40, 27)]); | 40 NSMakeRect(295, 0, 40, 27)]); |
| 39 [newTabButton_ setToolTip:l10n_util::GetNSString(IDS_TOOLTIP_NEW_TAB)]; | 41 [newTabButton_ setToolTip:l10n_util::GetNSString(IDS_TOOLTIP_NEW_TAB)]; |
| 40 | 42 |
| 41 // Set lastMouseUp_ = -1000.0 so that timestamp-lastMouseUp_ is big unless | 43 // Set lastMouseUp_ = -1000.0 so that timestamp-lastMouseUp_ is big unless |
| 42 // lastMouseUp_ has been reset. | 44 // lastMouseUp_ has been reset. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 strokeColor = [strokeColor colorWithAlphaComponent:100]; | 91 strokeColor = [strokeColor colorWithAlphaComponent:100]; |
| 90 [strokeColor set]; | 92 [strokeColor set]; |
| 91 | 93 |
| 92 NSRect borderRect = NSMakeRect(0.0, 0.0, self.bounds.size.width, | 94 NSRect borderRect = NSMakeRect(0.0, 0.0, self.bounds.size.width, |
| 93 [self cr_lineWidth]); | 95 [self cr_lineWidth]); |
| 94 NSRectFillUsingOperation(NSIntersectionRect(dirtyRect, borderRect), | 96 NSRectFillUsingOperation(NSIntersectionRect(dirtyRect, borderRect), |
| 95 NSCompositeSourceOver); | 97 NSCompositeSourceOver); |
| 96 } | 98 } |
| 97 | 99 |
| 98 - (void)drawRect:(NSRect)dirtyRect { | 100 - (void)drawRect:(NSRect)dirtyRect { |
| 101 const ui::ThemeProvider* themeProvider = [[self window] themeProvider]; |
| 102 bool hasCustomThemeImage = themeProvider && |
| 103 themeProvider->HasCustomImage(IDR_THEME_FRAME); |
| 104 BOOL supportsVibrancy = [self visualEffectView] != nil; |
| 105 BOOL isMainWindow = [[self window] isMainWindow]; |
| 106 |
| 107 // If in Material Design mode, decrease the tabstrip background's translucency |
| 108 // by overlaying it with a partially-transparent gray (but only if not themed, |
| 109 // and not being used to drag tabs between browser windows). The gray is |
| 110 // somewhat opaque for Incognito mode, very opaque for non-Incognito mode, and |
| 111 // completely opaque when the window is not active. |
| 112 if (themeProvider && !hasCustomThemeImage && !inATabDraggingOverlayWindow_) { |
| 113 NSColor* theColor = nil; |
| 114 if (isMainWindow) { |
| 115 if (supportsVibrancy && |
| 116 !themeProvider->HasCustomColor(ThemeProperties::COLOR_FRAME)) { |
| 117 theColor = themeProvider->GetNSColor( |
| 118 ThemeProperties::COLOR_FRAME_VIBRANCY_OVERLAY); |
| 119 } else if (!supportsVibrancy && themeProvider->InIncognitoMode()) { |
| 120 theColor = [NSColor colorWithSRGBRed:20 / 255. |
| 121 green:22 / 255. |
| 122 blue:24 / 255. |
| 123 alpha:1]; |
| 124 } else { |
| 125 theColor = themeProvider->GetNSColor(ThemeProperties::COLOR_FRAME); |
| 126 } |
| 127 } else { |
| 128 theColor = themeProvider->GetNSColor( |
| 129 ThemeProperties::COLOR_FRAME_INACTIVE); |
| 130 } |
| 131 |
| 132 if (theColor) { |
| 133 [theColor set]; |
| 134 NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver); |
| 135 } |
| 136 } |
| 137 |
| 99 [self drawBottomEdge:dirtyRect]; | 138 [self drawBottomEdge:dirtyRect]; |
| 100 | 139 |
| 101 // Draw drop-indicator arrow (if appropriate). | 140 // Draw drop-indicator arrow (if appropriate). |
| 102 // TODO(viettrungluu): this is all a stop-gap measure. | 141 // TODO(viettrungluu): this is all a stop-gap measure. |
| 103 if ([self dropArrowShown]) { | 142 if ([self dropArrowShown]) { |
| 104 // Programmer art: an arrow parametrized by many knobs. Note that the arrow | 143 // Programmer art: an arrow parametrized by many knobs. Note that the arrow |
| 105 // points downwards (so understand "width" and "height" accordingly). | 144 // points downwards (so understand "width" and "height" accordingly). |
| 106 | 145 |
| 107 // How many (pixels) to inset on the top/bottom. | 146 // How many (pixels) to inset on the top/bottom. |
| 108 const CGFloat kArrowTopInset = 1.5; | 147 const CGFloat kArrowTopInset = 1.5; |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 } | 340 } |
| 302 | 341 |
| 303 - (NewTabButton*)getNewTabButton { | 342 - (NewTabButton*)getNewTabButton { |
| 304 return newTabButton_; | 343 return newTabButton_; |
| 305 } | 344 } |
| 306 | 345 |
| 307 - (void)setNewTabButton:(NewTabButton*)button { | 346 - (void)setNewTabButton:(NewTabButton*)button { |
| 308 newTabButton_.reset([button retain]); | 347 newTabButton_.reset([button retain]); |
| 309 } | 348 } |
| 310 | 349 |
| 350 - (NSVisualEffectView*)visualEffectView { |
| 351 // NSVisualEffectView is only available on OS X 10.10 and higher. |
| 352 if (!base::mac::IsAtLeastOS10_10()) |
| 353 return nil; |
| 354 |
| 355 NSView* rootView = [[self window] contentView]; |
| 356 if (!chrome::ShouldUseFullSizeContentView()) { |
| 357 rootView = [rootView superview]; |
| 358 } |
| 359 |
| 360 Class nsVisualEffectViewClass = NSClassFromString(@"NSVisualEffectView"); |
| 361 DCHECK(nsVisualEffectViewClass); |
| 362 for (NSView* view in [rootView subviews]) { |
| 363 if ([view isKindOfClass:nsVisualEffectViewClass]) { |
| 364 return base::mac::ObjCCast<NSVisualEffectView>(view); |
| 365 } |
| 366 } |
| 367 return nil; |
| 368 } |
| 369 |
| 370 - (void)setController:(TabStripController*)controller { |
| 371 controller_ = controller; |
| 372 // If tearing down the browser window, there's nothing more to do. |
| 373 if (!controller_) { |
| 374 return; |
| 375 } |
| 376 |
| 377 // Finish configuring the NSVisualEffectView so that it matches the window's |
| 378 // theme. |
| 379 NSVisualEffectView* visualEffectView = [self visualEffectView]; |
| 380 const ui::ThemeProvider* themeProvider = [[self window] themeProvider]; |
| 381 if (!visualEffectView || !themeProvider) { |
| 382 return; |
| 383 } |
| 384 |
| 385 // Themes with custom frame images don't use vibrancy. Otherwise, if Incognito |
| 386 // use Material Dark. |
| 387 if (themeProvider->HasCustomImage(IDR_THEME_FRAME) || |
| 388 themeProvider->HasCustomColor(ThemeProperties::COLOR_FRAME)) { |
| 389 [visualEffectView setState:NSVisualEffectStateInactive]; |
| 390 } else if (themeProvider->InIncognitoMode()) { |
| 391 [visualEffectView setMaterial:NSVisualEffectMaterialDark]; |
| 392 [visualEffectView setAppearance: |
| 393 [NSAppearance appearanceNamed:NSAppearanceNameVibrantDark]]; |
| 394 } |
| 395 } |
| 396 |
| 311 // ThemedWindowDrawing implementation. | 397 // ThemedWindowDrawing implementation. |
| 312 | 398 |
| 313 - (void)windowDidChangeTheme { | 399 - (void)windowDidChangeTheme { |
| 314 [self setNeedsDisplay:YES]; | 400 [self setNeedsDisplay:YES]; |
| 401 [self updateVisualEffectState]; |
| 315 } | 402 } |
| 316 | 403 |
| 317 - (void)windowDidChangeActive { | 404 - (void)windowDidChangeActive { |
| 318 [self setNeedsDisplay:YES]; | 405 [self setNeedsDisplay:YES]; |
| 319 } | 406 } |
| 320 | 407 |
| 408 - (void)setVisualEffectsDisabledForFullscreen:(BOOL)disabled { |
| 409 visualEffectsDisabledForFullscreen_ = disabled; |
| 410 [self updateVisualEffectState]; |
| 411 } |
| 412 |
| 413 - (void)updateVisualEffectState { |
| 414 // Configure the NSVisualEffectView so that it does nothing if the user has |
| 415 // switched to a custom theme, or uses vibrancy if the user has switched back |
| 416 // to the default theme. |
| 417 NSVisualEffectView* visualEffectView = [self visualEffectView]; |
| 418 const ui::ThemeProvider* themeProvider = [[self window] themeProvider]; |
| 419 if (!visualEffectView || !themeProvider) { |
| 420 return; |
| 421 } |
| 422 if (visualEffectsDisabledForFullscreen_ || |
| 423 themeProvider->HasCustomImage(IDR_THEME_FRAME) || |
| 424 themeProvider->HasCustomColor(ThemeProperties::COLOR_FRAME)) { |
| 425 [visualEffectView setState:NSVisualEffectStateInactive]; |
| 426 } else { |
| 427 [visualEffectView setState:NSVisualEffectStateFollowsWindowActiveState]; |
| 428 } |
| 429 } |
| 430 |
| 321 @end | 431 @end |
| OLD | NEW |