Home | History | Annotate | Download | only in WebView
      1 /*
      2  * Copyright (C) 2009 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #import "WebWindowAnimation.h"
     27 #import "WebKitSystemInterface.h"
     28 #import <wtf/Assertions.h>
     29 
     30 static const CGFloat slowMotionFactor = 10.;
     31 
     32 static NSTimeInterval WebWindowAnimationDurationFromDuration(NSTimeInterval duration)
     33 {
     34     return ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) ? duration * slowMotionFactor : duration;
     35 }
     36 
     37 static NSRect scaledRect(NSRect _initialFrame, NSRect _finalFrame, double factor)
     38 {
     39     NSRect currentRect = _initialFrame;
     40     currentRect.origin.x += (NSMinX(_finalFrame) - NSMinX(_initialFrame)) * factor;
     41     currentRect.origin.y += (NSMinY(_finalFrame) - NSMinY(_initialFrame)) * factor;
     42     currentRect.size.width += (NSWidth(_finalFrame) - NSWidth(_initialFrame)) * factor;
     43     currentRect.size.height += (NSHeight(_finalFrame) - NSHeight(_initialFrame)) * factor;
     44     return currentRect;
     45 }
     46 
     47 static CGFloat squaredDistance(NSPoint point1, NSPoint point2)
     48 {
     49     CGFloat deltaX = point1.x - point2.x;
     50     CGFloat deltaY = point1.y - point2.y;
     51     return deltaX * deltaX + deltaY * deltaY;
     52 }
     53 
     54 @implementation WebWindowScaleAnimation
     55 
     56 - (id)init
     57 {
     58     self = [super init];
     59     if (!self)
     60         return nil;
     61 #ifndef BUILDING_ON_TIGER
     62     [self setAnimationBlockingMode:NSAnimationNonblockingThreaded];
     63 #endif
     64     [self setFrameRate:60.];
     65     return self;
     66 }
     67 
     68 - (id)initWithHintedDuration:(NSTimeInterval)duration window:(NSWindow *)window initalFrame:(NSRect)initialFrame finalFrame:(NSRect)finalFrame
     69 {
     70     self = [self init];
     71     if (!self)
     72         return nil;
     73     _hintedDuration = duration;
     74     _window = window;
     75     _initialFrame = initialFrame;
     76     _finalFrame = finalFrame;
     77     _realFrame = [window frame];
     78     return self;
     79 }
     80 
     81 - (void) dealloc
     82 {
     83     [_subAnimation release];
     84     [super dealloc];
     85 }
     86 
     87 - (void)setDuration:(NSTimeInterval)duration
     88 {
     89     [super setDuration:WebWindowAnimationDurationFromDuration(duration)];
     90 }
     91 
     92 - (void)setWindow:(NSWindow *)window
     93 {
     94     _window = window;
     95 }
     96 
     97 - (float)currentValue
     98 {
     99     return 0.5 - 0.5 * cos(M_PI * (1 - [self currentProgress]));
    100 }
    101 
    102 - (NSRect)currentFrame
    103 {
    104     return scaledRect(_finalFrame, _initialFrame, [self currentValue]);
    105 }
    106 
    107 - (void)setCurrentProgress:(NSAnimationProgress)progress
    108 {
    109     if (!_window)
    110         return;
    111 
    112     [super setCurrentProgress:progress];
    113 
    114     NSRect currentRect = [self currentFrame];
    115 #ifndef BUILDING_ON_TIGER
    116     WKWindowSetScaledFrame(_window, currentRect, _realFrame);
    117 #else
    118     [_window setFrame:currentRect display:YES];
    119 #endif
    120     [_subAnimation setCurrentProgress:progress];
    121 }
    122 
    123 - (void)setSubAnimation:(NSAnimation *)animation
    124 {
    125     id oldAnimation = _subAnimation;
    126     _subAnimation = [animation retain];
    127     [oldAnimation release];
    128 }
    129 
    130 - (NSTimeInterval)additionalDurationNeededToReachFinalFrame
    131 {
    132     static const CGFloat maxAdditionalDuration = 1.0;
    133     static const CGFloat speedFactor = 0.0001;
    134 
    135     CGFloat maxDist = squaredDistance(_initialFrame.origin, _finalFrame.origin);
    136     CGFloat dist;
    137 
    138     dist = squaredDistance(NSMakePoint(NSMaxX(_initialFrame), NSMinY(_initialFrame)), NSMakePoint(NSMaxX(_finalFrame), NSMinY(_finalFrame)));
    139     if (dist > maxDist)
    140         maxDist = dist;
    141 
    142     dist = squaredDistance(NSMakePoint(NSMaxX(_initialFrame), NSMaxY(_initialFrame)), NSMakePoint(NSMaxX(_finalFrame), NSMaxY(_finalFrame)));
    143     if (dist > maxDist)
    144         maxDist = dist;
    145 
    146     dist = squaredDistance(NSMakePoint(NSMinX(_initialFrame), NSMinY(_initialFrame)), NSMakePoint(NSMinX(_finalFrame), NSMinY(_finalFrame)));
    147     if (dist > maxDist)
    148         maxDist = dist;
    149 
    150     return MIN(sqrt(maxDist) * speedFactor, maxAdditionalDuration);
    151 }
    152 
    153 - (void)startAnimation
    154 {
    155     // Compute extra time
    156     if (_hintedDuration)
    157         [self setDuration:_hintedDuration + [self additionalDurationNeededToReachFinalFrame]];
    158     [super startAnimation];
    159 }
    160 
    161 - (void)stopAnimation
    162 {
    163     _window = nil;
    164     [super stopAnimation];
    165     [_subAnimation stopAnimation];
    166 }
    167 
    168 @end
    169 
    170 @implementation WebWindowFadeAnimation
    171 
    172 - (id)init
    173 {
    174     self = [super init];
    175     if (!self)
    176         return nil;
    177 #ifndef BUILDING_ON_TIGER
    178     [self setAnimationBlockingMode:NSAnimationNonblockingThreaded];
    179 #endif
    180     [self setFrameRate:60];
    181     [self setAnimationCurve:NSAnimationEaseInOut];
    182     return self;
    183 }
    184 
    185 - (id)initWithDuration:(NSTimeInterval)duration window:(NSWindow *)window initialAlpha:(CGFloat)initialAlpha finalAlpha:(CGFloat)finalAlpha
    186 {
    187     self = [self init];
    188     if (!self)
    189         return nil;
    190     _window = window;
    191     _initialAlpha = initialAlpha;
    192     _finalAlpha = finalAlpha;
    193     return self;
    194 }
    195 
    196 - (void)setDuration:(NSTimeInterval)duration
    197 {
    198     [super setDuration:WebWindowAnimationDurationFromDuration(duration)];
    199 }
    200 
    201 - (CGFloat)currentAlpha
    202 {
    203     return MAX(0.0, MIN(1.0, _initialAlpha + [self currentValue] * (_finalAlpha - _initialAlpha)));
    204 }
    205 
    206 - (void)setCurrentProgress:(NSAnimationProgress)progress
    207 {
    208     if (_isStopped)
    209         return;
    210 
    211     ASSERT(_window);
    212     [super setCurrentProgress:progress];
    213 
    214 #ifndef BUILDING_ON_TIGER
    215     WKWindowSetAlpha(_window, [self currentAlpha]);
    216 #else
    217     [_window setAlphaValue:[self currentAlpha]];
    218 #endif
    219 }
    220 
    221 - (void)setWindow:(NSWindow*)window
    222 {
    223     _window = window;
    224 }
    225 
    226 - (void)stopAnimation
    227 {
    228     // This is relevant when we are a sub animation of a scale animation.
    229     // In this case we are hosted in the animated thread of the parent
    230     // and even after [super stopAnimation], the parent might call
    231     // setCurrrentProgress.
    232     _isStopped = YES;
    233 
    234     [super stopAnimation];
    235 }
    236 
    237 @end
    238 
    239