| 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 <Cocoa/Cocoa.h> | 5 #import <Cocoa/Cocoa.h> |
| 6 #import <QuartzCore/QuartzCore.h> | 6 #import <QuartzCore/QuartzCore.h> |
| 7 | 7 |
| 8 #import "chrome/browser/ui/cocoa/confirm_quit_panel_controller.h" | 8 #import "chrome/browser/ui/cocoa/confirm_quit_panel_controller.h" |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/memory/scoped_nsobject.h" | 11 #include "base/mac/scoped_nsobject.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/prefs/pref_registry_simple.h" | 13 #include "base/prefs/pref_registry_simple.h" |
| 14 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
| 15 #include "chrome/browser/browser_process.h" | 15 #include "chrome/browser/browser_process.h" |
| 16 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/browser/profiles/profile_manager.h" | 17 #include "chrome/browser/profiles/profile_manager.h" |
| 18 #include "chrome/browser/ui/cocoa/confirm_quit.h" | 18 #include "chrome/browser/ui/cocoa/confirm_quit.h" |
| 19 #include "chrome/common/pref_names.h" | 19 #include "chrome/common/pref_names.h" |
| 20 #include "grit/generated_resources.h" | 20 #include "grit/generated_resources.h" |
| 21 #import "ui/base/accelerators/platform_accelerator_cocoa.h" | 21 #import "ui/base/accelerators/platform_accelerator_cocoa.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 @private | 58 @private |
| 59 NSTextField* message_; // Weak, owned by the view hierarchy. | 59 NSTextField* message_; // Weak, owned by the view hierarchy. |
| 60 } | 60 } |
| 61 - (void)setMessageText:(NSString*)text; | 61 - (void)setMessageText:(NSString*)text; |
| 62 @end | 62 @end |
| 63 | 63 |
| 64 @implementation ConfirmQuitFrameView | 64 @implementation ConfirmQuitFrameView |
| 65 | 65 |
| 66 - (id)initWithFrame:(NSRect)frameRect { | 66 - (id)initWithFrame:(NSRect)frameRect { |
| 67 if ((self = [super initWithFrame:frameRect])) { | 67 if ((self = [super initWithFrame:frameRect])) { |
| 68 scoped_nsobject<NSTextField> message( | 68 base::scoped_nsobject<NSTextField> message( |
| 69 // The frame will be fixed up when |-setMessageText:| is called. | 69 // The frame will be fixed up when |-setMessageText:| is called. |
| 70 [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)]); | 70 [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)]); |
| 71 message_ = message.get(); | 71 message_ = message.get(); |
| 72 [message_ setEditable:NO]; | 72 [message_ setEditable:NO]; |
| 73 [message_ setSelectable:NO]; | 73 [message_ setSelectable:NO]; |
| 74 [message_ setBezeled:NO]; | 74 [message_ setBezeled:NO]; |
| 75 [message_ setDrawsBackground:NO]; | 75 [message_ setDrawsBackground:NO]; |
| 76 [message_ setFont:[NSFont boldSystemFontOfSize:24]]; | 76 [message_ setFont:[NSFont boldSystemFontOfSize:24]]; |
| 77 [message_ setTextColor:[NSColor whiteColor]]; | 77 [message_ setTextColor:[NSColor whiteColor]]; |
| 78 [self addSubview:message_]; | 78 [self addSubview:message_]; |
| 79 } | 79 } |
| 80 return self; | 80 return self; |
| 81 } | 81 } |
| 82 | 82 |
| 83 - (void)drawRect:(NSRect)dirtyRect { | 83 - (void)drawRect:(NSRect)dirtyRect { |
| 84 const CGFloat kCornerRadius = 5.0; | 84 const CGFloat kCornerRadius = 5.0; |
| 85 NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:[self bounds] | 85 NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:[self bounds] |
| 86 xRadius:kCornerRadius | 86 xRadius:kCornerRadius |
| 87 yRadius:kCornerRadius]; | 87 yRadius:kCornerRadius]; |
| 88 | 88 |
| 89 NSColor* fillColor = [NSColor colorWithCalibratedWhite:0.2 alpha:0.75]; | 89 NSColor* fillColor = [NSColor colorWithCalibratedWhite:0.2 alpha:0.75]; |
| 90 [fillColor set]; | 90 [fillColor set]; |
| 91 [path fill]; | 91 [path fill]; |
| 92 } | 92 } |
| 93 | 93 |
| 94 - (void)setMessageText:(NSString*)text { | 94 - (void)setMessageText:(NSString*)text { |
| 95 const CGFloat kHorizontalPadding = 30; // In view coordinates. | 95 const CGFloat kHorizontalPadding = 30; // In view coordinates. |
| 96 | 96 |
| 97 // Style the string. | 97 // Style the string. |
| 98 scoped_nsobject<NSMutableAttributedString> attrString( | 98 base::scoped_nsobject<NSMutableAttributedString> attrString( |
| 99 [[NSMutableAttributedString alloc] initWithString:text]); | 99 [[NSMutableAttributedString alloc] initWithString:text]); |
| 100 scoped_nsobject<NSShadow> textShadow([[NSShadow alloc] init]); | 100 base::scoped_nsobject<NSShadow> textShadow([[NSShadow alloc] init]); |
| 101 [textShadow.get() setShadowColor:[NSColor colorWithCalibratedWhite:0 | 101 [textShadow.get() setShadowColor:[NSColor colorWithCalibratedWhite:0 |
| 102 alpha:0.6]]; | 102 alpha:0.6]]; |
| 103 [textShadow.get() setShadowOffset:NSMakeSize(0, -1)]; | 103 [textShadow.get() setShadowOffset:NSMakeSize(0, -1)]; |
| 104 [textShadow setShadowBlurRadius:1.0]; | 104 [textShadow setShadowBlurRadius:1.0]; |
| 105 [attrString addAttribute:NSShadowAttributeName | 105 [attrString addAttribute:NSShadowAttributeName |
| 106 value:textShadow | 106 value:textShadow |
| 107 range:NSMakeRange(0, [text length])]; | 107 range:NSMakeRange(0, [text length])]; |
| 108 [message_ setAttributedStringValue:attrString]; | 108 [message_ setAttributedStringValue:attrString]; |
| 109 | 109 |
| 110 // Fixup the frame of the string. | 110 // Fixup the frame of the string. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 + (ConfirmQuitPanelController*)sharedController { | 185 + (ConfirmQuitPanelController*)sharedController { |
| 186 if (!g_confirmQuitPanelController) { | 186 if (!g_confirmQuitPanelController) { |
| 187 g_confirmQuitPanelController = | 187 g_confirmQuitPanelController = |
| 188 [[ConfirmQuitPanelController alloc] init]; | 188 [[ConfirmQuitPanelController alloc] init]; |
| 189 } | 189 } |
| 190 return [[g_confirmQuitPanelController retain] autorelease]; | 190 return [[g_confirmQuitPanelController retain] autorelease]; |
| 191 } | 191 } |
| 192 | 192 |
| 193 - (id)init { | 193 - (id)init { |
| 194 const NSRect kWindowFrame = NSMakeRect(0, 0, 350, 70); | 194 const NSRect kWindowFrame = NSMakeRect(0, 0, 350, 70); |
| 195 scoped_nsobject<NSWindow> window( | 195 base::scoped_nsobject<NSWindow> window( |
| 196 [[NSWindow alloc] initWithContentRect:kWindowFrame | 196 [[NSWindow alloc] initWithContentRect:kWindowFrame |
| 197 styleMask:NSBorderlessWindowMask | 197 styleMask:NSBorderlessWindowMask |
| 198 backing:NSBackingStoreBuffered | 198 backing:NSBackingStoreBuffered |
| 199 defer:NO]); | 199 defer:NO]); |
| 200 if ((self = [super initWithWindow:window])) { | 200 if ((self = [super initWithWindow:window])) { |
| 201 [window setDelegate:self]; | 201 [window setDelegate:self]; |
| 202 [window setBackgroundColor:[NSColor clearColor]]; | 202 [window setBackgroundColor:[NSColor clearColor]]; |
| 203 [window setOpaque:NO]; | 203 [window setOpaque:NO]; |
| 204 [window setHasShadow:NO]; | 204 [window setHasShadow:NO]; |
| 205 | 205 |
| 206 // Create the content view. Take the frame from the existing content view. | 206 // Create the content view. Take the frame from the existing content view. |
| 207 NSRect frame = [[window contentView] frame]; | 207 NSRect frame = [[window contentView] frame]; |
| 208 scoped_nsobject<ConfirmQuitFrameView> frameView( | 208 base::scoped_nsobject<ConfirmQuitFrameView> frameView( |
| 209 [[ConfirmQuitFrameView alloc] initWithFrame:frame]); | 209 [[ConfirmQuitFrameView alloc] initWithFrame:frame]); |
| 210 contentView_ = frameView.get(); | 210 contentView_ = frameView.get(); |
| 211 [window setContentView:contentView_]; | 211 [window setContentView:contentView_]; |
| 212 | 212 |
| 213 // Set the proper string. | 213 // Set the proper string. |
| 214 NSString* message = l10n_util::GetNSStringF(IDS_CONFIRM_TO_QUIT_DESCRIPTION, | 214 NSString* message = l10n_util::GetNSStringF(IDS_CONFIRM_TO_QUIT_DESCRIPTION, |
| 215 base::SysNSStringToUTF16([[self class] keyCommandString])); | 215 base::SysNSStringToUTF16([[self class] keyCommandString])); |
| 216 [contentView_ setMessageText:message]; | 216 [contentView_ setMessageText:message]; |
| 217 } | 217 } |
| 218 return self; | 218 return self; |
| 219 } | 219 } |
| 220 | 220 |
| 221 + (BOOL)eventTriggersFeature:(NSEvent*)event { | 221 + (BOOL)eventTriggersFeature:(NSEvent*)event { |
| 222 if ([event type] != NSKeyDown) | 222 if ([event type] != NSKeyDown) |
| 223 return NO; | 223 return NO; |
| 224 ui::PlatformAcceleratorCocoa eventAccelerator( | 224 ui::PlatformAcceleratorCocoa eventAccelerator( |
| 225 [event charactersIgnoringModifiers], | 225 [event charactersIgnoringModifiers], |
| 226 [event modifierFlags] & NSDeviceIndependentModifierFlagsMask); | 226 [event modifierFlags] & NSDeviceIndependentModifierFlagsMask); |
| 227 scoped_ptr<ui::PlatformAcceleratorCocoa> quitAccelerator( | 227 scoped_ptr<ui::PlatformAcceleratorCocoa> quitAccelerator( |
| 228 [self quitAccelerator]); | 228 [self quitAccelerator]); |
| 229 return quitAccelerator->Equals(eventAccelerator); | 229 return quitAccelerator->Equals(eventAccelerator); |
| 230 } | 230 } |
| 231 | 231 |
| 232 - (NSApplicationTerminateReply)runModalLoopForApplication:(NSApplication*)app { | 232 - (NSApplicationTerminateReply)runModalLoopForApplication:(NSApplication*)app { |
| 233 scoped_nsobject<ConfirmQuitPanelController> keepAlive([self retain]); | 233 base::scoped_nsobject<ConfirmQuitPanelController> keepAlive([self retain]); |
| 234 | 234 |
| 235 // If this is the second of two such attempts to quit within a certain time | 235 // If this is the second of two such attempts to quit within a certain time |
| 236 // interval, then just quit. | 236 // interval, then just quit. |
| 237 // Time of last quit attempt, if any. | 237 // Time of last quit attempt, if any. |
| 238 static NSDate* lastQuitAttempt; // Initially nil, as it's static. | 238 static NSDate* lastQuitAttempt; // Initially nil, as it's static. |
| 239 NSDate* timeNow = [NSDate date]; | 239 NSDate* timeNow = [NSDate date]; |
| 240 if (lastQuitAttempt && | 240 if (lastQuitAttempt && |
| 241 [timeNow timeIntervalSinceDate:lastQuitAttempt] < kTimeDeltaFuzzFactor) { | 241 [timeNow timeIntervalSinceDate:lastQuitAttempt] < kTimeDeltaFuzzFactor) { |
| 242 // The panel tells users to Hold Cmd+Q. However, we also want to have a | 242 // The panel tells users to Hold Cmd+Q. However, we also want to have a |
| 243 // double-tap shortcut that allows for a quick quit path. For the users who | 243 // double-tap shortcut that allows for a quick quit path. For the users who |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 // Release all animations because CAAnimation retains its delegate (self), | 320 // Release all animations because CAAnimation retains its delegate (self), |
| 321 // which will cause a retain cycle. Break it! | 321 // which will cause a retain cycle. Break it! |
| 322 [[self window] setAnimations:[NSDictionary dictionary]]; | 322 [[self window] setAnimations:[NSDictionary dictionary]]; |
| 323 g_confirmQuitPanelController = nil; | 323 g_confirmQuitPanelController = nil; |
| 324 [self autorelease]; | 324 [self autorelease]; |
| 325 } | 325 } |
| 326 | 326 |
| 327 - (void)showWindow:(id)sender { | 327 - (void)showWindow:(id)sender { |
| 328 // If a panel that is fading out is going to be reused here, make sure it | 328 // If a panel that is fading out is going to be reused here, make sure it |
| 329 // does not get released when the animation finishes. | 329 // does not get released when the animation finishes. |
| 330 scoped_nsobject<ConfirmQuitPanelController> keepAlive([self retain]); | 330 base::scoped_nsobject<ConfirmQuitPanelController> keepAlive([self retain]); |
| 331 [[self window] setAnimations:[NSDictionary dictionary]]; | 331 [[self window] setAnimations:[NSDictionary dictionary]]; |
| 332 [[self window] center]; | 332 [[self window] center]; |
| 333 [[self window] setAlphaValue:1.0]; | 333 [[self window] setAlphaValue:1.0]; |
| 334 [super showWindow:sender]; | 334 [super showWindow:sender]; |
| 335 } | 335 } |
| 336 | 336 |
| 337 - (void)dismissPanel { | 337 - (void)dismissPanel { |
| 338 [self performSelector:@selector(animateFadeOut) | 338 [self performSelector:@selector(animateFadeOut) |
| 339 withObject:nil | 339 withObject:nil |
| 340 afterDelay:1.0]; | 340 afterDelay:1.0]; |
| 341 } | 341 } |
| 342 | 342 |
| 343 - (void)animateFadeOut { | 343 - (void)animateFadeOut { |
| 344 NSWindow* window = [self window]; | 344 NSWindow* window = [self window]; |
| 345 scoped_nsobject<CAAnimation> animation( | 345 base::scoped_nsobject<CAAnimation> animation( |
| 346 [[window animationForKey:@"alphaValue"] copy]); | 346 [[window animationForKey:@"alphaValue"] copy]); |
| 347 [animation setDelegate:self]; | 347 [animation setDelegate:self]; |
| 348 [animation setDuration:0.2]; | 348 [animation setDuration:0.2]; |
| 349 NSMutableDictionary* dictionary = | 349 NSMutableDictionary* dictionary = |
| 350 [NSMutableDictionary dictionaryWithDictionary:[window animations]]; | 350 [NSMutableDictionary dictionaryWithDictionary:[window animations]]; |
| 351 [dictionary setObject:animation forKey:@"alphaValue"]; | 351 [dictionary setObject:animation forKey:@"alphaValue"]; |
| 352 [window setAnimations:dictionary]; | 352 [window setAnimations:dictionary]; |
| 353 [[window animator] setAlphaValue:0.0]; | 353 [[window animator] setAlphaValue:0.0]; |
| 354 } | 354 } |
| 355 | 355 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 if (modifiers & NSAlternateKeyMask) | 415 if (modifiers & NSAlternateKeyMask) |
| 416 [string appendString:@"\u2325"]; | 416 [string appendString:@"\u2325"]; |
| 417 if (modifiers & NSShiftKeyMask) | 417 if (modifiers & NSShiftKeyMask) |
| 418 [string appendString:@"\u21E7"]; | 418 [string appendString:@"\u21E7"]; |
| 419 | 419 |
| 420 [string appendString:[item.characters() uppercaseString]]; | 420 [string appendString:[item.characters() uppercaseString]]; |
| 421 return string; | 421 return string; |
| 422 } | 422 } |
| 423 | 423 |
| 424 @end | 424 @end |
| OLD | NEW |