Diff
Modified: trunk/LayoutTests/ChangeLog (242793 => 242794)
--- trunk/LayoutTests/ChangeLog 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/LayoutTests/ChangeLog 2019-03-12 14:45:31 UTC (rev 242794)
@@ -1,3 +1,14 @@
+2019-03-12 Antti Koivisto <[email protected]>
+
+ Compositing layer that renders two positioned elements should not hit test
+ https://bugs.webkit.org/show_bug.cgi?id=195371
+ <rdar://problem/48649586>
+
+ Reviewed by Simon Fraser.
+
+ * fast/scrolling/ios/overflow-scroll-overlap-2-expected.txt: Added.
+ * fast/scrolling/ios/overflow-scroll-overlap-2.html: Added.
+
2019-03-12 Enrique Ocaña González <[email protected]>
[Media][MSE] Don't emit timeUpdate after play() if currentTime hasn't changed
Added: trunk/LayoutTests/fast/scrolling/ios/overflow-scroll-overlap-2-expected.txt (0 => 242794)
--- trunk/LayoutTests/fast/scrolling/ios/overflow-scroll-overlap-2-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/scrolling/ios/overflow-scroll-overlap-2-expected.txt 2019-03-12 14:45:31 UTC (rev 242794)
@@ -0,0 +1,9 @@
+Test that scrollable areas with non-trivial overlap are correctly targeted.
+
+case 1:
+case 2: Scrollable 2
+case 3: Scrollable 3
+case 4: Scrollable 4
+case 5: Scrollable 5
+case 6:
+
Added: trunk/LayoutTests/fast/scrolling/ios/overflow-scroll-overlap-2.html (0 => 242794)
--- trunk/LayoutTests/fast/scrolling/ios/overflow-scroll-overlap-2.html (rev 0)
+++ trunk/LayoutTests/fast/scrolling/ios/overflow-scroll-overlap-2.html 2019-03-12 14:45:31 UTC (rev 242794)
@@ -0,0 +1,190 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<style>
+body {
+ touch-action: none;
+}
+.case {
+ width: 200px;
+ height: 200px;
+ display: inline-block;
+ position: relative;
+}
+.scrollcontent {
+ width: 500px;
+ height: 500px;
+ background: green;
+}
+
+.overflowscroll {
+ overflow: scroll;
+ height: 100px;
+ width: 100px;
+ position: absolute;
+ border: 2px solid black;
+}
+.overlapping {
+ position:absolute;
+ left: 25px;
+ top: 25px;
+ width: 100px;
+ height: 100px;
+ background: red;
+}
+.clip {
+ position:absolute;
+ width: 100px;
+ height: 100px;
+ overflow:hidden;
+}
+.large {
+ width: 3000px;
+ height: 150px;
+}
+#log {
+ position:relative;
+ white-space: pre;
+}
+</style>
+<script src=""
+<script type="text/_javascript_">
+if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ internals.settings.setAsyncFrameScrollingEnabled(true);
+ internals.settings.setAsyncOverflowScrollingEnabled(true);
+}
+
+function sleep(delay)
+{
+ return new Promise((resolve) => { setTimeout(resolve, delay); });
+}
+
+async function runTest() {
+ for (const scrollable of document.querySelectorAll('.overflowscroll')) {
+ scrollable.addEventListener('scroll', function(e) {
+ logScroll(e.target);
+ });
+ }
+
+ {
+ let i = 0;
+ for (const scrollcontent of document.querySelectorAll('.scrollcontent'))
+ scrollcontent.innerText = "Scrollable " + ++i;
+ }
+ {
+ let i = 0;
+ for (const overlapping of document.querySelectorAll('.overlapping'))
+ overlapping.insertBefore(document.createTextNode("Overlapping " + ++i), overlapping.firstChild);
+ }
+
+
+ if (!window.testRunner || !testRunner.runUIScript)
+ return;
+
+ for (const testcase of document.querySelectorAll('.case'))
+ testcase.style.display = 'none';
+
+ {
+ let i = 0;
+ for (const testcase of document.querySelectorAll('.case')) {
+ ++i;
+ testcase.style.display = 'inline-block';
+
+ const target = testcase.querySelector('.target');
+ const rect = target.getBoundingClientRect();
+ const centerX = (rect.left + rect.right) / 2;
+ const centerY = (rect.top + rect.bottom) / 2;
+ await touchAndDragFromPointToPoint(centerX, centerY, centerX, centerY - 30);
+ await liftUpAtPoint(centerX, centerY - 30);
+ await sleep(500);
+
+ testcase.style.display = 'none';
+ outputCase(i);
+ }
+ }
+
+ for (const testcase of document.querySelectorAll('.case'))
+ testcase.style.display = 'none';
+
+ testRunner.notifyDone();
+}
+
+const scrolledElements = new Set();
+
+function logScroll(element) {
+ if (scrolledElements.has(element))
+ return;
+ scrolledElements.add(element);
+}
+
+function outputCase(i) {
+ log.innerText += "case " + i + ": ";
+ for (const scrolled of scrolledElements)
+ log.innerText += scrolled.getElementsByClassName("scrollcontent")[0].innerText + " ";
+ log.innerText += "\n";
+ scrolledElements.clear();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+<p>
+Test that scrollable areas with non-trivial overlap are correctly targeted.
+</p>
+<div class="case">
+ <div class="overflowscroll target">
+ <div class="scrollcontent"></div>
+ </div>
+ <div class="overlapping" style="left: 80px">
+ <div class="overlapping" style="left: -40px; top: -30px"></div>
+ </div>
+</div>
+
+<div class="case">
+ <div class="overflowscroll target">
+ <div class="scrollcontent"></div>
+ </div>
+ <div class="overlapping" style="box-shadow: 0px 0px 32px 32px blue; left: 60px; top: 60px">
+ </div>
+</div>
+
+<div class="case">
+ <div class="overflowscroll target">
+ <div class="scrollcontent"></div>
+ </div>
+ <div class="overlapping" style="pointer-events:none">
+ </div>
+</div>
+
+<div class="case">
+ <div class="overflowscroll target">
+ <div class="scrollcontent"></div>
+ </div>
+ <div class="overlapping" style="top:-60px">
+ Text text text text text text text text text text text text text text text text text text text text text text
+ </div>
+</div>
+
+<div class="case">
+ <div class="overflowscroll target">
+ <div class="scrollcontent"></div>
+ </div>
+ <div class="overlapping" style="top:-60px; padding-left:40px">
+ Text text text text text text text text text text text text text text text text text text text text text text
+ </div>
+</div>
+
+<div class="case">
+ <div class="overflowscroll target">
+ <div class="scrollcontent"></div>
+ </div>
+ <div class="overlapping" style="top:40px; left:40px; border-radius:50px; line-height:100px">
+ </div>
+</div>
+
+<div id=log></div>
+
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (242793 => 242794)
--- trunk/Source/WebCore/ChangeLog 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/ChangeLog 2019-03-12 14:45:31 UTC (rev 242794)
@@ -1,3 +1,52 @@
+2019-03-12 Antti Koivisto <[email protected]>
+
+ Compositing layer that renders two positioned elements should not hit test
+ https://bugs.webkit.org/show_bug.cgi?id=195371
+ <rdar://problem/48649586>
+
+ Reviewed by Simon Fraser.
+
+ Compute and pass an event region for layers if it differs from layer bounds.
+
+ This patch fixes various block overflow and layer expansion cases. It does not handle
+ overflowing line boxes yet (it adds tests for those too).
+
+ Test: fast/scrolling/ios/overflow-scroll-overlap-2.html
+
+ * platform/graphics/GraphicsLayer.cpp:
+ (WebCore::GraphicsLayer::setEventRegion):
+ * platform/graphics/GraphicsLayer.h:
+ (WebCore::GraphicsLayer::eventRegion):
+ * platform/graphics/Region.h:
+ * platform/graphics/ca/GraphicsLayerCA.cpp:
+ (WebCore::GraphicsLayerCA::setEventRegion):
+ (WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
+ (WebCore::GraphicsLayerCA::updateEventRegion):
+
+ Pass the region via the main platform layer of the graphics layer.
+
+ * platform/graphics/ca/GraphicsLayerCA.h:
+ * platform/graphics/ca/PlatformCALayer.h:
+ * platform/graphics/ca/cocoa/PlatformCALayerCocoa.h:
+ * rendering/PaintInfo.h:
+ * rendering/PaintPhase.h:
+
+ Add EventRegion paint phase that computes the region instead of painting anything.
+
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::paintObject):
+ * rendering/RenderLayer.cpp:
+ (WebCore::RenderLayer::paintForegroundForFragments):
+ (WebCore::RenderLayer::paintForegroundForFragmentsWithPhase):
+
+ Invoke EventRegion paint phase.
+
+ * rendering/RenderLayer.h:
+ * rendering/RenderLayerBacking.cpp:
+ (WebCore::RenderLayerBacking::paintIntoLayer):
+
+ Request event region when pointing a layer.
+
2019-03-12 Philippe Normand <[email protected]>
[GStreamer][v4l2] Synchronous video texture flushing support
Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp (242793 => 242794)
--- trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp 2019-03-12 14:45:31 UTC (rev 242794)
@@ -31,6 +31,7 @@
#include "FloatRect.h"
#include "GraphicsContext.h"
#include "LayoutRect.h"
+#include "Region.h"
#include "RotateTransformOperation.h"
#include <wtf/HashMap.h>
#include <wtf/NeverDestroyed.h>
@@ -411,6 +412,11 @@
#endif
}
+void GraphicsLayer::setEventRegion(std::unique_ptr<Region>&& eventRegion)
+{
+ m_eventRegion = WTFMove(eventRegion);
+}
+
void GraphicsLayer::noteDeviceOrPageScaleFactorChangedIncludingDescendants()
{
deviceOrPageScaleFactorChanged();
Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayer.h (242793 => 242794)
--- trunk/Source/WebCore/platform/graphics/GraphicsLayer.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayer.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -54,6 +54,7 @@
class GraphicsContext;
class GraphicsLayerFactory;
class Image;
+class Region;
class TiledBacking;
class TimingFunction;
class TransformationMatrix;
@@ -452,6 +453,10 @@
WindRule shapeLayerWindRule() const;
virtual void setShapeLayerWindRule(WindRule);
+ // Non-null if the event sensitive region of the layer differs from the layer bounds.
+ const Region* eventRegion() const { return m_eventRegion.get(); }
+ virtual void setEventRegion(std::unique_ptr<Region>&&);
+
// Transitions are identified by a special animation name that cannot clash with a keyframe identifier.
static String animationNameForTransition(AnimatedPropertyID);
@@ -726,6 +731,8 @@
FloatRoundedRect m_backdropFiltersRect;
Optional<FloatRect> m_animationExtent;
+ std::unique_ptr<Region> m_eventRegion;
+
#if USE(CA)
WindRule m_shapeLayerWindRule { WindRule::NonZero };
Path m_shapeLayerPath;
Modified: trunk/Source/WebCore/platform/graphics/Region.h (242793 => 242794)
--- trunk/Source/WebCore/platform/graphics/Region.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/platform/graphics/Region.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -53,10 +53,10 @@
// Returns true if the query region is a subset of this region.
WEBCORE_EXPORT bool contains(const Region&) const;
- bool contains(const IntPoint&) const;
+ WEBCORE_EXPORT bool contains(const IntPoint&) const;
// Returns true if the query region intersects any part of this region.
- bool intersects(const Region&) const;
+ WEBCORE_EXPORT bool intersects(const Region&) const;
WEBCORE_EXPORT unsigned totalArea() const;
Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (242793 => 242794)
--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp 2019-03-12 14:45:31 UTC (rev 242794)
@@ -39,6 +39,7 @@
#include "PlatformCAFilters.h"
#include "PlatformCALayer.h"
#include "PlatformScreen.h"
+#include "Region.h"
#include "RotateTransformOperation.h"
#include "ScaleTransformOperation.h"
#include "TiledBacking.h"
@@ -51,6 +52,7 @@
#include <wtf/HexNumber.h>
#include <wtf/MathExtras.h>
#include <wtf/NeverDestroyed.h>
+#include <wtf/PointerComparison.h>
#include <wtf/SetForScope.h>
#include <wtf/SystemTracing.h>
#include <wtf/text/StringConcatenateNumbers.h>
@@ -982,6 +984,15 @@
noteLayerPropertyChanged(WindRuleChanged);
}
+void GraphicsLayerCA::setEventRegion(std::unique_ptr<Region>&& eventRegion)
+{
+ if (arePointingToEqualData(eventRegion, m_eventRegion))
+ return;
+
+ GraphicsLayer::setEventRegion(WTFMove(eventRegion));
+ noteLayerPropertyChanged(EventRegionChanged, DontScheduleFlush);
+}
+
bool GraphicsLayerCA::shouldRepaintOnSizeChange() const
{
return drawsContent() && !tiledBacking();
@@ -1844,6 +1855,9 @@
if (m_uncommittedChanges & MasksToBoundsRectChanged) // Needs to happen before ChildrenChanged
updateMasksToBoundsRect();
+ if (m_uncommittedChanges & EventRegionChanged)
+ updateEventRegion();
+
if (m_uncommittedChanges & MaskLayerChanged) {
updateMaskLayer();
// If the mask layer becomes tiled it can set this flag again. Clear the flag so that
@@ -1853,7 +1867,7 @@
if (m_uncommittedChanges & ContentsNeedsDisplay)
updateContentsNeedsDisplay();
-
+
if (m_uncommittedChanges & SupportsSubpixelAntialiasedTextChanged)
updateSupportsSubpixelAntialiasedText();
@@ -2755,6 +2769,11 @@
}
}
+void GraphicsLayerCA::updateEventRegion()
+{
+ m_layer->setEventRegion(eventRegion());
+}
+
void GraphicsLayerCA::updateMaskLayer()
{
PlatformCALayer* maskCALayer = m_maskLayer ? downcast<GraphicsLayerCA>(*m_maskLayer).primaryLayer() : nullptr;
Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h (242793 => 242794)
--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -124,6 +124,8 @@
WEBCORE_EXPORT void setShapeLayerPath(const Path&) override;
WEBCORE_EXPORT void setShapeLayerWindRule(WindRule) override;
+ WEBCORE_EXPORT void setEventRegion(std::unique_ptr<Region>&&) override;
+
WEBCORE_EXPORT void suspendAnimations(MonotonicTime) override;
WEBCORE_EXPORT void resumeAnimations() override;
@@ -413,6 +415,7 @@
void updateContentsColorLayer();
void updateContentsRects();
void updateMasksToBoundsRect();
+ void updateEventRegion();
void updateMaskLayer();
void updateReplicatedLayers();
@@ -531,6 +534,7 @@
WindRuleChanged = 1LLU << 37,
UserInteractionEnabledChanged = 1LLU << 38,
NeedsComputeVisibleAndCoverageRect = 1LLU << 39,
+ EventRegionChanged = 1LLU << 40,
};
typedef uint64_t LayerChangeFlags;
void addUncommittedChanges(LayerChangeFlags);
Modified: trunk/Source/WebCore/platform/graphics/ca/PlatformCALayer.h (242793 => 242794)
--- trunk/Source/WebCore/platform/graphics/ca/PlatformCALayer.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/platform/graphics/ca/PlatformCALayer.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -233,6 +233,9 @@
virtual WindRule shapeWindRule() const = 0;
virtual void setShapeWindRule(WindRule) = 0;
+
+ virtual const Region* eventRegion() const = 0;
+ virtual void setEventRegion(const Region*) = 0;
virtual GraphicsLayer::CustomAppearance customAppearance() const = 0;
virtual void updateCustomAppearance(GraphicsLayer::CustomAppearance) = 0;
Modified: trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.h (242793 => 242794)
--- trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -168,6 +168,9 @@
GraphicsLayer::CustomAppearance customAppearance() const override { return m_customAppearance; }
void updateCustomAppearance(GraphicsLayer::CustomAppearance) override;
+ const Region* eventRegion() const override { return nullptr; }
+ void setEventRegion(const Region*) override { }
+
GraphicsLayer::EmbeddedViewID embeddedViewID() const override;
TiledBacking* tiledBacking() override;
Modified: trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.h (242793 => 242794)
--- trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -157,6 +157,9 @@
GraphicsLayer::CustomAppearance customAppearance() const override { return m_customAppearance; }
void updateCustomAppearance(GraphicsLayer::CustomAppearance customAppearance) override { m_customAppearance = customAppearance; }
+ const Region* eventRegion() const override { return nullptr; }
+ void setEventRegion(const Region*) override { }
+
GraphicsLayer::EmbeddedViewID embeddedViewID() const override;
TiledBacking* tiledBacking() override;
Modified: trunk/Source/WebCore/rendering/PaintInfo.h (242793 => 242794)
--- trunk/Source/WebCore/rendering/PaintInfo.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/rendering/PaintInfo.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -38,6 +38,7 @@
namespace WebCore {
class OverlapTestRequestClient;
+class Region;
class RenderInline;
class RenderLayer;
class RenderLayerModelObject;
@@ -129,6 +130,7 @@
const RenderLayerModelObject* paintContainer; // the layer object that originates the current painting
bool requireSecurityOriginAccessForWidgets { false };
const RenderLayer* m_enclosingSelfPaintingLayer { nullptr };
+ Region* eventRegion { nullptr }; // For PaintPhase::EventRegion.
private:
GraphicsContext* m_context;
Modified: trunk/Source/WebCore/rendering/PaintPhase.h (242793 => 242794)
--- trunk/Source/WebCore/rendering/PaintPhase.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/rendering/PaintPhase.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -49,7 +49,8 @@
CollapsedTableBorders,
TextClip,
Mask,
- ClippingMask
+ ClippingMask,
+ EventRegion,
};
enum class PaintBehavior : uint16_t {
Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (242793 => 242794)
--- trunk/Source/WebCore/rendering/RenderBlock.cpp 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp 2019-03-12 14:45:31 UTC (rev 242794)
@@ -1240,6 +1240,17 @@
if (paintInfo.paintRootBackgroundOnly())
return;
+ if (paintPhase == PaintPhase::EventRegion) {
+ // FIXME: Handle inlines, lineboxes, SVG too.
+ // FIXME: Transforms?
+ if (style().pointerEvents() != PointerEvents::None)
+ paintInfo.eventRegion->unite(enclosingIntRect(LayoutRect(paintOffset, size())));
+
+ // No need to check descendants if we don't have overflow.
+ if (!hasVisualOverflow())
+ return;
+ }
+
// Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).
LayoutPoint scrolledOffset = paintOffset;
scrolledOffset.moveBy(-scrollPosition());
Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (242793 => 242794)
--- trunk/Source/WebCore/rendering/RenderLayer.cpp 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp 2019-03-12 14:45:31 UTC (rev 242794)
@@ -4746,6 +4746,8 @@
paintForegroundForFragmentsWithPhase(PaintPhase::Float, layerFragments, context, localPaintingInfo, localPaintBehavior, subtreePaintRootForRenderer);
paintForegroundForFragmentsWithPhase(PaintPhase::Foreground, layerFragments, context, localPaintingInfo, localPaintBehavior, subtreePaintRootForRenderer);
paintForegroundForFragmentsWithPhase(PaintPhase::ChildOutlines, layerFragments, context, localPaintingInfo, localPaintBehavior, subtreePaintRootForRenderer);
+ if (localPaintingInfo.eventRegion)
+ paintForegroundForFragmentsWithPhase(PaintPhase::EventRegion, layerFragments, context, localPaintingInfo, localPaintBehavior, subtreePaintRootForRenderer);
}
if (shouldClip)
@@ -4767,6 +4769,8 @@
PaintInfo paintInfo(context, fragment.foregroundRect.rect(), phase, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this, localPaintingInfo.requireSecurityOriginAccessForWidgets);
if (phase == PaintPhase::Foreground)
paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests;
+ if (phase == PaintPhase::EventRegion)
+ paintInfo.eventRegion = localPaintingInfo.eventRegion;
renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
if (shouldClip)
Modified: trunk/Source/WebCore/rendering/RenderLayer.h (242793 => 242794)
--- trunk/Source/WebCore/rendering/RenderLayer.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/rendering/RenderLayer.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -66,6 +66,7 @@
class HitTestRequest;
class HitTestResult;
class HitTestingTransformState;
+class Region;
class RenderFragmentedFlow;
class RenderGeometryMap;
class RenderLayerBacking;
@@ -905,6 +906,7 @@
OptionSet<PaintBehavior> paintBehavior;
bool requireSecurityOriginAccessForWidgets;
bool clipToDirtyRect { true };
+ Region* eventRegion { nullptr };
};
// Compute, cache and return clip rects computed with the given layer as the root.
Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (242793 => 242794)
--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2019-03-12 14:45:31 UTC (rev 242794)
@@ -51,6 +51,7 @@
#include "PerformanceLoggingClient.h"
#include "PluginViewBase.h"
#include "ProgressTracker.h"
+#include "Region.h"
#include "RenderFragmentContainer.h"
#include "RenderFragmentedFlow.h"
#include "RenderHTMLCanvas.h"
@@ -2573,10 +2574,22 @@
if (m_owningLayer.isRenderViewLayer())
renderer().view().frameView().willPaintContents(context, paintDirtyRect, paintingState);
- // FIXME: GraphicsLayers need a way to split for RenderFragmentContainers.
RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, paintDirtyRect, paintBehavior, -m_subpixelOffsetFromRenderer);
+
+ auto eventRegion = std::make_unique<Region>();
+ paintingInfo.eventRegion = eventRegion.get();
+
m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags);
+ paintingInfo.eventRegion = nullptr;
+ // Use null event region to indicate the entire layer is sensitive to events (the common case).
+ // FIXME: We could optimize Region so it doesn't use lots of memory if it contains a single rect only.
+ if (eventRegion->contains(roundedIntRect(compositedBounds())))
+ eventRegion = nullptr;
+ else
+ eventRegion->translate(roundedIntSize(contentOffsetInCompositingLayer()));
+ m_graphicsLayer->setEventRegion(WTFMove(eventRegion));
+
if (m_owningLayer.containsDirtyOverlayScrollbars())
m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
Modified: trunk/Source/WebKit/ChangeLog (242793 => 242794)
--- trunk/Source/WebKit/ChangeLog 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebKit/ChangeLog 2019-03-12 14:45:31 UTC (rev 242794)
@@ -1,3 +1,51 @@
+2019-03-12 Antti Koivisto <[email protected]>
+
+ Compositing layer that renders two positioned elements should not hit test
+ https://bugs.webkit.org/show_bug.cgi?id=195371
+ <rdar://problem/48649586>
+
+ Reviewed by Simon Fraser.
+
+ * Shared/RemoteLayerTree/RemoteLayerTreePropertyApplier.mm:
+ (WebKit::RemoteLayerTreePropertyApplier::applyProperties):
+ * Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h:
+ * Shared/RemoteLayerTree/RemoteLayerTreeTransaction.mm:
+ (WebKit::RemoteLayerTreeTransaction::LayerProperties::LayerProperties):
+ (WebKit::RemoteLayerTreeTransaction::LayerProperties::encode const):
+ (WebKit::RemoteLayerTreeTransaction::LayerProperties::decode):
+
+ Pass event region to UI process.
+
+ * UIProcess/RemoteLayerTree/RemoteLayerTreeNode.h:
+ (WebKit::RemoteLayerTreeNode::layerID const):
+ (WebKit::RemoteLayerTreeNode::eventRegion const):
+ * UIProcess/RemoteLayerTree/RemoteLayerTreeNode.mm:
+ (WebKit::RemoteLayerTreeNode::RemoteLayerTreeNode):
+ (WebKit::RemoteLayerTreeNode::~RemoteLayerTreeNode):
+ (WebKit::RemoteLayerTreeNode::setEventRegion):
+
+ Maintain event region in RemoteLayerTreeNodes.
+
+ (WebKit::RemoteLayerTreeNode::initializeLayer):
+ (WebKit::RemoteLayerTreeNode::layerID):
+ (WebKit::RemoteLayerTreeNode::forCALayer):
+
+ Move layerID to RemoteLayerTreeNode and store RemoteLayerTreeNode pointer to CALayers instead.
+ This makes it easy to find the matching RemoteLayerTreeNode from a layer, globally.
+
+ (WebKit::RemoteLayerTreeNode::setLayerID): Deleted.
+ * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm:
+ (WebKit::collectDescendantViewsAtPoint):
+
+ If we have event region, use it for hit testing.
+
+ (-[UIView _web_findDescendantViewAtPoint:withEvent:]):
+ (collectDescendantViewsAtPoint): Deleted.
+ * WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.cpp:
+ (WebKit::PlatformCALayerRemote::eventRegion const):
+ (WebKit::PlatformCALayerRemote::setEventRegion):
+ * WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.h:
+
2019-03-12 Carlos Garcia Campos <[email protected]>
[WPE][GTK] Load events may occur in unexpected order when JS redirects page before subresource load finishes
Modified: trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreePropertyApplier.mm (242793 => 242794)
--- trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreePropertyApplier.mm 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreePropertyApplier.mm 2019-03-12 14:45:31 UTC (rev 242794)
@@ -261,6 +261,9 @@
updateChildren(node, properties, relatedLayers);
updateMask(node, properties, relatedLayers);
+ if (properties.changedProperties & RemoteLayerTreeTransaction::EventRegionChanged)
+ node.setEventRegion(properties.eventRegion ? std::make_unique<WebCore::Region>(*properties.eventRegion) : nullptr);
+
#if PLATFORM(IOS_FAMILY)
applyPropertiesToUIView(node.uiView(), properties, relatedLayers);
#endif
Modified: trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h (242793 => 242794)
--- trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -92,6 +92,7 @@
EdgeAntialiasingMaskChanged = 1LLU << 35,
CustomAppearanceChanged = 1LLU << 36,
UserInteractionEnabledChanged = 1LLU << 37,
+ EventRegionChanged = 1LLU << 38,
};
struct LayerCreationProperties {
@@ -171,6 +172,7 @@
bool opaque;
bool contentsHidden;
bool userInteractionEnabled;
+ std::unique_ptr<WebCore::Region> eventRegion;
};
explicit RemoteLayerTreeTransaction();
Modified: trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreeTransaction.mm (242793 => 242794)
--- trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreeTransaction.mm 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreeTransaction.mm 2019-03-12 14:45:31 UTC (rev 242794)
@@ -32,6 +32,7 @@
#import "WebCoreArgumentCoders.h"
#import <QuartzCore/QuartzCore.h>
#import <WebCore/LengthFunctions.h>
+#import <WebCore/Region.h>
#import <WebCore/TimingFunction.h>
#import <wtf/text/CString.h>
#import <wtf/text/TextStream.h>
@@ -154,6 +155,10 @@
if (other.filters)
filters = std::make_unique<WebCore::FilterOperations>(*other.filters);
+
+ if (other.eventRegion)
+ eventRegion = std::make_unique<WebCore::Region>(*other.eventRegion);
+
}
void RemoteLayerTreeTransaction::LayerProperties::encode(IPC::Encoder& encoder) const
@@ -276,6 +281,12 @@
if (changedProperties & UserInteractionEnabledChanged)
encoder << userInteractionEnabled;
+
+ if (changedProperties & EventRegionChanged) {
+ encoder << !!eventRegion;
+ if (eventRegion)
+ encoder << *eventRegion;
+ }
}
bool RemoteLayerTreeTransaction::LayerProperties::decode(IPC::Decoder& decoder, LayerProperties& result)
@@ -499,6 +510,18 @@
return false;
}
+ if (result.changedProperties & EventRegionChanged) {
+ bool hasEventRegion = false;
+ if (!decoder.decode(hasEventRegion))
+ return false;
+ if (hasEventRegion) {
+ auto eventRegion = std::make_unique<WebCore::Region>();
+ if (!decoder.decode(*eventRegion))
+ return false;
+ result.eventRegion = WTFMove(eventRegion);
+ }
+ }
+
return true;
}
Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeNode.h (242793 => 242794)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeNode.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeNode.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -53,18 +53,29 @@
UIView *uiView() const { return m_uiView.get(); }
#endif
+ WebCore::GraphicsLayer::PlatformLayerID layerID() const { return m_layerID; }
+
+ const WebCore::Region* eventRegion() const { return m_eventRegion.get(); }
+ void setEventRegion(std::unique_ptr<WebCore::Region>&&);
+
void detachFromParent();
static WebCore::GraphicsLayer::PlatformLayerID layerID(CALayer *);
+ static RemoteLayerTreeNode* forCALayer(CALayer *);
+
static NSString *appendLayerDescription(NSString *description, CALayer *);
private:
- void setLayerID(WebCore::GraphicsLayer::PlatformLayerID);
+ void initializeLayer();
+ WebCore::GraphicsLayer::PlatformLayerID m_layerID;
+
RetainPtr<CALayer> m_layer;
#if PLATFORM(IOS_FAMILY)
RetainPtr<UIView> m_uiView;
#endif
+
+ std::unique_ptr<WebCore::Region> m_eventRegion;
};
}
Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeNode.mm (242793 => 242794)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeNode.mm 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeNode.mm 2019-03-12 14:45:31 UTC (rev 242794)
@@ -45,23 +45,30 @@
namespace WebKit {
+static NSString *const WKRemoteLayerTreeNodePropertyKey = @"WKRemoteLayerTreeNode";
+
RemoteLayerTreeNode::RemoteLayerTreeNode(WebCore::GraphicsLayer::PlatformLayerID layerID, RetainPtr<CALayer> layer)
- : m_layer(WTFMove(layer))
+ : m_layerID(layerID)
+ , m_layer(WTFMove(layer))
{
- setLayerID(layerID);
+ initializeLayer();
[m_layer setDelegate:[WebActionDisablingCALayerDelegate shared]];
}
#if PLATFORM(IOS_FAMILY)
RemoteLayerTreeNode::RemoteLayerTreeNode(WebCore::GraphicsLayer::PlatformLayerID layerID, RetainPtr<UIView> uiView)
- : m_layer([uiView.get() layer])
+ : m_layerID(layerID)
+ , m_layer([uiView.get() layer])
, m_uiView(WTFMove(uiView))
{
- setLayerID(layerID);
+ initializeLayer();
}
#endif
-RemoteLayerTreeNode::~RemoteLayerTreeNode() = default;
+RemoteLayerTreeNode::~RemoteLayerTreeNode()
+{
+ [layer() setValue:nil forKey:WKRemoteLayerTreeNodePropertyKey];
+}
std::unique_ptr<RemoteLayerTreeNode> RemoteLayerTreeNode::createWithPlainLayer(WebCore::GraphicsLayer::PlatformLayerID layerID)
{
@@ -80,18 +87,27 @@
[layer() removeFromSuperlayer];
}
-static NSString *const WKLayerIDPropertyKey = @"WKLayerID";
+void RemoteLayerTreeNode::setEventRegion(std::unique_ptr<WebCore::Region>&& eventRegion)
+{
+ m_eventRegion = WTFMove(eventRegion);
+}
-void RemoteLayerTreeNode::setLayerID(WebCore::GraphicsLayer::PlatformLayerID layerID)
+void RemoteLayerTreeNode::initializeLayer()
{
- [layer() setValue:@(layerID) forKey:WKLayerIDPropertyKey];
+ [layer() setValue:[NSValue valueWithPointer:this] forKey:WKRemoteLayerTreeNodePropertyKey];
}
WebCore::GraphicsLayer::PlatformLayerID RemoteLayerTreeNode::layerID(CALayer *layer)
{
- return [[layer valueForKey:WKLayerIDPropertyKey] unsignedLongLongValue];
+ auto* node = forCALayer(layer);
+ return node ? node->layerID() : 0;
}
+RemoteLayerTreeNode* RemoteLayerTreeNode::forCALayer(CALayer *layer)
+{
+ return static_cast<RemoteLayerTreeNode*>([[layer valueForKey:WKRemoteLayerTreeNodePropertyKey] pointerValue]);
+}
+
NSString *RemoteLayerTreeNode::appendLayerDescription(NSString *description, CALayer *layer)
{
NSString *layerDescription = [NSString stringWithFormat:@" layerID = %llu \"%@\"", WebKit::RemoteLayerTreeNode::layerID(layer), layer.name ? layer.name : @""];
Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm (242793 => 242794)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm 2019-03-12 14:45:31 UTC (rev 242794)
@@ -29,11 +29,15 @@
#if PLATFORM(IOS_FAMILY)
#import "RemoteLayerTreeHost.h"
+#import "RemoteLayerTreeNode.h"
#import "UIKitSPI.h"
#import "WKDrawingView.h"
+#import <WebCore/Region.h>
#import <pal/spi/cocoa/QuartzCoreSPI.h>
#import <wtf/SoftLinking.h>
+namespace WebKit {
+
static void collectDescendantViewsAtPoint(Vector<UIView *, 16>& viewsAtPoint, UIView *parent, CGPoint point, UIEvent *event)
{
if (parent.clipsToBounds && ![parent pointInside:point withEvent:event])
@@ -53,8 +57,12 @@
return true;
}();
- if (!isTransparent && [view pointInside:subviewPoint withEvent:event])
- viewsAtPoint.append(view);
+ if (!isTransparent && [view pointInside:subviewPoint withEvent:event]) {
+ auto* node = RemoteLayerTreeNode::forCALayer(view.layer);
+ auto* eventRegion = node ? node->eventRegion() : nullptr;
+ if (!eventRegion || eventRegion->contains(WebCore::IntPoint(subviewPoint)))
+ viewsAtPoint.append(view);
+ }
if (![view subviews])
return;
@@ -63,6 +71,8 @@
};
}
+}
+
@interface UIView (WKHitTesting)
- (UIView *)_web_findDescendantViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event;
@end
@@ -72,7 +82,7 @@
- (UIView *)_web_findDescendantViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event
{
Vector<UIView *, 16> viewsAtPoint;
- collectDescendantViewsAtPoint(viewsAtPoint, self, point, event);
+ WebKit::collectDescendantViewsAtPoint(viewsAtPoint, self, point, event);
for (auto i = viewsAtPoint.size(); i--;) {
auto *view = viewsAtPoint[i];
Modified: trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.cpp (242793 => 242794)
--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.cpp 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.cpp 2019-03-12 14:45:31 UTC (rev 242794)
@@ -38,6 +38,7 @@
#import <WebCore/PlatformCAFilters.h>
#import <WebCore/PlatformCALayerCocoa.h>
#import <WebCore/TiledBacking.h>
+#import <wtf/PointerComparison.h>
namespace WebKit {
using namespace WebCore;
@@ -870,6 +871,21 @@
m_properties.notePropertiesChanged(RemoteLayerTreeTransaction::CustomAppearanceChanged);
}
+const Region* PlatformCALayerRemote::eventRegion() const
+{
+ return m_properties.eventRegion.get();
+}
+
+void PlatformCALayerRemote::setEventRegion(const WebCore::Region* eventRegion)
+{
+ const auto* oldEventRegion = m_properties.eventRegion.get();
+ if (arePointingToEqualData(oldEventRegion, eventRegion))
+ return;
+
+ m_properties.eventRegion = eventRegion ? std::make_unique<WebCore::Region>(*eventRegion) : nullptr;
+ m_properties.notePropertiesChanged(RemoteLayerTreeTransaction::EventRegionChanged);
+}
+
GraphicsLayer::EmbeddedViewID PlatformCALayerRemote::embeddedViewID() const
{
return m_embeddedViewID;
Modified: trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.h (242793 => 242794)
--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.h 2019-03-12 14:17:06 UTC (rev 242793)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/PlatformCALayerRemote.h 2019-03-12 14:45:31 UTC (rev 242794)
@@ -174,6 +174,9 @@
WebCore::GraphicsLayer::CustomAppearance customAppearance() const override;
void updateCustomAppearance(WebCore::GraphicsLayer::CustomAppearance) override;
+ const WebCore::Region* eventRegion() const override;
+ void setEventRegion(const WebCore::Region*) override;
+
WebCore::GraphicsLayer::EmbeddedViewID embeddedViewID() const override;
WebCore::TiledBacking* tiledBacking() override { return nullptr; }