Chromium Code Reviews| Index: chrome/browser/app_controller_mac.mm |
| diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm |
| index 34736e6251be73809fade4cc03caf67b8cdb177b..f1e93828cd8bbd23164ed0dbe09139e54ae19070 100644 |
| --- a/chrome/browser/app_controller_mac.mm |
| +++ b/chrome/browser/app_controller_mac.mm |
| @@ -106,6 +106,11 @@ NSString* NSPopoverDidShowNotification = @"NSPopoverDidShowNotification"; |
| NSString* NSPopoverDidCloseNotification = @"NSPopoverDidCloseNotification"; |
| #endif |
| +// How long we allow a workspace change notification to wait to be |
| +// associated with a dock activation. The animation lasts 250ms. See |
| +// applicationShouldHandleReopen:hasVisibleWindows:. |
| +static const int kWorkspaceChangeTimeoutMs = 500; |
| + |
| // True while AppController is calling chrome::NewEmptyWindow(). We need a |
| // global flag here, analogue to StartupBrowserCreator::InProcessStartup() |
| // because otherwise the SessionService will try to restore sessions when we |
| @@ -196,6 +201,7 @@ void RecordLastRunAppBundlePath() { |
| withReply:(NSAppleEventDescriptor*)reply; |
| - (void)submitCloudPrintJob:(NSAppleEventDescriptor*)event; |
| - (void)windowLayeringDidChange:(NSNotification*)inNotification; |
| +- (void)activeSpaceDidChange:(NSNotification*)inNotification; |
| - (void)windowChangedToProfile:(Profile*)profile; |
| - (void)checkForAnyKeyWindows; |
| - (BOOL)userWillWaitForInProgressDownloads:(int)downloadCount; |
| @@ -314,6 +320,13 @@ class AppControllerProfileObserver : public ProfileInfoCacheObserver { |
| object:nil]; |
| } |
| + // Register for space change notifications. |
| + [[[NSWorkspace sharedWorkspace] notificationCenter] |
| + addObserver:self |
| + selector:@selector(activeSpaceDidChange:) |
| + name:NSWorkspaceActiveSpaceDidChangeNotification |
| + object:nil]; |
| + |
| // Set up the command updater for when there are no windows open |
| [self initMenuState]; |
| @@ -556,6 +569,28 @@ class AppControllerProfileObserver : public ProfileInfoCacheObserver { |
| } |
| } |
| +- (void)activeSpaceDidChange:(NSNotification*)notify { |
| + if (reopenTime_.is_null() || |
| + ![NSApp isActive] || |
| + (base::TimeTicks::Now() - reopenTime_).InMilliseconds() > |
| + kWorkspaceChangeTimeoutMs) { |
| + return; |
| + } |
| + |
| + // The last applicationShouldHandleReopen:hasVisibleWindows: call |
| + // happened during a space change. Now that the change has |
| + // completed, raise browser windows. |
| + reopenTime_ = base::TimeTicks(); |
| + std::set<NSWindow*> browserWindows; |
| + for (chrome::BrowserIterator iter; !iter.done(); iter.Next()) { |
| + Browser* browser = *iter; |
| + browserWindows.insert(browser->window()->GetNativeWindow()); |
| + } |
| + if (!browserWindows.empty()) { |
| + ui::FocusWindowSet(browserWindows, false); |
| + } |
| +} |
| + |
| // Called on Lion and later when a popover (e.g. dictionary) is shown. |
| - (void)popoverDidShow:(NSNotification*)notify { |
| hasPopover_ = YES; |
| @@ -1082,9 +1117,18 @@ class AppControllerProfileObserver : public ProfileInfoCacheObserver { |
| browserWindows.insert(browser->window()->GetNativeWindow()); |
| } |
| if (!browserWindows.empty()) { |
| - ui::FocusWindowSet(browserWindows, false); |
| - // Return NO; we've done the unminimize, so AppKit shouldn't do |
| - // anything. |
| + NSWindow* keyWindow = [NSApp keyWindow]; |
| + if (keyWindow && ![keyWindow isOnActiveSpace]) { |
| + // The key window is not on the active space. We must be |
| + // mid-animation for a space change triggered by the |
| + // dock. Delay the call to ui::FocusWindowSet until the change |
| + // completes. |
| + reopenTime_ = base::TimeTicks::Now(); |
|
davidben
2013/10/23 16:04:45
Not calling FocusWindowSet here is apparently nece
|
| + } else { |
| + ui::FocusWindowSet(browserWindows, false); |
| + } |
| + // Return NO; we've done (or soon will do) the deminiaturize, so |
| + // AppKit shouldn't do anything. |
| return NO; |
| } |
| } |