| 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..10190585c2448d0443b078567865fc517dc733c6 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];
|
|
|
| @@ -330,6 +343,7 @@ class AppControllerProfileObserver : public ProfileInfoCacheObserver {
|
| [em removeEventHandlerForEventClass:'WWW!'
|
| andEventID:'OURL'];
|
| [[NSNotificationCenter defaultCenter] removeObserver:self];
|
| + [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
|
| }
|
|
|
| // (NSApplicationDelegate protocol) This is the Apple-approved place to override
|
| @@ -556,6 +570,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 +1118,26 @@ 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 transition triggered by the dock. Delay the call to
|
| + // |ui::FocusWindowSet| until the transition completes. Otherwise, the
|
| + // wrong space's windows get raised, resulting in an off-screen key
|
| + // window. It does not work to |ui::FocusWindowSet| twice, once here
|
| + // and once in |activeSpaceDidChange:|, as that appears to break when
|
| + // the omnibox is focused.
|
| + //
|
| + // This check relies on OS X setting the key window to a window on the
|
| + // target space before calling this method.
|
| + //
|
| + // See http://crbug.com/309656.
|
| + reopenTime_ = base::TimeTicks::Now();
|
| + } else {
|
| + ui::FocusWindowSet(browserWindows, false);
|
| + }
|
| + // Return NO; we've done (or soon will do) the deminiaturize, so
|
| + // AppKit shouldn't do anything.
|
| return NO;
|
| }
|
| }
|
|
|