Should find touch-action elements inside non-composited iframes
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Apr 2020 22:38:33 +0000 (22:38 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Apr 2020 22:38:33 +0000 (22:38 +0000)
https://bugs.webkit.org/show_bug.cgi?id=210041
<rdar://problem/61323558>

Reviewed by Simon Fraser.

Source/WebCore:

Fix up event region code to traverse non-composited iframes that have elements with a non-auto
touch-action. The event region is computed for each composited layer during a compositing layer
update and was retricted to being updated if the layer's associated document may have an element
with a non-auto touch-action. To make this work for non-composited iframes I find its enclosing
compositing layer, set a special bit that it needs an event region update because of the non-
composited child iframe and schedule a compositing layer update. When the update happens, it
checks to see if the special bit is set and if so overrides any restrictions that would have
prevented the event region from being updated. The painting code for widgets is also fixed up to
pass through an EventRegionContext to update during EventRegion painting.

This strategy works well for updating the event region. However debug paint overlays are not
updated (i.e. RenderLayerBacking::paintDebugOverlays() is not called) until the embedding client's
view is repainted. For now, to fix this up I added another a hack, a special bit (RenderView::needsRepaintHackAfterCompositingLayerUpdateForDebugOverlaysOnly())
that is only set if debug overlays are to be shown, to have the compositor repaint the view after
updating compositing layers.

Tests: pointerevents/ios/programmatic-touch-action-none-inside-iframe.html
       pointerevents/ios/touch-action-none-inside-iframe.html
       pointerevents/ios/touch-action-none-inside-nested-iframe.html

* dom/Document.cpp:
(WebCore::Document::invalidateEventRegionsForFrame): Added. Try to invalidate the event region.
This may fail if the document does not have an enclosing compositing layer for repaint (e.g. nested
composited iframes - see test pointerevents/ios/touch-action-none-inside-nested-iframe.html). If
this happens then recursive on our owner element's document. Recursion is used instead of a loop
to future proof this code for out-of-process (OOP) frames, which will likely introduce document proxy objects.
* dom/Document.h:
* page/Frame.cpp:
(WebCore::Frame::invalidateContentEventRegionsIfNeeded): Added. Check if our document has any elements with
a non-auto touch-action. If it does then ask the compositor if the enclosing compositing layer for
repaint's event region must be invalidated - it will only reply true if this is a non-composited iframe.
If it does then forward this invalidation request to the document. The reason I delegate to the document
instead of handling the logic here is to future proof this code for OOP iframes.
* page/Frame.h:
* page/FrameView.cpp:
(WebCore::FrameView::didLayout): Call Frame::invalidateContentEventRegionsIfNeeded(). Also while
I am here take out a ref on the document to ensure it lives through the end of this function, including
through the accessibility's postNotification() code that calls out to the embedding client.

(WebCore::FrameView::paintContents):
* page/FrameView.h:
* platform/ScrollView.cpp:
(WebCore::ScrollView::paint):
* platform/ScrollView.h:
* platform/Scrollbar.cpp:
(WebCore::Scrollbar::paint):
* platform/Scrollbar.h:
* platform/Widget.cpp:
(WebCore::Widget::paint):
* platform/Widget.h:
* platform/gtk/WidgetGtk.cpp:
(WebCore::Widget::paint):
* platform/ios/WidgetIOS.mm:
(WebCore::Widget::paint):
* platform/mac/WidgetMac.mm:
(WebCore::Widget::paint):
* platform/win/WidgetWin.cpp:
(WebCore::Widget::paint):
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::paintObject):
Pass an EventRegionContext through.

* rendering/RenderElement.cpp:
(WebCore::RenderElement::styleWillChange): Update code now that RendeLayer::invalidateEventRegion()
takes a reason.
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::paint): Pass the EventRegionContext through. If are passed one then update
paint flags to collect event region.
(WebCore::RenderLayer::invalidateEventRegion): Changed return value from void to bool so as to indicate
to the caller whether the event region was actually invalidated. Also made it take an argument as
to the reason for the invalidation. If invalidation is due to a non-composited iframe then sets some
state and schedule a compositing layer update.

* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateEventRegion):
(WebCore::RenderLayerBacking::setContentsNeedDisplay):
(WebCore::RenderLayerBacking::setContentsNeedDisplayInRect):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::updateCompositingLayers):
Pass an EventRegionContext through

(WebCore::RenderLayerCompositor::viewNeedsToInvalidateEventRegionOfEnclosingCompositingLayerForRepaint const): Added.

* rendering/RenderLayerCompositor.h:
* rendering/RenderScrollbar.cpp:
(WebCore::RenderScrollbar::paint):
* rendering/RenderScrollbar.h:
* rendering/RenderView.h:
Pass an EventRegionContext through.

* rendering/RenderWidget.cpp:
(WebCore::RenderWidget::paintContents): Translate the event region by our content paint offset.
(WebCore::RenderWidget::paint): Update for EventRegion. If painting the event region and the view
needs layout then do what we do now and bail out. Otherwise, proceed to paint the widget's content.
The changes to FrameView::didLayout() above means that for non-composited frames that need an event
region update they already performed a layout. So, these paints will be allowed to descend into
painting of the widget's content.

Source/WebKit:

Pass EventRegionContext through. It is unused as it's not applicable for plugin painting.

* WebProcess/Plugins/PluginView.cpp:
(WebKit::PluginView::paint):
* WebProcess/Plugins/PluginView.h:

Source/WebKitLegacy/win:

Pass EventRegionContext through. It is unused as it's not applicable for plugin painting.

* Plugins/PluginView.h:
* Plugins/PluginViewWin.cpp:
(WebCore::PluginView::paint):

LayoutTests:

Add more tests.

* pointerevents/ios/programmatic-touch-action-none-inside-iframe-expected.txt: Added.
* pointerevents/ios/programmatic-touch-action-none-inside-iframe.html: Added.
* pointerevents/ios/resources/touch-action-none-inside-iframe.html: Added.
* pointerevents/ios/touch-action-none-inside-iframe-expected.txt: Added.
* pointerevents/ios/touch-action-none-inside-iframe.html: Added.
* pointerevents/ios/touch-action-none-inside-nested-iframe-expected.txt: Added.
* pointerevents/ios/touch-action-none-inside-nested-iframe.html: Added.

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

42 files changed:
LayoutTests/ChangeLog
LayoutTests/pointerevents/ios/programmatic-touch-action-none-inside-iframe-expected.txt [new file with mode: 0644]
LayoutTests/pointerevents/ios/programmatic-touch-action-none-inside-iframe.html [new file with mode: 0644]
LayoutTests/pointerevents/ios/resources/touch-action-none-inside-iframe.html [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-none-inside-iframe-expected.txt [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-none-inside-iframe.html [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-none-inside-nested-iframe-expected.txt [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-none-inside-nested-iframe.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/page/Frame.cpp
Source/WebCore/page/Frame.h
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/platform/ScrollView.cpp
Source/WebCore/platform/ScrollView.h
Source/WebCore/platform/Scrollbar.cpp
Source/WebCore/platform/Scrollbar.h
Source/WebCore/platform/Widget.cpp
Source/WebCore/platform/Widget.h
Source/WebCore/platform/gtk/WidgetGtk.cpp
Source/WebCore/platform/ios/WidgetIOS.mm
Source/WebCore/platform/mac/WidgetMac.mm
Source/WebCore/platform/win/WidgetWin.cpp
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderElement.cpp
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h
Source/WebCore/rendering/RenderScrollbar.cpp
Source/WebCore/rendering/RenderScrollbar.h
Source/WebCore/rendering/RenderView.h
Source/WebCore/rendering/RenderWidget.cpp
Source/WebKit/ChangeLog
Source/WebKit/WebProcess/Plugins/PluginView.cpp
Source/WebKit/WebProcess/Plugins/PluginView.h
Source/WebKitLegacy/win/ChangeLog
Source/WebKitLegacy/win/Plugins/PluginView.h
Source/WebKitLegacy/win/Plugins/PluginViewWin.cpp

index 8089562..954eaf8 100644 (file)
@@ -1,3 +1,21 @@
+2020-04-08  Daniel Bates  <dabates@apple.com>
+
+        Should find touch-action elements inside non-composited iframes
+        https://bugs.webkit.org/show_bug.cgi?id=210041
+        <rdar://problem/61323558>
+
+        Reviewed by Simon Fraser.
+
+        Add more tests.
+
+        * pointerevents/ios/programmatic-touch-action-none-inside-iframe-expected.txt: Added.
+        * pointerevents/ios/programmatic-touch-action-none-inside-iframe.html: Added.
+        * pointerevents/ios/resources/touch-action-none-inside-iframe.html: Added.
+        * pointerevents/ios/touch-action-none-inside-iframe-expected.txt: Added.
+        * pointerevents/ios/touch-action-none-inside-iframe.html: Added.
+        * pointerevents/ios/touch-action-none-inside-nested-iframe-expected.txt: Added.
+        * pointerevents/ios/touch-action-none-inside-nested-iframe.html: Added.
+
 2020-04-08  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, unskip http/tests/notifications/event-listener-crash.html
diff --git a/LayoutTests/pointerevents/ios/programmatic-touch-action-none-inside-iframe-expected.txt b/LayoutTests/pointerevents/ios/programmatic-touch-action-none-inside-iframe-expected.txt
new file mode 100644 (file)
index 0000000..7f73434
--- /dev/null
@@ -0,0 +1,22 @@
+
+(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)
+        (touch-action
+          (none          
+            (rect (18,18) width=102 height=102)
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/pointerevents/ios/programmatic-touch-action-none-inside-iframe.html b/LayoutTests/pointerevents/ios/programmatic-touch-action-none-inside-iframe.html
new file mode 100644 (file)
index 0000000..95c8945
--- /dev/null
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<body>
+<iframe id="testFrame" srcdoc="<div style='width: 100px; height: 100px; border:1px solid black'></div>" onload="runTest()"></iframe>
+<pre id="results"></pre>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function runTest()
+{
+    testFrame.contentDocument.querySelector("div").style.touchAction = "none";
+    if (window.internals)
+        results.innerText = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+</script>
+</body>
+</html>
diff --git a/LayoutTests/pointerevents/ios/resources/touch-action-none-inside-iframe.html b/LayoutTests/pointerevents/ios/resources/touch-action-none-inside-iframe.html
new file mode 100644 (file)
index 0000000..a978308
--- /dev/null
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<iframe srcdoc="<div style='touch-action: none; width: 100px; height: 100px; border:1px solid black'></div>" onload="window.parent && window.parent.dumpRegion()"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/pointerevents/ios/touch-action-none-inside-iframe-expected.txt b/LayoutTests/pointerevents/ios/touch-action-none-inside-iframe-expected.txt
new file mode 100644 (file)
index 0000000..7f73434
--- /dev/null
@@ -0,0 +1,22 @@
+
+(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)
+        (touch-action
+          (none          
+            (rect (18,18) width=102 height=102)
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-none-inside-iframe.html b/LayoutTests/pointerevents/ios/touch-action-none-inside-iframe.html
new file mode 100644 (file)
index 0000000..cb74eec
--- /dev/null
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<body>
+<iframe id="testFrame" srcdoc="<div style='touch-action: none; width: 100px; height: 100px; border:1px solid black'></div>" onload="runTest()"></iframe>
+<pre id="results"></pre>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function runTest()
+{
+    if (window.internals)
+        results.innerText = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+</script>
+</body>
+</html>
diff --git a/LayoutTests/pointerevents/ios/touch-action-none-inside-nested-iframe-expected.txt b/LayoutTests/pointerevents/ios/touch-action-none-inside-nested-iframe-expected.txt
new file mode 100644 (file)
index 0000000..7333af8
--- /dev/null
@@ -0,0 +1,22 @@
+
+(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)
+        (touch-action
+          (none          
+            (rect (28,28) width=102 height=102)
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-none-inside-nested-iframe.html b/LayoutTests/pointerevents/ios/touch-action-none-inside-nested-iframe.html
new file mode 100644 (file)
index 0000000..5351f28
--- /dev/null
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<body>
+<iframe id="testFrame" src="resources/touch-action-none-inside-iframe.html"></iframe>
+<pre id="results"></pre>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function dumpRegion()
+{
+    if (window.internals)
+        results.innerText = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+</script>
+</body>
+</html>
index 5b60331..e9e68d9 100644 (file)
@@ -1,3 +1,109 @@
+2020-04-08  Daniel Bates  <dabates@apple.com>
+
+        Should find touch-action elements inside non-composited iframes
+        https://bugs.webkit.org/show_bug.cgi?id=210041
+        <rdar://problem/61323558>
+
+        Reviewed by Simon Fraser.
+
+        Fix up event region code to traverse non-composited iframes that have elements with a non-auto
+        touch-action. The event region is computed for each composited layer during a compositing layer
+        update and was retricted to being updated if the layer's associated document may have an element
+        with a non-auto touch-action. To make this work for non-composited iframes I find its enclosing
+        compositing layer, set a special bit that it needs an event region update because of the non-
+        composited child iframe and schedule a compositing layer update. When the update happens, it
+        checks to see if the special bit is set and if so overrides any restrictions that would have
+        prevented the event region from being updated. The painting code for widgets is also fixed up to
+        pass through an EventRegionContext to update during EventRegion painting.
+
+        This strategy works well for updating the event region. However debug paint overlays are not
+        updated (i.e. RenderLayerBacking::paintDebugOverlays() is not called) until the embedding client's
+        view is repainted. For now, to fix this up I added another a hack, a special bit (RenderView::needsRepaintHackAfterCompositingLayerUpdateForDebugOverlaysOnly())
+        that is only set if debug overlays are to be shown, to have the compositor repaint the view after
+        updating compositing layers.
+
+        Tests: pointerevents/ios/programmatic-touch-action-none-inside-iframe.html
+               pointerevents/ios/touch-action-none-inside-iframe.html
+               pointerevents/ios/touch-action-none-inside-nested-iframe.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::invalidateEventRegionsForFrame): Added. Try to invalidate the event region.
+        This may fail if the document does not have an enclosing compositing layer for repaint (e.g. nested
+        composited iframes - see test pointerevents/ios/touch-action-none-inside-nested-iframe.html). If
+        this happens then recursive on our owner element's document. Recursion is used instead of a loop
+        to future proof this code for out-of-process (OOP) frames, which will likely introduce document proxy objects.
+        * dom/Document.h:
+        * page/Frame.cpp:
+        (WebCore::Frame::invalidateContentEventRegionsIfNeeded): Added. Check if our document has any elements with
+        a non-auto touch-action. If it does then ask the compositor if the enclosing compositing layer for
+        repaint's event region must be invalidated - it will only reply true if this is a non-composited iframe.
+        If it does then forward this invalidation request to the document. The reason I delegate to the document
+        instead of handling the logic here is to future proof this code for OOP iframes.
+        * page/Frame.h:
+        * page/FrameView.cpp:
+        (WebCore::FrameView::didLayout): Call Frame::invalidateContentEventRegionsIfNeeded(). Also while
+        I am here take out a ref on the document to ensure it lives through the end of this function, including
+        through the accessibility's postNotification() code that calls out to the embedding client.
+
+        (WebCore::FrameView::paintContents):
+        * page/FrameView.h:
+        * platform/ScrollView.cpp:
+        (WebCore::ScrollView::paint):
+        * platform/ScrollView.h:
+        * platform/Scrollbar.cpp:
+        (WebCore::Scrollbar::paint):
+        * platform/Scrollbar.h:
+        * platform/Widget.cpp:
+        (WebCore::Widget::paint):
+        * platform/Widget.h:
+        * platform/gtk/WidgetGtk.cpp:
+        (WebCore::Widget::paint):
+        * platform/ios/WidgetIOS.mm:
+        (WebCore::Widget::paint):
+        * platform/mac/WidgetMac.mm:
+        (WebCore::Widget::paint):
+        * platform/win/WidgetWin.cpp:
+        (WebCore::Widget::paint):
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::paintObject):
+        Pass an EventRegionContext through.
+
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::styleWillChange): Update code now that RendeLayer::invalidateEventRegion()
+        takes a reason. 
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::paint): Pass the EventRegionContext through. If are passed one then update
+        paint flags to collect event region.
+        (WebCore::RenderLayer::invalidateEventRegion): Changed return value from void to bool so as to indicate
+        to the caller whether the event region was actually invalidated. Also made it take an argument as
+        to the reason for the invalidation. If invalidation is due to a non-composited iframe then sets some
+        state and schedule a compositing layer update.
+
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateEventRegion):
+        (WebCore::RenderLayerBacking::setContentsNeedDisplay):
+        (WebCore::RenderLayerBacking::setContentsNeedDisplayInRect):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::updateCompositingLayers):
+        Pass an EventRegionContext through
+
+        (WebCore::RenderLayerCompositor::viewNeedsToInvalidateEventRegionOfEnclosingCompositingLayerForRepaint const): Added.
+
+        * rendering/RenderLayerCompositor.h:
+        * rendering/RenderScrollbar.cpp:
+        (WebCore::RenderScrollbar::paint):
+        * rendering/RenderScrollbar.h:
+        * rendering/RenderView.h:
+        Pass an EventRegionContext through.
+
+        * rendering/RenderWidget.cpp:
+        (WebCore::RenderWidget::paintContents): Translate the event region by our content paint offset.
+        (WebCore::RenderWidget::paint): Update for EventRegion. If painting the event region and the view
+        needs layout then do what we do now and bail out. Otherwise, proceed to paint the widget's content.
+        The changes to FrameView::didLayout() above means that for non-composited frames that need an event
+        region update they already performed a layout. So, these paints will be allowed to descend into
+        painting of the widget's content.
+
 2020-04-08  Rob Buis  <rbuis@igalia.com>
 
         Make more use of FrameLoader pageID/frameID getters
index 2fb40e3..c4088cf 100644 (file)
@@ -4234,6 +4234,19 @@ void Document::elementInActiveChainDidDetach(Element& element)
         m_activeElement = m_activeElement->parentElement();
 }
 
+void Document::invalidateEventRegionsForFrame(HTMLFrameOwnerElement& element)
+{
+    auto* renderer = element.renderer();
+    if (!renderer)
+        return;
+    if (auto* layer = renderer->enclosingLayer()) {
+        if (layer->invalidateEventRegion(RenderLayer::EventRegionInvalidationReason::NonCompositedFrame))
+            return;
+    }
+    if (auto* ownerElement = this->ownerElement())
+        ownerElement->document().invalidateEventRegionsForFrame(*ownerElement);
+}
+
 void Document::invalidateRenderingDependentRegions()
 {
 #if PLATFORM(IOS_FAMILY) && ENABLE(TOUCH_EVENTS)
index ebbfc52..c5ad3df 100644 (file)
@@ -1140,6 +1140,7 @@ public:
     WEBCORE_EXPORT String displayStringModifiedByEncoding(const String&) const;
 
     void invalidateRenderingDependentRegions();
+    void invalidateEventRegionsForFrame(HTMLFrameOwnerElement&);
 
     void removeAllEventListeners() final;
 
index e6271d7..93138f3 100644 (file)
@@ -305,6 +305,20 @@ void Frame::setDocument(RefPtr<Document>&& newDocument)
     m_documentIsBeingReplaced = false;
 }
 
+void Frame::invalidateContentEventRegionsIfNeeded()
+{
+    if (!m_page || !m_doc || !m_doc->renderView())
+        return;
+#if PLATFORM(IOS)
+    if (!m_doc->mayHaveElementsWithNonAutoTouchAction())
+        return;
+#endif
+    if (!m_doc->renderView()->compositor().viewNeedsToInvalidateEventRegionOfEnclosingCompositingLayerForRepaint())
+        return;
+    if (m_ownerElement)
+        m_ownerElement->document().invalidateEventRegionsForFrame(*m_ownerElement);
+}
+
 #if ENABLE(ORIENTATION_EVENTS)
 void Frame::orientationChanged()
 {
index eb97a61..3d43a94 100644 (file)
@@ -305,6 +305,8 @@ public:
     void didPrewarmLocalStorage();
     bool mayPrewarmLocalStorage() const;
 
+    void invalidateContentEventRegionsIfNeeded();
+
 // ========
 
     void selfOnlyRef();
index f59baa8..620124d 100644 (file)
@@ -1261,12 +1261,15 @@ void FrameView::didLayout(WeakPtr<RenderElement> layoutRoot)
 
     updateCompositingLayersAfterLayout();
 
+    auto document = makeRef(*frame().document());
+
 #if PLATFORM(COCOA) || PLATFORM(WIN) || PLATFORM(GTK)
-    if (auto* cache = frame().document()->existingAXObjectCache())
+    if (auto* cache = document->existingAXObjectCache())
         cache->postNotification(layoutRoot.get(), AXObjectCache::AXLayoutComplete);
 #endif
 
-    frame().document()->invalidateRenderingDependentRegions();
+    frame().invalidateContentEventRegionsIfNeeded();
+    document->invalidateRenderingDependentRegions();
 
     updateCanBlitOnScrollRecursively();
 
@@ -1274,10 +1277,10 @@ void FrameView::didLayout(WeakPtr<RenderElement> layoutRoot)
 
     handleDeferredScrollbarsUpdateAfterDirectionChange();
 
-    if (frame().document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
+    if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
         updateOverflowStatus(layoutWidth() < contentsWidth(), layoutHeight() < contentsHeight());
 
-    frame().document()->markers().invalidateRectsForAllMarkers();
+    document->markers().invalidateRectsForAllMarkers();
 }
 
 bool FrameView::shouldDeferScrollUpdateAfterContentSizeChange()
@@ -4229,7 +4232,7 @@ void FrameView::didPaintContents(GraphicsContext& context, const IntRect& dirtyR
     }
 }
 
-void FrameView::paintContents(GraphicsContext& context, const IntRect& dirtyRect, SecurityOriginPaintPolicy securityOriginPaintPolicy)
+void FrameView::paintContents(GraphicsContext& context, const IntRect& dirtyRect, SecurityOriginPaintPolicy securityOriginPaintPolicy, EventRegionContext* eventRegionContext)
 {
 #ifndef NDEBUG
     bool fillWithWarningColor;
@@ -4290,8 +4293,8 @@ void FrameView::paintContents(GraphicsContext& context, const IntRect& dirtyRect
     while (is<RenderInline>(renderer) && !downcast<RenderInline>(*renderer).firstLineBox())
         renderer = renderer->parent();
 
-    rootLayer->paint(context, dirtyRect, LayoutSize(), m_paintBehavior, renderer, { }, securityOriginPaintPolicy == SecurityOriginPaintPolicy::AnyOrigin ? RenderLayer::SecurityOriginPaintPolicy::AnyOrigin : RenderLayer::SecurityOriginPaintPolicy::AccessibleOriginOnly);
-    if (rootLayer->containsDirtyOverlayScrollbars())
+    rootLayer->paint(context, dirtyRect, LayoutSize(), m_paintBehavior, renderer, { }, securityOriginPaintPolicy == SecurityOriginPaintPolicy::AnyOrigin ? RenderLayer::SecurityOriginPaintPolicy::AnyOrigin : RenderLayer::SecurityOriginPaintPolicy::AccessibleOriginOnly, eventRegionContext);
+    if (rootLayer->containsDirtyOverlayScrollbars() && !eventRegionContext)
         rootLayer->paintOverlayScrollbars(context, dirtyRect, m_paintBehavior, renderer);
 
     didPaintContents(context, dirtyRect, paintingState);
index 0aecde8..8984535 100644 (file)
@@ -57,6 +57,7 @@ namespace WebCore {
 
 class AXObjectCache;
 class Element;
+class EventRegionContext;
 class FloatSize;
 class Frame;
 class HTMLFrameOwnerElement;
@@ -351,7 +352,7 @@ public:
     void addEmbeddedObjectToUpdate(RenderEmbeddedObject&);
     void removeEmbeddedObjectToUpdate(RenderEmbeddedObject&);
 
-    WEBCORE_EXPORT void paintContents(GraphicsContext&, const IntRect& dirtyRect, SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin) final;
+    WEBCORE_EXPORT void paintContents(GraphicsContext&, const IntRect& dirtyRect, SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin, EventRegionContext* = nullptr) final;
 
     struct PaintingState {
         OptionSet<PaintBehavior> paintBehavior;
index 3e216e1..361f053 100644 (file)
@@ -1237,14 +1237,14 @@ void ScrollView::paintPanScrollIcon(GraphicsContext& context)
     context.drawImage(panScrollIcon, iconGCPoint);
 }
 
-void ScrollView::paint(GraphicsContext& context, const IntRect& rect, SecurityOriginPaintPolicy securityOriginPaintPolicy)
+void ScrollView::paint(GraphicsContext& context, const IntRect& rect, SecurityOriginPaintPolicy securityOriginPaintPolicy, EventRegionContext* eventRegionContext)
 {
     if (platformWidget()) {
         Widget::paint(context, rect);
         return;
     }
 
-    if (context.paintingDisabled() && !context.performingPaintInvalidation())
+    if (context.paintingDisabled() && !context.performingPaintInvalidation() && !eventRegionContext)
         return;
 
     notifyPageThatContentAreaWillPaint();
@@ -1269,7 +1269,7 @@ void ScrollView::paint(GraphicsContext& context, const IntRect& rect, SecurityOr
             context.clip(visibleContentRect(LegacyIOSDocumentVisibleRect));
         }
 
-        paintContents(context, documentDirtyRect, securityOriginPaintPolicy);
+        paintContents(context, documentDirtyRect, securityOriginPaintPolicy, eventRegionContext);
     }
 
 #if ENABLE(RUBBER_BANDING)
index 14ad384..8f5df8e 100644 (file)
@@ -57,6 +57,7 @@ OBJC_CLASS WAKView;
 
 namespace WebCore {
 
+class EventRegionContext;
 class HostWindow;
 class LegacyTileCache;
 class Scrollbar;
@@ -350,7 +351,7 @@ public:
     }
 
     // Widget override. Handles painting of the contents of the view as well as the scrollbars.
-    WEBCORE_EXPORT void paint(GraphicsContext&, const IntRect&, Widget::SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin) final;
+    WEBCORE_EXPORT void paint(GraphicsContext&, const IntRect&, Widget::SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin, EventRegionContext* = nullptr) final;
     void paintScrollbars(GraphicsContext&, const IntRect&);
 
     // Widget overrides to ensure that our children's visibility status is kept up to date when we get shown and hidden.
@@ -388,7 +389,7 @@ protected:
     ScrollView();
 
     virtual void repaintContentRectangle(const IntRect&);
-    virtual void paintContents(GraphicsContext&, const IntRect& damageRect, SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin) = 0;
+    virtual void paintContents(GraphicsContext&, const IntRect& damageRect, SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin, EventRegionContext* = nullptr) = 0;
 
     virtual void paintOverhangAreas(GraphicsContext&, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect);
 
index 1293e2d..a6b5807 100644 (file)
@@ -140,7 +140,7 @@ void Scrollbar::updateThumbProportion()
     updateThumb();
 }
 
-void Scrollbar::paint(GraphicsContext& context, const IntRect& damageRect, Widget::SecurityOriginPaintPolicy)
+void Scrollbar::paint(GraphicsContext& context, const IntRect& damageRect, Widget::SecurityOriginPaintPolicy, EventRegionContext*)
 {
     if (context.invalidatingControlTints() && theme().supportsControlTints()) {
         invalidate();
index cb950e2..ed3896c 100644 (file)
@@ -83,7 +83,7 @@ public:
     WEBCORE_EXPORT void setProportion(int visibleSize, int totalSize);
     void setPressedPos(int p) { m_pressedPos = p; }
 
-    void paint(GraphicsContext&, const IntRect& damageRect, Widget::SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin) override;
+    void paint(GraphicsContext&, const IntRect& damageRect, Widget::SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin, EventRegionContext* = nullptr) override;
 
     bool enabled() const { return m_enabled; }
     virtual void setEnabled(bool);
index e9f5d81..a7fe380 100644 (file)
@@ -285,7 +285,7 @@ void Widget::setFrameRect(const IntRect& rect)
     notImplemented();
 }
 
-void Widget::paint(GraphicsContext&, const IntRect&, SecurityOriginPaintPolicy)
+void Widget::paint(GraphicsContext&, const IntRect&, SecurityOriginPaintPolicy, EventRegionContext*)
 {
     notImplemented();
 }
index 1cf931c..4f302ab 100644 (file)
@@ -60,6 +60,7 @@ namespace WebCore {
 
 class Cursor;
 class Event;
+class EventRegionContext;
 class FontCascade;
 class FrameView;
 class GraphicsContext;
@@ -109,7 +110,7 @@ public:
 
     enum class SecurityOriginPaintPolicy { AnyOrigin, AccessibleOriginOnly };
 
-    WEBCORE_EXPORT virtual void paint(GraphicsContext&, const IntRect&, SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin);
+    WEBCORE_EXPORT virtual void paint(GraphicsContext&, const IntRect&, SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin, EventRegionContext* = nullptr);
     void invalidate() { invalidateRect(boundsRect()); }
     virtual void invalidateRect(const IntRect&) = 0;
 
index 6919ee4..7c45dcf 100644 (file)
@@ -62,7 +62,7 @@ void Widget::hide()
     setSelfVisible(false);
 }
 
-void Widget::paint(GraphicsContext&, const IntRect&, SecurityOriginPaintPolicy)
+void Widget::paint(GraphicsContext&, const IntRect&, SecurityOriginPaintPolicy, EventRegionContext*)
 {
 }
 
index 3e09c11..4e07bd7 100644 (file)
@@ -146,7 +146,7 @@ NSView* Widget::getOuterView() const
     return view;
 }
 
-void Widget::paint(GraphicsContext& p, const IntRect& r, SecurityOriginPaintPolicy)
+void Widget::paint(GraphicsContext& p, const IntRect& r, SecurityOriginPaintPolicy, EventRegionContext*)
 {
     if (p.paintingDisabled())
         return;
index 266b042..3045888 100644 (file)
@@ -186,7 +186,7 @@ NSView *Widget::getOuterView() const
     return view;
 }
 
-void Widget::paint(GraphicsContext& p, const IntRect& r, SecurityOriginPaintPolicy)
+void Widget::paint(GraphicsContext& p, const IntRect& r, SecurityOriginPaintPolicy, EventRegionContext*)
 {
     if (p.paintingDisabled())
         return;
index ffd86a0..965df83 100644 (file)
@@ -70,7 +70,7 @@ void Widget::setCursor(const Cursor& cursor)
     view->hostWindow()->setCursor(cursor);
 }
 
-void Widget::paint(GraphicsContext&, const IntRect&, SecurityOriginPaintPolicy)
+void Widget::paint(GraphicsContext&, const IntRect&, SecurityOriginPaintPolicy, EventRegionContext*)
 {
 }
 
index ec6fd8c..f2b2fd3 100644 (file)
@@ -1255,8 +1255,7 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
             paintInfo.eventRegionContext->unite(borderRegion, style());
         }
 
-        // No need to check descendants if we don't have overflow and don't contain floats and the area is already covered.
-        bool needsTraverseDescendants = hasVisualOverflow() || containsFloats() || !paintInfo.eventRegionContext->contains(enclosingIntRect(borderRect));
+        bool needsTraverseDescendants = hasVisualOverflow() || containsFloats() || !paintInfo.eventRegionContext->contains(enclosingIntRect(borderRect)) || view().needsEventRegionUpdateForNonCompositedFrame();
 #if PLATFORM(IOS_FAMILY)
         needsTraverseDescendants = needsTraverseDescendants || document().mayHaveElementsWithNonAutoTouchAction();
 #endif
index 877f480..5ea09a5 100644 (file)
@@ -745,7 +745,7 @@ void RenderElement::styleWillChange(StyleDifference diff, const RenderStyle& new
         if (needsInvalidateEventRegion()) {
             // Usually the event region gets updated as a result of paint invalidation. Here we need to request an update explicitly.
             if (auto* layer = enclosingLayer())
-                layer->invalidateEventRegion();
+                layer->invalidateEventRegion(RenderLayer::EventRegionInvalidationReason::Style);
         }
 
         if (m_parent && (newStyle.outlineSize() < m_style.outlineSize() || shouldRepaintForStyleDifference(diff)))
index 2e90f0d..b9b7adf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
  * Copyright (C) 2019 Adobe. All rights reserved.
  *
  * Portions are Copyright (C) 1998 Netscape Communications Corporation.
@@ -4203,11 +4203,15 @@ bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularit
     return ScrollableArea::scroll(direction, granularity, multiplier);
 }
 
-void RenderLayer::paint(GraphicsContext& context, const LayoutRect& damageRect, const LayoutSize& subpixelOffset, OptionSet<PaintBehavior> paintBehavior, RenderObject* subtreePaintRoot, OptionSet<PaintLayerFlag> paintFlags, SecurityOriginPaintPolicy paintPolicy)
+void RenderLayer::paint(GraphicsContext& context, const LayoutRect& damageRect, const LayoutSize& subpixelOffset, OptionSet<PaintBehavior> paintBehavior, RenderObject* subtreePaintRoot, OptionSet<PaintLayerFlag> paintFlags, SecurityOriginPaintPolicy paintPolicy, EventRegionContext* eventRegionContext)
 {
     OverlapTestRequestMap overlapTestRequests;
 
     LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, subpixelOffset, subtreePaintRoot, &overlapTestRequests, paintPolicy == SecurityOriginPaintPolicy::AccessibleOriginOnly);
+    if (eventRegionContext) {
+        paintingInfo.eventRegionContext = eventRegionContext;
+        paintFlags.add(RenderLayer::PaintLayerCollectingEventRegion);
+    }
     paintLayer(context, paintingInfo, paintFlags);
 
     for (auto& widget : overlapTestRequests.keys())
@@ -7001,12 +7005,13 @@ bool RenderLayer::isTransparentRespectingParentFrames() const
     return false;
 }
 
-void RenderLayer::invalidateEventRegion()
+bool RenderLayer::invalidateEventRegion(EventRegionInvalidationReason reason)
 {
+    // FIXME: This should not be conditioned on PLATFORM(IOS_FAMILY). See <https://webkit.org/b/210216>.
 #if PLATFORM(IOS_FAMILY)
     auto* compositingLayer = enclosingCompositingLayerForRepaint();
     if (!compositingLayer)
-        return;
+        return false;
 
     auto maintainsEventRegion = [&] {
         // UI side scroll overlap testing.
@@ -7018,10 +7023,22 @@ void RenderLayer::invalidateEventRegion()
         return false;
     };
 
-    if (!maintainsEventRegion())
-        return;
+    if (reason != EventRegionInvalidationReason::NonCompositedFrame && !maintainsEventRegion())
+        return false;
 
     compositingLayer->setNeedsCompositingConfigurationUpdate();
+
+    if (reason == EventRegionInvalidationReason::NonCompositedFrame) {
+        auto& view = renderer().view();
+        view.setNeedsEventRegionUpdateForNonCompositedFrame();
+        if (renderer().settings().visibleDebugOverlayRegions() & NonFastScrollableRegion)
+            view.setNeedsRepaintHackAfterCompositingLayerUpdateForDebugOverlaysOnly();
+        view.compositor().scheduleCompositingLayerUpdate();
+    }
+    return true;
+#else
+    UNUSED_PARAM(reason);
+    return false;
 #endif
 }
 
index d1659b0..b03f1e3 100644 (file)
@@ -695,7 +695,7 @@ public:
     // front.  The hitTest method looks for mouse events by walking
     // layers that intersect the point from front to back.
     void paint(GraphicsContext&, const LayoutRect& damageRect, const LayoutSize& subpixelOffset = LayoutSize(), OptionSet<PaintBehavior> = PaintBehavior::Normal,
-        RenderObject* subtreePaintRoot = nullptr, OptionSet<PaintLayerFlag> = { }, SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin);
+        RenderObject* subtreePaintRoot = nullptr, OptionSet<PaintLayerFlag> = { }, SecurityOriginPaintPolicy = SecurityOriginPaintPolicy::AnyOrigin, EventRegionContext* = nullptr);
     bool hitTest(const HitTestRequest&, HitTestResult&);
     bool hitTest(const HitTestRequest&, const HitTestLocation&, HitTestResult&);
     void paintOverlayScrollbars(GraphicsContext&, const LayoutRect& damageRect, OptionSet<PaintBehavior>, RenderObject* subtreePaintRoot = nullptr);
@@ -924,7 +924,10 @@ public:
 
     WEBCORE_EXPORT bool isTransparentRespectingParentFrames() const;
 
-    void invalidateEventRegion();
+    // Invalidation can fail if there is no enclosing compositing layer (e.g. nested iframe)
+    // or the layer does not maintain an event region.
+    enum class EventRegionInvalidationReason { Paint, Style, NonCompositedFrame };
+    bool invalidateEventRegion(EventRegionInvalidationReason);
 
     String debugDescription() const final;
 
index 4bbe3e0..ff89f5e 100644 (file)
@@ -1618,11 +1618,12 @@ void RenderLayerBacking::updateEventRegion()
     if (paintsIntoCompositedAncestor())
         return;
 
+    bool needsEventRegionUpdateForNonCompositedFrame = renderer().view().needsEventRegionUpdateForNonCompositedFrame();
     bool hasTouchActionElements = false;
 #if PLATFORM(IOS_FAMILY)
     hasTouchActionElements = renderer().document().mayHaveElementsWithNonAutoTouchAction();
 #endif
-    if (!hasTouchActionElements) {
+    if (!hasTouchActionElements && !needsEventRegionUpdateForNonCompositedFrame) {
         if (m_owningLayer.isRenderViewLayer())
             return;
 
@@ -1666,6 +1667,9 @@ void RenderLayerBacking::updateEventRegion()
 
     if (m_scrolledContentsLayer)
         updateEventRegionForLayer(*m_scrolledContentsLayer);
+
+    if (needsEventRegionUpdateForNonCompositedFrame)
+        renderer().view().setNeedsEventRegionUpdateForNonCompositedFrame(false);
 }
 #endif
 
@@ -2781,7 +2785,7 @@ void RenderLayerBacking::setContentsNeedDisplay(GraphicsLayer::ShouldClipToLayer
     if (!m_owningLayer.isRenderViewLayer())
         m_owningLayer.setNeedsCompositingConfigurationUpdate();
 
-    m_owningLayer.invalidateEventRegion();
+    m_owningLayer.invalidateEventRegion(RenderLayer::EventRegionInvalidationReason::Paint);
 
     auto& frameView = renderer().view().frameView();
     if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
@@ -2821,7 +2825,7 @@ void RenderLayerBacking::setContentsNeedDisplayInRect(const LayoutRect& r, Graph
     if (!m_owningLayer.isRenderViewLayer())
         m_owningLayer.setNeedsCompositingConfigurationUpdate();
 
-    m_owningLayer.invalidateEventRegion();
+    m_owningLayer.invalidateEventRegion(RenderLayer::EventRegionInvalidationReason::Paint);
 
     FloatRect pixelSnappedRectForPainting = snapRectToDevicePixels(r, deviceScaleFactor());
     auto& frameView = renderer().view().frameView();
index f54d850..2d3b753 100644 (file)
@@ -858,6 +858,11 @@ bool RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
 
     InspectorInstrumentation::layerTreeDidChange(&page());
 
+    if (m_renderView.needsRepaintHackAfterCompositingLayerUpdateForDebugOverlaysOnly()) {
+        m_renderView.repaintRootContents();
+        m_renderView.setNeedsRepaintHackAfterCompositingLayerUpdateForDebugOverlaysOnly(false);
+    }
+
     return true;
 }
 
@@ -3725,6 +3730,14 @@ GraphicsLayer* RenderLayerCompositor::updateLayerForFooter(bool wantsLayer)
 
 #endif
 
+bool RenderLayerCompositor::viewNeedsToInvalidateEventRegionOfEnclosingCompositingLayerForRepaint() const
+{
+    // Event regions are only updated on compositing layers. Non-composited layers must
+    // delegate to their enclosing compositing layer for repaint to update the event region
+    // for elements inside them.
+    return !m_renderView.isComposited();
+}
+
 bool RenderLayerCompositor::viewHasTransparentBackground(Color* backgroundColor) const
 {
     if (m_renderView.frameView().isTransparent()) {
index 946dfc4..7ce638c 100644 (file)
@@ -358,6 +358,8 @@ public:
 
     bool viewHasTransparentBackground(Color* backgroundColor = nullptr) const;
 
+    bool viewNeedsToInvalidateEventRegionOfEnclosingCompositingLayerForRepaint() const;
+
     bool hasNonMainLayersWithTiledBacking() const { return m_layersWithTiledBackingCount; }
 
     OptionSet<CompositingReason> reasonsForCompositing(const RenderLayer&) const;
index 0ca2da0..5e36d1a 100644 (file)
@@ -100,7 +100,7 @@ void RenderScrollbar::styleChanged()
     updateScrollbarParts();
 }
 
-void RenderScrollbar::paint(GraphicsContext& context, const IntRect& damageRect, Widget::SecurityOriginPaintPolicy)
+void RenderScrollbar::paint(GraphicsContext& context, const IntRect& damageRect, Widget::SecurityOriginPaintPolicy, EventRegionContext*)
 {
     if (context.invalidatingControlTints()) {
         updateScrollbarParts();
index ea358df..ba17235 100644 (file)
@@ -68,7 +68,7 @@ private:
     void setParent(ScrollView*) override;
     void setEnabled(bool) override;
 
-    void paint(GraphicsContext&, const IntRect& damageRect, Widget::SecurityOriginPaintPolicy) override;
+    void paint(GraphicsContext&, const IntRect& damageRect, Widget::SecurityOriginPaintPolicy, EventRegionContext*) override;
 
     void setHoveredPart(ScrollbarPart) override;
     void setPressedPart(ScrollbarPart) override;
index 914ebbc..f083b52 100644 (file)
@@ -68,6 +68,12 @@ public:
 
     FrameView& frameView() const { return m_frameView; }
 
+    bool needsRepaintHackAfterCompositingLayerUpdateForDebugOverlaysOnly() const { return m_needsRepaintHackAfterCompositingLayerUpdateForDebugOverlaysOnly; };
+    void setNeedsRepaintHackAfterCompositingLayerUpdateForDebugOverlaysOnly(bool value = true) { m_needsRepaintHackAfterCompositingLayerUpdateForDebugOverlaysOnly = value; }
+
+    bool needsEventRegionUpdateForNonCompositedFrame() const { return m_needsEventRegionUpdateForNonCompositedFrame; }
+    void setNeedsEventRegionUpdateForNonCompositedFrame(bool value = true) { m_needsEventRegionUpdateForNonCompositedFrame = value; }
+
     Optional<LayoutRect> computeVisibleRectInContainer(const LayoutRect&, const RenderLayerModelObject* container, VisibleRectContext) const override;
     void repaintRootContents();
     void repaintViewRectangle(const LayoutRect&) const;
@@ -255,6 +261,8 @@ private:
     bool m_hasSoftwareFilters { false };
     bool m_usesFirstLineRules { false };
     bool m_usesFirstLetterRules { false };
+    bool m_needsRepaintHackAfterCompositingLayerUpdateForDebugOverlaysOnly { false };
+    bool m_needsEventRegionUpdateForNonCompositedFrame { false };
 
     HashMap<RenderElement*, Vector<CachedImage*>> m_renderersWithPausedImageAnimation;
     HashSet<RenderElement*> m_visibleInViewportRenderers;
index 3f6f33b..1c48db6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  * Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2006, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2020 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -246,8 +246,18 @@ void RenderWidget::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintO
         paintInfo.context().translate(widgetPaintOffset);
         paintRect.move(-widgetPaintOffset);
     }
+
+    if (paintInfo.eventRegionContext) {
+        AffineTransform transform;
+        transform.translate(contentPaintOffset);
+        paintInfo.eventRegionContext->pushTransform(transform);
+    }
+
     // FIXME: Remove repaintrect enclosing/integral snapping when RenderWidget becomes device pixel snapped.
-    m_widget->paint(paintInfo.context(), snappedIntRect(paintRect), paintInfo.requireSecurityOriginAccessForWidgets ? Widget::SecurityOriginPaintPolicy::AccessibleOriginOnly : Widget::SecurityOriginPaintPolicy::AnyOrigin);
+    m_widget->paint(paintInfo.context(), snappedIntRect(paintRect), paintInfo.requireSecurityOriginAccessForWidgets ? Widget::SecurityOriginPaintPolicy::AccessibleOriginOnly : Widget::SecurityOriginPaintPolicy::AnyOrigin, paintInfo.eventRegionContext);
+
+    if (paintInfo.eventRegionContext)
+        paintInfo.eventRegionContext->popTransform();
 
     if (!widgetPaintOffset.isZero())
         paintInfo.context().translate(-widgetPaintOffset);
@@ -282,7 +292,7 @@ void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
     if ((paintInfo.phase == PaintPhase::Outline || paintInfo.phase == PaintPhase::SelfOutline) && hasOutline())
         paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size()));
 
-    if (paintInfo.phase != PaintPhase::Foreground)
+    if (paintInfo.phase != PaintPhase::Foreground && (paintInfo.phase != PaintPhase::EventRegion || view().needsLayout()))
         return;
 
     if (style().hasBorderRadius()) {
@@ -304,6 +314,9 @@ void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
     if (style().hasBorderRadius())
         paintInfo.context().restore();
 
+    if (paintInfo.phase == PaintPhase::EventRegion)
+        return;
+
     // Paint a partially transparent wash over selected widgets.
     if (isSelected() && !document().printing()) {
         // FIXME: selectionRect() is in absolute, not painting coordinates.
index fc6b2e8..5de4159 100644 (file)
@@ -1,3 +1,17 @@
+2020-04-08  Daniel Bates  <dabates@apple.com>
+
+        Should find touch-action elements inside non-composited iframes
+        https://bugs.webkit.org/show_bug.cgi?id=210041
+        <rdar://problem/61323558>
+
+        Reviewed by Simon Fraser.
+
+        Pass EventRegionContext through. It is unused as it's not applicable for plugin painting.
+
+        * WebProcess/Plugins/PluginView.cpp:
+        (WebKit::PluginView::paint):
+        * WebProcess/Plugins/PluginView.h:
+
 2020-04-08  Brady Eidson  <beidson@apple.com>
 
         Fix handling non-linearized PDFs when incremental PDF loading is enabled.
index b605a28..c7fbaec 100644 (file)
@@ -783,7 +783,7 @@ void PluginView::setFrameRect(const WebCore::IntRect& rect)
     viewGeometryDidChange();
 }
 
-void PluginView::paint(GraphicsContext& context, const IntRect& /*dirtyRect*/, Widget::SecurityOriginPaintPolicy)
+void PluginView::paint(GraphicsContext& context, const IntRect& /*dirtyRect*/, Widget::SecurityOriginPaintPolicy, EventRegionContext*)
 {
     if (!m_plugin || !m_isInitialized || m_pluginElement->displayState() < HTMLPlugInElement::Restarting)
         return;
index 84d4264..03a91bc 100644 (file)
@@ -173,7 +173,7 @@ private:
 
     // WebCore::Widget
     void setFrameRect(const WebCore::IntRect&) override;
-    void paint(WebCore::GraphicsContext&, const WebCore::IntRect&, WebCore::Widget::SecurityOriginPaintPolicy) override;
+    void paint(WebCore::GraphicsContext&, const WebCore::IntRect&, WebCore::Widget::SecurityOriginPaintPolicy, WebCore::EventRegionContext*) override;
     void invalidateRect(const WebCore::IntRect&) override;
     void setFocus(bool) override;
     void frameRectsChanged() override;
index fa3a576..804be5a 100644 (file)
@@ -1,3 +1,17 @@
+2020-04-08  Daniel Bates  <dabates@apple.com>
+
+        Should find touch-action elements inside non-composited iframes
+        https://bugs.webkit.org/show_bug.cgi?id=210041
+        <rdar://problem/61323558>
+
+        Reviewed by Simon Fraser.
+
+        Pass EventRegionContext through. It is unused as it's not applicable for plugin painting.
+
+        * Plugins/PluginView.h:
+        * Plugins/PluginViewWin.cpp:
+        (WebCore::PluginView::paint):
+
 2020-04-03  Alex Christensen  <achristensen@webkit.org>
 
         Add SPI to make WKUserScripts wait for a notification
index b5b60a8..dee76cd 100644 (file)
@@ -181,7 +181,7 @@ namespace WebCore {
         void setFocus(bool) override;
         void show() override;
         void hide() override;
-        void paint(GraphicsContext&, const IntRect&, Widget::SecurityOriginPaintPolicy) override;
+        void paint(GraphicsContext&, const IntRect&, Widget::SecurityOriginPaintPolicy, EventRegionContext*) override;
         void clipRectChanged() override;
 
         // This method is used by plugins on all platforms to obtain a clip rect that includes clips set by WebCore,
index 5204594..b63b6a6 100644 (file)
@@ -530,7 +530,7 @@ void PluginView::paintWindowedPluginIntoContext(GraphicsContext& context, const
 #endif
 }
 
-void PluginView::paint(GraphicsContext& context, const IntRect& rect, Widget::SecurityOriginPaintPolicy)
+void PluginView::paint(GraphicsContext& context, const IntRect& rect, Widget::SecurityOriginPaintPolicy, EventRegionContext*)
 {
     if (!m_isStarted) {
         // Draw the "missing plugin" image