RESOLVED FIXED 172917
[Mac] Implement basic hit testing in the scrolling tree
https://bugs.webkit.org/show_bug.cgi?id=172917
Summary [Mac] Implement basic hit testing in the scrolling tree
Frédéric Wang (:fredw)
Reported 2017-06-05 04:52:58 PDT
After bug 172914, we can implement basic hit testing (which does not take into account overlapping or transformations for now).
Attachments
Patch (3.50 KB, patch)
2017-06-05 05:05 PDT, Frédéric Wang (:fredw)
no flags
Patch (22.72 KB, patch)
2017-06-08 10:55 PDT, Frédéric Wang (:fredw)
simon.fraser: review-
Patch (WIP) (24.53 KB, patch)
2017-09-08 10:09 PDT, Frédéric Wang (:fredw)
no flags
Patch (WIP) (25.48 KB, patch)
2017-09-12 08:21 PDT, Frédéric Wang (:fredw)
no flags
Patch (172914+172917) (65.78 KB, patch)
2017-09-13 02:08 PDT, Frédéric Wang (:fredw)
buildbot: commit-queue-
Archive of layout-test-results from ews107 for mac-elcapitan-wk2 (1.61 MB, application/zip)
2017-09-13 03:25 PDT, Build Bot
no flags
Patch (31.05 KB, patch)
2017-09-13 10:05 PDT, Frédéric Wang (:fredw)
no flags
Patch (37.24 KB, patch)
2017-09-14 02:42 PDT, Frédéric Wang (:fredw)
no flags
Patch (37.24 KB, patch)
2017-09-15 09:59 PDT, Frédéric Wang (:fredw)
no flags
Patch (37.19 KB, patch)
2018-11-22 12:52 PST, Frédéric Wang (:fredw)
no flags
Patch for EWS (includes patch from 172914) (69.48 KB, patch)
2018-11-26 06:53 PST, Frédéric Wang (:fredw)
ews-watchlist: commit-queue-
Archive of layout-test-results from ews101 for mac-sierra (2.45 MB, application/zip)
2018-11-26 07:58 PST, EWS Watchlist
no flags
Archive of layout-test-results from ews105 for mac-sierra-wk2 (3.05 MB, application/zip)
2018-11-26 08:09 PST, EWS Watchlist
no flags
Archive of layout-test-results from ews117 for mac-sierra (2.19 MB, application/zip)
2018-11-26 08:48 PST, EWS Watchlist
no flags
Archive of layout-test-results from ews203 for win-future (12.50 MB, application/zip)
2018-11-26 08:52 PST, EWS Watchlist
no flags
Temporary patch to set parentRelativeScrollableRect on scrolling nodes (10.75 KB, patch)
2018-11-29 01:17 PST, Frédéric Wang (:fredw)
no flags
Patch (37.08 KB, patch)
2018-11-29 07:13 PST, Frédéric Wang (:fredw)
no flags
Patch (36.67 KB, patch)
2018-11-29 23:14 PST, Frédéric Wang (:fredw)
no flags
Temporary patch to set parentRelativeScrollableRect on scrolling nodes (applies on top of bug 192358) (10.03 KB, patch)
2018-12-04 09:15 PST, Frédéric Wang (:fredw)
no flags
Temporary patch to set parentRelativeScrollableRect on scrolling nodes (24.02 KB, patch)
2019-01-07 03:32 PST, Frédéric Wang (:fredw)
no flags
Patch (36.65 KB, patch)
2019-01-07 03:32 PST, Frédéric Wang (:fredw)
no flags
Patch (38.58 KB, patch)
2019-01-09 07:40 PST, Frédéric Wang (:fredw)
no flags
Patch (61.53 KB, patch)
2019-01-30 17:06 PST, Simon Fraser (smfr)
no flags
Patch (63.06 KB, patch)
2019-01-30 17:38 PST, Simon Fraser (smfr)
no flags
Patch (63.06 KB, patch)
2019-01-30 18:42 PST, Simon Fraser (smfr)
no flags
Patch (65.92 KB, patch)
2019-01-30 19:28 PST, Simon Fraser (smfr)
no flags
Archive of layout-test-results from ews107 for mac-highsierra-wk2 (2.69 MB, application/zip)
2019-01-30 21:11 PST, EWS Watchlist
no flags
Patch (65.94 KB, patch)
2019-01-30 22:15 PST, Simon Fraser (smfr)
koivisto: review+
Frédéric Wang (:fredw)
Comment 1 2017-06-05 05:05:48 PDT Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 2 2017-06-08 10:55:20 PDT Comment hidden (obsolete)
Alexey Proskuryakov
Comment 3 2017-06-09 22:42:16 PDT Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 4 2017-06-09 22:46:34 PDT Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 5 2017-06-15 07:59:59 PDT
Comment on attachment 312321 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=312321&action=review > Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp:171 > + for (auto& child : *children()) { Note: the scrolling tree is in the order of the layer tree, so we should really select the latest (upmost) frame containing the mouse pointer. That still does not solve the issue of overlapping with layers outside the scrolling tree...
Frédéric Wang (:fredw)
Comment 6 2017-06-20 08:19:12 PDT
Comment on attachment 312321 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=312321&action=review > Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp:185 > + return this; More notes: - We should verify whether the localPosition is inside the frame rect before trying to check the children (otherwise e.g. on attachment 311465 [details] the blue rect is accessible from outside its parent frame). - The frame rect is not correct, see https://bugs.webkit.org/show_bug.cgi?id=172914#c8
Radar WebKit Bug Importer
Comment 7 2017-09-01 14:22:49 PDT
Simon Fraser (smfr)
Comment 8 2017-09-05 08:47:03 PDT Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 9 2017-09-08 10:09:06 PDT Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 10 2017-09-12 08:21:13 PDT Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 11 2017-09-13 02:08:06 PDT Comment hidden (obsolete)
Build Bot
Comment 12 2017-09-13 03:25:29 PDT Comment hidden (obsolete)
Build Bot
Comment 13 2017-09-13 03:25:30 PDT Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 14 2017-09-13 10:05:08 PDT Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 15 2017-09-14 02:42:57 PDT
Created attachment 320752 [details] Patch OK, it seems I had forgotten to rename the option "AsyncFrameScrollingEnabled" in tests. Now I realized that hit testing for overlapping elements has random pass/fail result. I believe this is due to the same issue I noticed in bug 172914: the order of iframe nodes in the layer tree is random (probably in the order they are loaded) so we can't rely on that order to determine which iframe is above and which one is below. Additionally, I added a test for axis-aligned transforms but it is currently failing (see bug 172914 comment 29).
Simon Fraser (smfr)
Comment 16 2017-09-14 08:21:53 PDT
(In reply to Frédéric Wang (:fredw) from comment #15) > Created attachment 320752 [details] > Patch > > OK, it seems I had forgotten to rename the option > "AsyncFrameScrollingEnabled" in tests. Now I realized that hit testing for > overlapping elements has random pass/fail result. I believe this is due to > the same issue I noticed in bug 172914: the order of iframe nodes in the > layer tree is random (probably in the order they are loaded) so we can't > rely on that order to determine which iframe is above and which one is below. We need to fix that; they have to be in z-order (which matches compositing layer and RenderLayer z-index order). I guess when adding nodes to the tree we need to do ordered insertion.
Frédéric Wang (:fredw)
Comment 17 2017-09-14 09:22:27 PDT
(In reply to Simon Fraser (smfr) from comment #16) > We need to fix that; they have to be in z-order (which matches compositing > layer and RenderLayer z-index order). I guess when adding nodes to the tree > we need to do ordered insertion. I opened bug 176914 for that.
Frédéric Wang (:fredw)
Comment 18 2017-09-15 09:59:19 PDT Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 19 2018-11-22 12:52:02 PST Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 20 2018-11-26 06:53:56 PST Comment hidden (obsolete)
EWS Watchlist
Comment 21 2018-11-26 07:58:17 PST Comment hidden (obsolete)
EWS Watchlist
Comment 22 2018-11-26 07:58:19 PST Comment hidden (obsolete)
EWS Watchlist
Comment 23 2018-11-26 08:09:21 PST Comment hidden (obsolete)
EWS Watchlist
Comment 24 2018-11-26 08:09:24 PST Comment hidden (obsolete)
EWS Watchlist
Comment 25 2018-11-26 08:48:35 PST Comment hidden (obsolete)
EWS Watchlist
Comment 26 2018-11-26 08:48:37 PST Comment hidden (obsolete)
EWS Watchlist
Comment 27 2018-11-26 08:52:10 PST Comment hidden (obsolete)
EWS Watchlist
Comment 28 2018-11-26 08:52:21 PST Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 29 2018-11-29 01:17:13 PST Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 30 2018-11-29 07:13:48 PST Comment hidden (obsolete)
Simon Fraser (smfr)
Comment 31 2018-11-29 10:44:14 PST
Comment on attachment 356005 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=356005&action=review > Source/WebCore/page/scrolling/ScrollingTree.cpp:109 > + target = target->parent(); So this is going to propagate scrolling in z-order tree order (when we have overflow scroll). handleWheelEventInAppropriateEnclosingBox() oddly uses containingBlock order, and normal events are in DOM order, so this is all really inconsistent. > Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp:178 > +ScrollingTreeScrollingNode* ScrollingTreeScrollingNode::scrollingTargetForWheelEvent(const PlatformWheelEvent& wheelEvent, LayoutPoint position) wheelEvent is not used by this function; why pass it? > Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp:186 > + LayoutPoint localPosition = position + -parentRelativeScrollableRect().location(); + -! > Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h:78 > + ScrollingTreeScrollingNode* scrollingTargetForWheelEvent(const PlatformWheelEvent&, LayoutPoint position); Maybe call this scrollingNodeForPoint()
Frédéric Wang (:fredw)
Comment 32 2018-11-29 11:10:21 PST
Comment on attachment 356005 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=356005&action=review >> Source/WebCore/page/scrolling/ScrollingTree.cpp:109 >> + target = target->parent(); > > So this is going to propagate scrolling in z-order tree order (when we have overflow scroll). handleWheelEventInAppropriateEnclosingBox() oddly uses containingBlock order, and normal events are in DOM order, so this is all really inconsistent. Not sure I understand the comment about z-order, I thought it is going to be containingBlock order. >> Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp:178 >> +ScrollingTreeScrollingNode* ScrollingTreeScrollingNode::scrollingTargetForWheelEvent(const PlatformWheelEvent& wheelEvent, LayoutPoint position) > > wheelEvent is not used by this function; why pass it? Right, this was used in previous patches and I forgot to removed it. >> Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp:186 >> + LayoutPoint localPosition = position + -parentRelativeScrollableRect().location(); > > + -! I need to check if the - operator is supported for LayoutPoint. >> Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h:78 >> + ScrollingTreeScrollingNode* scrollingTargetForWheelEvent(const PlatformWheelEvent&, LayoutPoint position); > > Maybe call this scrollingNodeForPoint() Yes, it makes sense now that I'm no longer using the wheel event here.
Frédéric Wang (:fredw)
Comment 33 2018-11-29 23:14:36 PST
Created attachment 356149 [details] Patch Addressing review comments and improving how the code is written (not tested yet).
Frédéric Wang (:fredw)
Comment 34 2018-12-04 09:15:29 PST Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 35 2019-01-07 03:32:17 PST Comment hidden (obsolete)
Frédéric Wang (:fredw)
Comment 36 2019-01-07 03:32:50 PST
Simon Fraser (smfr)
Comment 37 2019-01-07 15:55:03 PST
Comment on attachment 358491 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=358491&action=review > LayoutTests/fast/scrolling/iframe-hit-testing-axis-aligned-transforms.html:29 > +function checkForInnerFrameScroll() { JS functions should have brace on new line. > Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp:183 > + for (auto iterator = children()->rbegin(), end = children()->rend(); iterator != end; iterator++) { Does this take into account scrolling offsets that happened since parentRelativeScrollableRect was computed? > Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp:188 > + if (is<ScrollingTreeScrollingNode>(**iterator)) { > + auto& scrollingNode = downcast<ScrollingTreeScrollingNode>(**iterator); > + if (scrollingNode.parentRelativeScrollableRect().contains(localPosition)) > + return scrollingNode.scrollingNodeForPoint(localPosition); > + } This seems like it will never hit scrolling nodes nested inside of fixed or sticky nodes.
Frédéric Wang (:fredw)
Comment 38 2019-01-09 02:39:48 PST
Comment on attachment 358491 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=358491&action=review Hi Simon. Thanks for the feedback. I'm wondering what's your plan exactly for the parentRelativeScrollableRect property? I understood that you wanted to do something while refactoring RenderLayerCompositor and the part I extracted (attachment 358490 [details]) to set parentRelativeScrollableRect was just a temporary solution until you're done with your work. Also, I expected that parentRelativeScrollableRect would just be properly updated when scrolling happens. Are these assumptions correct? >> Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp:183 >> + for (auto iterator = children()->rbegin(), end = children()->rend(); iterator != end; iterator++) { > > Does this take into account scrolling offsets that happened since parentRelativeScrollableRect was computed? I just tried with a basic iframe in the main view and indeed the updateScrollCoordinationForThisFrame is generally not called for the subframe when scrolling the main frame (exceptions are e.g. when the iframe goes out of the visible rect). So parentRelativeScrollableRect will not be updated for the subframe with attachment 358490 [details]. I understand that ideally update should have happened during scrolling or maybe you mean scrollingNodeForPoint should be aware of potential offset changes? >> Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp:188 >> + } > > This seems like it will never hit scrolling nodes nested inside of fixed or sticky nodes. Yes, this seems wrong indeed (I actually checked with a test case too). I guess we should have a generic implementation of scrollingNodeForPoint that just forwards the call to descendants.
Frédéric Wang (:fredw)
Comment 39 2019-01-09 07:40:22 PST Comment hidden (obsolete)
Simon Fraser (smfr)
Comment 40 2019-01-19 21:15:59 PST
I've taken the patch here and have it mostly working (need to test overflow inside fixed etc). Fred, do you mind if I take the bug?
Frédéric Wang (:fredw)
Comment 41 2019-01-19 21:26:08 PST
(In reply to Simon Fraser (smfr) from comment #40) > I've taken the patch here and have it mostly working (need to test overflow > inside fixed etc). > > Fred, do you mind if I take the bug? No, feel free to take it.
Simon Fraser (smfr)
Comment 42 2019-01-29 20:26:39 PST
*** Bug 193880 has been marked as a duplicate of this bug. ***
Simon Fraser (smfr)
Comment 43 2019-01-29 20:28:50 PST
Adding the geometry info via bug 194002. I'll keep this for the hit testing.
Simon Fraser (smfr)
Comment 44 2019-01-29 20:42:29 PST
This is next on my list after bug 194002 lands.
Simon Fraser (smfr)
Comment 45 2019-01-30 17:06:39 PST Comment hidden (obsolete)
Simon Fraser (smfr)
Comment 46 2019-01-30 17:38:03 PST Comment hidden (obsolete)
Simon Fraser (smfr)
Comment 47 2019-01-30 18:42:28 PST Comment hidden (obsolete)
Simon Fraser (smfr)
Comment 48 2019-01-30 19:28:29 PST Comment hidden (obsolete)
EWS Watchlist
Comment 49 2019-01-30 21:11:09 PST Comment hidden (obsolete)
EWS Watchlist
Comment 50 2019-01-30 21:11:11 PST Comment hidden (obsolete)
Simon Fraser (smfr)
Comment 51 2019-01-30 21:59:35 PST
Comment on attachment 360677 [details] Patch This breaks rubber-banding.
Simon Fraser (smfr)
Comment 52 2019-01-30 22:15:13 PST
Antti Koivisto
Comment 53 2019-01-30 23:48:41 PST
Comment on attachment 360691 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=360691&action=review > Source/WebCore/ChangeLog:22 > + Nodes in the scrolling tree implement scrollingNodeForPoint() to implement hit testing. > + Two helper functions exist to simplify coordinate conversion: parentToLocalPoint() > + and localToContentsPoint(). Child nodes are hit-testing in reverse order to find nodes > + hightest in Z first. Only scrolling nodes are returned (not sure if we'll ever need > + to hit-test non-scrolling nodes). Nodes use parentRelativeScrollableRect and scroll positions > + to do these point mappings. It is still bit unclear to me why we want to do it like this. Wouldn't it be simpler and more robust to hit test in the layer tree, then find the corresponding ScrollingNode for the layer hit (several approaches for this)? Does that not work in some case?
Antti Koivisto
Comment 54 2019-01-31 00:17:18 PST
Still r+ because most of what this patch does is good.
Simon Fraser (smfr)
Comment 55 2019-01-31 08:01:41 PST
(In reply to Antti Koivisto from comment #53) > Comment on attachment 360691 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=360691&action=review > > > Source/WebCore/ChangeLog:22 > > + Nodes in the scrolling tree implement scrollingNodeForPoint() to implement hit testing. > > + Two helper functions exist to simplify coordinate conversion: parentToLocalPoint() > > + and localToContentsPoint(). Child nodes are hit-testing in reverse order to find nodes > > + hightest in Z first. Only scrolling nodes are returned (not sure if we'll ever need > > + to hit-test non-scrolling nodes). Nodes use parentRelativeScrollableRect and scroll positions > > + to do these point mappings. > > It is still bit unclear to me why we want to do it like this. Wouldn't it be > simpler and more robust to hit test in the layer tree, then find the > corresponding ScrollingNode for the layer hit (several approaches for this)? > Does that not work in some case? We have to hit-test on the scrolling thread on macOS. The GraphicsLayer tree is not thread-safe, and is not synchronized with commits (layout can nuke the graphics layer tree). CALayers don't have th right info for hit testing (there can be CALayers whose bounds don't reflect the right hit-testing areas, and some CALayers should be transparent to hit testing).
Simon Fraser (smfr)
Comment 56 2019-01-31 08:30:40 PST
Antti Koivisto
Comment 57 2019-01-31 08:40:53 PST
> We have to hit-test on the scrolling thread on macOS. The GraphicsLayer tree > is not thread-safe, and is not synchronized with commits (layout can nuke > the graphics layer tree). CALayers don't have th right info for hit testing > (there can be CALayers whose bounds don't reflect the right hit-testing > areas, and some CALayers should be transparent to hit testing). Scrolling thread :( In case of UI side scrolling, it would be easy to include any amount of hit testing meta data along with the layers (in RemoteLayerTreeNodes). Doesn't maintaining correct hit testing areas in ScrollingTree become complex in presence of transforms etc?
Simon Fraser (smfr)
Comment 58 2019-01-31 10:51:42 PST
(In reply to Antti Koivisto from comment #57) > > We have to hit-test on the scrolling thread on macOS. The GraphicsLayer tree > > is not thread-safe, and is not synchronized with commits (layout can nuke > > the graphics layer tree). CALayers don't have th right info for hit testing > > (there can be CALayers whose bounds don't reflect the right hit-testing > > areas, and some CALayers should be transparent to hit testing). > > Scrolling thread :( > > In case of UI side scrolling, it would be easy to include any amount of hit > testing meta data along with the layers (in RemoteLayerTreeNodes). Right, and that's what I plan to do. For macOS with the scrolling thread, either I'll have to push "overlap" layers into the scrolling tree, or somehow compute overlapped regions for each scroller, which gets hard. > Doesn't maintaining correct hit testing areas in ScrollingTree become > complex in presence of transforms etc? yes.
Frédéric Wang (:fredw)
Comment 59 2019-02-21 08:23:34 PST
> > Doesn't maintaining correct hit testing areas in ScrollingTree become > > complex in presence of transforms etc? > > yes. @Simon: Is bug 173354 still valid? Should we close it or are you working on it?
Note You need to log in before you can comment on or make changes to this bug.