diff options
Diffstat (limited to 'chrome/browser/app_controller_mac.mm')
| -rw-r--r-- | chrome/browser/app_controller_mac.mm | 105 |
1 files changed, 104 insertions, 1 deletions
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 22de42f..6c8a9f1 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm @@ -13,7 +13,8 @@ #include "base/message_loop.h" #include "base/string_number_conversions.h" #include "base/sys_string_conversions.h" -#include "chrome/app/chrome_dll_resource.h" +#import "base/worker_pool_mac.h" +#include "chrome/app/chrome_command_ids.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_init.h" #include "chrome/browser/browser_list.h" @@ -27,6 +28,7 @@ #import "chrome/browser/cocoa/browser_window_controller.h" #import "chrome/browser/cocoa/bug_report_window_controller.h" #import "chrome/browser/cocoa/clear_browsing_data_controller.h" +#import "chrome/browser/cocoa/confirm_quit_panel_controller.h" #import "chrome/browser/cocoa/encoding_menu_controller_delegate_mac.h" #import "chrome/browser/cocoa/history_menu_bridge.h" #import "chrome/browser/cocoa/import_settings_dialog.h" @@ -221,6 +223,15 @@ void RecordLastRunAppBundlePath() { if (parsed_command_line.HasSwitch(switches::kActivateOnLaunch)) { [NSApp activateIgnoringOtherApps:YES]; } + + // Temporary flag to revert to the old WorkerPool implementation. + // This will be removed once we either fix the Mac WorkerPool + // implementation, or completely switch to the shared (with Linux) + // implementation. + // http://crbug.com/44392 + if (parsed_command_line.HasSwitch(switches::kDisableLinuxWorkerPool)) { + worker_pool_mac::SetUseLinuxWorkerPool(false); + } } // (NSApplicationDelegate protocol) This is the Apple-approved place to override @@ -242,6 +253,12 @@ void RecordLastRunAppBundlePath() { // them in, but I'm not sure about UX; we'd also want to disable other things // though.) http://crbug.com/40861 + // Check if the user really wants to quit by employing the confirm-to-quit + // mechanism. + if (!browser_shutdown::IsTryingToQuit() && + [self applicationShouldTerminate:app] != NSTerminateNow) + return NO; + size_t num_browsers = BrowserList::size(); // Give any print jobs in progress time to finish. @@ -267,6 +284,92 @@ void RecordLastRunAppBundlePath() { } } +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)app { + // Check if the experiment is enabled. + const CommandLine* commandLine(CommandLine::ForCurrentProcess()); + if (!commandLine->HasSwitch(switches::kEnableConfirmToQuit)) + return NSTerminateNow; + + // 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) { + ConfirmQuitPanelController* quitPanel = + [[ConfirmQuitPanelController alloc] init]; // Releases self. + // Show the info panel that explains what the user must to do confirm quit. + [quitPanel 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]; + } + } + [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. + [quitPanel dismissPanel]; + return NSTerminateCancel; + } + } // if event type is KeyDown + + // Default case: terminate. + return NSTerminateNow; +} + // Called when the app is shutting down. Clean-up as appropriate. - (void)applicationWillTerminate:(NSNotification*)aNotification { NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; |
