Commit 346fb30b authored by sail@chromium.org's avatar sail@chromium.org

Mac: Don't change active Space when entering or exiting full screen

There are two ways that entering full screen could cause the active Space to change:
  1: Assign a default Space to the application. Move the browser window to a different Space. Enter full screen. The new full screen window opens in the default Space instead of the active Space. crbug.com/69454
  2: Enter full screen. Press F8 to enter Spaces mode. Move the full screen window to a different Space. Exit Spaces. The Single Window window opens in its original Space instead of the active Space. crbug.com/41693

r60063 fixed the second issue but not the first and it also relied on using private APIs.

This change fixes both issues without using private APIs. Instead we now temporarily set the window's collection behavior to NSWindowCollectionBehaviorMoveToActiveSpace. This prevents the active space from changing.

Patch idea by Bjorn Winckler. See:
https://github.com/b4winckler/macvim/commit/6863b04a52fdb501c6df509635b9b3b3dd062e68

BUG=69454, 41693
TEST=Ran on 10.5 and 10.6. Verified that both bugs were fixed.


git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71276 0039d316-1c4b-4281-b951-d872f2087c98
parent 678da8d7
......@@ -44,7 +44,6 @@
#import "chrome/browser/ui/cocoa/infobar_container_controller.h"
#import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
#import "chrome/browser/ui/cocoa/previewable_contents_controller.h"
#import "chrome/browser/ui/cocoa/nswindow_additions.h"
#import "chrome/browser/ui/cocoa/sad_tab_controller.h"
#import "chrome/browser/ui/cocoa/sidebar_controller.h"
#import "chrome/browser/ui/cocoa/status_bubble_mac.h"
......@@ -1902,11 +1901,6 @@ willAnimateFromState:(bookmarks::VisualState)oldState
DCHECK(savedRegularWindow_);
destWindow = [savedRegularWindow_ autorelease];
savedRegularWindow_ = nil;
CGSWorkspaceID workspace;
if ([window cr_workspace:&workspace]) {
[destWindow cr_moveToWorkspace:workspace];
}
}
DCHECK(destWindow);
......@@ -1957,7 +1951,15 @@ willAnimateFromState:(bookmarks::VisualState)oldState
[destWindow setTitle:[window title]];
// The window needs to be onscreen before we can set its first responder.
// Ordering the window to the front can change the active Space (either to
// the window's old Space or to the application's assigned Space). To prevent
// this by temporarily change the collectionBehavior.
NSWindowCollectionBehavior behavior = [window collectionBehavior];
[destWindow setCollectionBehavior:
NSWindowCollectionBehaviorMoveToActiveSpace];
[destWindow makeKeyAndOrderFront:self];
[destWindow setCollectionBehavior:behavior];
[focusTracker restoreFocusInWindow:destWindow];
[window orderOut:self];
......
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_COCOA_NSWINDOW_ADDITIONS_H_
#define CHROME_BROWSER_UI_COCOA_NSWINDOW_ADDITIONS_H_
#pragma once
#import <Cocoa/Cocoa.h>
// ID of a Space. Starts at 1.
typedef int CGSWorkspaceID;
@interface NSWindow(ChromeAdditions)
// Gets the Space that the window is currently on. YES on success, NO on
// failure.
- (BOOL)cr_workspace:(CGSWorkspaceID*)outWorkspace;
// Moves the window to the given Space. YES on success, NO on failure.
- (BOOL)cr_moveToWorkspace:(CGSWorkspaceID)workspace;
@end
#endif // CHROME_BROWSER_UI_COCOA_NSWINDOW_ADDITIONS_H_
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "chrome/browser/ui/cocoa/nswindow_additions.h"
#include <dlfcn.h>
#include "base/logging.h"
typedef void* CGSConnectionID;
typedef int CGSWindowID;
typedef int CGSError;
typedef int CGSWorkspaceID;
// These are private APIs we look up at run time.
typedef CGSConnectionID (*CGSDefaultConnectionFunc)(void);
typedef CGSError (*CGSGetWindowWorkspaceFunc)(const CGSConnectionID cid,
CGSWindowID wid,
CGSWorkspaceID* workspace);
typedef CGSError (*CGSMoveWorkspaceWindowListFunc)(const CGSConnectionID cid,
CGSWindowID* wids,
int count,
CGSWorkspaceID workspace);
static CGSDefaultConnectionFunc sCGSDefaultConnection;
static CGSGetWindowWorkspaceFunc sCGSGetWindowWorkspace;
static CGSMoveWorkspaceWindowListFunc sCGSMoveWorkspaceWindowList;
@implementation NSWindow(ChromeAdditions)
// Looks up private Spaces APIs using dlsym.
- (BOOL)cr_initializeWorkspaceAPIs {
static BOOL shouldInitialize = YES;
if (shouldInitialize) {
shouldInitialize = NO;
NSBundle* coreGraphicsBundle =
[NSBundle bundleWithIdentifier:@"com.apple.CoreGraphics"];
NSString* coreGraphicsPath = [[coreGraphicsBundle bundlePath]
stringByAppendingPathComponent:@"CoreGraphics"];
void* coreGraphicsLibrary = dlopen([coreGraphicsPath UTF8String],
RTLD_GLOBAL | RTLD_LAZY);
if (coreGraphicsLibrary) {
sCGSDefaultConnection =
(CGSDefaultConnectionFunc)dlsym(coreGraphicsLibrary,
"_CGSDefaultConnection");
if (!sCGSDefaultConnection) {
LOG(ERROR) << "Failed to lookup _CGSDefaultConnection API" << dlerror();
}
sCGSGetWindowWorkspace =
(CGSGetWindowWorkspaceFunc)dlsym(coreGraphicsLibrary,
"CGSGetWindowWorkspace");
if (!sCGSGetWindowWorkspace) {
LOG(ERROR) << "Failed to lookup CGSGetWindowWorkspace API" << dlerror();
}
sCGSMoveWorkspaceWindowList =
(CGSMoveWorkspaceWindowListFunc)dlsym(coreGraphicsLibrary,
"CGSMoveWorkspaceWindowList");
if (!sCGSMoveWorkspaceWindowList) {
LOG(ERROR) << "Failed to lookup CGSMoveWorkspaceWindowList API"
<< dlerror();
}
} else {
LOG(ERROR) << "Failed to load CoreGraphics lib" << dlerror();
}
}
return sCGSDefaultConnection != NULL &&
sCGSGetWindowWorkspace != NULL &&
sCGSMoveWorkspaceWindowList != NULL;
}
- (BOOL)cr_workspace:(CGSWorkspaceID*)outWorkspace {
if (![self cr_initializeWorkspaceAPIs]) {
return NO;
}
// If this ASSERT fails then consider using CGSDefaultConnectionForThread()
// instead of CGSDefaultConnection().
DCHECK([NSThread isMainThread]);
CGSConnectionID cid = sCGSDefaultConnection();
CGSWindowID wid = [self windowNumber];
CGSError err = sCGSGetWindowWorkspace(cid, wid, outWorkspace);
return err == 0;
}
- (BOOL)cr_moveToWorkspace:(CGSWorkspaceID)workspace {
if (![self cr_initializeWorkspaceAPIs]) {
return NO;
}
// If this ASSERT fails then consider using CGSDefaultConnectionForThread()
// instead of CGSDefaultConnection().
DCHECK([NSThread isMainThread]);
CGSConnectionID cid = sCGSDefaultConnection();
CGSWindowID wid = [self windowNumber];
// CGSSetWorkspaceForWindow doesn't seem to work for some reason.
CGSError err = sCGSMoveWorkspaceWindowList(cid, &wid, 1, workspace);
return err == 0;
}
@end
......@@ -2955,8 +2955,6 @@
'browser/ui/cocoa/notifications/balloon_view.mm',
'browser/ui/cocoa/nsmenuitem_additions.h',
'browser/ui/cocoa/nsmenuitem_additions.mm',
'browser/ui/cocoa/nswindow_additions.h',
'browser/ui/cocoa/nswindow_additions.mm',
'browser/ui/cocoa/objc_method_swizzle.h',
'browser/ui/cocoa/objc_method_swizzle.mm',
'browser/ui/cocoa/objc_zombie.h',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment