summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa/tab_view.mm
diff options
context:
space:
mode:
authordavidben@chromium.org <davidben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-19 23:05:37 +0000
committerdavidben@chromium.org <davidben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-19 23:05:37 +0000
commite5f5d63c986365509b388146d6985cd968cb46d9 (patch)
tree7ca863b2fd41ee36de05f9291d03dcff4789ec77 /chrome/browser/cocoa/tab_view.mm
parentef044ebebc47d4ee9636f25c61ab079411630126 (diff)
downloadchromium_src-e5f5d63c986365509b388146d6985cd968cb46d9.zip
chromium_src-e5f5d63c986365509b388146d6985cd968cb46d9.tar.gz
chromium_src-e5f5d63c986365509b388146d6985cd968cb46d9.tar.bz2
Respect Spaces when dragging tabs on OS X
For 10.6 and above, we can simply filter windows out with isOnActiveSpace. For 10.5, there is another API in CoreGraphics that gives us the same information. It is slow and causes noticeable CPU usage during a drag, so cache it per-drag. R=pinkerton BUG=32796 TEST=open windows on separate spaces, drag a tab over where a window is on the other space Review URL: http://codereview.chromium.org/2962018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52960 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/cocoa/tab_view.mm')
-rw-r--r--chrome/browser/cocoa/tab_view.mm67
1 files changed, 67 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/tab_view.mm b/chrome/browser/cocoa/tab_view.mm
index 7f34aa5..82217de 100644
--- a/chrome/browser/cocoa/tab_view.mm
+++ b/chrome/browser/cocoa/tab_view.mm
@@ -5,7 +5,9 @@
#import "chrome/browser/cocoa/tab_view.h"
#include "base/logging.h"
+#import "base/mac_util.h"
#include "base/nsimage_cache_mac.h"
+#include "base/scoped_cftyperef.h"
#include "chrome/browser/browser_theme_provider.h"
#import "chrome/browser/cocoa/tab_controller.h"
#import "chrome/browser/cocoa/tab_window_controller.h"
@@ -46,6 +48,8 @@ const CGFloat kRapidCloseDist = 2.5;
- (void)resetLastGlowUpdateTime;
- (NSTimeInterval)timeElapsedSinceLastGlowUpdate;
- (void)adjustGlowValue;
+// TODO(davidben): When we stop supporting 10.5, this can be removed.
+- (int)getWorkspaceID:(NSWindow*)window useCache:(BOOL)useCache;
@end // TabView(Private)
@@ -161,6 +165,20 @@ const CGFloat kRapidCloseDist = 2.5;
for (NSWindow* window in [NSApp orderedWindows]) {
if (window == dragWindow) continue;
if (![window isVisible]) continue;
+ // Skip windows on the wrong space.
+ if ([window respondsToSelector:@selector(isOnActiveSpace)]) {
+ if (![window performSelector:@selector(isOnActiveSpace)])
+ continue;
+ } else {
+ // TODO(davidben): When we stop supporting 10.5, this can be
+ // removed.
+ //
+ // We don't cache the workspace of |dragWindow| because it may
+ // move around spaces.
+ if ([self getWorkspaceID:dragWindow useCache:NO] !=
+ [self getWorkspaceID:window useCache:YES])
+ continue;
+ }
NSWindowController* controller = [window windowController];
if ([controller isKindOfClass:[TabWindowController class]]) {
TabWindowController* realController =
@@ -180,6 +198,7 @@ const CGFloat kRapidCloseDist = 2.5;
sourceController_ = nil;
sourceWindow_ = nil;
targetController_ = nil;
+ workspaceIDCache_.clear();
}
// Sets whether the window background should be visible or invisible when
@@ -963,4 +982,52 @@ const CGFloat kRapidCloseDist = 2.5;
[self setNeedsDisplay:YES];
}
+// Returns the workspace id of |window|. If |useCache|, then lookup
+// and remember the value in |workspaceIDCache_| until the end of the
+// current drag.
+- (int)getWorkspaceID:(NSWindow*)window useCache:(BOOL)useCache {
+ CGWindowID windowID = [window windowNumber];
+ if (useCache) {
+ std::map<CGWindowID, int>::iterator iter =
+ workspaceIDCache_.find(windowID);
+ if (iter != workspaceIDCache_.end())
+ return iter->second;
+ }
+
+ int workspace = -1;
+ // It's possible to query in bulk, but probably not necessary.
+ scoped_cftyperef<CFArrayRef> windowIDs(CFArrayCreate(
+ NULL, reinterpret_cast<const void **>(&windowID), 1, NULL));
+ scoped_cftyperef<CFArrayRef> descriptions(
+ CGWindowListCreateDescriptionFromArray(windowIDs));
+ DCHECK(CFArrayGetCount(descriptions.get()) <= 1);
+ if (CFArrayGetCount(descriptions.get()) > 0) {
+ CFDictionaryRef dict = static_cast<CFDictionaryRef>(
+ CFArrayGetValueAtIndex(descriptions.get(), 0));
+ DCHECK(CFGetTypeID(dict) == CFDictionaryGetTypeID());
+
+ // Sanity check the ID.
+ CFNumberRef otherIDRef = (CFNumberRef)mac_util::GetValueFromDictionary(
+ dict, kCGWindowNumber, CFNumberGetTypeID());
+ CGWindowID otherID;
+ if (otherIDRef &&
+ CFNumberGetValue(otherIDRef, kCGWindowIDCFNumberType, &otherID) &&
+ otherID == windowID) {
+ // And then get the workspace.
+ CFNumberRef workspaceRef = (CFNumberRef)mac_util::GetValueFromDictionary(
+ dict, kCGWindowWorkspace, CFNumberGetTypeID());
+ if (!workspaceRef ||
+ !CFNumberGetValue(workspaceRef, kCFNumberIntType, &workspace)) {
+ workspace = -1;
+ }
+ } else {
+ NOTREACHED();
+ }
+ }
+ if (useCache) {
+ workspaceIDCache_[windowID] = workspace;
+ }
+ return workspace;
+}
+
@end // @implementation TabView(Private)