Title: [209675] trunk
Revision
209675
Author
simon.fra...@apple.com
Date
2016-12-10 14:29:24 -0800 (Sat, 10 Dec 2016)

Log Message

Animation followed by transition doesn't always fire transitionend event
https://bugs.webkit.org/show_bug.cgi?id=165731
rdar://problem/28471240

Reviewed by Zalan Bujtas.
Source/WebCore:

After r200047, a keyframe animation of an accelerated property followed by a
transition didn't always fire a transitionend event.

This happened if CompositeAnimation::timeToNextService() happend to be called
when the transitions's timeToNextService() returned a positive value, but the
keyframe animation still existed, but its timeToNextService() returned -1. In
this case that -1 would clobber the positing minT.

Fix by just continuing in each loop when the timeToNextService() returns -1.

This code should probably be rewritten to use std::optional<double> rather than
magic values.

Test: animations/animation-followed-by-transition.html

* page/animation/CompositeAnimation.cpp:
(WebCore::CompositeAnimation::timeToNextService):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::addAnimation):
(WebCore::GraphicsLayerCA::pauseAnimation):
(WebCore::GraphicsLayerCA::removeAnimation):
(WebCore::GraphicsLayerCA::platformCALayerAnimationStarted):
(WebCore::GraphicsLayerCA::platformCALayerAnimationEnded):

LayoutTests:

* animations/animation-followed-by-transition-expected.txt: Added.
* animations/animation-followed-by-transition.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (209674 => 209675)


--- trunk/LayoutTests/ChangeLog	2016-12-10 22:13:58 UTC (rev 209674)
+++ trunk/LayoutTests/ChangeLog	2016-12-10 22:29:24 UTC (rev 209675)
@@ -1,3 +1,14 @@
+2016-12-10  Simon Fraser  <simon.fra...@apple.com>
+
+        Animation followed by transition doesn't always fire transitionend event
+        https://bugs.webkit.org/show_bug.cgi?id=165731
+        rdar://problem/28471240
+
+        Reviewed by Zalan Bujtas.
+
+        * animations/animation-followed-by-transition-expected.txt: Added.
+        * animations/animation-followed-by-transition.html: Added.
+
 2016-12-09  Sam Weinig  <s...@webkit.org>
 
         [WebIDL] Remove custom bindings for Geolocation

Added: trunk/LayoutTests/animations/animation-followed-by-transition-expected.txt (0 => 209675)


--- trunk/LayoutTests/animations/animation-followed-by-transition-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/animations/animation-followed-by-transition-expected.txt	2016-12-10 22:29:24 UTC (rev 209675)
@@ -0,0 +1,5 @@
+Should see animationend followed by transitionend.
+
+animationend
+transitionend
+

Added: trunk/LayoutTests/animations/animation-followed-by-transition.html (0 => 209675)


--- trunk/LayoutTests/animations/animation-followed-by-transition.html	                        (rev 0)
+++ trunk/LayoutTests/animations/animation-followed-by-transition.html	2016-12-10 22:29:24 UTC (rev 209675)
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        #test {
+            position: absolute;
+            top: 100px;
+            left: 100px;
+            height: 100px;
+            width: 100px;
+            background: green;
+            transition: transform 40ms;
+            transform: translate3d(0,0,0);
+            animation: slideInUp 50ms;
+        }
+
+        #test.trans {
+            transform: translateX(200%);
+        }
+
+        @keyframes slideInUp {
+            0% { 
+                transform: translate3d(-100%, 0, 0);
+            }
+            100% {
+                transform: translate3d(0, 0, 0);
+            }
+        }
+    </style>
+</head>
+<body>
+    <div id="test"></div>
+<p>Should see animationend followed by transitionend.</p>
+<pre id="logging"></pre>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function doLog(s)
+        {
+            document.getElementById('logging').textContent += s + '\n';
+        }
+        
+        var testDiv = document.getElementById('test');
+        testDiv.addEventListener("transitionend", function() {
+            doLog("transitionend");
+            if (window.testRunner)
+                testRunner.notifyDone();
+        });
+
+        testDiv.addEventListener("animationend", function() {
+            doLog("animationend");
+            window.setTimeout(function() {
+                testDiv.classList.add('trans');
+            }, 0)
+
+            // Watchdog timer.
+            window.setTimeout(function() {
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            }, 500)
+        });
+    </script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (209674 => 209675)


--- trunk/Source/WebCore/ChangeLog	2016-12-10 22:13:58 UTC (rev 209674)
+++ trunk/Source/WebCore/ChangeLog	2016-12-10 22:29:24 UTC (rev 209675)
@@ -1,3 +1,35 @@
+2016-12-10  Simon Fraser  <simon.fra...@apple.com>
+
+        Animation followed by transition doesn't always fire transitionend event
+        https://bugs.webkit.org/show_bug.cgi?id=165731
+        rdar://problem/28471240
+
+        Reviewed by Zalan Bujtas.
+        
+        After r200047, a keyframe animation of an accelerated property followed by a
+        transition didn't always fire a transitionend event.
+        
+        This happened if CompositeAnimation::timeToNextService() happend to be called
+        when the transitions's timeToNextService() returned a positive value, but the
+        keyframe animation still existed, but its timeToNextService() returned -1. In
+        this case that -1 would clobber the positing minT.
+
+        Fix by just continuing in each loop when the timeToNextService() returns -1.
+
+        This code should probably be rewritten to use std::optional<double> rather than
+        magic values.
+
+        Test: animations/animation-followed-by-transition.html
+
+        * page/animation/CompositeAnimation.cpp:
+        (WebCore::CompositeAnimation::timeToNextService):
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::addAnimation):
+        (WebCore::GraphicsLayerCA::pauseAnimation):
+        (WebCore::GraphicsLayerCA::removeAnimation):
+        (WebCore::GraphicsLayerCA::platformCALayerAnimationStarted):
+        (WebCore::GraphicsLayerCA::platformCALayerAnimationEnded):
+
 2016-12-10  Sam Weinig  <s...@webkit.org>
 
         [WebIDL] Merge JSDictionary into Dictionary, and remove unused bits

Modified: trunk/Source/WebCore/page/animation/CompositeAnimation.cpp (209674 => 209675)


--- trunk/Source/WebCore/page/animation/CompositeAnimation.cpp	2016-12-10 22:13:58 UTC (rev 209674)
+++ trunk/Source/WebCore/page/animation/CompositeAnimation.cpp	2016-12-10 22:29:24 UTC (rev 209675)
@@ -375,6 +375,8 @@
     if (!m_transitions.isEmpty()) {
         for (auto& transition : m_transitions.values()) {
             double t = transition->timeToNextService();
+            if (t == -1)
+                continue;
             if (t < minT || minT == -1)
                 minT = t;
             if (minT == 0)
@@ -385,6 +387,8 @@
         m_keyframeAnimations.checkConsistency();
         for (auto& animation : m_keyframeAnimations.values()) {
             double t = animation->timeToNextService();
+            if (t == -1)
+                continue;
             if (t < minT || minT == -1)
                 minT = t;
             if (minT == 0)

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (209674 => 209675)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2016-12-10 22:13:58 UTC (rev 209674)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2016-12-10 22:29:24 UTC (rev 209675)
@@ -936,6 +936,8 @@
 
 bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& animationName, double timeOffset)
 {
+    LOG(Animations, "GraphicsLayerCA %p addAnimation %s (can be accelerated %d)", this, animationName.utf8().data(), animationCanBeAccelerated(valueList, anim));
+
     ASSERT(!animationName.isEmpty());
 
     if (!animationCanBeAccelerated(valueList, anim))
@@ -965,6 +967,8 @@
 
 void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset)
 {
+    LOG(Animations, "GraphicsLayerCA %p pauseAnimation %s (running %d)", this, animationName.utf8().data(), animationIsRunning(animationName));
+
     if (!animationIsRunning(animationName))
         return;
 
@@ -982,6 +986,8 @@
 
 void GraphicsLayerCA::removeAnimation(const String& animationName)
 {
+    LOG(Animations, "GraphicsLayerCA %p removeAnimation %s (running %d)", this, animationName.utf8().data(), animationIsRunning(animationName));
+
     if (!animationIsRunning(animationName))
         return;
 
@@ -991,11 +997,13 @@
 
 void GraphicsLayerCA::platformCALayerAnimationStarted(const String& animationKey, CFTimeInterval startTime)
 {
+    LOG(Animations, "GraphicsLayerCA %p platformCALayerAnimationStarted %s at %f", this, animationKey.utf8().data(), startTime);
     client().notifyAnimationStarted(this, animationKey, startTime);
 }
 
 void GraphicsLayerCA::platformCALayerAnimationEnded(const String& animationKey)
 {
+    LOG(Animations, "GraphicsLayerCA %p platformCALayerAnimationEnded %s", this, animationKey.utf8().data());
     client().notifyAnimationEnded(this, animationKey);
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to