Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(883)

Unified Diff: chrome/browser/cocoa/tab_view.mm

Issue 243080: Fix several issues with dragging tabs and quickly letting go, including crash... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/cocoa/tab_view.mm
===================================================================
--- chrome/browser/cocoa/tab_view.mm (revision 27606)
+++ chrome/browser/cocoa/tab_view.mm (working copy)
@@ -49,6 +49,8 @@
}
- (void)dealloc {
+ // Cancel any delayed requests that may still be pending (drags or hover).
+ [NSObject cancelPreviousPerformRequestsWithTarget:self];
// [self gtm_unregisterForThemeNotifications];
[closeButton_ removeTrackingArea:closeTrackingArea_.get()];
[super dealloc];
@@ -164,6 +166,16 @@
return targets;
}
+// Call to clear out transient weak references we hold during drags.
+- (void)resetDragControllers {
+ draggedController_ = nil;
+ dragWindow_ = nil;
+ dragOverlay_ = nil;
+ sourceController_ = nil;
+ sourceWindow_ = nil;
+ targetController_ = nil;
+}
+
// 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
@@ -198,6 +210,8 @@
[[controller_ target] performSelector:[controller_ action]
withObject:self];
+ [self resetDragControllers];
+
// Resolve overlay back to original window.
sourceWindow_ = [self window];
if ([sourceWindow_ isKindOfClass:[NSPanel class]]) {
@@ -207,10 +221,6 @@
sourceWindowFrame_ = [sourceWindow_ frame];
sourceTabFrame_ = [self frame];
sourceController_ = [sourceWindow_ windowController];
- draggedController_ = nil;
- dragWindow_ = nil;
- dragOverlay_ = nil;
- targetController_ = nil;
tabWasDragged_ = NO;
tearTime_ = 0.0;
draggingWithinTabStrip_ = YES;
@@ -378,8 +388,18 @@
tearOrigin_ = sourceWindowFrame_.origin;
}
+ DCHECK(draggedController_);
+ DCHECK(sourceController_);
+
+ // When the user first tears off the window, we want slide the window to
+ // the current mouse location (to reduce the jarring appearance). We do this
+ // by calling ourselves back with additional mouseDragged calls (not actual
+ // events). |tearProgress| is a normalized measure of how far through this
+ // tear "animation" (of length kTearDuration) we are and has values [0..1].
+ // We use sqrt() so the animation is non-linear (slow down near the end
+ // point).
float tearProgress = [NSDate timeIntervalSinceReferenceDate] - tearTime_;
- tearProgress /= kTearDuration;
+ tearProgress /= kTearDuration; // Normalize.
tearProgress = sqrtf(MAX(MIN(tearProgress, 1.0), 0.0));
// Move the dragged window to the right place on the screen.
@@ -389,13 +409,16 @@
if (tearProgress < 1) {
// If the tear animation is not complete, call back to ourself with the
- // same event to animate even if the mouse isn't moving.
+ // same event to animate even if the mouse isn't moving. We need to make
+ // sure these get cancelled in mouseUp:.
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self performSelector:@selector(mouseDragged:)
withObject:theEvent
afterDelay:1.0f/30.0f];
- origin.x = (1 - tearProgress) * tearOrigin_.x + tearProgress * origin.x;
+ // Set the current window origin based on how far we've progressed through
+ // the tear animation.
+ origin.x = (1 - tearProgress) * tearOrigin_.x + tearProgress * origin.x;
origin.y = (1 - tearProgress) * tearOrigin_.y + tearProgress * origin.y;
}
@@ -443,18 +466,19 @@
BOOL chromeShouldBeVisible = targetController_ == nil;
if (chromeIsVisible_ != chromeShouldBeVisible) {
+ // TODO(pinkerton): There appears to be a race-condition in CoreAnimation
+ // where if we use animators to set the alpha values, we can't guarantee
+ // that we cancel them. This has the side effect of sometimes leaving
+ // the dragged window translucent or invisible. We should re-visit this,
+ // but for now, don't animate the alpha change.
[dragWindow_ setHasShadow:YES];
+ [[draggedController_ overlayWindow] setAlphaValue:1.0];
if (targetController_) {
- [NSAnimationContext beginGrouping];
- [[NSAnimationContext currentContext] setDuration:0.00001];
- [[dragWindow_ animator] setAlphaValue:0.0];
- [NSAnimationContext endGrouping];
+ [dragWindow_ setAlphaValue:0.0];
[[draggedController_ overlayWindow] setHasShadow:YES];
- [[[draggedController_ overlayWindow] animator] setAlphaValue:1.0];
} else {
- [[draggedController_ overlayWindow] setAlphaValue:1.0];
+ [dragWindow_ setAlphaValue:0.5];
[[draggedController_ overlayWindow] setHasShadow:NO];
- [[dragWindow_ animator] setAlphaValue:0.5];
}
chromeIsVisible_ = chromeShouldBeVisible;
}
@@ -468,6 +492,9 @@
if (moveWindowOnDrag_)
return;
+ // Cancel any delayed -mouseDragged: requests that may still be pending.
+ [NSObject cancelPreviousPerformRequestsWithTarget:self];
+
// We are now free to re-display the new tab button in the window we're
// dragging. It will show when the next call to -layoutTabs (which happens
// indrectly by several of the calls below, such as removing the placeholder).
@@ -490,7 +517,8 @@
fromController:draggedController_];
[targetController_ showWindow:nil];
} else {
- // Tab dragging did move window only.
+ // Only move the window around on screen. Make sure it's set back to
+ // normal state (fully opaque, has shadow, has key, etc).
[draggedController_ removeOverlay];
// Don't want to re-show the window if it was closed during the drag.
if ([dragWindow_ isVisible]) {
@@ -504,6 +532,8 @@
}
[sourceController_ removePlaceholder];
chromeIsVisible_ = YES;
+
+ [self resetDragControllers];
}
- (void)otherMouseUp:(NSEvent*)theEvent {
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698