diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog index 0307058ccae52d62142f87386369a7c6a3d70cb6..b217bf5ec3e0f9ee857282ca34aa695bb11cb7ff 100644 --- a/LayoutTests/ChangeLog +++ b/LayoutTests/ChangeLog @@ -1,3 +1,34 @@ +2011-01-11 James Robinson + + Reviewed by NOBODY (OOPS!). + + Implement mozilla's requestAnimationFrame API + https://bugs.webkit.org/show_bug.cgi?id=51218 + + Tests for window.webkitRequestAnimationFrame(). The new tests + are in the Skipped lists for platforms that do not set + ENABLE(REQUEST_ANIMATION_FRAME) - which is currently all but chromium. + + * fast/animation/request-animation-frame-cancel-expected.txt: Added. + * fast/animation/request-animation-frame-cancel.html: Added. + Tests cancelling a callback within a webkitRequestAnimationFrame() callback. + * fast/animation/request-animation-frame-cancel2-expected.txt: Added. + * fast/animation/request-animation-frame-cancel2.html: Added. + Tests interactions between multiple webkitRequestAnimationFrame() callbacks. + * fast/animation/request-animation-frame-display-expected.txt: Added. + * fast/animation/request-animation-frame-display.html: Added. + Tests changing the display: property of an element within a callback. + * fast/animation/request-animation-frame-expected.txt: Added. + * fast/animation/request-animation-frame.html: Added. + Tests the basic use of window.webkitRequestAnimationFrame(). + * fast/animation/request-animation-frame-within-callback-expected.txt: Added. + * fast/animation/request-animation-frame-within-callback.html: Added. + Tests setting one webkit.webkitRequestAnimationFrame() callback within another. + * platform/gtk/Skipped: + * platform/mac/Skipped: + * platform/qt/Skipped: + * platform/win/Skipped: + 2011-01-11 Dimitri Glazkov Reviewed by Eric Seidel. diff --git a/LayoutTests/fast/animation/request-animation-frame-cancel-expected.txt b/LayoutTests/fast/animation/request-animation-frame-cancel-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..7ef22e9a431ad0272713b71fdc8794016c8ef12f --- /dev/null +++ b/LayoutTests/fast/animation/request-animation-frame-cancel-expected.txt @@ -0,0 +1 @@ +PASS diff --git a/LayoutTests/fast/animation/request-animation-frame-cancel.html b/LayoutTests/fast/animation/request-animation-frame-cancel.html new file mode 100644 index 0000000000000000000000000000000000000000..4210f7b9f69e6016a3c7a24d93574488d899910f --- /dev/null +++ b/LayoutTests/fast/animation/request-animation-frame-cancel.html @@ -0,0 +1,17 @@ + + +PASS + diff --git a/LayoutTests/fast/animation/request-animation-frame-cancel2-expected.txt b/LayoutTests/fast/animation/request-animation-frame-cancel2-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..7ef22e9a431ad0272713b71fdc8794016c8ef12f --- /dev/null +++ b/LayoutTests/fast/animation/request-animation-frame-cancel2-expected.txt @@ -0,0 +1 @@ +PASS diff --git a/LayoutTests/fast/animation/request-animation-frame-cancel2.html b/LayoutTests/fast/animation/request-animation-frame-cancel2.html new file mode 100644 index 0000000000000000000000000000000000000000..4ac2e93fd335856cd626f4a61dcff41d3546a029 --- /dev/null +++ b/LayoutTests/fast/animation/request-animation-frame-cancel2.html @@ -0,0 +1,21 @@ + + +PASS + diff --git a/LayoutTests/fast/animation/request-animation-frame-display-expected.txt b/LayoutTests/fast/animation/request-animation-frame-display-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..7ef22e9a431ad0272713b71fdc8794016c8ef12f --- /dev/null +++ b/LayoutTests/fast/animation/request-animation-frame-display-expected.txt @@ -0,0 +1 @@ +PASS diff --git a/LayoutTests/fast/animation/request-animation-frame-display.html b/LayoutTests/fast/animation/request-animation-frame-display.html new file mode 100644 index 0000000000000000000000000000000000000000..b82257719e070471481e72d38c6768dcbc6ac23b --- /dev/null +++ b/LayoutTests/fast/animation/request-animation-frame-display.html @@ -0,0 +1,22 @@ + + + +FAIL + + diff --git a/LayoutTests/fast/animation/request-animation-frame-expected.txt b/LayoutTests/fast/animation/request-animation-frame-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..7ef22e9a431ad0272713b71fdc8794016c8ef12f --- /dev/null +++ b/LayoutTests/fast/animation/request-animation-frame-expected.txt @@ -0,0 +1 @@ +PASS diff --git a/LayoutTests/fast/animation/request-animation-frame-within-callback-expected.txt b/LayoutTests/fast/animation/request-animation-frame-within-callback-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..7ef22e9a431ad0272713b71fdc8794016c8ef12f --- /dev/null +++ b/LayoutTests/fast/animation/request-animation-frame-within-callback-expected.txt @@ -0,0 +1 @@ +PASS diff --git a/LayoutTests/fast/animation/request-animation-frame-within-callback.html b/LayoutTests/fast/animation/request-animation-frame-within-callback.html new file mode 100644 index 0000000000000000000000000000000000000000..d5a366fee0458343945d00fc965ae859d5352aa9 --- /dev/null +++ b/LayoutTests/fast/animation/request-animation-frame-within-callback.html @@ -0,0 +1,28 @@ + + +FAIL + diff --git a/LayoutTests/fast/animation/request-animation-frame.html b/LayoutTests/fast/animation/request-animation-frame.html new file mode 100644 index 0000000000000000000000000000000000000000..7d67a977421685e4f1dc6b7e9d02b0e98d64c509 --- /dev/null +++ b/LayoutTests/fast/animation/request-animation-frame.html @@ -0,0 +1,14 @@ + + +FAIL + diff --git a/LayoutTests/platform/gtk/Skipped b/LayoutTests/platform/gtk/Skipped index d03d31109952a81d82e55b255a376bd5683a25a1..63fc8e554612a9f870d3caca2978f7c7d81bdac1 100644 --- a/LayoutTests/platform/gtk/Skipped +++ b/LayoutTests/platform/gtk/Skipped @@ -5594,3 +5594,9 @@ http/tests/inspector/console-websocket-error.html # layoutTestController.queueLoad() does not work http/tests/xmlhttprequest/basic-auth-nouser.html http/tests/xmlhttprequest/basic-auth-nopassword.html + +# Requires requestAnimationFrame support +fast/animation/ + +# https://bugs.webkit.org/show_bug.cgi?id=51734 +fast/multicol/span/double-merge-anonymous-block-crash.html diff --git a/LayoutTests/platform/mac/Skipped b/LayoutTests/platform/mac/Skipped index b21beba266bbb54907b8be5bf9452f0f115f07f5..ead25bca839bfbee694be9ba2ad3cb9dc245d216 100644 --- a/LayoutTests/platform/mac/Skipped +++ b/LayoutTests/platform/mac/Skipped @@ -284,3 +284,6 @@ editing/selection/caret-mode-paragraph-keys-navigation.html # This test is failing on the Leopard Intel Debug buildbot # https://bugs.webkit.org/show_bug.cgi?id=51807 fast/blockflow/broken-ideograph-small-caps.html + +# Requires requestAnimationFrame support +fast/animation/ diff --git a/LayoutTests/platform/qt/Skipped b/LayoutTests/platform/qt/Skipped index 9455e52a5b468d5e1ed1b1fb71e17bb6eecc4391..372efc5474ef91f2dc784e74a0b2726ccbaa33b1 100644 --- a/LayoutTests/platform/qt/Skipped +++ b/LayoutTests/platform/qt/Skipped @@ -5369,6 +5369,9 @@ editing/selection/caret-bidi-first-and-last-letters.html # https://bugs.webkit.org/show_bug.cgi?id=52155 fast/text/emphasis-avoid-ruby.html +# Requires requestAnimationFrame support +fast/animation/ + # https://bugs.webkit.org/show_bug.cgi?id=42578 # [Qt] DRT sideeffect revealed by r63657 and r75305 fast/tokenizer/flush-characters-in-document-write-evil.html diff --git a/LayoutTests/platform/win/Skipped b/LayoutTests/platform/win/Skipped index 4cd6e287573f0bb56b326531792f74273583e8ed..42bd41de3bb1e55fda03449b3dc4143422ba1470 100644 --- a/LayoutTests/platform/win/Skipped +++ b/LayoutTests/platform/win/Skipped @@ -1114,3 +1114,6 @@ fast/loader/user-stylesheet-fast-path.html # DRT does not support toggling caret browsing on / off editing/selection/caret-mode-paragraph-keys-navigation.html + +# Requires requestAnimationFrame support +fast/animation/ diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index 67fb77f7283b18aeb511743b1b5dde2619e9a652..7e70665a04780e4034ae8f39309b117aa51b1ddc 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,5 +1,71 @@ 2011-01-11 James Robinson + Reviewed by NOBODY (OOPS!). + + Implement mozilla's requestAnimationFrame API + https://bugs.webkit.org/show_bug.cgi?id=51218 + + This implements mozilla's proposed requestAnimationFrame API. The idea with this API is that + an author driving an animation from script could use window.requestAnimationFrame(callback) + instead of window.setTimeout(callback, 0) to schedule their update logic and let the browser + decide when to update the animations. This avoids doing unnecessary work when the page content + is offscreen or is being displayed at a different framerate than what the page author expects. + + Mozilla's proposal is here: https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame + This implements window.mozRequestAnimationFrame as window.webkitRequestAnimationFrame with the + following changes: + *) Only the callback syntax is supported, there is no before paint event + *) webkitRequestAnimationFrame supports a second parameter Element to let the author indicate + what content they intend to animate. That way if the page is being displayed but the element + in question is offscreen, we can avoid invoking the callback. + *) No timestamp is provided to the caller and there is no window.animationStartTime property + (see https://bugs.webkit.org/show_bug.cgi?id=51952 for discussion of this property) + *) window.webkitRequestAnimationFrame returns a numerical id that can be used to cancel the callback + using window.cancelWebkitRequestAnimationFrame, to parallel window.setTimeout()/window.clearTime(). + + The implementation depends on the embedder scheduling the callbacks since the callback invocation + depends on the page's visibility and the embedder's paint scheduling, neither of which are exposed + to WebCore. The expectation for the embedder is that at some point Chrome::scheduleAnimation() is + called FrameView::serviceScriptedAnimations() should be called for the associated Page's main frame. + Ideally serviceScriptedAnimations() would be called prior to rendering - although in practice the + embedder has to rate limit callbacks and may not be able to tie the callback directly to the + rendering loop. + + Tests: fast/animation/request-animation-frame-cancel.html + fast/animation/request-animation-frame-cancel2.html + fast/animation/request-animation-frame-display.html + fast/animation/request-animation-frame-within-callback.html + fast/animation/request-animation-frame.html + + * WebCore.gypi: + * dom/Document.cpp: + (WebCore::Document::Document): + (WebCore::Document::webkitRequestAnimationFrame): + (WebCore::Document::webkitCancelRequestAnimationFrame): + (WebCore::Document::serviceScriptedAnimations): + * dom/Document.h: + * dom/RequestAnimationFrameCallback.h: Added. + (WebCore::RequestAnimationFrameCallback::~RequestAnimationFrameCallback): + * dom/RequestAnimationFrameCallback.idl: Added. + * loader/EmptyClients.h: + (WebCore::EmptyChromeClient::scheduleAnimation): + * page/Chrome.cpp: + (WebCore::Chrome::scheduleAnimation): + * page/Chrome.h: + * page/ChromeClient.h: + * page/DOMWindow.cpp: + (WebCore::DOMWindow::webkitRequestAnimationFrame): + (WebCore::DOMWindow::webkitCancelRequestAnimationFrame): + * page/DOMWindow.h: + * page/DOMWindow.idl: + * page/FrameView.cpp: + (WebCore::FrameView::scheduleAnimation): + (WebCore::FrameView::serviceScriptedAnimations): + * page/FrameView.h: + * platform/HostWindow.h: + +2011-01-11 James Robinson + Reviewed by Dimitri Glazkov. Set all RenderBlocks as replaced when an inline display type is specified diff --git a/Source/WebCore/WebCore.gypi b/Source/WebCore/WebCore.gypi index 83e55d46d7c969373a61ab875e918e048175f690..37d7b29253d646919fc95ed2fcd37ca830b3e961 100644 --- a/Source/WebCore/WebCore.gypi +++ b/Source/WebCore/WebCore.gypi @@ -75,6 +75,7 @@ 'dom/ProgressEvent.idl', 'dom/Range.idl', 'dom/RangeException.idl', + 'dom/RequestAnimationFrameCallback.idl', 'dom/Text.idl', 'dom/TextEvent.idl', 'dom/Touch.idl', @@ -1314,6 +1315,7 @@ 'dom/Range.h', 'dom/RangeBoundaryPoint.h', 'dom/RangeException.h', + 'dom/RequestAnimationFrameCallback.h', 'dom/RawDataDocumentParser.h', 'dom/RegisteredEventListener.cpp', 'dom/RegisteredEventListener.h', diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp index 1e12958e0bd0a1be97f268efbaf0c43311258e62..e62be7ccdde2beb17a96cb127d1f334b30eca458 100644 --- a/Source/WebCore/dom/Document.cpp +++ b/Source/WebCore/dom/Document.cpp @@ -207,6 +207,10 @@ #include "RenderFullScreen.h" #endif +#if ENABLE(REQUEST_ANIMATION_FRAME) +#include "RequestAnimationFrameCallback.h" +#endif + using namespace std; using namespace WTF; using namespace Unicode; @@ -425,6 +429,9 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML, con , m_loadEventDelayTimer(this, &Document::loadEventDelayTimerFired) , m_directionSetOnDocumentElement(false) , m_writingModeSetOnDocumentElement(false) +#if ENABLE(REQUEST_ANIMATION_FRAME) + , m_nextRequestAnimationFrameCallbackId(0) +#endif { m_document = this; @@ -4947,6 +4954,86 @@ void Document::loadEventDelayTimerFired(Timer*) frame()->loader()->checkCompleted(); } +#if ENABLE(REQUEST_ANIMATION_FRAME) +int Document::webkitRequestAnimationFrame(PassRefPtr callback, Element* e) +{ + if (!m_requestAnimationFrameCallbacks) + m_requestAnimationFrameCallbacks = new RequestAnimationFrameCallbackList; + int id = m_nextRequestAnimationFrameCallbackId++; + callback->m_firedOrCancelled = false; + callback->m_id = id; + callback->m_element = e; + m_requestAnimationFrameCallbacks->append(callback); + if (FrameView* v = view()) + v->scheduleAnimation(); + return id; +} + +void Document::webkitCancelRequestAnimationFrame(int id) +{ + if (!m_requestAnimationFrameCallbacks) + return; + for (size_t i = 0; i < m_requestAnimationFrameCallbacks->size(); ++i) { + if (m_requestAnimationFrameCallbacks->at(i)->m_id == id) { + m_requestAnimationFrameCallbacks->at(i)->m_firedOrCancelled = true; + m_requestAnimationFrameCallbacks->remove(i); + return; + } + } +} + +void Document::serviceScriptedAnimations() +{ + if (!m_requestAnimationFrameCallbacks) + return; + // We want to run the callback for all elements in the document that have registered + // for a callback and that are visible. Running the callbacks can cause new callbacks + // to be registered, existing callbacks to be cancelled, and elements to gain or lose + // visibility so this code has to iterate carefully. + + // FIXME: Currently, this code doesn't do any visibility tests beyond checking display: + + // First, generate a list of callbacks to consider. Callbacks registered from this point + // on are considered only for the "next" frame, not this one. + RequestAnimationFrameCallbackList callbacks(*m_requestAnimationFrameCallbacks); + + // Firing the callback may cause the visibility of other elements to change. To avoid + // missing any callbacks, we keep iterating through the list of candiate callbacks and firing + // them until nothing new becomes visible. + bool firedCallback; + do { + firedCallback = false; + // A previous iteration may have invalidated style (or layout). Update styles for each iteration + // for now since all we check is the existence of a renderer. + updateStyleIfNeeded(); + for (size_t i = 0; i < callbacks.size(); ++i) { + RequestAnimationFrameCallback* callback = callbacks[i].get(); + if (!callback->m_firedOrCancelled && (!callback->m_element || callback->m_element->renderer())) { + callback->m_firedOrCancelled = true; + callback->handleEvent(); + firedCallback = true; + callbacks.remove(i); + break; + } + } + } while (firedCallback); + + // Remove any callbacks we fired from the list of pending callbacks. + for (size_t i = 0; i < m_requestAnimationFrameCallbacks->size();) { + if (m_requestAnimationFrameCallbacks->at(i)->m_firedOrCancelled) + m_requestAnimationFrameCallbacks->remove(i); + else + ++i; + } + + // In most cases we expect this list to be empty, so no need to keep around the vector's inline buffer. + if (!m_requestAnimationFrameCallbacks->size()) + m_requestAnimationFrameCallbacks.clear(); + else if (FrameView* v = view()) + v->scheduleAnimation(); +} +#endif + #if ENABLE(TOUCH_EVENTS) PassRefPtr Document::createTouch(DOMWindow* window, EventTarget* target, int identifier, int pageX, int pageY, int screenX, int screenY, ExceptionCode&) const { diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h index fb1ae31a57d85b750f3277db492bf344a48fe14b..274c1b9a4df47f5aadffb3fa80ce687fdb679894 100644 --- a/Source/WebCore/dom/Document.h +++ b/Source/WebCore/dom/Document.h @@ -147,6 +147,10 @@ class Touch; class TouchList; #endif +#if ENABLE(REQUEST_ANIMATION_FRAME) +class RequestAnimationFrameCallback; +#endif + typedef int ExceptionCode; class FormElementKey { @@ -1072,6 +1076,12 @@ public: const DocumentTiming* timing() const { return &m_documentTiming; } +#if ENABLE(REQUEST_ANIMATION_FRAME) + int webkitRequestAnimationFrame(PassRefPtr, Element*); + void webkitCancelRequestAnimationFrame(int id); + void serviceScriptedAnimations(); +#endif + bool mayCauseFlashOfUnstyledContent() const; void initDNSPrefetch(); @@ -1391,6 +1401,12 @@ private: DocumentTiming m_documentTiming; RefPtr m_mediaQueryMatcher; + +#if ENABLE(REQUEST_ANIMATION_FRAME) + typedef Vector > RequestAnimationFrameCallbackList; + OwnPtr m_requestAnimationFrameCallbacks; + int m_nextRequestAnimationFrameCallbackId; +#endif }; inline bool Document::DocumentOrderedMap::contains(AtomicStringImpl* id) const diff --git a/Source/WebCore/dom/RequestAnimationFrameCallback.h b/Source/WebCore/dom/RequestAnimationFrameCallback.h new file mode 100644 index 0000000000000000000000000000000000000000..819e4956ea3deefa64ebc50b7230306d8a758287 --- /dev/null +++ b/Source/WebCore/dom/RequestAnimationFrameCallback.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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. + */ + +#ifndef RequestAnimationFrameCallback_h +#define RequestAnimationFrameCallback_h + +#include "Element.h" +#include +#include + +namespace WebCore { + +class RequestAnimationFrameCallback : public RefCounted { +public: + virtual ~RequestAnimationFrameCallback() { } + virtual bool handleEvent() = 0; + + RefPtr m_element; + int m_id; + bool m_firedOrCancelled; +}; + +} + +#endif // RequestAnimationFrameCallback_h + diff --git a/Source/WebCore/dom/RequestAnimationFrameCallback.idl b/Source/WebCore/dom/RequestAnimationFrameCallback.idl new file mode 100644 index 0000000000000000000000000000000000000000..8d232e5f4c8bb1a82adcfdfcc8e235a5d3db4bdf --- /dev/null +++ b/Source/WebCore/dom/RequestAnimationFrameCallback.idl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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. + */ + +module core { + interface [ + Callback=FunctionOnly,Conditional=REQUEST_ANIMATION_FRAME + ] RequestAnimationFrameCallback{ + boolean handleEvent(); + }; +} diff --git a/Source/WebCore/loader/EmptyClients.h b/Source/WebCore/loader/EmptyClients.h index e4cefc54aa0776b976fa61c34a00a5b6505272f9..5a6bda09d76dcd211c31e26f80140825d81a61d1 100644 --- a/Source/WebCore/loader/EmptyClients.h +++ b/Source/WebCore/loader/EmptyClients.h @@ -157,6 +157,9 @@ public: #if ENABLE(TILED_BACKING_STORE) virtual void delegatedScrollRequested(const IntSize&) { } #endif +#if ENABLE(REQUEST_ANIMATION_FRAME) + virtual void scheduleAnimation() { } +#endif virtual IntPoint screenToWindow(const IntPoint& p) const { return p; } virtual IntRect windowToScreen(const IntRect& r) const { return r; } diff --git a/Source/WebCore/page/Chrome.cpp b/Source/WebCore/page/Chrome.cpp index a8010650de243df5cb8e8602eac17d9bdec32cb8..3da9d157ee52f11955d8e30369cf9a1d1473a8a7 100644 --- a/Source/WebCore/page/Chrome.cpp +++ b/Source/WebCore/page/Chrome.cpp @@ -448,6 +448,13 @@ void Chrome::setCursor(const Cursor& cursor) m_client->setCursor(cursor); } +#if ENABLE(REQUEST_ANIMATION_FRAME) +void Chrome::scheduleAnimation() +{ + m_client->scheduleAnimation(); +} +#endif + #if ENABLE(NOTIFICATIONS) NotificationPresenter* Chrome::notificationPresenter() const { diff --git a/Source/WebCore/page/Chrome.h b/Source/WebCore/page/Chrome.h index 93b8c4a712d67f080a254b77e0fa6b33fb4c289b..0afd807dd0d6c3e6bde600a9ae0fcf1f057edabf 100644 --- a/Source/WebCore/page/Chrome.h +++ b/Source/WebCore/page/Chrome.h @@ -78,6 +78,9 @@ namespace WebCore { virtual PlatformPageClient platformPageClient() const; virtual void scrollbarsModeDidChange() const; virtual void setCursor(const Cursor&); +#if ENABLE(REQUEST_ANIMATION_FRAME) + virtual void scheduleAnimation(); +#endif void scrollRectIntoView(const IntRect&) const; diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h index 67e13252a8d4e91761c5320bceac629fde9d7912..e348afbca4fc68d484b0a9cf6523dfdf178b384f 100644 --- a/Source/WebCore/page/ChromeClient.h +++ b/Source/WebCore/page/ChromeClient.h @@ -151,6 +151,9 @@ namespace WebCore { virtual PlatformPageClient platformPageClient() const = 0; virtual void scrollbarsModeDidChange() const = 0; virtual void setCursor(const Cursor&) = 0; +#if ENABLE(REQUEST_ANIMATION_FRAME) + virtual void scheduleAnimation() = 0; +#endif // End methods used by HostWindow. virtual void dispatchViewportDataDidChange(const ViewportArguments&) const { } diff --git a/Source/WebCore/page/DOMWindow.cpp b/Source/WebCore/page/DOMWindow.cpp index 02140d5866f54257b29657951c913d12a4342045..832e9565fb223de9e7206b54209a9e41f95dac53 100644 --- a/Source/WebCore/page/DOMWindow.cpp +++ b/Source/WebCore/page/DOMWindow.cpp @@ -105,6 +105,10 @@ #include "LocalFileSystem.h" #endif +#if ENABLE(REQUEST_ANIMATION_FRAME) +#include "RequestAnimationFrameCallback.h" +#endif + using std::min; using std::max; @@ -1464,6 +1468,21 @@ void DOMWindow::clearInterval(int timeoutId) DOMTimer::removeById(context, timeoutId); } +#if ENABLE(REQUEST_ANIMATION_FRAME) +int DOMWindow::webkitRequestAnimationFrame(PassRefPtr callback, Element* e) +{ + if (Document* d = document()) + return d->webkitRequestAnimationFrame(callback, e); + return 0; +} + +void DOMWindow::webkitCancelRequestAnimationFrame(int id) +{ + if (Document* d = document()) + d->webkitCancelRequestAnimationFrame(id); +} +#endif + bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr listener, bool useCapture) { if (!EventTarget::addEventListener(eventType, listener, useCapture)) diff --git a/Source/WebCore/page/DOMWindow.h b/Source/WebCore/page/DOMWindow.h index 9e72dec318a1105040c9660a1e5db1395c9f7830..366b4859420bf681f1452109d277028542c11257 100644 --- a/Source/WebCore/page/DOMWindow.h +++ b/Source/WebCore/page/DOMWindow.h @@ -64,6 +64,10 @@ namespace WebCore { class StyleMedia; class WebKitPoint; +#if ENABLE(REQUEST_ANIMATION_FRAME) + class RequestAnimationFrameCallback; +#endif + struct WindowFeatures; typedef int ExceptionCode; @@ -237,6 +241,12 @@ namespace WebCore { int setInterval(PassOwnPtr, int timeout, ExceptionCode&); void clearInterval(int timeoutId); + // WebKit animation extensions +#if ENABLE(REQUEST_ANIMATION_FRAME) + int webkitRequestAnimationFrame(PassRefPtr, Element*); + void webkitCancelRequestAnimationFrame(int id); +#endif + // Events // EventTarget API virtual bool addEventListener(const AtomicString& eventType, PassRefPtr, bool useCapture); diff --git a/Source/WebCore/page/DOMWindow.idl b/Source/WebCore/page/DOMWindow.idl index 389d5eda4006dcf588579e6622630bb8c02af936..7c7ce18e0e8b91c56eb2f2a2f3e10f57f19b8536 100644 --- a/Source/WebCore/page/DOMWindow.idl +++ b/Source/WebCore/page/DOMWindow.idl @@ -235,6 +235,12 @@ module window { // [Custom] long setInterval(in DOMString code, in long timeout); void clearInterval(in long handle); +#if defined(ENABLE_REQUEST_ANIMATION_FRAME) + // WebKit animation extensions + long webkitRequestAnimationFrame(in [Callback] RequestAnimationFrameCallback callback, in Element element); + void webkitCancelRequestAnimationFrame(in long id); +#endif + // Base64 DOMString atob(in [ConvertNullToNullString] DOMString string) raises(DOMException); diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp index 77e19762f14b4013176e257d788681b75e71f8eb..7b35c29b4cd42cb94032bd1a751f2f67302b93fc 100644 --- a/Source/WebCore/page/FrameView.cpp +++ b/Source/WebCore/page/FrameView.cpp @@ -342,6 +342,14 @@ void FrameView::setFrameRect(const IntRect& newRect) #endif } +#if ENABLE(REQUEST_ANIMATION_FRAME) +void FrameView::scheduleAnimation() +{ + if (hostWindow()) + hostWindow()->scheduleAnimation(); +} +#endif + void FrameView::setMarginWidth(int w) { // make it update the rendering area when set @@ -1639,6 +1647,14 @@ void FrameView::unscheduleRelayout() m_delayedLayout = false; } +#if ENABLE(REQUEST_ANIMATION_FRAME) +void FrameView::serviceScriptedAnimations() +{ + for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) + frame->document()->serviceScriptedAnimations(); +} +#endif + bool FrameView::isTransparent() const { return m_isTransparent; diff --git a/Source/WebCore/page/FrameView.h b/Source/WebCore/page/FrameView.h index a2f5815b4e55e0027ba8b42ebd04de7f058c877a..4ffabc66464488063b432286df60591a90a24a44 100644 --- a/Source/WebCore/page/FrameView.h +++ b/Source/WebCore/page/FrameView.h @@ -62,6 +62,9 @@ public: virtual void invalidateRect(const IntRect&); virtual void setFrameRect(const IntRect&); +#if ENABLE(REQUEST_ANIMATION_FRAME) + void scheduleAnimation(); +#endif Frame* frame() const { return m_frame.get(); } void clearFrame(); @@ -97,6 +100,10 @@ public: bool needsFullRepaint() const { return m_doFullRepaint; } +#if ENABLE(REQUEST_ANIMATION_FRAME) + void serviceScriptedAnimations(); +#endif + #if USE(ACCELERATED_COMPOSITING) void updateCompositingLayers(); diff --git a/Source/WebCore/platform/HostWindow.h b/Source/WebCore/platform/HostWindow.h index 7882d48fb4c291bb234f47a8184ce0aaf8f19d5a..45c887b63d658800f937a2f8f3329d18a88fa5c5 100644 --- a/Source/WebCore/platform/HostWindow.h +++ b/Source/WebCore/platform/HostWindow.h @@ -66,6 +66,10 @@ public: // Request that the cursor change. virtual void setCursor(const Cursor&) = 0; + +#if ENABLE(REQUEST_ANIMATION_FRAME) + virtual void scheduleAnimation() = 0; +#endif }; } // namespace WebCore diff --git a/Tools/ChangeLog b/Tools/ChangeLog index e9ccd7a34e09077e4260cc86b73579cb12e6de58..78edce273f784267b88368ea370eee7a19f009b7 100644 --- a/Tools/ChangeLog +++ b/Tools/ChangeLog @@ -1,3 +1,18 @@ +2011-01-11 James Robinson + + Reviewed by NOBODY (OOPS!). + + Implement mozilla's requestAnimationFrame API + https://bugs.webkit.org/show_bug.cgi?id=51218 + + Chromium DumpRenderTree support for window.webkitRequestAnimationFrame. + + * DumpRenderTree/chromium/WebViewHost.cpp: + (invokeScheduleComposite): + (WebViewHost::scheduleAnimation): + (WebViewHost::paintInvalidatedRegion): + * DumpRenderTree/chromium/WebViewHost.h: + 2011-01-11 Eric Seidel Unreviewed. diff --git a/Tools/DumpRenderTree/chromium/WebViewHost.cpp b/Tools/DumpRenderTree/chromium/WebViewHost.cpp index f5dd7fdbc539c14c38f1abafbc6acfae7375fa39..9b1d85aee28539870e4a586d7135a7e540172583 100644 --- a/Tools/DumpRenderTree/chromium/WebViewHost.cpp +++ b/Tools/DumpRenderTree/chromium/WebViewHost.cpp @@ -624,6 +624,19 @@ void WebViewHost::scheduleComposite() didInvalidateRect(clientRect); } +#if ENABLE(REQUEST_ANIMATION_FRAME) +static void invokeScheduleComposite(void* context) +{ + WebViewHost* wvh = static_cast(context); + wvh->scheduleComposite(); +} + +void WebViewHost::scheduleAnimation() +{ + webkit_support::PostDelayedTask(invokeScheduleComposite, this, 0); +} +#endif + void WebViewHost::didFocus() { m_shell->setFocus(webWidget(), true); @@ -1438,6 +1451,9 @@ void WebViewHost::paintRect(const WebRect& rect) void WebViewHost::paintInvalidatedRegion() { +#if ENABLE(REQUEST_ANIMATION_FRAME) + webWidget()->animate(); +#endif webWidget()->layout(); WebSize widgetSize = webWidget()->size(); WebRect clientRect(0, 0, widgetSize.width, widgetSize.height); diff --git a/Tools/DumpRenderTree/chromium/WebViewHost.h b/Tools/DumpRenderTree/chromium/WebViewHost.h index 86c23a5607bd8021852b5b1e9a4ade016dc98e75..373eeac9513141d0448bc0d597fe35bfbb54ee83 100644 --- a/Tools/DumpRenderTree/chromium/WebViewHost.h +++ b/Tools/DumpRenderTree/chromium/WebViewHost.h @@ -147,6 +147,9 @@ class WebViewHost : public WebKit::WebViewClient, public WebKit::WebFrameClient, virtual void didInvalidateRect(const WebKit::WebRect&); virtual void didScrollRect(int dx, int dy, const WebKit::WebRect&); virtual void scheduleComposite(); +#if ENABLE(REQUEST_ANIMATION_FRAME) + virtual void scheduleAnimation(); +#endif virtual void didFocus(); virtual void didBlur(); virtual void didChangeCursor(const WebKit::WebCursorInfo&); diff --git a/WebKit/chromium/ChangeLog b/WebKit/chromium/ChangeLog index 9a4b9ada4a40984aaa2da70c9d674cc277742291..c9f3479127a71f661748151310f844c3d848f01d 100644 --- a/WebKit/chromium/ChangeLog +++ b/WebKit/chromium/ChangeLog @@ -1,3 +1,27 @@ +2011-01-11 James Robinson + + Reviewed by NOBODY (OOPS!). + + Implement mozilla's requestAnimationFrame API + https://bugs.webkit.org/show_bug.cgi?id=51218 + + Chromium WebKit API support for window.webkitRequestAnimationFrame() + + * features.gypi: + * public/WebWidget.h: + * public/WebWidgetClient.h: + (WebKit::WebWidgetClient::scheduleAnimation): + * src/ChromeClientImpl.cpp: + (WebKit::ChromeClientImpl::scheduleAnimation): + * src/ChromeClientImpl.h: + * src/WebPopupMenuImpl.cpp: + (WebKit::WebPopupMenuImpl::animate): + (WebKit::WebPopupMenuImpl::scheduleAnimation): + * src/WebPopupMenuImpl.h: + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::animate): + * src/WebViewImpl.h: + 2011-01-11 Pavel Feldman Reviewed by Yury Semikhatsky. diff --git a/WebKit/chromium/features.gypi b/WebKit/chromium/features.gypi index 372cc5c504009f12313b17e98bc2847aa25793cd..7f4cda6193f08970ac0b1cc3ed315e921d6774c1 100644 --- a/WebKit/chromium/features.gypi +++ b/WebKit/chromium/features.gypi @@ -69,6 +69,7 @@ 'ENABLE_OPENTYPE_SANITIZER=1', 'ENABLE_ORIENTATION_EVENTS=0', 'ENABLE_PROGRESS_TAG=1', + 'ENABLE_REQUEST_ANIMATION_FRAME=1', 'ENABLE_SHARED_WORKERS=1', 'ENABLE_SVG=1', 'ENABLE_SVG_ANIMATION=1', diff --git a/WebKit/chromium/public/WebWidget.h b/WebKit/chromium/public/WebWidget.h index ccad134f634e84f3fc0b9c644e660fc680f3ef12..36fbf313ad17464c41d8d927cb2132adab6ae881 100644 --- a/WebKit/chromium/public/WebWidget.h +++ b/WebKit/chromium/public/WebWidget.h @@ -56,6 +56,10 @@ public: // Called to resize the WebWidget. virtual void resize(const WebSize&) = 0; + // Called to update imperative animation state. This should be called before + // paint, although the client can rate-limit these calls. + virtual void animate() = 0; + // Called to layout the WebWidget. This MUST be called before Paint, // and it may result in calls to WebWidgetClient::didInvalidateRect. virtual void layout() = 0; diff --git a/WebKit/chromium/public/WebWidgetClient.h b/WebKit/chromium/public/WebWidgetClient.h index 373426df4f68c713913f9e728ce9900de663c7ac..85e4015a71e7e7ba9ecd620787039bd6e8364b33 100644 --- a/WebKit/chromium/public/WebWidgetClient.h +++ b/WebKit/chromium/public/WebWidgetClient.h @@ -56,6 +56,9 @@ public: // Called when a call to WebWidget::composite is required virtual void scheduleComposite() { } + // Called when a call to WebWidget::animate is required + virtual void scheduleAnimation() { } + // Called when the widget acquires or loses focus, respectively. virtual void didFocus() { } virtual void didBlur() { } diff --git a/WebKit/chromium/src/ChromeClientImpl.cpp b/WebKit/chromium/src/ChromeClientImpl.cpp index 1a984c12f389b3d1f6f2d4ea24cc1e5eb9cb2a08..10d184f32ba1ac1a20ba0b6d9df019a222d2d044 100644 --- a/WebKit/chromium/src/ChromeClientImpl.cpp +++ b/WebKit/chromium/src/ChromeClientImpl.cpp @@ -532,6 +532,13 @@ void ChromeClientImpl::invalidateContentsForSlowScroll(const IntRect& updateRect invalidateContentsAndWindow(updateRect, immediate); } +#if ENABLE(REQUEST_ANIMATION_FRAME) +void ChromeClientImpl::scheduleAnimation() +{ + m_webView->client()->scheduleAnimation(); +} +#endif + void ChromeClientImpl::scroll( const IntSize& scrollDelta, const IntRect& scrollRect, const IntRect& clipRect) diff --git a/WebKit/chromium/src/ChromeClientImpl.h b/WebKit/chromium/src/ChromeClientImpl.h index b024bc01ecc9024bcdcb5051288a32b37222041e..57feb92e1fc80d66dd3b95de23129242fd1c8cbe 100644 --- a/WebKit/chromium/src/ChromeClientImpl.h +++ b/WebKit/chromium/src/ChromeClientImpl.h @@ -105,6 +105,9 @@ public: virtual void invalidateWindow(const WebCore::IntRect&, bool); virtual void invalidateContentsAndWindow(const WebCore::IntRect&, bool); virtual void invalidateContentsForSlowScroll(const WebCore::IntRect&, bool); +#if ENABLE(REQUEST_ANIMATION_FRAME) + virtual void scheduleAnimation(); +#endif virtual void scroll( const WebCore::IntSize& scrollDelta, const WebCore::IntRect& rectToScroll, const WebCore::IntRect& clipRect); diff --git a/WebKit/chromium/src/WebPopupMenuImpl.cpp b/WebKit/chromium/src/WebPopupMenuImpl.cpp index 63ebed809befb04e80f643136fbd31d7e8c69271..a209e6a2a88660c12eb36fd1260a903812bfaa7f 100644 --- a/WebKit/chromium/src/WebPopupMenuImpl.cpp +++ b/WebKit/chromium/src/WebPopupMenuImpl.cpp @@ -151,6 +151,10 @@ void WebPopupMenuImpl::resize(const WebSize& newSize) } } +void WebPopupMenuImpl::animate() +{ +} + void WebPopupMenuImpl::layout() { } @@ -299,6 +303,10 @@ void WebPopupMenuImpl::invalidateContentsForSlowScroll(const IntRect& updateRect invalidateContentsAndWindow(updateRect, immediate); } +void WebPopupMenuImpl::scheduleAnimation() +{ +} + void WebPopupMenuImpl::scroll(const IntSize& scrollDelta, const IntRect& scrollRect, const IntRect& clipRect) diff --git a/WebKit/chromium/src/WebPopupMenuImpl.h b/WebKit/chromium/src/WebPopupMenuImpl.h index b8ef7ba8e4b99fee904b8fb6793d6e6629e2ab49..9bf14d5904acdbd84f71477c145c5cf069ccfee8 100644 --- a/WebKit/chromium/src/WebPopupMenuImpl.h +++ b/WebKit/chromium/src/WebPopupMenuImpl.h @@ -61,6 +61,7 @@ public: virtual void close(); virtual WebSize size() { return m_size; } virtual void resize(const WebSize&); + virtual void animate(); virtual void layout(); virtual void paint(WebCanvas* canvas, const WebRect& rect); virtual void themeChanged(); @@ -105,6 +106,7 @@ public: virtual void invalidateWindow(const WebCore::IntRect&, bool); virtual void invalidateContentsAndWindow(const WebCore::IntRect&, bool); virtual void invalidateContentsForSlowScroll(const WebCore::IntRect&, bool); + virtual void scheduleAnimation(); virtual void scroll( const WebCore::IntSize& scrollDelta, const WebCore::IntRect& scrollRect, const WebCore::IntRect& clipRect); diff --git a/WebKit/chromium/src/WebViewImpl.cpp b/WebKit/chromium/src/WebViewImpl.cpp index 44efeea62a24b284176a7f61cb94ec86263e48f0..6851381af3d0e5c93ea1f6c758a103f489c5d650 100644 --- a/WebKit/chromium/src/WebViewImpl.cpp +++ b/WebKit/chromium/src/WebViewImpl.cpp @@ -973,6 +973,18 @@ void WebViewImpl::resize(const WebSize& newSize) #endif } +void WebViewImpl::animate() +{ +#if ENABLE(REQUEST_ANIMATION_FRAME) + WebFrameImpl* webframe = mainFrameImpl(); + if (webframe) { + FrameView* view = webframe->frameView(); + if (view) + view->serviceScriptedAnimations(); + } +#endif +} + void WebViewImpl::layout() { WebFrameImpl* webframe = mainFrameImpl(); diff --git a/WebKit/chromium/src/WebViewImpl.h b/WebKit/chromium/src/WebViewImpl.h index c9ecc16cca0c06301a09cd4070a3820ac618e84c..ed782923857e4ee3c8ff9835651197836a3c3f75 100644 --- a/WebKit/chromium/src/WebViewImpl.h +++ b/WebKit/chromium/src/WebViewImpl.h @@ -92,6 +92,7 @@ public: virtual void close(); virtual WebSize size() { return m_size; } virtual void resize(const WebSize&); + virtual void animate(); virtual void layout(); virtual void paint(WebCanvas*, const WebRect&); virtual void themeChanged();