Title: [265092] trunk
Revision
265092
Author
rn...@webkit.org
Date
2020-07-30 13:14:26 -0700 (Thu, 30 Jul 2020)

Log Message

Clicking on a shadow DOM does not move the selection to the focused element when delegatesFocus is set to true
https://bugs.webkit.org/show_bug.cgi?id=214859
<rdar://problem/66192901>

Reviewed by Wenson Hsieh.

Source/WebCore:

The bug was caused by EventHandler moving the selection to where the user had clicked, not to where the focus
had been delegated, which is a uniquely WebKit behavior. Fixed the bug by revealing the focused element as done
in Element::focus in EventHandler::dispatchMouseEvent and avoid updating the selection to the clicked point
later in EventHandler::handleMousePressEventSingleClick by adding an early exit.

Test: fast/shadow-dom/delegates-focus-and-types-into-input.html

* dom/Element.cpp:
(WebCore::Element::focus):
(WebCore::Element::revealFocusedElement): Extracted from Element::focus.
* dom/Element.h:
* page/EventHandler.cpp:
(WebCore::EventHandler::handleMousePressEventSingleClick): Added an early exit when dispatchMouseEvent had
delegated the focus to an element different from the one the user had clicked.
(WebCore::EventHandler::dispatchMouseEvent): Added a code to reveal the newly focused element when the focus
had been delegated.
* page/EventHandler.h:

LayoutTests:

Added a regression test.

* fast/shadow-dom/delegates-focus-and-types-into-input-expected.txt: Added.
* fast/shadow-dom/delegates-focus-and-types-into-input.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (265091 => 265092)


--- trunk/LayoutTests/ChangeLog	2020-07-30 18:25:47 UTC (rev 265091)
+++ trunk/LayoutTests/ChangeLog	2020-07-30 20:14:26 UTC (rev 265092)
@@ -1,3 +1,16 @@
+2020-07-30  Ryosuke Niwa  <rn...@webkit.org>
+
+        Clicking on a shadow DOM does not move the selection to the focused element when delegatesFocus is set to true
+        https://bugs.webkit.org/show_bug.cgi?id=214859
+        <rdar://problem/66192901>
+
+        Reviewed by Wenson Hsieh.
+
+        Added a regression test.
+
+        * fast/shadow-dom/delegates-focus-and-types-into-input-expected.txt: Added.
+        * fast/shadow-dom/delegates-focus-and-types-into-input.html: Added.
+
 2020-07-30  Antoine Quint  <grao...@webkit.org>
 
         [iOS] Unable to swipe on IMDB.com after long press on image

Added: trunk/LayoutTests/fast/shadow-dom/delegates-focus-and-types-into-input-expected.txt (0 => 265092)


--- trunk/LayoutTests/fast/shadow-dom/delegates-focus-and-types-into-input-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/delegates-focus-and-types-into-input-expected.txt	2020-07-30 20:14:26 UTC (rev 265092)
@@ -0,0 +1,16 @@
+This tests delegating focus in a shadow tree to an input element. WebKit should move the selection as well as the focus
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.activeElement is host
+PASS shadowRoot.querySelector("input") is target
+PASS shadowRoot.activeElement is target
+PASS target.value is ""
+PASS target.value is "hello"
+PASS target.selectionStart is 5
+PASS target.selectionEnd is 5
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/shadow-dom/delegates-focus-and-types-into-input.html (0 => 265092)


--- trunk/LayoutTests/fast/shadow-dom/delegates-focus-and-types-into-input.html	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/delegates-focus-and-types-into-input.html	2020-07-30 20:14:26 UTC (rev 265092)
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+</head>
+<body>
+<script src=""
+<script src=""
+<script>
+
+description('This tests delegating focus in a shadow tree to an input element. WebKit should move the selection as well as the focus');
+
+jsTestIsAsync = true;
+
+const host = document.createElement('div');
+document.body.appendChild(host);
+
+const shadowRoot = host.attachShadow({mode: 'closed', delegatesFocus: true});
+shadowRoot.innerHTML = `<input type="text" id="target">
+<div _onclick_="checkSelection()">Click here</div>`;
+const target = shadowRoot.getElementById("target");
+
+async function runTest() {
+    const divRect = shadowRoot.querySelector('div').getBoundingClientRect();
+    await UIHelper.activateAt(divRect.x + 5, divRect.y + 5);
+    await UIHelper.ensurePresentationUpdate();
+    await new Promise(requestAnimationFrame);
+    await selectionCheck;
+}
+
+let resolveSelectionCheck;
+const selectionCheck = new Promise((resolve) => resolveSelectionCheck = resolve);
+function checkSelection() {
+    shouldBe('document.activeElement', 'host');
+    shouldBe('shadowRoot.querySelector("input")', 'target');
+    shouldBe('shadowRoot.activeElement', 'target');
+    shouldBeEqualToString('target.value', '');
+    document.execCommand('insertText', false, 'hello');
+    shouldBeEqualToString('target.value', 'hello');
+    shouldBe('target.selectionStart', '5');
+    shouldBe('target.selectionEnd', '5');
+    resolveSelectionCheck();
+}
+
+if (window.testRunner)
+    UIHelper.wait(runTest());
+else
+    selectionCheck.then(() => finishJSTest());
+
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (265091 => 265092)


--- trunk/Source/WebCore/ChangeLog	2020-07-30 18:25:47 UTC (rev 265091)
+++ trunk/Source/WebCore/ChangeLog	2020-07-30 20:14:26 UTC (rev 265092)
@@ -1,3 +1,29 @@
+2020-07-30  Ryosuke Niwa  <rn...@webkit.org>
+
+        Clicking on a shadow DOM does not move the selection to the focused element when delegatesFocus is set to true
+        https://bugs.webkit.org/show_bug.cgi?id=214859
+        <rdar://problem/66192901>
+
+        Reviewed by Wenson Hsieh.
+
+        The bug was caused by EventHandler moving the selection to where the user had clicked, not to where the focus
+        had been delegated, which is a uniquely WebKit behavior. Fixed the bug by revealing the focused element as done
+        in Element::focus in EventHandler::dispatchMouseEvent and avoid updating the selection to the clicked point
+        later in EventHandler::handleMousePressEventSingleClick by adding an early exit.
+
+        Test: fast/shadow-dom/delegates-focus-and-types-into-input.html
+
+        * dom/Element.cpp:
+        (WebCore::Element::focus):
+        (WebCore::Element::revealFocusedElement): Extracted from Element::focus.
+        * dom/Element.h:
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::handleMousePressEventSingleClick): Added an early exit when dispatchMouseEvent had
+        delegated the focus to an element different from the one the user had clicked.
+        (WebCore::EventHandler::dispatchMouseEvent): Added a code to reveal the newly focused element when the focus
+        had been delegated.
+        * page/EventHandler.h:
+
 2020-07-30  Tim Horton  <timothy_hor...@apple.com>
 
         Web content gets stuck in an inactive state (no cursor updates or text insertion caret) when activating a tab with a thumbnail visible

Modified: trunk/Source/WebCore/dom/Element.cpp (265091 => 265092)


--- trunk/Source/WebCore/dom/Element.cpp	2020-07-30 18:25:47 UTC (rev 265091)
+++ trunk/Source/WebCore/dom/Element.cpp	2020-07-30 20:14:26 UTC (rev 265092)
@@ -3032,6 +3032,11 @@
             return;
     }
 
+    newTarget->revealFocusedElement(restorePreviousSelection ? SelectionRestorationMode::Restore : SelectionRestorationMode::SetDefault);
+}
+
+void Element::revealFocusedElement(SelectionRestorationMode selectionMode)
+{
     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
 
 #if PLATFORM(IOS_FAMILY)
@@ -3038,7 +3043,7 @@
     // Focusing a form element triggers animation in UIKit to scroll to the right position.
     // Calling updateFocusAppearance() would generate an unnecessary call to ScrollView::setScrollPosition(),
     // which would jump us around during this animation. See <rdar://problem/6699741>.
-    if (is<HTMLFormControlElement>(newTarget))
+    if (is<HTMLFormControlElement>(*this))
         revealMode = SelectionRevealMode::RevealUpToMainFrame;
 #endif
 
@@ -3046,7 +3051,7 @@
     if (!target)
         return;
 
-    target->updateFocusAppearance(restorePreviousSelection ? SelectionRestorationMode::Restore : SelectionRestorationMode::SetDefault, revealMode);
+    target->updateFocusAppearance(selectionMode, revealMode);
 }
 
 // https://html.spec.whatwg.org/#focus-processing-model

Modified: trunk/Source/WebCore/dom/Element.h (265091 => 265092)


--- trunk/Source/WebCore/dom/Element.h	2020-07-30 18:25:47 UTC (rev 265091)
+++ trunk/Source/WebCore/dom/Element.h	2020-07-30 20:14:26 UTC (rev 265092)
@@ -396,6 +396,7 @@
 
     static AXTextStateChangeIntent defaultFocusTextStateChangeIntent() { return AXTextStateChangeIntent(AXTextStateChangeTypeSelectionMove, AXTextSelection { AXTextSelectionDirectionDiscontiguous, AXTextSelectionGranularityUnknown, true }); }
     virtual void focus(bool restorePreviousSelection = true, FocusDirection = FocusDirectionNone);
+    void revealFocusedElement(SelectionRestorationMode);
     virtual RefPtr<Element> focusAppearanceUpdateTarget();
     virtual void updateFocusAppearance(SelectionRestorationMode, SelectionRevealMode = SelectionRevealMode::Reveal);
     virtual void blur();

Modified: trunk/Source/WebCore/page/EventHandler.cpp (265091 => 265092)


--- trunk/Source/WebCore/page/EventHandler.cpp	2020-07-30 18:25:47 UTC (rev 265091)
+++ trunk/Source/WebCore/page/EventHandler.cpp	2020-07-30 20:14:26 UTC (rev 265092)
@@ -687,7 +687,7 @@
 
     m_frame.document()->updateLayoutIgnorePendingStylesheets();
     Node* targetNode = event.targetNode();
-    if (!(targetNode && targetNode->renderer() && m_mouseDownMayStartSelect))
+    if (!targetNode || !targetNode->renderer() || !m_mouseDownMayStartSelect || m_mouseDownDelegatedFocus)
         return false;
 
     // Extend the selection if the Shift key is down, unless the click is in a link.
@@ -2711,6 +2711,8 @@
     if (eventType != eventNames().mousedownEvent)
         return true;
 
+    m_mouseDownDelegatedFocus = false;
+
     // If clicking on a frame scrollbar, do not make any change to which element is focused.
     auto* view = m_frame.view();
     if (view && view->scrollbarAtPoint(platformMouseEvent.position()))
@@ -2730,6 +2732,7 @@
         if (auto* shadowRoot = element->shadowRoot()) {
             if (shadowRoot->delegatesFocus()) {
                 element = findFirstMouseFocusableElementInComposedTree(*element);
+                m_mouseDownDelegatedFocus = true;
                 break;
             }
         }
@@ -2758,6 +2761,9 @@
     if (page && !page->focusController().setFocusedElement(element.get(), m_frame))
         return false;
 
+    if (m_mouseDownDelegatedFocus)
+        element->revealFocusedElement(SelectionRestorationMode::SetDefault);
+
     return true;
 }
 

Modified: trunk/Source/WebCore/page/EventHandler.h (265091 => 265092)


--- trunk/Source/WebCore/page/EventHandler.h	2020-07-30 18:25:47 UTC (rev 265091)
+++ trunk/Source/WebCore/page/EventHandler.h	2020-07-30 20:14:26 UTC (rev 265092)
@@ -524,6 +524,7 @@
     bool m_dragMayStartSelectionInstead { false };
 #endif
 
+    bool m_mouseDownDelegatedFocus { false };
     bool m_mouseDownWasSingleClickInSelection { false };
     enum SelectionInitiationState { HaveNotStartedSelection, PlacedCaret, ExtendedSelection };
     SelectionInitiationState m_selectionInitiationState { HaveNotStartedSelection };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to