Title: [276698] trunk
Revision
276698
Author
[email protected]
Date
2021-04-28 01:51:37 -0700 (Wed, 28 Apr 2021)

Log Message

[selectors] Using a modifier key on an element makes it stop matching :focus-visible
https://bugs.webkit.org/show_bug.cgi?id=225075

Reviewed by Ryosuke Niwa.

LayoutTests/imported/w3c:

* web-platform-tests/css/selectors/focus-visible-021-expected.txt: Added.
* web-platform-tests/css/selectors/focus-visible-021.html: Added.

Source/WebCore:

When we used a modifier key on a element that was matching :focus-visible, we stopped matching :focus-visible.
That was wrong, we shouldn't just start matching :focus-visible when a modifier key is used but not the other way around.

This patches fixed that without doing any work if the element is already matching :focus-visible when the user type a key.

Test: imported/w3c/web-platform-tests/css/selectors/focus-visible-021.html

* dom/Element.cpp:
(WebCore::shouldAlwaysHaveFocusVisibleWhenFocused): Helper method for inputs and content editable elements.
(WebCore::Element::setFocus): Use the new helper method.
(WebCore::Element::setHasFocusVisible): Add asserts to avoid setting/unsetting :focus-visible flag wrongly.
* dom/Node.cpp:
(WebCore::Node::isContentEditable const): Just mark as const.
(WebCore::Node::isContentRichlyEditable const): Ditto.
* dom/Node.h: Ditto.
* page/EventHandler.cpp:
(WebCore::EventHandler::internalKeyEvent): Don't do anything regarding :focus-visible flag if the element already matches :focus-visible.

LayoutTests:

* platform/ios/TestExpectations: Skip new test.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (276697 => 276698)


--- trunk/LayoutTests/ChangeLog	2021-04-28 08:39:01 UTC (rev 276697)
+++ trunk/LayoutTests/ChangeLog	2021-04-28 08:51:37 UTC (rev 276698)
@@ -1,3 +1,12 @@
+2021-04-28  Manuel Rego Casasnovas  <[email protected]>
+
+        [selectors] Using a modifier key on an element makes it stop matching :focus-visible
+        https://bugs.webkit.org/show_bug.cgi?id=225075
+
+        Reviewed by Ryosuke Niwa.
+
+        * platform/ios/TestExpectations: Skip new test.
+
 2021-04-28  Cameron McCormack  <[email protected]>
 
         Fix some test typos.

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (276697 => 276698)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-04-28 08:39:01 UTC (rev 276697)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-04-28 08:51:37 UTC (rev 276698)
@@ -1,3 +1,13 @@
+2021-04-28  Manuel Rego Casasnovas  <[email protected]>
+
+        [selectors] Using a modifier key on an element makes it stop matching :focus-visible
+        https://bugs.webkit.org/show_bug.cgi?id=225075
+
+        Reviewed by Ryosuke Niwa.
+
+        * web-platform-tests/css/selectors/focus-visible-021-expected.txt: Added.
+        * web-platform-tests/css/selectors/focus-visible-021.html: Added.
+
 2021-04-28  Cameron McCormack  <[email protected]>
 
         Make img elements perform source selection even when not in the document.

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/focus-visible-021-expected.txt (0 => 276698)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/focus-visible-021-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/focus-visible-021-expected.txt	2021-04-28 08:51:37 UTC (rev 276698)
@@ -0,0 +1,9 @@
+This test checks that using a modifier key does not make the element to stop matching :focus-visible.
+If the element that says "Focused" has a red background, then the test result is a FAILURE.
+Press the Ctrl key.
+If the element keeps the green outline and has not a red background, then the test result is SUCCESS.
+Focused
+
+PASS ":focus-visible" should be a valid selector
+PASS Ctrl key doesn't make an element to stop matching :focus-visible
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/focus-visible-021.html (0 => 276698)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/focus-visible-021.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/selectors/focus-visible-021.html	2021-04-28 08:51:37 UTC (rev 276698)
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>CSS Test (Selectors): Modifier key doesn't make element to stop matching :focus-visible</title>
+<link rel="author" title="Manuel Rego Casasnovas" href=""
+<link rel="help" href="" />
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<style>
+  #warning {
+    display: none;
+    background: red;
+  }
+
+  @supports not selector(:focus-visible) {
+    #instructions {
+      display: none;
+    }
+
+    #warning {
+      display: block;
+    }
+  }
+
+  :focus-visible {
+    outline: solid thick green;
+  }
+
+  :focus:not(:focus-visible) {
+    outline: none;
+    background-color: red;
+  }
+</style>
+
+This test checks that using a modifier key does not make the element to stop matching <code>:focus-visible</code>.
+<ol id="instructions">
+  <li>If the element that says "Focused" has a red background, then the test result is a FAILURE.</li>
+  <li>Press the Ctrl key.</li>
+  <li>If the element keeps the green outline and has not a red background, then the test result is SUCCESS.</li>
+</ol>
+<p id="warning">Your user-agent does not support <code>:focus-visible</code> pseudo-class, please SKIP this test.</p>
+
+<div id="target" tabindex="0">Focused</div>
+<script>
+  // Check that :focus-visible is supported.
+  test_valid_selector(':focus-visible');
+
+  async_test(function(t) {
+    target.addEventListener("focus", t.step_func(() => {
+      assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+      assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+
+      const ctrl_key = '\uE009';
+      test_driver.send_keys(target, ctrl_key);
+    }));
+
+    target.addEventListener("keyup", t.step_func_done(() => {
+      assert_equals(getComputedStyle(target).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${target.tagName}#${target.id} should be green`);
+      assert_not_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", `backgroundColor for ${target.tagName}#${target.id} should NOT be red`);
+    }));
+
+  }, "Ctrl key doesn't make an element to stop matching :focus-visible");
+
+  target.focus();
+</script>

Modified: trunk/LayoutTests/platform/ios/TestExpectations (276697 => 276698)


--- trunk/LayoutTests/platform/ios/TestExpectations	2021-04-28 08:39:01 UTC (rev 276697)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2021-04-28 08:51:37 UTC (rev 276698)
@@ -3282,6 +3282,7 @@
 webkit.org/b/209734 imported/w3c/web-platform-tests/css/selectors/focus-visible-012.html [ Skip ]
 webkit.org/b/209734 imported/w3c/web-platform-tests/css/selectors/focus-visible-013.html [ Skip ]
 webkit.org/b/209734 imported/w3c/web-platform-tests/css/selectors/focus-visible-019.html [ Skip ]
+webkit.org/b/209734 imported/w3c/web-platform-tests/css/selectors/focus-visible-021.html [ Skip ]
 webkit.org/b/209734 imported/w3c/web-platform-tests/css/selectors/focus-visible-script-focus-004.html [ Skip ]
 webkit.org/b/209734 imported/w3c/web-platform-tests/css/selectors/focus-visible-script-focus-005.html [ Skip ]
 webkit.org/b/209734 imported/w3c/web-platform-tests/css/selectors/focus-visible-script-focus-012.html [ Skip ]

Modified: trunk/Source/WebCore/ChangeLog (276697 => 276698)


--- trunk/Source/WebCore/ChangeLog	2021-04-28 08:39:01 UTC (rev 276697)
+++ trunk/Source/WebCore/ChangeLog	2021-04-28 08:51:37 UTC (rev 276698)
@@ -1,3 +1,28 @@
+2021-04-28  Manuel Rego Casasnovas  <[email protected]>
+
+        [selectors] Using a modifier key on an element makes it stop matching :focus-visible
+        https://bugs.webkit.org/show_bug.cgi?id=225075
+
+        Reviewed by Ryosuke Niwa.
+
+        When we used a modifier key on a element that was matching :focus-visible, we stopped matching :focus-visible.
+        That was wrong, we shouldn't just start matching :focus-visible when a modifier key is used but not the other way around.
+
+        This patches fixed that without doing any work if the element is already matching :focus-visible when the user type a key.
+
+        Test: imported/w3c/web-platform-tests/css/selectors/focus-visible-021.html
+
+        * dom/Element.cpp:
+        (WebCore::shouldAlwaysHaveFocusVisibleWhenFocused): Helper method for inputs and content editable elements.
+        (WebCore::Element::setFocus): Use the new helper method.
+        (WebCore::Element::setHasFocusVisible): Add asserts to avoid setting/unsetting :focus-visible flag wrongly.
+        * dom/Node.cpp:
+        (WebCore::Node::isContentEditable const): Just mark as const.
+        (WebCore::Node::isContentRichlyEditable const): Ditto.
+        * dom/Node.h: Ditto.
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::internalKeyEvent): Don't do anything regarding :focus-visible flag if the element already matches :focus-visible.
+
 2021-04-28  Cameron McCormack  <[email protected]>
 
         Make img elements perform source selection even when not in the document.

Modified: trunk/Source/WebCore/dom/Element.cpp (276697 => 276698)


--- trunk/Source/WebCore/dom/Element.cpp	2021-04-28 08:39:01 UTC (rev 276697)
+++ trunk/Source/WebCore/dom/Element.cpp	2021-04-28 08:51:37 UTC (rev 276698)
@@ -745,6 +745,11 @@
     }
 }
 
+static bool shouldAlwaysHaveFocusVisibleWhenFocused(const Element& element)
+{
+    return element.isTextField() || element.isContentEditable();
+}
+
 void Element::setFocus(bool flag, FocusVisibility visibility)
 {
     if (flag == focused())
@@ -764,8 +769,7 @@
     for (auto* element = this; element; element = element->parentElementInComposedTree())
         element->setHasFocusWithin(flag);
 
-    // Elements that support keyboard input (form inputs and contenteditable) always match :focus-visible when focused.
-    setHasFocusVisible(flag && (visibility == FocusVisibility::Visible || isTextField() || isContentEditable()));
+    setHasFocusVisible(flag && (visibility == FocusVisibility::Visible || shouldAlwaysHaveFocusVisibleWhenFocused(*this)));
 }
 
 void Element::setHasFocusVisible(bool flag)
@@ -773,6 +777,11 @@
     if (!document().settings().focusVisibleEnabled())
         return;
 
+#if ASSERT_ENABLED
+    ASSERT(!flag || focused());
+    ASSERT(!focused() || !shouldAlwaysHaveFocusVisibleWhenFocused(*this) || flag);
+#endif
+
     if (hasFocusVisible() == flag)
         return;
 

Modified: trunk/Source/WebCore/dom/Node.cpp (276697 => 276698)


--- trunk/Source/WebCore/dom/Node.cpp	2021-04-28 08:39:01 UTC (rev 276697)
+++ trunk/Source/WebCore/dom/Node.cpp	2021-04-28 08:51:37 UTC (rev 276698)
@@ -732,12 +732,12 @@
     return nullAtom();
 }
 
-bool Node::isContentEditable()
+bool Node::isContentEditable() const
 {
     return computeEditability(UserSelectAllDoesNotAffectEditability, ShouldUpdateStyle::Update) != Editability::ReadOnly;
 }
 
-bool Node::isContentRichlyEditable()
+bool Node::isContentRichlyEditable() const
 {
     return computeEditability(UserSelectAllIsAlwaysNonEditable, ShouldUpdateStyle::Update) == Editability::CanEditRichly;
 }

Modified: trunk/Source/WebCore/dom/Node.h (276697 => 276698)


--- trunk/Source/WebCore/dom/Node.h	2021-04-28 08:39:01 UTC (rev 276697)
+++ trunk/Source/WebCore/dom/Node.h	2021-04-28 08:51:37 UTC (rev 276698)
@@ -317,8 +317,8 @@
     bool hasEventTargetData() const { return hasNodeFlag(NodeFlag::HasEventTargetData); }
     void setHasEventTargetData(bool flag) { setNodeFlag(NodeFlag::HasEventTargetData, flag); }
 
-    WEBCORE_EXPORT bool isContentEditable();
-    bool isContentRichlyEditable();
+    WEBCORE_EXPORT bool isContentEditable() const;
+    bool isContentRichlyEditable() const;
 
     WEBCORE_EXPORT void inspect();
 

Modified: trunk/Source/WebCore/page/EventHandler.cpp (276697 => 276698)


--- trunk/Source/WebCore/page/EventHandler.cpp	2021-04-28 08:39:01 UTC (rev 276697)
+++ trunk/Source/WebCore/page/EventHandler.cpp	2021-04-28 08:51:37 UTC (rev 276698)
@@ -3543,16 +3543,15 @@
         keydown->preventDefault();
     keydown->setTarget(element);
 
-    auto shouldMatchFocusVisible = [initialKeyEvent, keydown](const Element& element) {
-        if (!element.focused())
-            return false;
-
+    auto setHasFocusVisibleIfNeeded = [initialKeyEvent, keydown](Element& element) {
         // If the user interacts with the page via the keyboard, the currently focused element should match :focus-visible.
         // Just typing a modifier key is not considered user interaction with the page, but Shift + a (or Caps Lock + a) is considered an interaction.
-        return keydown->modifierKeys().isEmpty() || ((keydown->shiftKey() || keydown->capsLockKey()) && !initialKeyEvent.text().isEmpty());
+        bool userHasInteractedViaKeyword = keydown->modifierKeys().isEmpty() || ((keydown->shiftKey() || keydown->capsLockKey()) && !initialKeyEvent.text().isEmpty());
+
+        if (element.focused() && userHasInteractedViaKeyword)
+            element.setHasFocusVisible(true);
     };
-    // FIXME: This is wrong for text form controls and contenteditable elements (https://webkit.org/b/225075).
-    element->setHasFocusVisible(shouldMatchFocusVisible(*element));
+    setHasFocusVisibleIfNeeded(*element);
 
     if (initialKeyEvent.type() == PlatformEvent::RawKeyDown) {
         element->dispatchEvent(keydown);
@@ -3599,12 +3598,10 @@
     // Focus may have changed during keydown handling, so refetch element.
     // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original element.
     if (!keydownResult) {
-        element->setHasFocusVisible(false);
         element = eventTargetElementForDocument(m_frame.document());
         if (!element)
             return false;
-        // FIXME: This is wrong for text form controls and contenteditable elements (https://webkit.org/b/225075).
-        element->setHasFocusVisible(shouldMatchFocusVisible(*element));
+        setHasFocusVisibleIfNeeded(*element);
     }
 
     PlatformKeyboardEvent keyPressEvent = initialKeyEvent;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to