Changeset 287777 in webkit
- Timestamp:
- Jan 7, 2022, 12:28:04 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/page/ModalContainerObserver.cpp (modified) (6 diffs)
-
Source/WebCore/page/ModalContainerObserver.h (modified) (3 diffs)
-
Source/WebCore/style/StyleAdjuster.cpp (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKit/modal-container-with-overlay.html (modified) (4 diffs)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/ModalContainerObservation.mm (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r287772 r287777 1 2022-01-07 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 Teach modal container observer to make the body element scrollable if necessary 4 https://bugs.webkit.org/show_bug.cgi?id=234708 5 rdar://86960677 6 7 Reviewed by Tim Horton. 8 9 Add a mechanism to allow ModalContainerObserver to force the body and/or document elements in the main document 10 to become vertically scrollable, in the case where a modal container has been detected. 11 12 In particular, if a modal container has already been detected and hidden away, the frame is non-scrollable, and 13 the body and/or document element satisfies both conditions: 14 15 1. Has a height that is taller than the visible height of the top FrameView 16 2. Has `overflow-y: hidden;` 17 18 ...then we'll flag one or both of those elements and force them to be vertically scrollable during style 19 adjustment (i.e. return `true` from `shouldMakeVerticallyScrollable()`). 20 21 Covered by augmenting an existing API test: 22 ModalContainerObservation.HideUserInteractionBlockingElementAndMakeDocumentScrollable 23 24 * page/ModalContainerObserver.cpp: 25 (WebCore::ModalContainerObserver::setContainer): 26 (WebCore::ModalContainerObserver::collectClickableElementsTimerFired): 27 (WebCore::ModalContainerObserver::makeBodyAndDocumentElementScrollableIfNeeded): 28 29 Helper method that contains logic for overriding scrollability on the body or html element, if needed. 30 31 (WebCore::ModalContainerObserver::clearScrollabilityOverrides): 32 (WebCore::ModalContainerObserver::hideUserInteractionBlockingElementIfNeeded): 33 34 Drive-by fix: `target` is just a raw pointer here, so just assign it directly to `foundElement` instead of 35 trying to use move semantics. 36 37 (WebCore::ModalContainerObserver::revealModalContainer): 38 (WebCore::ModalContainerObserver::shouldMakeVerticallyScrollable const): 39 40 Add a helper method (similar to `shouldHide()`) that can be used to make elements vertically scrollable during 41 style adjustment time. See above for more details. 42 43 (WebCore::ModalContainerObserver::tryToMakeBodyAndDocumentElementScrollableThroughQuirks): 44 * page/ModalContainerObserver.h: 45 * style/StyleAdjuster.cpp: 46 (WebCore::Style::Adjuster::adjust const): 47 48 Consult `shouldMakeVerticallyScrollable` in addition to `shouldHide` if `ModalContainerObserver` is present. 49 1 50 2022-01-07 Antti Koivisto <antti@apple.com> 2 51 -
trunk/Source/WebCore/page/ModalContainerObserver.cpp
r287671 r287777 263 263 return; 264 264 265 if (auto observer = container->document().modalContainerObserverIfExists(); observer && container == observer->container()) 266 observer->hideUserInteractionBlockingElementIfNeeded(); 265 auto observer = container->document().modalContainerObserverIfExists(); 266 if (!observer || container != observer->container()) 267 return; 268 269 observer->hideUserInteractionBlockingElementIfNeeded(); 270 observer->makeBodyAndDocumentElementScrollableIfNeeded(); 267 271 }); 268 272 } … … 539 543 return; 540 544 541 if (RefPtr controlToClick = classifiedControls.controlToClick(decision)) 545 if (RefPtr controlToClick = classifiedControls.controlToClick(decision)) { 546 observer->clearScrollabilityOverrides(*document); 542 547 controlToClick->dispatchSimulatedClick(nullptr, SendMouseUpDownEvents, DoNotShowPressedLook); 548 } 543 549 544 550 decisionScope.continueHidingModalContainerAfterScope(); … … 548 554 } 549 555 556 void ModalContainerObserver::makeBodyAndDocumentElementScrollableIfNeeded() 557 { 558 if (!container()) 559 return; 560 561 Ref document = container()->document(); 562 RefPtr view = document->view(); 563 if (!view || view->isScrollable()) 564 return; 565 566 document->updateLayoutIgnorePendingStylesheets(); 567 568 auto visibleHeight = view->visibleSize().height(); 569 auto shouldMakeElementScrollable = [visibleHeight] (Element* element) { 570 if (!element) 571 return false; 572 573 auto renderer = element->renderer(); 574 if (!renderer || renderer->style().overflowY() != Overflow::Hidden) 575 return false; 576 577 return element->boundingClientRect().height() > visibleHeight; 578 }; 579 580 if (!m_makeBodyElementScrollable) { 581 if (RefPtr body = document->body(); shouldMakeElementScrollable(body.get())) { 582 m_makeBodyElementScrollable = true; 583 body->invalidateStyle(); 584 } 585 } 586 587 if (!m_makeDocumentElementScrollable) { 588 if (RefPtr documentElement = document->documentElement(); shouldMakeElementScrollable(documentElement.get())) { 589 m_makeDocumentElementScrollable = true; 590 documentElement->invalidateStyle(); 591 } 592 } 593 } 594 595 void ModalContainerObserver::clearScrollabilityOverrides(Document& document) 596 { 597 if (std::exchange(m_makeBodyElementScrollable, false)) { 598 if (auto element = document.body()) 599 element->invalidateStyle(); 600 } 601 602 if (std::exchange(m_makeDocumentElementScrollable, false)) { 603 if (auto element = document.documentElement()) 604 element->invalidateStyle(); 605 } 606 } 607 550 608 void ModalContainerObserver::hideUserInteractionBlockingElementIfNeeded() 551 609 { 552 if (m_userInteractionBlockingElement) { 553 ASSERT_NOT_REACHED(); 554 return; 555 } 610 if (m_userInteractionBlockingElement) 611 return; 556 612 557 613 RefPtr container = this->container(); … … 594 650 595 651 if (!foundElement) 596 foundElement = WTFMove(target);652 foundElement = target; 597 653 } 598 654 … … 604 660 { 605 661 auto [container, frameOwner] = std::exchange(m_containerAndFrameOwnerForControls, { }); 606 if (container) 662 if (container) { 607 663 container->invalidateStyle(); 664 clearScrollabilityOverrides(container->document()); 665 } 608 666 609 667 if (auto element = std::exchange(m_userInteractionBlockingElement, { })) … … 661 719 } 662 720 721 bool ModalContainerObserver::shouldMakeVerticallyScrollable(const Element& element) const 722 { 723 if (m_makeBodyElementScrollable && element.document().body() == &element) 724 return true; 725 726 if (m_makeDocumentElementScrollable && element.document().documentElement() == &element) 727 return true; 728 729 return false; 730 } 731 663 732 } // namespace WebCore -
trunk/Source/WebCore/page/ModalContainerObserver.h
r287671 r287777 51 51 ~ModalContainerObserver(); 52 52 53 bool shouldMakeVerticallyScrollable(const Element&) const; 53 54 inline bool shouldHide(const Element&) const; 54 55 void updateModalContainerIfNeeded(const FrameView&); … … 64 65 void setContainer(Element&, HTMLFrameOwnerElement* = nullptr); 65 66 void searchForModalContainerOnBehalfOfFrameOwnerIfNeeded(HTMLFrameOwnerElement&); 67 68 void makeBodyAndDocumentElementScrollableIfNeeded(); 69 void clearScrollabilityOverrides(Document&); 66 70 67 71 Element* container() const; … … 79 83 bool m_collectingClickableElements { false }; 80 84 bool m_hasAttemptedToFulfillPolicy { false }; 85 bool m_makeBodyElementScrollable { false }; 86 bool m_makeDocumentElementScrollable { false }; 81 87 }; 82 88 -
trunk/Source/WebCore/style/StyleAdjuster.cpp
r287742 r287777 554 554 555 555 if (m_element) { 556 if (auto observer = m_element->document().modalContainerObserver(); observer && observer->shouldHide(*m_element)) 557 style.setDisplay(DisplayType::None); 556 if (auto observer = m_element->document().modalContainerObserverIfExists()) { 557 if (observer->shouldHide(*m_element)) 558 style.setDisplay(DisplayType::None); 559 if (observer->shouldMakeVerticallyScrollable(*m_element)) 560 style.setOverflowY(Overflow::Auto); 561 } 558 562 } 559 563 -
trunk/Tools/ChangeLog
r287773 r287777 1 2022-01-07 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 Teach modal container observer to make the body element scrollable if necessary 4 https://bugs.webkit.org/show_bug.cgi?id=234708 5 rdar://86960677 6 7 Reviewed by Tim Horton. 8 9 Adjust an existing API test to exercise the change. 10 11 * TestWebKitAPI/Tests/WebKit/modal-container-with-overlay.html: 12 * TestWebKitAPI/Tests/WebKitCocoa/ModalContainerObservation.mm: 13 (TestWebKitAPI::TEST): 14 1 15 2022-01-07 Ryan Haddad <ryanhaddad@apple.com> 2 16 -
trunk/Tools/TestWebKitAPI/Tests/WebKit/modal-container-with-overlay.html
r287671 r287777 1 1 <!DOCTYPE html> 2 <html >2 <html style="overflow: hidden;"> 3 3 <head> 4 4 <meta name="viewport" content="width=device-width, initial-scale=1"> … … 8 8 background-color: #EFEFEF; 9 9 font-family: system-ui; 10 } 11 12 body { 13 height: 3000px; 10 14 } 11 15 … … 59 63 </script> 60 64 </head> 61 <body >65 <body style="overflow: hidden;"> 62 66 <p id="content">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p> 63 67 <div id="overlay"></div> … … 68 72 <script> 69 73 button.addEventListener("click", () => { 74 document.body.style.removeProperty("overflow"); 75 document.documentElement.style.removeProperty("overflow"); 70 76 fixed.remove(); 71 77 overlay.remove(); -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ModalContainerObservation.mm
r287671 r287777 257 257 } 258 258 259 TEST(ModalContainerObservation, HideUserInteractionBlockingElement )259 TEST(ModalContainerObservation, HideUserInteractionBlockingElementAndMakeDocumentScrollable) 260 260 { 261 261 auto webView = createModalContainerWebView(); … … 267 267 NSString *hitTestedText = [webView stringByEvaluatingJavaScript:@"document.elementFromPoint(50, 50).textContent"]; 268 268 EXPECT_TRUE([hitTestedText containsString:@"Lorem"]); 269 EXPECT_WK_STREQ("auto", [webView stringByEvaluatingJavaScript:@"getComputedStyle(document.documentElement).overflowY"]); 270 EXPECT_WK_STREQ("auto", [webView stringByEvaluatingJavaScript:@"getComputedStyle(document.body).overflowY"]); 269 271 } 270 272
Note:
See TracChangeset
for help on using the changeset viewer.