summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/app_controller_mac.mm148
1 files changed, 82 insertions, 66 deletions
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 3b43753..184b196 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -293,76 +293,92 @@ void RecordLastRunAppBundlePath() {
// If the application is going to terminate as the result of a Cmd+Q
// invocation, use the special sauce to prevent accidental quitting.
// http://dev.chromium.org/developers/design-documents/confirm-to-quit-experiment
- NSEvent* currentEvent = [app currentEvent];
- if ([currentEvent type] == NSKeyDown) {
- // Show the info panel that explains what the user must to do confirm quit.
- [[ConfirmQuitPanelController sharedController] showWindow:self];
-
- // How long the user must hold down Cmd+Q to confirm the quit.
- const NSTimeInterval kTimeToConfirmQuit = 1.5;
- // Leeway between the |targetDate| and the current time that will confirm a
- // quit.
- const NSTimeInterval kTimeDeltaFuzzFactor = 1.0;
- // Duration of the window fade out animation.
- const NSTimeInterval kWindowFadeAnimationDuration = 0.2;
-
- // Spin a nested run loop until the |targetDate| is reached or a KeyUp event
- // is sent.
- NSDate* targetDate =
- [NSDate dateWithTimeIntervalSinceNow:kTimeToConfirmQuit];
- BOOL willQuit = NO;
- NSEvent* nextEvent = nil;
- do {
- // Dequeue events until a key up is received.
- nextEvent = [app nextEventMatchingMask:NSKeyUpMask
- untilDate:nil
- inMode:NSEventTrackingRunLoopMode
- dequeue:YES];
-
- // Wait for the time expiry to happen. Once past the hold threshold,
- // commit to quitting and hide all the open windows.
- if (!willQuit) {
- NSDate* now = [NSDate date];
- NSTimeInterval difference = [targetDate timeIntervalSinceDate:now];
- if (difference < kTimeDeltaFuzzFactor) {
- willQuit = YES;
-
- // At this point, the quit has been confirmed and windows should all
- // fade out to convince the user to release the key combo to finalize
- // the quit.
- [NSAnimationContext beginGrouping];
- [[NSAnimationContext currentContext] setDuration:
- kWindowFadeAnimationDuration];
- for (NSWindow* aWindow in [app windows]) {
- // Windows that are set to animate and have a delegate do not
- // expect to be animated by other things and could result in an
- // invalid state. If a window is set up like so, just force the
- // alpha value to 0. Otherwise, animate all pretty and stuff.
- if (![[aWindow animationForKey:@"alphaValue"] delegate]) {
- [[aWindow animator] setAlphaValue:0.0];
- } else {
- [aWindow setAlphaValue:0.0];
- }
+
+ // How long the user must hold down Cmd+Q to confirm the quit.
+ const NSTimeInterval kTimeToConfirmQuit = 1.5;
+ // Leeway between the |targetDate| and the current time that will confirm a
+ // quit.
+ const NSTimeInterval kTimeDeltaFuzzFactor = 1.0;
+ // Duration of the window fade out animation.
+ const NSTimeInterval kWindowFadeAnimationDuration = 0.2;
+
+ // This logic is only for keyboard-initiated quits.
+ if ([[app currentEvent] type] != NSKeyDown)
+ return NSTerminateNow;
+
+ // If this is the second of two such attempts to quit within a certain time
+ // interval, then just quit.
+ // Time of last quit attempt, if any.
+ static NSDate* lastQuitAttempt; // Initially nil, as it's static.
+ NSDate* timeNow = [NSDate date];
+ if (lastQuitAttempt &&
+ [timeNow timeIntervalSinceDate:lastQuitAttempt] < kTimeDeltaFuzzFactor) {
+ return NSTerminateNow;
+ } else {
+ [lastQuitAttempt release]; // Harmless if already nil.
+ lastQuitAttempt = [timeNow retain]; // Record this attempt for next time.
+ }
+
+ // Show the info panel that explains what the user must to do confirm quit.
+ [[ConfirmQuitPanelController sharedController] showWindow:self];
+
+ // Spin a nested run loop until the |targetDate| is reached or a KeyUp event
+ // is sent.
+ NSDate* targetDate =
+ [NSDate dateWithTimeIntervalSinceNow:kTimeToConfirmQuit];
+ BOOL willQuit = NO;
+ NSEvent* nextEvent = nil;
+ do {
+ // Dequeue events until a key up is received.
+ nextEvent = [app nextEventMatchingMask:NSKeyUpMask
+ untilDate:nil
+ inMode:NSEventTrackingRunLoopMode
+ dequeue:YES];
+
+ // Wait for the time expiry to happen. Once past the hold threshold,
+ // commit to quitting and hide all the open windows.
+ if (!willQuit) {
+ NSDate* now = [NSDate date];
+ NSTimeInterval difference = [targetDate timeIntervalSinceDate:now];
+ if (difference < kTimeDeltaFuzzFactor) {
+ willQuit = YES;
+
+ // At this point, the quit has been confirmed and windows should all
+ // fade out to convince the user to release the key combo to finalize
+ // the quit.
+ [NSAnimationContext beginGrouping];
+ [[NSAnimationContext currentContext] setDuration:
+ kWindowFadeAnimationDuration];
+ for (NSWindow* aWindow in [app windows]) {
+ // Windows that are set to animate and have a delegate do not
+ // expect to be animated by other things and could result in an
+ // invalid state. If a window is set up like so, just force the
+ // alpha value to 0. Otherwise, animate all pretty and stuff.
+ if (![[aWindow animationForKey:@"alphaValue"] delegate]) {
+ [[aWindow animator] setAlphaValue:0.0];
+ } else {
+ [aWindow setAlphaValue:0.0];
}
- [NSAnimationContext endGrouping];
}
+ [NSAnimationContext endGrouping];
}
- } while (!nextEvent);
-
- // The user has released the key combo. Discard any events (i.e. the
- // repeated KeyDown Cmd+Q).
- [app discardEventsMatchingMask:NSAnyEventMask beforeEvent:nextEvent];
- if (willQuit) {
- // The user held down the combination long enough that quitting should
- // happen.
- return NSTerminateNow;
- } else {
- // Slowly fade the confirm window out in case the user doesn't
- // understand what they have to do to quit.
- [[ConfirmQuitPanelController sharedController] dismissPanel];
- return NSTerminateCancel;
}
- } // if event type is KeyDown
+ } while (!nextEvent);
+
+ // The user has released the key combo. Discard any events (i.e. the
+ // repeated KeyDown Cmd+Q).
+ [app discardEventsMatchingMask:NSAnyEventMask beforeEvent:nextEvent];
+
+ if (willQuit) {
+ // The user held down the combination long enough that quitting should
+ // happen.
+ return NSTerminateNow;
+ } else {
+ // Slowly fade the confirm window out in case the user doesn't
+ // understand what they have to do to quit.
+ [[ConfirmQuitPanelController sharedController] dismissPanel];
+ return NSTerminateCancel;
+ }
// Default case: terminate.
return NSTerminateNow;