2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
27 #import "FindIndicatorWindow.h"
29 #import "FindIndicator.h"
31 #import <WebCore/GraphicsContext.h>
33 static const double bounceAnimationDuration = 0.12;
34 static const double timeBeforeFadeStarts = bounceAnimationDuration + 0.2;
35 static const double fadeOutAnimationDuration = 0.3;
37 using namespace WebCore;
39 @interface WebFindIndicatorView : NSView {
40 RefPtr<WebKit::FindIndicator> _findIndicator;
43 - (id)_initWithFindIndicator:(PassRefPtr<WebKit::FindIndicator>)findIndicator;
46 @implementation WebFindIndicatorView
48 - (id)_initWithFindIndicator:(PassRefPtr<WebKit::FindIndicator>)findIndicator
50 if ((self = [super initWithFrame:NSZeroRect]))
51 _findIndicator = findIndicator;
56 - (void)drawRect:(NSRect)rect
58 GraphicsContext graphicsContext(static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]));
60 _findIndicator->draw(graphicsContext, enclosingIntRect(rect));
70 @interface WebFindIndicatorWindowAnimation : NSAnimation<NSAnimationDelegate> {
71 WebKit::FindIndicatorWindow* _findIndicatorWindow;
72 void (WebKit::FindIndicatorWindow::*_animationProgressCallback)(double progress);
73 void (WebKit::FindIndicatorWindow::*_animationDidEndCallback)();
76 - (id)_initWithFindIndicatorWindow:(WebKit::FindIndicatorWindow *)findIndicatorWindow
77 animationDuration:(CFTimeInterval)duration
78 animationProgressCallback:(void (WebKit::FindIndicatorWindow::*)(double progress))animationProgressCallback
79 animationDidEndCallback:(void (WebKit::FindIndicatorWindow::*)())animationDidEndCallback;
82 @implementation WebFindIndicatorWindowAnimation
84 - (id)_initWithFindIndicatorWindow:(WebKit::FindIndicatorWindow *)findIndicatorWindow
85 animationDuration:(CFTimeInterval)animationDuration
86 animationProgressCallback:(void (WebKit::FindIndicatorWindow::*)(double progress))animationProgressCallback
87 animationDidEndCallback:(void (WebKit::FindIndicatorWindow::*)())animationDidEndCallback
89 if ((self = [super initWithDuration:animationDuration animationCurve:NSAnimationEaseInOut])) {
90 _findIndicatorWindow = findIndicatorWindow;
91 _animationProgressCallback = animationProgressCallback;
92 _animationDidEndCallback = animationDidEndCallback;
93 [self setDelegate:self];
94 [self setAnimationBlockingMode:NSAnimationNonblocking];
99 - (void)setCurrentProgress:(NSAnimationProgress)progress
101 (_findIndicatorWindow->*_animationProgressCallback)(progress);
104 - (void)animationDidEnd:(NSAnimation *)animation
106 ASSERT(animation == self);
108 (_findIndicatorWindow->*_animationDidEndCallback)();
115 PassOwnPtr<FindIndicatorWindow> FindIndicatorWindow::create(WKView *wkView)
117 return adoptPtr(new FindIndicatorWindow(wkView));
120 FindIndicatorWindow::FindIndicatorWindow(WKView *wkView)
122 , m_bounceAnimationContext(0)
123 , m_startFadeOutTimer(RunLoop::main(), this, &FindIndicatorWindow::startFadeOutTimerFired)
127 FindIndicatorWindow::~FindIndicatorWindow()
132 void FindIndicatorWindow::setFindIndicator(PassRefPtr<FindIndicator> findIndicator, bool fadeOut)
134 if (m_findIndicator == findIndicator)
137 m_findIndicator = findIndicator;
139 // Get rid of the old window.
142 if (!m_findIndicator)
145 NSRect contentRect = m_findIndicator->frameRect();
146 NSRect windowFrameRect = NSIntegralRect([m_wkView convertRect:contentRect toView:nil]);
147 windowFrameRect.origin = [[m_wkView window] convertBaseToScreen:windowFrameRect.origin];
149 NSRect windowContentRect = [NSWindow contentRectForFrameRect:windowFrameRect styleMask:NSBorderlessWindowMask];
151 m_findIndicatorWindow.adoptNS([[NSWindow alloc] initWithContentRect:windowContentRect
152 styleMask:NSBorderlessWindowMask
153 backing:NSBackingStoreBuffered
156 [m_findIndicatorWindow.get() setBackgroundColor:[NSColor clearColor]];
157 [m_findIndicatorWindow.get() setOpaque:NO];
158 [m_findIndicatorWindow.get() setIgnoresMouseEvents:YES];
160 RetainPtr<WebFindIndicatorView> findIndicatorView(AdoptNS, [[WebFindIndicatorView alloc] _initWithFindIndicator:m_findIndicator]);
161 [m_findIndicatorWindow.get() setContentView:findIndicatorView.get()];
163 [[m_wkView window] addChildWindow:m_findIndicatorWindow.get() ordered:NSWindowAbove];
164 [m_findIndicatorWindow.get() setReleasedWhenClosed:NO];
166 // Start the bounce animation.
167 m_bounceAnimationContext = WKWindowBounceAnimationContextCreate(m_findIndicatorWindow.get());
168 m_bounceAnimation.adoptNS([[WebFindIndicatorWindowAnimation alloc] _initWithFindIndicatorWindow:this
169 animationDuration:bounceAnimationDuration
170 animationProgressCallback:&FindIndicatorWindow::bounceAnimationCallback
171 animationDidEndCallback:&FindIndicatorWindow::bounceAnimationDidEnd]);
172 [m_bounceAnimation.get() startAnimation];
175 m_startFadeOutTimer.startOneShot(timeBeforeFadeStarts);
178 void FindIndicatorWindow::closeWindow()
180 if (!m_findIndicatorWindow)
183 m_startFadeOutTimer.stop();
185 if (m_fadeOutAnimation) {
186 [m_fadeOutAnimation.get() stopAnimation];
187 m_fadeOutAnimation = nullptr;
190 if (m_bounceAnimation) {
191 [m_bounceAnimation.get() stopAnimation];
192 m_bounceAnimation = nullptr;
195 if (m_bounceAnimationContext)
196 WKWindowBounceAnimationContextDestroy(m_bounceAnimationContext);
198 [[m_findIndicatorWindow.get() parentWindow] removeChildWindow:m_findIndicatorWindow.get()];
199 [m_findIndicatorWindow.get() close];
200 m_findIndicatorWindow = nullptr;
203 void FindIndicatorWindow::startFadeOutTimerFired()
205 ASSERT(!m_fadeOutAnimation);
207 m_fadeOutAnimation.adoptNS([[WebFindIndicatorWindowAnimation alloc] _initWithFindIndicatorWindow:this
208 animationDuration:fadeOutAnimationDuration
209 animationProgressCallback:&FindIndicatorWindow::fadeOutAnimationCallback
210 animationDidEndCallback:&FindIndicatorWindow::fadeOutAnimationDidEnd]);
211 [m_fadeOutAnimation.get() startAnimation];
214 void FindIndicatorWindow::fadeOutAnimationCallback(double progress)
216 ASSERT(m_fadeOutAnimation);
218 [m_findIndicatorWindow.get() setAlphaValue:1.0 - progress];
221 void FindIndicatorWindow::fadeOutAnimationDidEnd()
223 ASSERT(m_fadeOutAnimation);
224 ASSERT(m_findIndicatorWindow);
229 void FindIndicatorWindow::bounceAnimationCallback(double progress)
231 ASSERT(m_bounceAnimation);
232 ASSERT(m_bounceAnimationContext);
234 WKWindowBounceAnimationSetAnimationProgress(m_bounceAnimationContext, progress);
237 void FindIndicatorWindow::bounceAnimationDidEnd()
239 ASSERT(m_bounceAnimation);
240 ASSERT(m_bounceAnimationContext);
241 ASSERT(m_findIndicatorWindow);
243 WKWindowBounceAnimationContextDestroy(m_bounceAnimationContext);
244 m_bounceAnimationContext = 0;
247 } // namespace WebKit