Changeset 251043 in webkit
- Timestamp:
- Oct 11, 2019 11:09:04 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 14 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/imported/w3c/ChangeLog
r250993 r251043 1 2019-10-11 Ryosuke Niwa <rniwa@webkit.org> 2 3 Add the support for ShadowRoot.delegateFocus 4 https://bugs.webkit.org/show_bug.cgi?id=166484 5 <rdar://problem/29816058> 6 7 Reviewed by Antti Koivisto. 8 9 Import W3C tests from https://github.com/web-platform-tests/wpt/pull/18035/commits/a8a89f224f2170723170a452cb18b46cafb723b6. 10 11 * web-platform-tests/resources/testdriver-vendor.js: 12 * web-platform-tests/shadow-dom/focus/click-focus-delegatesFocus-click-method-expected.txt: Added. 13 * web-platform-tests/shadow-dom/focus/click-focus-delegatesFocus-click-method.html: Added. 14 * web-platform-tests/shadow-dom/focus/click-focus-delegatesFocus-tabindex-varies-expected.txt: Added. 15 * web-platform-tests/shadow-dom/focus/click-focus-delegatesFocus-tabindex-varies.html: Added. 16 * web-platform-tests/shadow-dom/focus/click-focus-delegatesFocus-tabindex-zero-expected.txt: Added. 17 * web-platform-tests/shadow-dom/focus/click-focus-delegatesFocus-tabindex-zero.html: Added. 18 * web-platform-tests/shadow-dom/focus/focus-method-delegatesFocus-expected.txt: Added. 19 * web-platform-tests/shadow-dom/focus/focus-method-delegatesFocus.html: Added. 20 * web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-negative-delegatesFocus-expected.txt: Added. 21 * web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-negative-delegatesFocus.html: Added. 22 * web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-varying-delegatesFocus-expected.txt: Added. 23 * web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-varying-delegatesFocus.html: Added. 24 * web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-delegatesFocus-expected.txt: Added. 25 * web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-delegatesFocus.html: Added. 26 1 27 2019-10-10 Carlos Alberto Lopez Perez <clopez@igalia.com> 2 28 -
trunk/LayoutTests/imported/w3c/web-platform-tests/resources/testdriver-vendor.js
r250696 r251043 179 179 } 180 180 181 window.test_driver_internal.click = function (element, coords) 182 { 183 if (!window.eventSender) 184 return Promise.reject(new Error("window.eventSender is undefined.")); 185 186 if (testRunner.isIOSFamily && testRunner.isWebKit2) { 187 return new Promise((resolve) => { 188 testRunner.runUIScript(` 189 uiController.singleTapAtPoint(${coords.x}, ${coords.y}, function() { 190 uiController.uiScriptComplete(); 191 });`, resolve); 192 }); 193 } 194 195 eventSender.mouseMoveTo(coords.x, coords.y); 196 eventSender.mouseDown(); 197 eventSender.mouseUp(); 198 199 return Promise.resolve(); 200 } 201 181 202 window.test_driver_internal.action_sequence = function(sources) 182 203 { -
trunk/Source/WebCore/ChangeLog
r251041 r251043 1 2019-10-11 Ryosuke Niwa <rniwa@webkit.org> 2 3 Add the support for ShadowRoot.delegateFocus 4 https://bugs.webkit.org/show_bug.cgi?id=166484 5 <rdar://problem/29816058> 6 7 Reviewed by Antti Koivisto. 8 9 Implement delegatesFocus as specified in https://github.com/whatwg/html/pull/4796 10 11 When the shadow root of an element has delegates focus flag set, focusing on the shadow host would automatically 12 "delegates" focus to the first focusable element in the shadow tree instead. 13 14 The first focusable element is determined as the first element that is programatically focusable or mouse focusable 15 in the flat tree (composed tree in WebKit's terminology) in the case of the element getting focused via DOM API, 16 Element.prototype.focus, by via mouse down. In the case of sequential focus navigation (via tab key), it's the 17 first keyboard focusable element in the tabIndex order. 18 19 Tests: imported/w3c/web-platform-tests/shadow-dom/focus/click-focus-delegatesFocus-click-method.html 20 imported/w3c/web-platform-tests/shadow-dom/focus/click-focus-delegatesFocus-tabindex-varies.html 21 imported/w3c/web-platform-tests/shadow-dom/focus/click-focus-delegatesFocus-tabindex-zero.html 22 imported/w3c/web-platform-tests/shadow-dom/focus/focus-method-delegatesFocus.html 23 imported/w3c/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-negative-delegatesFocus.html 24 imported/w3c/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-varying-delegatesFocus.html 25 imported/w3c/web-platform-tests/shadow-dom/focus/focus-tabindex-order-shadow-zero-delegatesFocus.html 26 27 * dom/Element.cpp: 28 (WebCore::Element::isKeyboardFocusable const): A shadow host with the delegates focus flag is not considered as 29 keyboard focusable. The rest is taken care of by the existing logic in FocusController. 30 (WebCore::isProgramaticallyFocusable): Extracted from Element::focus. 31 (WebCore::findFirstProgramaticallyFocusableElementInComposedTree): Added. 32 (WebCore::Element::focus): Added the support for delegatesFocus. 33 * dom/Element.h: 34 (WebCore::ShadowRootInit::delegatesFocus): Added. 35 * dom/Element.idl: Ditto. 36 * dom/ShadowRoot.cpp: 37 (WebCore::ShadowRoot::ShadowRoot): Added delegatesFocus to the constructor. 38 * dom/ShadowRoot.h: 39 * page/EventHandler.cpp: 40 (WebCore::findFirstMouseFocusableElementInComposedTree): Added. 41 (WebCore::EventHandler::dispatchMouseEvent): Added the support for delegatesFocus. Uses the first mouse focusable 42 element in the flat tree (composed tree) order. 43 * page/FocusController.cpp: 44 (WebCore::FocusController::findFirstFocusableElementInShadowRoot): 45 * page/FocusController.h: 46 1 47 2019-10-11 Rob Buis <rbuis@igalia.com> 2 48 -
trunk/Source/WebCore/dom/Element.cpp
r250821 r251043 36 36 #include "ClassChangeInvalidation.h" 37 37 #include "ComposedTreeAncestorIterator.h" 38 #include "ComposedTreeIterator.h" 38 39 #include "ContainerNodeAlgorithms.h" 39 40 #include "CustomElementReactionQueue.h" … … 279 280 bool Element::isKeyboardFocusable(KeyboardEvent*) const 280 281 { 281 return isFocusable() && !shouldBeIgnoredInSequentialFocusNavigation() && tabIndexSetExplicitly().valueOr(0) >= 0; 282 if (!(isFocusable() && !shouldBeIgnoredInSequentialFocusNavigation() && tabIndexSetExplicitly().valueOr(0) >= 0)) 283 return false; 284 if (auto* root = shadowRoot()) { 285 if (root->delegatesFocus()) 286 return false; 287 } 288 return true; 282 289 } 283 290 … … 2334 2341 if (init.mode == ShadowRootMode::UserAgent) 2335 2342 return Exception { TypeError }; 2336 auto shadow = ShadowRoot::create(document(), init.mode );2343 auto shadow = ShadowRoot::create(document(), init.mode, init.delegatesFocus ? ShadowRoot::DelegatesFocus::Yes : ShadowRoot::DelegatesFocus::No); 2337 2344 auto& result = shadow.get(); 2338 2345 addShadowRoot(WTFMove(shadow)); … … 2882 2889 } 2883 2890 2891 static bool isProgramaticallyFocusable(Element& element) 2892 { 2893 ScriptDisallowedScope::InMainThread scriptDisallowedScope; 2894 // If the stylesheets have already been loaded we can reliably check isFocusable. 2895 // If not, we continue and set the focused node on the focus controller below so that it can be updated soon after attach. 2896 if (element.document().haveStylesheetsLoaded()) { 2897 if (!element.isFocusable()) 2898 return false; 2899 } 2900 return element.supportsFocus(); 2901 } 2902 2903 static RefPtr<Element> findFirstProgramaticallyFocusableElementInComposedTree(Element& host) 2904 { 2905 ASSERT(host.shadowRoot()); 2906 for (auto& node : composedTreeDescendants(host)) { 2907 if (!is<Element>(node)) 2908 continue; 2909 auto& element = downcast<Element>(node); 2910 if (isProgramaticallyFocusable(element)) 2911 return &element; 2912 } 2913 return nullptr; 2914 } 2915 2884 2916 void Element::focus(bool restorePreviousSelection, FocusDirection direction) 2885 2917 { … … 2887 2919 return; 2888 2920 2889 if (document().focusedElement() == this) { 2890 if (document().page()) 2891 document().page()->chrome().client().elementDidRefocus(*this); 2892 2893 return; 2894 } 2895 2896 // If the stylesheets have already been loaded we can reliably check isFocusable. 2897 // If not, we continue and set the focused node on the focus controller below so 2898 // that it can be updated soon after attach. 2899 if (document().haveStylesheetsLoaded()) { 2900 document().updateStyleIfNeeded(); 2901 if (!isFocusable()) 2902 return; 2903 } 2904 2905 if (!supportsFocus()) 2906 return; 2907 2908 RefPtr<Node> protect; 2909 if (Page* page = document().page()) { 2910 auto& frame = *document().frame(); 2911 if (!frame.hasHadUserInteraction() && !frame.isMainFrame() && !document().topDocument().securityOrigin().canAccess(document().securityOrigin())) 2921 auto document = makeRef(this->document()); 2922 if (document->focusedElement() == this) { 2923 if (document->page()) 2924 document->page()->chrome().client().elementDidRefocus(*this); 2925 return; 2926 } 2927 2928 RefPtr<Element> newTarget = this; 2929 if (document->haveStylesheetsLoaded()) 2930 document->updateStyleIfNeeded(); 2931 2932 if (&newTarget->document() != document.ptr()) 2933 return; 2934 2935 if (auto root = makeRefPtr(shadowRoot())) { 2936 if (root->delegatesFocus()) { 2937 newTarget = findFirstProgramaticallyFocusableElementInComposedTree(*this); 2938 if (!newTarget) 2939 return; 2940 } 2941 } 2942 2943 if (document->focusedElement() == newTarget) { 2944 if (document->page()) 2945 document->page()->chrome().client().elementDidRefocus(*newTarget); 2946 return; 2947 } 2948 2949 if (!isProgramaticallyFocusable(*newTarget)) 2950 return; 2951 2952 if (Page* page = document->page()) { 2953 auto& frame = *document->frame(); 2954 if (!frame.hasHadUserInteraction() && !frame.isMainFrame() && !document->topDocument().securityOrigin().canAccess(document->securityOrigin())) 2912 2955 return; 2913 2956 … … 2915 2958 // If a focus event handler changes the focus to a different node it 2916 2959 // does not make sense to continue and update appearence. 2917 protect = this; 2918 if (!page->focusController().setFocusedElement(this, *document().frame(), direction)) 2960 if (!page->focusController().setFocusedElement(newTarget.get(), *document->frame(), direction)) 2919 2961 return; 2920 2962 } … … 2925 2967 // Calling updateFocusAppearance() would generate an unnecessary call to ScrollView::setScrollPosition(), 2926 2968 // which would jump us around during this animation. See <rdar://problem/6699741>. 2927 bool isFormControl = is<HTMLFormControlElement>( *this);2969 bool isFormControl = is<HTMLFormControlElement>(newTarget); 2928 2970 if (isFormControl) 2929 2971 revealMode = SelectionRevealMode::RevealUpToMainFrame; … … 2937 2979 } 2938 2980 2981 // https://html.spec.whatwg.org/#focus-processing-model 2939 2982 RefPtr<Element> Element::focusAppearanceUpdateTarget() 2940 2983 { -
trunk/Source/WebCore/dom/Element.h
r250584 r251043 291 291 struct ShadowRootInit { 292 292 ShadowRootMode mode; 293 bool delegatesFocus { false }; 293 294 }; 294 295 ExceptionOr<ShadowRoot&> attachShadow(const ShadowRootInit&); -
trunk/Source/WebCore/dom/Element.idl
r250584 r251043 152 152 dictionary ShadowRootInit { 153 153 required ShadowRootMode mode; 154 boolean delegatesFocus = false; 154 155 }; 155 156 -
trunk/Source/WebCore/dom/ShadowRoot.cpp
r250914 r251043 57 57 COMPILE_ASSERT(sizeof(ShadowRoot) == sizeof(SameSizeAsShadowRoot), shadowroot_should_stay_small); 58 58 59 ShadowRoot::ShadowRoot(Document& document, ShadowRootMode type )59 ShadowRoot::ShadowRoot(Document& document, ShadowRootMode type, DelegatesFocus delegatesFocus) 60 60 : DocumentFragment(document, CreateShadowRoot) 61 61 , TreeScope(*this, document) 62 , m_delegatesFocus(delegatesFocus == DelegatesFocus::Yes) 62 63 , m_type(type) 63 64 , m_styleScope(makeUnique<Style::Scope>(*this)) -
trunk/Source/WebCore/dom/ShadowRoot.h
r250902 r251043 42 42 WTF_MAKE_ISO_ALLOCATED(ShadowRoot); 43 43 public: 44 static Ref<ShadowRoot> create(Document& document, ShadowRootMode type) 44 45 enum class DelegatesFocus : uint8_t { Yes, No }; 46 47 static Ref<ShadowRoot> create(Document& document, ShadowRootMode type, DelegatesFocus delegatesFocus = DelegatesFocus::No) 45 48 { 46 return adoptRef(*new ShadowRoot(document, type ));49 return adoptRef(*new ShadowRoot(document, type, delegatesFocus)); 47 50 } 48 51 … … 62 65 void setResetStyleInheritance(bool); 63 66 67 bool delegatesFocus() const { return m_delegatesFocus; } 64 68 bool containsFocusedElement() const { return m_containsFocusedElement; } 65 69 void setContainsFocusedElement(bool flag) { m_containsFocusedElement = flag; } … … 101 105 void invalidatePartMappings(); 102 106 103 protected: 104 ShadowRoot(Document&, ShadowRootMode); 105 107 private: 108 ShadowRoot(Document&, ShadowRootMode, DelegatesFocus); 106 109 ShadowRoot(Document&, std::unique_ptr<SlotAssignment>&&); 107 110 108 private:109 111 bool childTypeAllowed(NodeType) const override; 110 112 … … 118 120 bool m_resetStyleInheritance { false }; 119 121 bool m_hasBegunDeletingDetachedChildren { false }; 122 bool m_delegatesFocus { false }; 120 123 bool m_containsFocusedElement { false }; 121 124 ShadowRootMode m_type { ShadowRootMode::UserAgent }; -
trunk/Source/WebCore/page/EventHandler.cpp
r251041 r251043 35 35 #include "ChromeClient.h" 36 36 #include "ComposedTreeAncestorIterator.h" 37 #include "ComposedTreeIterator.h" 37 38 #include "CursorList.h" 38 39 #include "DocumentMarkerController.h" … … 2620 2621 } 2621 2622 2623 static RefPtr<Element> findFirstMouseFocusableElementInComposedTree(Element& host) 2624 { 2625 ASSERT(host.shadowRoot()); 2626 for (auto& node : composedTreeDescendants(host)) { 2627 if (!is<Element>(node)) 2628 continue; 2629 auto& element = downcast<Element>(node); 2630 if (element.isMouseFocusable()) 2631 return &element; 2632 } 2633 return nullptr; 2634 } 2635 2622 2636 bool EventHandler::dispatchMouseEvent(const AtomString& eventType, Node* targetNode, bool /*cancelable*/, int clickCount, const PlatformMouseEvent& platformMouseEvent, bool setUnder) 2623 2637 { … … 2651 2665 RefPtr<Element> element; 2652 2666 for (element = m_elementUnderMouse.get(); element; element = element->parentElementInComposedTree()) { 2667 if (auto* shadowRoot = element->shadowRoot()) { 2668 if (shadowRoot->delegatesFocus()) { 2669 element = findFirstMouseFocusableElementInComposedTree(*element); 2670 break; 2671 } 2672 } 2653 2673 if (element->isMouseFocusable()) 2654 2674 break;
Note: See TracChangeset
for help on using the changeset viewer.