Title: [238759] trunk
Revision
238759
Author
[email protected]
Date
2018-11-30 16:08:50 -0800 (Fri, 30 Nov 2018)

Log Message

Can’t use RalphLauren.com on iPad because hover menus don’t stay up
https://bugs.webkit.org/show_bug.cgi?id=192236
<rdar://problem/45792118>

Reviewed by Geoffrey Garen.

Source/WebCore:

This patch introduces asynchronous content change observation.
1. Start observing synchronous content change and timer install as the result of dispatching mouseMoved event.
2. Start observing synchronous content change and style recalc schedule as the result of a timer callback (installed at #1).
3. Start observing synchronous content change as the result of a style recalc (scheduled at #2).

This patch also extends the timeout value from 100ms to 250ms. Certain content prefer longer timeouts (see http://briancherne.github.io/jquery-hoverIntent/ for details).

Test: fast/events/touch/ios/hover-when-style-change-is-async.html

* dom/Document.cpp:
(WebCore::Document::scheduleStyleRecalc):
(WebCore::Document::updateStyleIfNeeded):
* page/DOMTimer.cpp:
(WebCore::DOMTimer::install):
(WebCore::DOMTimer::fired):
* platform/ios/wak/WKContentObservation.cpp:
(WKStartObservingStyleRecalcScheduling):
(WKStopObservingStyleRecalcScheduling):
(WKIsObservingStyleRecalcScheduling):
(WKSetShouldObserveNextStyleRecalc):
(WKShouldObserveNextStyleRecalc):
(WKSetObservedContentChange):
* platform/ios/wak/WKContentObservation.h:

LayoutTests:

* fast/events/touch/ios/hover-when-style-change-is-async-expected.txt: Added.
* fast/events/touch/ios/hover-when-style-change-is-async.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (238758 => 238759)


--- trunk/LayoutTests/ChangeLog	2018-11-30 23:33:39 UTC (rev 238758)
+++ trunk/LayoutTests/ChangeLog	2018-12-01 00:08:50 UTC (rev 238759)
@@ -1,3 +1,14 @@
+2018-11-30  Zalan Bujtas  <[email protected]>
+
+        Can’t use RalphLauren.com on iPad because hover menus don’t stay up
+        https://bugs.webkit.org/show_bug.cgi?id=192236
+        <rdar://problem/45792118>
+
+        Reviewed by Geoffrey Garen.
+
+        * fast/events/touch/ios/hover-when-style-change-is-async-expected.txt: Added.
+        * fast/events/touch/ios/hover-when-style-change-is-async.html: Added.
+
 2018-11-30  Ryosuke Niwa  <[email protected]>
 
         ShadowRoot should have styleSheets property

Added: trunk/LayoutTests/fast/events/touch/ios/hover-when-style-change-is-async-expected.txt (0 => 238759)


--- trunk/LayoutTests/fast/events/touch/ios/hover-when-style-change-is-async-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/hover-when-style-change-is-async-expected.txt	2018-12-01 00:08:50 UTC (rev 238759)
@@ -0,0 +1,2 @@
+PASS if no 'clicked' text is shown below.
+

Added: trunk/LayoutTests/fast/events/touch/ios/hover-when-style-change-is-async.html (0 => 238759)


--- trunk/LayoutTests/fast/events/touch/ios/hover-when-style-change-is-async.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/hover-when-style-change-is-async.html	2018-12-01 00:08:50 UTC (rev 238759)
@@ -0,0 +1,63 @@
+<html>
+<head>
+<title>This test that we trigger hover when the content change is async.</title>
+<script src=""
+<style>
+#tapthis {
+    width: 400px;
+    height: 400px;
+    border: 1px solid green;
+}
+
+#hiddenFirst {
+    visibility: hidden;
+    width: 100px;
+    height: 100px;
+    background-color: green;
+}
+</style>
+<script>
+async function test() {
+    if (!window.testRunner || !testRunner.runUIScript)
+        return;
+
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+
+    let rect = tapthis.getBoundingClientRect();
+    let x = rect.left + rect.width / 2;
+    let y = rect.top + rect.height / 2;
+
+    await tapAtPoint(x, y);
+}
+</script>
+</head>
+<body _onload_="test()">
+<div id=tapthis>PASS if no 'clicked' text is shown below.</div>
+<div id=hiddenFirst></div>
+<pre id=result></pre>
+<script>
+tapthis.addEventListener("mouseover", function( event ) {
+    // 1. Install a timer on hover
+    setTimeout(function() {
+        // 2. Trigger a non-forcing style change
+        hiddenFirst.style.visibility = "visible";
+        // 3. Install a timer for style recalc
+        setTimeout(function() {
+            document.body.offsetHeight;
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }, 10);
+    }, 0);
+}, false);
+
+hiddenFirst.addEventListener("click", function( event ) {   
+    result.innerHTML = "clicked";
+}, false);
+
+tapthis.addEventListener("click", function( event ) {   
+    result.innerHTML = "clicked";
+}, false);
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (238758 => 238759)


--- trunk/Source/WebCore/ChangeLog	2018-11-30 23:33:39 UTC (rev 238758)
+++ trunk/Source/WebCore/ChangeLog	2018-12-01 00:08:50 UTC (rev 238759)
@@ -1,3 +1,35 @@
+2018-11-30  Zalan Bujtas  <[email protected]>
+
+        Can’t use RalphLauren.com on iPad because hover menus don’t stay up
+        https://bugs.webkit.org/show_bug.cgi?id=192236
+        <rdar://problem/45792118>
+
+        Reviewed by Geoffrey Garen.
+
+        This patch introduces asynchronous content change observation.
+        1. Start observing synchronous content change and timer install as the result of dispatching mouseMoved event.
+        2. Start observing synchronous content change and style recalc schedule as the result of a timer callback (installed at #1).
+        3. Start observing synchronous content change as the result of a style recalc (scheduled at #2).
+
+        This patch also extends the timeout value from 100ms to 250ms. Certain content prefer longer timeouts (see http://briancherne.github.io/jquery-hoverIntent/ for details).  
+
+        Test: fast/events/touch/ios/hover-when-style-change-is-async.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::scheduleStyleRecalc):
+        (WebCore::Document::updateStyleIfNeeded):
+        * page/DOMTimer.cpp:
+        (WebCore::DOMTimer::install):
+        (WebCore::DOMTimer::fired):
+        * platform/ios/wak/WKContentObservation.cpp:
+        (WKStartObservingStyleRecalcScheduling):
+        (WKStopObservingStyleRecalcScheduling):
+        (WKIsObservingStyleRecalcScheduling):
+        (WKSetShouldObserveNextStyleRecalc):
+        (WKShouldObserveNextStyleRecalc):
+        (WKSetObservedContentChange):
+        * platform/ios/wak/WKContentObservation.h:
+
 2018-11-30  Ryosuke Niwa  <[email protected]>
 
         ShadowRoot should have styleSheets property

Modified: trunk/Source/WebCore/dom/Document.cpp (238758 => 238759)


--- trunk/Source/WebCore/dom/Document.cpp	2018-11-30 23:33:39 UTC (rev 238758)
+++ trunk/Source/WebCore/dom/Document.cpp	2018-12-01 00:08:50 UTC (rev 238759)
@@ -264,6 +264,7 @@
 #include "Navigator.h"
 #include "NavigatorGeolocation.h"
 #include "WKContentObservation.h"
+#include "WKContentObservationInternal.h"
 #endif
 
 #if ENABLE(IOS_GESTURE_EVENTS)
@@ -1794,6 +1795,11 @@
 
     ASSERT(childNeedsStyleRecalc() || m_pendingStyleRecalcShouldForce);
 
+#if PLATFORM(IOS_FAMILY)
+    if (WKIsObservingStyleRecalcScheduling())
+        WKSetObservedContentChange(WKContentIndeterminateChange);
+#endif
+
     // FIXME: Why on earth is this here? This is clearly misplaced.
     invalidateAccessKeyMap();
 
@@ -2028,10 +2034,29 @@
             return false;
     }
 
+#if PLATFORM(IOS_FAMILY)
+    auto observingContentChange = WKShouldObserveNextStyleRecalc();
+    if (observingContentChange) {
+        WKSetShouldObserveNextStyleRecalc(false);
+        WKStartObservingContentChanges();
+    }
+#endif
     // The early exit above for !needsStyleRecalc() is needed when updateWidgetPositions() is called in runOrScheduleAsynchronousTasks().
     RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(isSafeToUpdateStyleOrLayout(*this));
 
     resolveStyle();
+
+#if PLATFORM(IOS_FAMILY)
+    if (observingContentChange) {
+        WKStopObservingContentChanges();
+
+        auto inDeterminedState = WKObservedContentChange() == WKContentVisibilityChange || !WebThreadCountOfObservedDOMTimers();  
+        if (inDeterminedState) {
+            if (auto* page = this->page())
+                page->chrome().client().observedContentChange(*frame());
+        }
+    }
+#endif
     return true;
 }
 

Modified: trunk/Source/WebCore/page/DOMTimer.cpp (238758 => 238759)


--- trunk/Source/WebCore/page/DOMTimer.cpp	2018-11-30 23:33:39 UTC (rev 238758)
+++ trunk/Source/WebCore/page/DOMTimer.cpp	2018-12-01 00:08:50 UTC (rev 238759)
@@ -222,7 +222,7 @@
 #if PLATFORM(IOS_FAMILY)
     if (WKIsObservingDOMTimerScheduling() && is<Document>(context)) {
         bool didDeferTimeout = context.activeDOMObjectsAreSuspended();
-        if (!didDeferTimeout && timeout <= 100_ms && singleShot) {
+        if (!didDeferTimeout && timeout <= 250_ms && singleShot) {
             WKSetObservedContentChange(WKContentIndeterminateChange);
             WebThreadAddObservedDOMTimer(timer);
         }
@@ -341,18 +341,16 @@
     context.removeTimeout(m_timeoutId);
 
 #if PLATFORM(IOS_FAMILY)
-    bool shouldReportLackOfChanges;
-    bool shouldBeginObservingChanges;
+    auto isObversingLastTimer = false;
+    auto shouldBeginObservingChanges = false;
     if (is<Document>(context)) {
-        shouldReportLackOfChanges = WebThreadCountOfObservedDOMTimers() == 1;
+        isObversingLastTimer = WebThreadCountOfObservedDOMTimers() == 1;
         shouldBeginObservingChanges = WebThreadContainsObservedDOMTimer(this);
-    } else {
-        shouldReportLackOfChanges = false;
-        shouldBeginObservingChanges = false;
     }
 
     if (shouldBeginObservingChanges) {
         WKStartObservingContentChanges();
+        WKStartObservingStyleRecalcScheduling();
         WebThreadRemoveObservedDOMTimer(this);
     }
 #endif
@@ -366,12 +364,19 @@
 
 #if PLATFORM(IOS_FAMILY)
     if (shouldBeginObservingChanges) {
+        WKStopObservingStyleRecalcScheduling();
         WKStopObservingContentChanges();
 
-        if (WKObservedContentChange() == WKContentVisibilityChange || shouldReportLackOfChanges) {
-            Document& document = downcast<Document>(context);
-            if (Page* page = document.page())
+        auto observedContentChange = WKObservedContentChange();
+        // Check if the timer callback triggered either a sync or async style update.
+        auto inDeterminedState = observedContentChange == WKContentVisibilityChange || (isObversingLastTimer && observedContentChange == WKContentNoChange);  
+        if (inDeterminedState) {
+            auto& document = downcast<Document>(context);
+            if (auto* page = document.page())
                 page->chrome().client().observedContentChange(*document.frame());
+        } else if (observedContentChange == WKContentIndeterminateChange) {
+            // An async style recalc has been scheduled. Let's observe it.
+            WKSetShouldObserveNextStyleRecalc(true);
         }
     }
 #endif

Modified: trunk/Source/WebCore/platform/ios/wak/WKContentObservation.cpp (238758 => 238759)


--- trunk/Source/WebCore/platform/ios/wak/WKContentObservation.cpp	2018-11-30 23:33:39 UTC (rev 238758)
+++ trunk/Source/WebCore/platform/ios/wak/WKContentObservation.cpp	2018-12-01 00:08:50 UTC (rev 238759)
@@ -37,8 +37,9 @@
 WKContentChange _WKContentChange                    = WKContentNoChange;
 bool            _WKObservingContentChanges          = false;
 bool            _WKObservingDOMTimerScheduling      = false;
+bool            _WKObservingStyleRecalScheduling    = false;
+bool            _WKObservingNextStyleRecalc         = false;
 
-
 bool WKObservingContentChanges(void)
 {
     return _WKObservingContentChanges;
@@ -71,6 +72,31 @@
     return _WKObservingDOMTimerScheduling;
 }
 
+void WKStartObservingStyleRecalcScheduling(void)
+{
+    _WKObservingStyleRecalScheduling = true;
+}
+
+void WKStopObservingStyleRecalcScheduling(void)
+{
+    _WKObservingStyleRecalScheduling = false;
+}
+
+bool WKIsObservingStyleRecalcScheduling(void)
+{
+    return _WKObservingStyleRecalScheduling;
+}
+
+void WKSetShouldObserveNextStyleRecalc(bool observe)
+{
+    _WKObservingNextStyleRecalc = observe;
+}
+
+bool WKShouldObserveNextStyleRecalc(void)
+{
+    return _WKObservingNextStyleRecalc;
+}
+
 WKContentChange WKObservedContentChange(void)
 {
     return _WKContentChange;
@@ -84,8 +110,9 @@
 
     if (change == WKContentVisibilityChange) {
         _WKContentChange = change;
-        // Don't need to listen to DOM timers anymore.
+        // Don't need to listen to DOM timers/style recalcs anymore.
         WebThreadClearObservedDOMTimers();
+        _WKObservingNextStyleRecalc = false;
         return;
     }
 

Modified: trunk/Source/WebCore/platform/ios/wak/WKContentObservation.h (238758 => 238759)


--- trunk/Source/WebCore/platform/ios/wak/WKContentObservation.h	2018-11-30 23:33:39 UTC (rev 238758)
+++ trunk/Source/WebCore/platform/ios/wak/WKContentObservation.h	2018-12-01 00:08:50 UTC (rev 238759)
@@ -46,6 +46,13 @@
 WEBCORE_EXPORT void WKStopObservingDOMTimerScheduling(void);
 WEBCORE_EXPORT bool WKIsObservingDOMTimerScheduling(void);
 
+WEBCORE_EXPORT void WKStartObservingStyleRecalcScheduling(void);
+WEBCORE_EXPORT void WKStopObservingStyleRecalcScheduling(void);
+WEBCORE_EXPORT bool WKIsObservingStyleRecalcScheduling(void);
+
+WEBCORE_EXPORT void WKSetShouldObserveNextStyleRecalc(bool);
+WEBCORE_EXPORT bool WKShouldObserveNextStyleRecalc(void);
+
 WEBCORE_EXPORT WKContentChange WKObservedContentChange(void);
 
 WEBCORE_EXPORT int WebThreadCountOfObservedDOMTimers(void);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to