Index: chrome/browser/cocoa/tab_view.mm |
=================================================================== |
--- chrome/browser/cocoa/tab_view.mm (revision 25857) |
+++ chrome/browser/cocoa/tab_view.mm (working copy) |
@@ -2,11 +2,12 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "chrome/browser/cocoa/tab_view.h" |
+#import "chrome/browser/cocoa/tab_view.h" |
+#include "base/logging.h" |
#include "chrome/browser/cocoa/nsimage_cache.h" |
-#include "chrome/browser/cocoa/tab_controller.h" |
-#include "chrome/browser/cocoa/tab_window_controller.h" |
+#import "chrome/browser/cocoa/tab_controller.h" |
+#import "chrome/browser/cocoa/tab_window_controller.h" |
// Constants for inset and control points for tab shape. |
static const CGFloat kInsetMultiplier = 2.0/3.0; |
@@ -142,6 +143,27 @@ |
return YES; |
} |
+// Find all the windows that could be a target. It has to be of the |
+// appropriate class, and visible (obviously). Note that the window cannot be |
+// a target for itself. |
+- (NSArray*)dropTargetsForController:(TabWindowController*)dragController { |
+ NSMutableArray* targets = [NSMutableArray array]; |
+ NSWindow* dragWindow = [dragController window]; |
+ for (NSWindow* window in [NSApp windows]) { |
+ if (window == dragWindow) continue; |
+ if (![window isVisible]) continue; |
+ NSWindowController *controller = [window windowController]; |
+ if ([controller isKindOfClass:[TabWindowController class]]) { |
+ TabWindowController* realController = |
+ static_cast<TabWindowController*>(controller); |
+ if ([realController canReceiveFrom:dragController]) { |
+ [targets addObject:controller]; |
+ } |
+ } |
+ } |
+ return targets; |
+} |
+ |
// Handle clicks and drags in this button. We get here because we have |
// overridden acceptsFirstMouse: and the click is within our bounds. |
// TODO(pinkerton/alcor): This routine needs *a lot* of work to marry Cole's |
@@ -193,13 +215,19 @@ |
tearTime_ = 0.0; |
draggingWithinTabStrip_ = YES; |
- // We don't want to "tear off" a tab if there's only one in the window. Treat |
- // it like we're dragging around a tab we've already detached. Note that |
- // unit tests might have |-numberOfTabs| reporting zero since the model |
- // won't be fully hooked up. We need to be prepared for that and not send |
- // them into the "magnetic" codepath. |
+ // If there's more than one potential window to be a drop target, we want to |
+ // treat a drag of a tab just like dragging around a tab that's already |
+ // detached. Note that unit tests might have |-numberOfTabs| reporting zero |
+ // since the model won't be fully hooked up. We need to be prepared for that |
+ // and not send them into the "magnetic" codepath. |
+ NSArray* targets = [self dropTargetsForController:sourceController_]; |
moveWindowOnDrag_ = |
- [sourceController_ numberOfTabs] <= 1 || ![self canBeDragged]; |
+ ([sourceController_ numberOfTabs] < 2 && ![targets count]) || |
+ ![self canBeDragged]; |
rohitrao (ping after 24h)
2009/09/10 19:03:56
Should this be in line with the "(" above?
pink (ping after 24hrs)
2009/09/10 19:05:55
No, the first two should bind together, or'd with
pink (ping after 24hrs)
2009/09/10 19:06:31
Oops, my bad, yes. Misunderstood.
|
+ // If we are dragging a tab, a window with a single tab should immediately |
+ // snap off and not drag within the tab strip. |
+ if (!moveWindowOnDrag_) |
+ draggingWithinTabStrip_ = [sourceController_ numberOfTabs] > 1; |
dragOrigin_ = [NSEvent mouseLocation]; |
@@ -286,30 +314,13 @@ |
// Do not start dragging until the user has "torn" the tab off by |
// moving more than 3 pixels. |
- NSDate* targetDwellDate = nil; // The date this target was first chosen |
- NSMutableArray* targets = [NSMutableArray array]; |
+ NSDate* targetDwellDate = nil; // The date this target was first chosen. |
NSPoint thisPoint = [NSEvent mouseLocation]; |
- // Find all the windows that could be a target. It has to be of the |
- // appropriate class, and visible (obviously). |
- if (![targets count]) { |
- for (NSWindow* window in [NSApp windows]) { |
- if (window == dragWindow_) continue; |
- if (![window isVisible]) continue; |
- NSWindowController *controller = [window windowController]; |
- if ([controller isKindOfClass:[TabWindowController class]]) { |
- TabWindowController* realController = |
- static_cast<TabWindowController*>(controller); |
- if ([realController canReceiveFrom:sourceController_]) { |
- [targets addObject:controller]; |
- } |
- } |
- } |
- } |
- |
// Iterate over possible targets checking for the one the mouse is in. |
// The mouse can be in either the tab or window frame. |
+ NSArray* targets = [self dropTargetsForController:draggedController_]; |
TabWindowController* newTarget = nil; |
for (TabWindowController* target in targets) { |
NSRect windowFrame = [[target window] frame]; |
@@ -338,10 +349,18 @@ |
// Create or identify the dragged controller. |
if (!draggedController_) { |
- // Detach from the current window and put it in a new window. |
+ // Detach from the current window and put it in a new window. If there are |
+ // no more tabs remaining after detaching, the source window is about to |
+ // go away (it's been autoreleased) so we need to ensure we don't reference |
+ // it any more. In that case the new controller becomes our source |
+ // controller. |
draggedController_ = [sourceController_ detachTabToNewWindow:self]; |
dragWindow_ = [draggedController_ window]; |
[dragWindow_ setAlphaValue:0.0]; |
+ if (![sourceController_ numberOfTabs]) { |
+ sourceController_ = draggedController_; |
+ sourceWindow_ = dragWindow_; |
+ } |
// If dragging the tab only moves the current window, do not show overlay |
// so that sheets stay on top of the window. |
@@ -398,7 +417,6 @@ |
if (![[targetController_ window] isKeyWindow]) { |
// && ([targetDwellDate timeIntervalSinceNow] < -REQUIRED_DWELL)) { |
[[targetController_ window] orderFront:nil]; |
- [targets removeAllObjects]; |
rohitrao (ping after 24h)
2009/09/10 19:03:56
This is ok to delete because targets is never refe
pink (ping after 24hrs)
2009/09/10 19:05:55
Correct. It must have been leftover from something
|
targetDwellDate = nil; |
} |
@@ -458,6 +476,7 @@ |
if (draggingWithinTabStrip_) { |
if (tabWasDragged_) { |
// Move tab to new location. |
+ DCHECK([sourceController_ numberOfTabs]); |
TabWindowController* dropController = sourceController_; |
[dropController moveTabView:[dropController selectedTabView] |
fromController:nil]; |