summaryrefslogtreecommitdiffstats
path: root/chrome
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
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')
-rw-r--r--chrome/browser/cocoa/tab_view.h9
-rw-r--r--chrome/browser/cocoa/tab_view.mm67
2 files changed, 76 insertions, 0 deletions
diff --git a/chrome/browser/cocoa/tab_view.h b/chrome/browser/cocoa/tab_view.h
index 0e1149f..6d4898e 100644
--- a/chrome/browser/cocoa/tab_view.h
+++ b/chrome/browser/cocoa/tab_view.h
@@ -6,6 +6,9 @@
#define CHROME_BROWSER_COCOA_TAB_VIEW_H_
#import <Cocoa/Cocoa.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+#include <map>
#include "base/scoped_nsobject.h"
#import "chrome/browser/cocoa/background_gradient_view.h"
@@ -81,6 +84,12 @@ enum AlertState {
TabWindowController* draggedController_; // weak. Controller being dragged.
NSWindow* dragWindow_; // weak. The window being dragged
NSWindow* dragOverlay_; // weak. The overlay being dragged
+ // Cache workspace IDs per-drag because computing them on 10.5 with
+ // CGWindowListCreateDescriptionFromArray is expensive.
+ // resetDragControllers clears this cache.
+ //
+ // TODO(davidben): When 10.5 becomes unsupported, remove this.
+ std::map<CGWindowID, int> workspaceIDCache_;
TabWindowController* targetController_; // weak. Controller being targeted
NSCellStateValue state_;
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)