Bug 171667

Summary: [Mac] Make frames fast-scrollable
Product: WebKit Reporter: Frédéric Wang (:fredw) <fred.wang>
Component: FramesAssignee: Frédéric Wang (:fredw) <fred.wang>
Status: RESOLVED CONFIGURATION CHANGED    
Severity: Normal CC: ajuma, buildbot, fred.wang, rbuis, rbyers, rniwa, simon.fraser, steve, tonikitoo
Priority: P2    
Version: Safari Technology Preview   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 173354, 177009, 182925, 171923, 171974, 172287, 172349, 172806, 172825, 172851, 172914, 172917, 173359, 173644, 180002, 183081    
Bug Blocks:    
Attachments:
Description Flags
WIP Patch
none
WIP Patch
none
testcase
none
WIP Patch
buildbot: commit-queue-
Archive of layout-test-results from ews105 for mac-elcapitan-wk2
none
Archive of layout-test-results from ews126 for ios-simulator-wk2
none
Patch
buildbot: commit-queue-
Archive of layout-test-results from ews106 for mac-elcapitan-wk2
none
Archive of layout-test-results from ews122 for ios-simulator-wk2
none
Archive of layout-test-results from ews125 for ios-simulator-wk2
none
Patch
none
Patch
none
Patch
buildbot: commit-queue-
Archive of layout-test-results from ews105 for mac-elcapitan-wk2
none
testcase
none
Patch
none
Patch (do not use async scrolling when there are transformed nodes)
none
Patch
none
Test Patch to enable async frame scrolling none

Frédéric Wang (:fredw)
Reported 2017-05-04 09:32:13 PDT
From bug 149264 comment 17, this involves: > 1. Creating the right layer hierarchy with tiled backing store for the iframe contents, as we do for the main frame. > 2. Creating ScrollingStateFrameScrollingNodes for them > 3. Making sure the scrolling tree handles nested ScrollingStateFrameScrollingNodes properly > 4. Not putting iframe's ScrollableAreas into the non-fast scrollable region > 5. Teaching the scrolling thread to direct a mouse wheel at the appropriate ScrollingTreeFrameScrollingNode > 6. Making sure that scroll latching works > 7. Probably more
Attachments
WIP Patch (1.32 KB, patch)
2017-05-04 09:57 PDT, Frédéric Wang (:fredw)
no flags
WIP Patch (3.68 KB, patch)
2017-05-05 01:17 PDT, Frédéric Wang (:fredw)
no flags
testcase (721 bytes, text/html)
2017-05-05 03:35 PDT, Frédéric Wang (:fredw)
no flags
WIP Patch (4.97 KB, patch)
2017-05-10 05:43 PDT, Frédéric Wang (:fredw)
buildbot: commit-queue-
Archive of layout-test-results from ews105 for mac-elcapitan-wk2 (787.39 KB, application/zip)
2017-05-10 06:19 PDT, Build Bot
no flags
Archive of layout-test-results from ews126 for ios-simulator-wk2 (736.02 KB, application/zip)
2017-05-10 07:18 PDT, Build Bot
no flags
Patch (6.43 KB, patch)
2017-05-10 08:48 PDT, Frédéric Wang (:fredw)
buildbot: commit-queue-
Archive of layout-test-results from ews106 for mac-elcapitan-wk2 (527.90 KB, application/zip)
2017-05-17 06:54 PDT, Build Bot
no flags
Archive of layout-test-results from ews122 for ios-simulator-wk2 (856.76 KB, application/zip)
2017-05-17 08:09 PDT, Build Bot
no flags
Archive of layout-test-results from ews125 for ios-simulator-wk2 (926.35 KB, application/zip)
2017-05-17 09:37 PDT, Build Bot
no flags
Patch (22.71 KB, patch)
2017-05-24 11:04 PDT, Frédéric Wang (:fredw)
no flags
Patch (24.75 KB, patch)
2017-05-26 03:36 PDT, Frédéric Wang (:fredw)
no flags
Patch (26.12 KB, patch)
2017-05-29 00:45 PDT, Frédéric Wang (:fredw)
buildbot: commit-queue-
Archive of layout-test-results from ews105 for mac-elcapitan-wk2 (1.07 MB, application/zip)
2017-05-29 01:44 PDT, Build Bot
no flags
testcase (2.57 KB, text/html)
2017-05-29 01:47 PDT, Frédéric Wang (:fredw)
no flags
Patch (26.11 KB, patch)
2017-05-29 01:57 PDT, Frédéric Wang (:fredw)
no flags
Patch (do not use async scrolling when there are transformed nodes) (11.26 KB, patch)
2017-05-30 06:44 PDT, Frédéric Wang (:fredw)
no flags
Patch (1.43 KB, patch)
2017-06-14 02:14 PDT, Frédéric Wang (:fredw)
no flags
Test Patch to enable async frame scrolling (970 bytes, patch)
2017-06-26 08:08 PDT, Frédéric Wang (:fredw)
no flags
Frédéric Wang (:fredw)
Comment 1 2017-05-04 09:57:39 PDT
Created attachment 309057 [details] WIP Patch This is a first patch to address the points: > 1. Creating the right layer hierarchy with tiled backing store for the iframe contents, as we do for the main frame. > 4. Not putting iframe's ScrollableAreas into the non-fast scrollable region This is the layer tree I get for attachment 307586 [details] after applying this patch: layer 0x110b5f138 at (0,0) size 1039x644 (composited, bounds=at (0,0) size 1039x644, drawsContent=1, paints into ancestor=0) RenderView 0x1113dad00 at (0,0) size 1039x644 (needs layout: child) positive z-order list(1) layer 0x110b5f4e0 at (0,0) size 1039x166 RenderBlock 0x110a627e0 {HTML} at (0,0) size 1039x166 (needs layout: child) RenderBody 0x110a62c60 {BODY} at (8,16) size 1023x142 (needs layout: child) RenderBlock 0x110a62d80 {P} at (0,0) size 1023x18 RenderText 0x110ae49c0 {#text} at (0,0) size 211x18 text run at (0,0) width 211: "This iframe should be scrollable:" RenderBlock (anonymous) 0x110a62ea0 at (0,34) size 1023x108 (needs layout: child) RenderText 0x110ae4b40 {#text} at (0,0) size 0x0 normal flow list(1) layer 0x110b5f750 at (0,0) size 0x0 RenderIFrame 0x110b556f0 {IFRAME} at (0,0) size 304x104 [border: (2px inset #000000)] (needs layout: self) layer 0x110b5fd68 at (0,0) size 300x1016 (composited, bounds=at (0,0) size 300x1016, drawsContent=1, paints into ancestor=0) RenderView 0x1113f6d00 at (0,0) size 300x100 (layout overflow 0,0 300x1016) positive z-order list(1) layer 0x110b5fea0 at (0,0) size 300x1016 RenderBlock 0x110a62a20 {HTML} at (0,0) size 300x1016 RenderBody 0x110ae8360 {BODY} at (8,8) size 284x1000 RenderBlock 0x110ae8480 {DIV} at (0,0) size 284x1000 Also, the frame is no longer drawn as a non-fast scrollable region when one enables debug overlay. However, this breaks scrolling of the iframe for now :-) @Simon: I'm not sure the scrolling nodes are properly created yet, but I had one doubt. Again, IIUC the class hierarchy (https://people.igalia.com/fwang/ios/class-hierarchy/), each frame has its own Page with its own ScrollingCoordinator and hence their own Scrolling(State)Trees. So I am not sure I understand to which tree the ScrollingStateFrameScrollingNodes should belong? BTW, I also noticed this comment in RenderLayerCompositor::updateBacking, which might be related: // At this time, the ScrollingCoordinator only supports the top-level frame. if (layer.isRootLayer() && isMainFrameCompositor()) {
Frédéric Wang (:fredw)
Comment 2 2017-05-05 01:17:43 PDT
Created attachment 309151 [details] WIP Patch New version, trying to get the correct scrolling tree. This is what I get for attachment 307586 [details]: (Frame scrolling node (scrollable area size 924 465) (contents size 924 465) (layout viewport at (0,0) size 924x465) (min layout viewport origin (0,0)) (max layout viewport origin (0,0)) (fixed behavior: stick to viewport) (children 1 (Frame scrolling node (scrollable area size 285 100) (contents size 285 1016) (layout viewport at (0,0) size 285x100) (min layout viewport origin (0,0)) (max layout viewport origin (0,916)) (fixed behavior: stick to viewport) ) ) )
Frédéric Wang (:fredw)
Comment 3 2017-05-05 03:35:42 PDT
Created attachment 309154 [details] testcase
Frédéric Wang (:fredw)
Comment 4 2017-05-05 10:15:13 PDT
> 1. Creating the right layer hierarchy with tiled backing store for the iframe contents, as we do for the main frame. > 2. Creating ScrollingStateFrameScrollingNodes for them > 4. Not putting iframe's ScrollableAreas into the non-fast scrollable region These points are handled by attachment 309151 [details]. > 3. Making sure the scrolling tree handles nested ScrollingStateFrameScrollingNodes properly I am not sure what is expected here, but the scrolling tree in comment 2 looks good to me and I did not find any specific problem with nested ScrollingStateFrameScrollingNodes for now. > 5. Teaching the scrolling thread to direct a mouse wheel at the appropriate ScrollingTreeFrameScrollingNode So this is going to be the next task for me next week. The main problem is that ScrollingTree::handleWheelEvent sends the wheel event to the root of the scrolling tree. I tested a quick hack to forward the event to its children: - if (m_rootNode) + if (m_rootNode) { + for (auto& child : *m_rootNode->children()) { + downcast<ScrollingTreeScrollingNode>(*child).handleWheelEvent(wheelEvent); + } downcast<ScrollingTreeScrollingNode>(*m_rootNode).handleWheelEvent(wheelEvent); + } and this makes the iframes wheel-scroll correctly. So it seems the only remaining thing is to find the element that should receive the event. There is some logic in EventHandler::handleWheelEvent EventHandlerMac's EventHandler::platformPrepareForWheelEvents and findEnclosingScrollableContainer that should probably be shared i.e. we find the candidate to scroll and use the ThreadedScrollingTree (if it is fast-scrollabled) or delegate to the main thread otherwise (as currently always done). @Simon: Any suggestion about how to do this refactoring is welcomed ;-) > 6. Making sure that scroll latching works I tried it on the testcase with my little hack above and that seems to work too ;-)
Simon Fraser (smfr)
Comment 5 2017-05-05 10:25:50 PDT
(In reply to Frédéric Wang (:fredw) from comment #4) > > 1. Creating the right layer hierarchy with tiled backing store for the iframe contents, as we do for the main frame. > > 2. Creating ScrollingStateFrameScrollingNodes for them > > 4. Not putting iframe's ScrollableAreas into the non-fast scrollable region > > These points are handled by attachment 309151 [details]. > > > 3. Making sure the scrolling tree handles nested ScrollingStateFrameScrollingNodes properly > > I am not sure what is expected here, but the scrolling tree in comment 2 > looks good to me and I did not find any specific problem with nested > ScrollingStateFrameScrollingNodes for now. This is things like making sure the following work: * fast-scrolling iframe gaining or losing a position:fixed ancestor * fast-scrolling iframe inside fast-scrolling overflow:scroll (doesn't happen on Mac now, but will happen on iOS, and on Mac when overflow becomes fast-scrollable) * fast-scrolling iframe gains or loses fast-scrolling overflow:scroll ancestor > > 5. Teaching the scrolling thread to direct a mouse wheel at the appropriate ScrollingTreeFrameScrollingNode > > So this is going to be the next task for me next week. The main problem is > that ScrollingTree::handleWheelEvent sends the wheel event to the root of > the scrolling tree. I tested a quick hack to forward the event to its > children: > > - if (m_rootNode) > + if (m_rootNode) { > + for (auto& child : *m_rootNode->children()) { > + > downcast<ScrollingTreeScrollingNode>(*child).handleWheelEvent(wheelEvent); > + } > > downcast<ScrollingTreeScrollingNode>(*m_rootNode). > handleWheelEvent(wheelEvent); > + } > > and this makes the iframes wheel-scroll correctly. So it seems the only > remaining thing is to find the element that should receive the event. There > is some logic in > > EventHandler::handleWheelEvent > EventHandlerMac's EventHandler::platformPrepareForWheelEvents and > findEnclosingScrollableContainer > > that should probably be shared i.e. we find the candidate to scroll and use > the ThreadedScrollingTree (if it is fast-scrollabled) or delegate to the > main thread otherwise (as currently always done). @Simon: Any suggestion > about how to do this refactoring is welcomed ;-) I haven't really thought about this, but it's basically a hit-test on the scrolling tree. We'll have to make sure that transformed frames work OK, and those with elements on top from the parent frame. > > 6. Making sure that scroll latching works > > I tried it on the testcase with my little hack above and that seems to work > too ;-)
Frédéric Wang (:fredw)
Comment 6 2017-05-05 10:37:29 PDT
(In reply to Simon Fraser (smfr) from comment #5) > This is things like making sure the following work: > * fast-scrolling iframe gaining or losing a position:fixed ancestor > * fast-scrolling iframe inside fast-scrolling overflow:scroll (doesn't > happen on Mac now, but will happen on iOS, and on Mac when overflow becomes > fast-scrollable) > * fast-scrolling iframe gains or loses fast-scrolling overflow:scroll > ancestor I see. More things to test :-) > I haven't really thought about this, but it's basically a hit-test on the > scrolling tree. We'll have to make sure that transformed frames work OK, and > those with elements on top from the parent frame. Right, however the code I mentioned does more work (for example if an iframe is already scrolled to its maximum in the scroll direction, then we have to forward the scroll to another scrollable element e.g. an ancestor). Also, I believe if we have a non-fast scrollable elements inside a fast-scrollable element (if that's ever possible) then we should not select that fast-scrollable element from the scrolling tree but instead redirect the scroll event to the non-fast scrollable using the main thread.
Frédéric Wang (:fredw)
Comment 7 2017-05-09 09:53:01 PDT
@Simon: I have some more questions on this: > I haven't really thought about this, but it's basically a hit-test on the scrolling tree. We'll have to make sure that transformed frames work OK, and those with elements on top from the parent frame. 1) I'm not sure I understand how to perform the hit-test. My initial thought was to do like the slow path (EventHandler::handleWheelEvent and EventHandlerMac's EventHandler::platformPrepareForWheelEvents and findEnclosingScrollableContainer) but it's probably not a good idea (or even permitted) to check the DOM tree here. Using only the scrolling tree, I don't see much data available but ScrollingStateFrameScrollingNode::m_eventTrackingRegions to detect whether the mouse position is in a frame. It will probably not work for general scrolling nodes though. Was the plan to attach more data into the scrolling tree for that purpose? 2) I see FIXME comments in the following functions mentioned handling SynchronousScrollingReasons for more than the main frame: ScrollingCoordinator::updateSynchronousScrollingReasons ScrollingCoordinator::replaySessionStateDidChange and there are already data in the corresponding Scrolling{Tree|State}FrameScrollingNode. Do you what's the plan here and what should be done exactly? It looks like this is a kind of refactoring that could be done in a preliminary step/bug.
Frédéric Wang (:fredw)
Comment 8 2017-05-10 05:43:18 PDT
Created attachment 309595 [details] WIP Patch
Build Bot
Comment 9 2017-05-10 05:45:35 PDT
Attachment 309595 [details] did not pass style-queue: ERROR: Source/WebCore/rendering/RenderLayerCompositor.h:463: The parameter name "layer" adds no information, so it should be removed. [readability/parameter_name] [5] Total errors found: 1 in 4 files If any of these errors are false positives, please file a bug against check-webkit-style.
Build Bot
Comment 10 2017-05-10 06:19:54 PDT
Comment on attachment 309595 [details] WIP Patch Attachment 309595 [details] did not pass mac-wk2-ews (mac-wk2): Output: http://webkit-queues.webkit.org/results/3711637 Number of test failures exceeded the failure limit.
Build Bot
Comment 11 2017-05-10 06:19:55 PDT
Created attachment 309598 [details] Archive of layout-test-results from ews105 for mac-elcapitan-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews105 Port: mac-elcapitan-wk2 Platform: Mac OS X 10.11.6
Build Bot
Comment 12 2017-05-10 07:18:14 PDT
Comment on attachment 309595 [details] WIP Patch Attachment 309595 [details] did not pass ios-sim-ews (ios-simulator-wk2): Output: http://webkit-queues.webkit.org/results/3711764 New failing tests: compositing/iframes/scrolling-iframe.html
Build Bot
Comment 13 2017-05-10 07:18:16 PDT
Created attachment 309602 [details] Archive of layout-test-results from ews126 for ios-simulator-wk2 The attached test failures were seen while running run-webkit-tests on the ios-sim-ews. Bot: ews126 Port: ios-simulator-wk2 Platform: Mac OS X 10.11.6
Frédéric Wang (:fredw)
Comment 14 2017-05-10 08:48:57 PDT
Created attachment 309610 [details] Patch > 2) I see FIXME comments in the following functions mentioned handling SynchronousScrollingReasons for more than the main frame: I'm updating this patch to hopefully address this FIXME. Preliminary refactoring moved to bug 171923.
Build Bot
Comment 15 2017-05-17 06:54:08 PDT
Comment on attachment 309610 [details] Patch Attachment 309610 [details] did not pass mac-wk2-ews (mac-wk2): Output: http://webkit-queues.webkit.org/results/3762691 Number of test failures exceeded the failure limit.
Build Bot
Comment 16 2017-05-17 06:54:10 PDT
Created attachment 310386 [details] Archive of layout-test-results from ews106 for mac-elcapitan-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews106 Port: mac-elcapitan-wk2 Platform: Mac OS X 10.11.6
Build Bot
Comment 17 2017-05-17 08:09:11 PDT
Comment on attachment 309610 [details] Patch Attachment 309610 [details] did not pass ios-sim-ews (ios-simulator-wk2): Output: http://webkit-queues.webkit.org/results/3762790 New failing tests: compositing/iframes/scrolling-iframe.html
Build Bot
Comment 18 2017-05-17 08:09:12 PDT
Created attachment 310392 [details] Archive of layout-test-results from ews122 for ios-simulator-wk2 The attached test failures were seen while running run-webkit-tests on the ios-sim-ews. Bot: ews122 Port: ios-simulator-wk2 Platform: Mac OS X 10.11.6
Build Bot
Comment 19 2017-05-17 09:37:18 PDT
Comment on attachment 309610 [details] Patch Attachment 309610 [details] did not pass ios-sim-ews (ios-simulator-wk2): Output: http://webkit-queues.webkit.org/results/3763253 New failing tests: compositing/iframes/scrolling-iframe.html
Build Bot
Comment 20 2017-05-17 09:37:19 PDT
Created attachment 310399 [details] Archive of layout-test-results from ews125 for ios-simulator-wk2 The attached test failures were seen while running run-webkit-tests on the ios-sim-ews. Bot: ews125 Port: ios-simulator-wk2 Platform: Mac OS X 10.11.6
Frédéric Wang (:fredw)
Comment 21 2017-05-24 11:04:00 PDT
Frédéric Wang (:fredw)
Comment 22 2017-05-24 11:15:43 PDT
> 18:45:47 - smfr : fredw: i think ScrollingTreeScrollingNode will need an offset from its parent or something > 18:46:37 - fredw : smfr: OK, that makese sense. IIRC the size is already available. Not sure about the transforms you mentioned in the past, or even the "z-index" > 18:47:32 - smfr : fredw: we probabty should just bail out of there’s a non-axis-aligned transform > 18:47:53 - smfr : handling overlapping elements will be tricky; we’ll need to compute overlap somewhere > 18:48:35 - fredw : smfr: bail out = you mean use the non-fast path, right? > 18:48:59 - smfr : right @Simon: So I just uploaded a new patch that adds an "offset from parent" value. I was wondering what size should I use ScrollableTreeScrollingNode::m_reachableContentsSize?
Frédéric Wang (:fredw)
Comment 23 2017-05-26 03:36:27 PDT
Created attachment 311348 [details] Patch This patch implements basic support but there are still many things to do, for example: 1) do not pass the scrolling event to a box scrolled at maximum 2) transformations 3) overlapping I discussed a bit with a colleague working on scrolling in Servo. For 2), it seems we can just apply the transform to the mouse position in order to move to the child's coordinate (similarly to what is done for the offsetInParent). For 3), Servo uses the display list which provides a better browsing order to get the clicked child.
Frédéric Wang (:fredw)
Comment 24 2017-05-29 00:45:43 PDT
Created attachment 311463 [details] Patch do not pass the scrolling event to a box scrolled at maximum
Build Bot
Comment 25 2017-05-29 00:47:16 PDT
Attachment 311463 [details] did not pass style-queue: ERROR: Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h:70: The parameter name "wheelEvent" adds no information, so it should be removed. [readability/parameter_name] [5] Total errors found: 1 in 12 files If any of these errors are false positives, please file a bug against check-webkit-style.
Build Bot
Comment 26 2017-05-29 01:44:02 PDT
Comment on attachment 311463 [details] Patch Attachment 311463 [details] did not pass mac-wk2-ews (mac-wk2): Output: http://webkit-queues.webkit.org/results/3836006 Number of test failures exceeded the failure limit.
Build Bot
Comment 27 2017-05-29 01:44:04 PDT
Created attachment 311464 [details] Archive of layout-test-results from ews105 for mac-elcapitan-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews105 Port: mac-elcapitan-wk2 Platform: Mac OS X 10.11.6
Frédéric Wang (:fredw)
Comment 28 2017-05-29 01:47:17 PDT
Created attachment 311465 [details] testcase More test cases.
Frédéric Wang (:fredw)
Comment 29 2017-05-29 01:57:29 PDT
Frédéric Wang (:fredw)
Comment 30 2017-05-30 06:44:56 PDT
Created attachment 311503 [details] Patch (do not use async scrolling when there are transformed nodes) This is an attempt to avoid async scrolling when there are transformed nodes, but it does not work.
Frédéric Wang (:fredw)
Comment 31 2017-06-14 02:09:17 PDT
Comment on attachment 311503 [details] Patch (do not use async scrolling when there are transformed nodes) Moved to bug 173354.
Frédéric Wang (:fredw)
Comment 32 2017-06-14 02:14:07 PDT
Created attachment 312873 [details] Patch Attachment 311466 [details] has been split into "Depends on" bugs, so the only remaining change here is the defaultScrollingTreeIncludesFrames setting.
Frédéric Wang (:fredw)
Comment 33 2017-06-26 08:08:38 PDT
Created attachment 313839 [details] Test Patch to enable async frame scrolling
Frédéric Wang (:fredw)
Comment 34 2017-11-15 08:43:08 PST
Comment on attachment 313839 [details] Test Patch to enable async frame scrolling minibrowser and iOS11 have UI to enable async scrolling, so this patch is no longer useful.
Simon Fraser (smfr)
Comment 35 2021-12-19 13:28:49 PST
This is complete now.
Note You need to log in before you can comment on or make changes to this bug.