- 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 };