diff --git a/AppKit/CPDragServer.j b/AppKit/CPDragServer.j index a26189618..bd2b09a74 100644 --- a/AppKit/CPDragServer.j +++ b/AppKit/CPDragServer.j @@ -26,6 +26,7 @@ @import "CPPasteboard.j" @import "CPView.j" @import "CPWindow_Constants.j" +@import "CPViewAnimation.j" @class CPWindow // This file is imported by CPWindow.j @class _CPDOMDataTransferPasteboard @@ -132,6 +133,10 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, unsigned _dragOperation; CPTimer _draggingUpdateTimer; + + // Animation State + CGPoint _pendingEndLocation; + CPDragOperation _pendingEndOperation; } /* @@ -325,6 +330,46 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, [_draggingUpdateTimer invalidate]; _draggingUpdateTimer = nil; + // Check if we should slide back (drag failed + slideBack requested) + if (![CPPlatform supportsDragAndDrop] && _shouldSlideBack && anOperation === CPDragOperationNone) + { + // Store state to finalize drag after animation completes + _pendingEndLocation = aLocation; + _pendingEndOperation = anOperation; + + var currentFrame = [_draggedWindow frame], + targetFrame = CGRectMake(_startDragLocation.x, _startDragLocation.y, currentFrame.size.width, currentFrame.size.height); + + // We use CPViewAnimation. Even though _draggedWindow is a CPWindow, + // CPViewAnimation supports targets that respond to setFrame: (like NSViewAnimation does for NSWindow). + var animation = [[CPViewAnimation alloc] initWithViewAnimations:[ + [CPDictionary dictionaryWithObjects:[_draggedWindow, currentFrame, targetFrame] + forKeys:[CPViewAnimationTargetKey, CPViewAnimationStartFrameKey, CPViewAnimationEndFrameKey]] + ]]; + + [animation setAnimationCurve:CPAnimationEaseOut]; + [animation setDuration:0.25]; + [animation setDelegate:self]; + [animation startAnimation]; + + return; + } + + [self _performFinalCleanupWithLocation:aLocation operation:anOperation]; +} + +- (void)animationDidEnd:(CPAnimation)anAnimation +{ + [self _performFinalCleanupWithLocation:_pendingEndLocation operation:_pendingEndOperation]; +} + +- (void)animationDidStop:(CPAnimation)anAnimation +{ + [self _performFinalCleanupWithLocation:_pendingEndLocation operation:_pendingEndOperation]; +} + +- (void)_performFinalCleanupWithLocation:(CGPoint)aLocation operation:(CPDragOperation)anOperation +{ [_draggedView removeFromSuperview]; if (![CPPlatform supportsDragAndDrop])