diff -r 000000000000 -r 4f2f89ce4247 WebKit/mac/WebView/WebWindowAnimation.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebKit/mac/WebView/WebWindowAnimation.m Fri Sep 17 09:02:29 2010 +0300 @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebWindowAnimation.h" +#import "WebKitSystemInterface.h" +#import + +static const CGFloat slowMotionFactor = 10.; + +static NSTimeInterval WebWindowAnimationDurationFromDuration(NSTimeInterval duration) +{ + return ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) ? duration * slowMotionFactor : duration; +} + +static NSRect scaledRect(NSRect _initialFrame, NSRect _finalFrame, double factor) +{ + NSRect currentRect = _initialFrame; + currentRect.origin.x += (NSMinX(_finalFrame) - NSMinX(_initialFrame)) * factor; + currentRect.origin.y += (NSMinY(_finalFrame) - NSMinY(_initialFrame)) * factor; + currentRect.size.width += (NSWidth(_finalFrame) - NSWidth(_initialFrame)) * factor; + currentRect.size.height += (NSHeight(_finalFrame) - NSHeight(_initialFrame)) * factor; + return currentRect; +} + +static CGFloat squaredDistance(NSPoint point1, NSPoint point2) +{ + CGFloat deltaX = point1.x - point2.x; + CGFloat deltaY = point1.y - point2.y; + return deltaX * deltaX + deltaY * deltaY; +} + +@implementation WebWindowScaleAnimation + +- (id)init +{ + self = [super init]; + if (!self) + return nil; +#ifndef BUILDING_ON_TIGER + [self setAnimationBlockingMode:NSAnimationNonblockingThreaded]; +#endif + [self setFrameRate:60.]; + return self; +} + +- (id)initWithHintedDuration:(NSTimeInterval)duration window:(NSWindow *)window initalFrame:(NSRect)initialFrame finalFrame:(NSRect)finalFrame +{ + self = [self init]; + if (!self) + return nil; + _hintedDuration = duration; + _window = window; + _initialFrame = initialFrame; + _finalFrame = finalFrame; + _realFrame = [window frame]; + return self; +} + +- (void) dealloc +{ + [_subAnimation release]; + [super dealloc]; +} + +- (void)setDuration:(NSTimeInterval)duration +{ + [super setDuration:WebWindowAnimationDurationFromDuration(duration)]; +} + +- (void)setWindow:(NSWindow *)window +{ + _window = window; +} + +- (float)currentValue +{ + return 0.5 - 0.5 * cos(M_PI * (1 - [self currentProgress])); +} + +- (NSRect)currentFrame +{ + return scaledRect(_finalFrame, _initialFrame, [self currentValue]); +} + +- (void)setCurrentProgress:(NSAnimationProgress)progress +{ + if (!_window) + return; + + [super setCurrentProgress:progress]; + + NSRect currentRect = [self currentFrame]; +#ifndef BUILDING_ON_TIGER + WKWindowSetScaledFrame(_window, currentRect, _realFrame); +#else + [_window setFrame:currentRect display:YES]; +#endif + [_subAnimation setCurrentProgress:progress]; +} + +- (void)setSubAnimation:(NSAnimation *)animation +{ + id oldAnimation = _subAnimation; + _subAnimation = [animation retain]; + [oldAnimation release]; +} + +- (NSTimeInterval)additionalDurationNeededToReachFinalFrame +{ + static const CGFloat maxAdditionalDuration = 1.0; + static const CGFloat speedFactor = 0.0001; + + CGFloat maxDist = squaredDistance(_initialFrame.origin, _finalFrame.origin); + CGFloat dist; + + dist = squaredDistance(NSMakePoint(NSMaxX(_initialFrame), NSMinY(_initialFrame)), NSMakePoint(NSMaxX(_finalFrame), NSMinY(_finalFrame))); + if (dist > maxDist) + maxDist = dist; + + dist = squaredDistance(NSMakePoint(NSMaxX(_initialFrame), NSMaxY(_initialFrame)), NSMakePoint(NSMaxX(_finalFrame), NSMaxY(_finalFrame))); + if (dist > maxDist) + maxDist = dist; + + dist = squaredDistance(NSMakePoint(NSMinX(_initialFrame), NSMinY(_initialFrame)), NSMakePoint(NSMinX(_finalFrame), NSMinY(_finalFrame))); + if (dist > maxDist) + maxDist = dist; + + return MIN(sqrt(maxDist) * speedFactor, maxAdditionalDuration); +} + +- (void)startAnimation +{ + // Compute extra time + if (_hintedDuration) + [self setDuration:_hintedDuration + [self additionalDurationNeededToReachFinalFrame]]; + [super startAnimation]; +} + +- (void)stopAnimation +{ + _window = nil; + [super stopAnimation]; + [_subAnimation stopAnimation]; +} + +@end + +@implementation WebWindowFadeAnimation + +- (id)init +{ + self = [super init]; + if (!self) + return nil; +#ifndef BUILDING_ON_TIGER + [self setAnimationBlockingMode:NSAnimationNonblockingThreaded]; +#endif + [self setFrameRate:60]; + [self setAnimationCurve:NSAnimationEaseInOut]; + return self; +} + +- (id)initWithDuration:(NSTimeInterval)duration window:(NSWindow *)window initialAlpha:(CGFloat)initialAlpha finalAlpha:(CGFloat)finalAlpha +{ + self = [self init]; + if (!self) + return nil; + _window = window; + _initialAlpha = initialAlpha; + _finalAlpha = finalAlpha; + return self; +} + +- (void)setDuration:(NSTimeInterval)duration +{ + [super setDuration:WebWindowAnimationDurationFromDuration(duration)]; +} + +- (CGFloat)currentAlpha +{ + return MAX(0.0, MIN(1.0, _initialAlpha + [self currentValue] * (_finalAlpha - _initialAlpha))); +} + +- (void)setCurrentProgress:(NSAnimationProgress)progress +{ + if (_isStopped) + return; + + ASSERT(_window); + [super setCurrentProgress:progress]; + +#ifndef BUILDING_ON_TIGER + WKWindowSetAlpha(_window, [self currentAlpha]); +#else + [_window setAlphaValue:[self currentAlpha]]; +#endif +} + +- (void)setWindow:(NSWindow*)window +{ + _window = window; +} + +- (void)stopAnimation +{ + // This is relevant when we are a sub animation of a scale animation. + // In this case we are hosted in the animated thread of the parent + // and even after [super stopAnimation], the parent might call + // setCurrrentProgress. + _isStopped = YES; + + [super stopAnimation]; +} + +@end +