[Wheel event region] Invalidation for root style
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 May 2020 17:50:11 +0000 (17:50 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 May 2020 17:50:11 +0000 (17:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=212029

Reviewed by Simon Fraser.

Source/WebCore:

Test: fast/scrolling/mac/wheel-event-listener-region-root-invalidation.html

Invalidate the region when event listeners change on Document or Window.

* dom/Document.cpp:
(WebCore::Document::invalidateEventListenerRegions):
* dom/Document.h:
(isType):
* dom/Element.cpp:
(WebCore::Element::invalidateEventListenerRegions):
* dom/Element.h:
* dom/EventTarget.cpp:
(WebCore::EventTarget::addEventListener):
(WebCore::EventTarget::removeEventListener):
(WebCore::EventTarget::removeAllEventListeners):
(WebCore::EventTarget::invalidateEventListenerRegions):
* dom/EventTarget.h:
* style/StyleAdjuster.cpp:
(WebCore::Style::Adjuster::adjustEventListenerRegionTypesForRootStyle):
* style/StyleAdjuster.h:
* style/StyleResolveForDocument.cpp:
(WebCore::Style::resolveForDocument):

LayoutTests:

* fast/scrolling/mac/wheel-event-listener-region-root-invalidation-expected.txt: Added.
* fast/scrolling/mac/wheel-event-listener-region-root-invalidation.html: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@261820 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/scrolling/mac/wheel-event-listener-region-root-invalidation-expected.txt [new file with mode: 0644]
LayoutTests/fast/scrolling/mac/wheel-event-listener-region-root-invalidation.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Element.h
Source/WebCore/dom/EventTarget.cpp
Source/WebCore/dom/EventTarget.h
Source/WebCore/style/StyleAdjuster.cpp
Source/WebCore/style/StyleAdjuster.h
Source/WebCore/style/StyleResolveForDocument.cpp

index 154bdf9..f766dc9 100644 (file)
@@ -1,3 +1,13 @@
+2020-05-18  Antti Koivisto  <antti@apple.com>
+
+        [Wheel event region] Invalidation for root style
+        https://bugs.webkit.org/show_bug.cgi?id=212029
+
+        Reviewed by Simon Fraser.
+
+        * fast/scrolling/mac/wheel-event-listener-region-root-invalidation-expected.txt: Added.
+        * fast/scrolling/mac/wheel-event-listener-region-root-invalidation.html: Added.
+
 2020-05-18  Simon Fraser  <simon.fraser@apple.com>
 
         Find doesn't always scroll search results into view
diff --git a/LayoutTests/fast/scrolling/mac/wheel-event-listener-region-root-invalidation-expected.txt b/LayoutTests/fast/scrolling/mac/wheel-event-listener-region-root-invalidation-expected.txt
new file mode 100644 (file)
index 0000000..2a4e3a0
--- /dev/null
@@ -0,0 +1,40 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 600.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (contentsOpaque 1)
+      (drawsContent 1)
+      (backgroundColor #FFFFFF)
+      (event region
+        (rect (0,0) width=800 height=600)
+      (wheel event listener region
+        (rect (0,0) width=800 height=600)
+        (non-passive
+          (rect (0,0) width=800 height=600)
+        )
+      )
+      )
+    )
+  )
+)
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 600.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (contentsOpaque 1)
+      (drawsContent 1)
+      (backgroundColor #FFFFFF)
+      (event region
+        (rect (0,0) width=800 height=600)
+      (wheel event listener region
+        (rect (0,0) width=800 height=600)
+      )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/fast/scrolling/mac/wheel-event-listener-region-root-invalidation.html b/LayoutTests/fast/scrolling/mac/wheel-event-listener-region-root-invalidation.html
new file mode 100644 (file)
index 0000000..a2c525a
--- /dev/null
@@ -0,0 +1,56 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:AsyncOverflowScrollingEnabled=true ] -->
+<html>
+<style>
+.event {
+    position:relative;
+    background-color:blue;
+    width:200px;
+    height:200px;
+}
+.child {
+    position:relative;
+    background-color:blue;
+    left:200px;
+    width:50px;
+    height:50px;
+}
+.offset {
+    left: 200px;
+}
+
+</style>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+
+window.onload = () => {
+    document.body.offsetLeft;
+
+    function listener() {
+        results.textContent += 'wheel\n';
+    }
+    window.addEventListener("wheel", listener);
+
+    let log = "";
+    if (window.internals)
+        log += internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+
+    window.removeEventListener('wheel', listener);
+    document.addEventListener('wheel', () => { results.textContent += 'passive wheel\n' }, { passive: true });
+
+    if (window.internals)
+        log += internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+
+    results.textContent = log;
+}
+</script>
+<body>
+<div class="event" id="active">
+    <div class="child"></div>
+</div>
+<div class="event offset" id="passive">
+    <div class="child"></div>
+</div>
+<pre id="results"></pre>
+</body>
+</html>
index 5bfaedc..5104884 100644 (file)
@@ -1,3 +1,33 @@
+2020-05-18  Antti Koivisto  <antti@apple.com>
+
+        [Wheel event region] Invalidation for root style
+        https://bugs.webkit.org/show_bug.cgi?id=212029
+
+        Reviewed by Simon Fraser.
+
+        Test: fast/scrolling/mac/wheel-event-listener-region-root-invalidation.html
+
+        Invalidate the region when event listeners change on Document or Window.
+
+        * dom/Document.cpp:
+        (WebCore::Document::invalidateEventListenerRegions):
+        * dom/Document.h:
+        (isType):
+        * dom/Element.cpp:
+        (WebCore::Element::invalidateEventListenerRegions):
+        * dom/Element.h:
+        * dom/EventTarget.cpp:
+        (WebCore::EventTarget::addEventListener):
+        (WebCore::EventTarget::removeEventListener):
+        (WebCore::EventTarget::removeAllEventListeners):
+        (WebCore::EventTarget::invalidateEventListenerRegions):
+        * dom/EventTarget.h:
+        * style/StyleAdjuster.cpp:
+        (WebCore::Style::Adjuster::adjustEventListenerRegionTypesForRootStyle):
+        * style/StyleAdjuster.h:
+        * style/StyleResolveForDocument.cpp:
+        (WebCore::Style::resolveForDocument):
+
 2020-05-18  Simon Fraser  <simon.fraser@apple.com>
 
         Find doesn't always scroll search results into view
index bef4869..cb38db2 100644 (file)
 #include "SocketProvider.h"
 #include "StorageEvent.h"
 #include "StringCallback.h"
+#include "StyleAdjuster.h"
 #include "StyleColor.h"
 #include "StyleProperties.h"
 #include "StyleResolveForDocument.h"
@@ -4272,6 +4273,19 @@ void Document::invalidateEventRegionsForFrame(HTMLFrameOwnerElement& element)
         ownerElement->document().invalidateEventRegionsForFrame(*ownerElement);
 }
 
+void Document::invalidateEventListenerRegions()
+{
+    if (!renderView() || !documentElement())
+        return;
+
+    // We don't track style validity for Document and full rebuild is too big of a hammer.
+    // Instead just mutate the style directly and trigger a minimal style update.
+    auto& rootStyle = renderView()->mutableStyle();
+    Style::Adjuster::adjustEventListenerRegionTypesForRootStyle(rootStyle, *this);
+
+    documentElement()->invalidateStyleInternal();
+}
+
 void Document::invalidateRenderingDependentRegions()
 {
 #if PLATFORM(IOS_FAMILY) && ENABLE(TOUCH_EVENTS)
index 77ecb7a..9fc37d1 100644 (file)
@@ -1148,6 +1148,8 @@ public:
     void invalidateRenderingDependentRegions();
     void invalidateEventRegionsForFrame(HTMLFrameOwnerElement&);
 
+    void invalidateEventListenerRegions();
+
     void removeAllEventListeners() final;
 
     WEBCORE_EXPORT const SVGDocumentExtensions* svgExtensions();
@@ -2175,4 +2177,5 @@ inline ScriptExecutionContext* Node::scriptExecutionContext() const
 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::Document)
     static bool isType(const WebCore::ScriptExecutionContext& context) { return context.isDocument(); }
     static bool isType(const WebCore::Node& node) { return node.isDocumentNode(); }
+    static bool isType(const WebCore::EventTarget& target) { return is<WebCore::Node>(target) && isType(downcast<WebCore::Node>(target)); }
 SPECIALIZE_TYPE_TRAITS_END()
index 0b5af2f..d9f8378 100644 (file)
@@ -1966,6 +1966,12 @@ void Element::invalidateStyleForSubtreeInternal()
     Node::invalidateStyle(Style::Validity::SubtreeInvalid);
 }
 
+void Element::invalidateEventListenerRegions()
+{
+    // Event listener region is updated via style update.
+    invalidateStyleInternal();
+}
+
 bool Element::hasDisplayContents() const
 {
     if (!hasRareData())
index 0dbf898..31d0228 100644 (file)
@@ -591,6 +591,8 @@ public:
     void invalidateStyleInternal();
     void invalidateStyleForSubtreeInternal();
 
+    void invalidateEventListenerRegions();
+
     bool hasDisplayContents() const;
     void storeDisplayContentsStyle(std::unique_ptr<RenderStyle>);
 
index e56ed4d..0ccfcc1 100644 (file)
@@ -95,10 +95,8 @@ bool EventTarget::addEventListener(const AtomString& eventType, Ref<EventListene
     if (listenerCreatedFromScript)
         InspectorInstrumentation::didAddEventListener(*this, eventType, listenerRef.get(), options.capture);
 
-    if (eventNames().isWheelEventType(eventType)) {
-        if (is<Element>(*this))
-            downcast<Element>(*this).invalidateStyleInternal();
-    }
+    if (eventNames().isWheelEventType(eventType))
+        invalidateEventListenerRegions();
 
     eventListenersDidChange();
     return true;
@@ -141,10 +139,8 @@ bool EventTarget::removeEventListener(const AtomString& eventType, EventListener
     InspectorInstrumentation::willRemoveEventListener(*this, eventType, listener, options.capture);
 
     if (data->eventListenerMap.remove(eventType, listener, options.capture)) {
-        if (eventNames().isWheelEventType(eventType)) {
-            if (is<Element>(*this))
-                downcast<Element>(*this).invalidateStyleInternal();
-        }
+        if (eventNames().isWheelEventType(eventType))
+            invalidateEventListenerRegions();
 
         eventListenersDidChange();
         return true;
@@ -377,10 +373,8 @@ void EventTarget::removeAllEventListeners()
 
     auto* data = eventTargetData();
     if (data && !data->eventListenerMap.isEmpty()) {
-        if (data->eventListenerMap.contains(eventNames().wheelEvent) || data->eventListenerMap.contains(eventNames().mousewheelEvent)) {
-            if (is<Element>(*this))
-                downcast<Element>(*this).invalidateStyleInternal();
-        }
+        if (data->eventListenerMap.contains(eventNames().wheelEvent) || data->eventListenerMap.contains(eventNames().mousewheelEvent))
+            invalidateEventListenerRegions();
 
         data->eventListenerMap.clear();
         eventListenersDidChange();
@@ -401,4 +395,23 @@ void EventTarget::visitJSEventListeners(JSC::SlotVisitor& visitor)
         listener->visitJSFunction(visitor);
 }
 
+void EventTarget::invalidateEventListenerRegions()
+{
+    if (is<Element>(*this)) {
+        downcast<Element>(*this).invalidateEventListenerRegions();
+        return;
+    }
+
+    auto* document = [&]() -> Document* {
+        if (is<Document>(*this))
+            return &downcast<Document>(*this);
+        if (is<DOMWindow>(*this))
+            return downcast<DOMWindow>(*this).document();
+        return nullptr;
+    }();
+
+    if (document)
+        document->invalidateEventListenerRegions();
+}
+
 } // namespace WebCore
index 4801234..cfcb2cb 100644 (file)
@@ -132,6 +132,7 @@ private:
     virtual void derefEventTarget() = 0;
     
     void innerInvokeEventListeners(Event&, EventListenerVector, EventInvokePhase);
+    void invalidateEventListenerRegions();
 
     friend class EventListenerIterator;
 };
index 4f4e85e..7fb4d2b 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "AnimationBase.h"
 #include "CSSFontSelector.h"
+#include "DOMWindow.h"
 #include "Element.h"
 #include "EventNames.h"
 #include "FrameView.h"
@@ -193,6 +194,15 @@ static OptionSet<TouchAction> computeEffectiveTouchActions(const RenderStyle& st
     return sharedTouchActions;
 }
 
+void Adjuster::adjustEventListenerRegionTypesForRootStyle(RenderStyle& rootStyle, const Document& document)
+{
+    auto regionTypes = computeEventListenerRegionTypes(document, { });
+    if (auto* window = document.domWindow())
+        regionTypes.add(computeEventListenerRegionTypes(*window, { }));
+
+    rootStyle.setEventListenerRegionTypes(regionTypes);
+}
+
 OptionSet<EventListenerRegionType> Adjuster::computeEventListenerRegionTypes(const EventTarget& eventTarget, OptionSet<EventListenerRegionType> parentTypes)
 {
 #if !PLATFORM(IOS_FAMILY)
index 5990c7d..9ddb8c6 100644 (file)
@@ -50,7 +50,7 @@ public:
     static void adjustSVGElementStyle(RenderStyle&, const SVGElement&);
     static void adjustAnimatedStyle(RenderStyle&, const RenderStyle* parentBoxStyle, OptionSet<AnimationImpact>);
     
-    static OptionSet<EventListenerRegionType> computeEventListenerRegionTypes(const EventTarget&, OptionSet<EventListenerRegionType>);
+    static void adjustEventListenerRegionTypesForRootStyle(RenderStyle&, const Document&);
 
 #if ENABLE(TEXT_AUTOSIZING)
     struct AdjustmentForTextAutosizing {
@@ -67,6 +67,7 @@ public:
 private:
     void adjustDisplayContentsStyle(RenderStyle&) const;
     void adjustForSiteSpecificQuirks(RenderStyle&) const;
+    static OptionSet<EventListenerRegionType> computeEventListenerRegionTypes(const EventTarget&, OptionSet<EventListenerRegionType>);
 
     const Document& m_document;
     const RenderStyle& m_parentStyle;
index adf3c72..ceeefdf 100644 (file)
@@ -30,7 +30,6 @@
 #include "StyleResolveForDocument.h"
 
 #include "CSSFontSelector.h"
-#include "DOMWindow.h"
 #include "Document.h"
 #include "FontCascade.h"
 #include "Frame.h"
@@ -74,11 +73,7 @@ RenderStyle resolveForDocument(const Document& document)
         documentStyle.setTextSizeAdjust(TextSizeAdjustment(NoTextSizeAdjustment));
 #endif
 
-    auto regionTypes = Adjuster::computeEventListenerRegionTypes(document, { });
-    if (auto* window = document.domWindow())
-        regionTypes.add(Adjuster::computeEventListenerRegionTypes(*window, { }));
-
-    documentStyle.setEventListenerRegionTypes(regionTypes);
+    Adjuster::adjustEventListenerRegionTypesForRootStyle(documentStyle, document);
 
     Element* docElement = document.documentElement();
     RenderObject* docElementRenderer = docElement ? docElement->renderer() : nullptr;