Changeset 228417 in webkit


Ignore:
Timestamp:
Feb 12, 2018 11:59:28 PM (6 years ago)
Author:
Chris Fleizach
Message:

AX: defer focusedUIElement notifications
https://bugs.webkit.org/show_bug.cgi?id=182643
<rdar://problem/37394310>

Reviewed by Zalan Bujtas.

Source/WebCore:

Deferring focus changes for accessibility has a number of benefits.

1) Reduces the chance of calling into layout during layout.
2) Coalesces multiple focus notifications that would be needlessly sent.
3) Improves performance by not calling out to the accessibility notification machinery during layout.

In this patch, I also started making more AXObjectCache calls private. This will reduce the chance that clients
will call into AXObjectCache during unexpected times.

  • accessibility/AXObjectCache.cpp:

(WebCore::AXObjectCache::deferFocusedUIElementChangeIfNeeded):
(WebCore::conditionallyAddNodeToFilterList):
(WebCore::filterVectorPairForRemoval):
(WebCore::filterMapForRemoval):
(WebCore::filterListForRemoval):
(WebCore::AXObjectCache::prepareForDocumentDestruction):
(WebCore::AXObjectCache::performDeferredCacheUpdate):

  • accessibility/AXObjectCache.h:
  • dom/Document.cpp:

(WebCore::Document::setFocusedElement):

LayoutTests:

  • accessibility/mac/aria-menu-item-selected-notification.html:

Rewrite test to accomodate that focus changes happen asynchronously.

  • accessibility/mac/selection-notification-focus-change-expected.txt:
  • platform/mac-wk2/accessibility/mac/selection-notification-focus-change-expected.txt:

The order of notifications is different now that focus changes happen later.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r228416 r228417  
     12018-02-12  Chris Fleizach  <cfleizach@apple.com>
     2
     3        AX: defer focusedUIElement notifications
     4        https://bugs.webkit.org/show_bug.cgi?id=182643
     5        <rdar://problem/37394310>
     6
     7        Reviewed by Zalan Bujtas.
     8
     9        * accessibility/mac/aria-menu-item-selected-notification.html:
     10             Rewrite test to accomodate that focus changes happen asynchronously.
     11        * accessibility/mac/selection-notification-focus-change-expected.txt:
     12        * platform/mac-wk2/accessibility/mac/selection-notification-focus-change-expected.txt:
     13             The order of notifications is different now that focus changes happen later.
     14
    1152018-02-12  John Wilander  <wilander@apple.com>
    216
  • trunk/LayoutTests/accessibility/mac/aria-menu-item-selected-notification.html

    r228390 r228417  
    4747        document.getElementById("item1").focus();
    4848
    49         // Trigger notification through aria-selected.
    50         document.getElementById("item2").setAttribute("aria-selected", "true");
     49        setTimeout(function() {
     50            // Trigger notification through aria-selected.
     51            document.getElementById("item2").setAttribute("aria-selected", "true");
    5152
    52         // Ensure we don't get a notification when aria-selected is false.
    53         document.getElementById("item2").setAttribute("aria-selected", "false");
     53            setTimeout(function() {
     54                // Ensure we don't get a notification when aria-selected is false.
     55                document.getElementById("item2").setAttribute("aria-selected", "false");
    5456
    55         // Trigger another notification through focus to ensure we don't
    56         document.getElementById("item3").focus();
     57                setTimeout(function() {
     58                    // Trigger another notification through focus to ensure we don't
     59                    document.getElementById("item3").focus();
     60                }, 1);
     61            }, 1);
     62        }, 1);
    5763    }
    5864
  • trunk/LayoutTests/accessibility/mac/selection-notification-focus-change-expected.txt

    r228390 r228417  
    1717
    1818eventSender.keyDown(tabCharacter)
    19 Received AXFocusChanged
    2019Received AXSelectedTextChanged
    2120PASS userInfo["AXTextSelectionChangedFocus"] is true
     21Received AXFocusChanged
    2222Received AXSelectedTextChanged
    2323PASS userInfo["AXTextSelectionChangedFocus"] is true
  • trunk/LayoutTests/platform/mac-wk2/accessibility/mac/selection-notification-focus-change-expected.txt

    r227983 r228417  
    88Received AXSelectedTextChanged
    99PASS userInfo["AXTextSelectionChangedFocus"] is true
    10 Received AXFocusChanged
    1110Received AXSelectedTextChanged
    1211PASS userInfo["AXTextSelectionChangedFocus"] is true
     12Received AXFocusChanged
    1313
    1414PASS accessibilityController.accessibleElementById("1").isFocusable is true
     
    1717
    1818eventSender.keyDown(tabCharacter)
    19 Received AXFocusChanged
    2019Received AXSelectedTextChanged
    2120PASS userInfo["AXTextSelectionChangedFocus"] is true
     21Received AXFocusChanged
    2222PASS successfullyParsed is true
    2323
  • trunk/Source/WebCore/ChangeLog

    r228416 r228417  
     12018-02-12  Chris Fleizach  <cfleizach@apple.com>
     2
     3        AX: defer focusedUIElement notifications
     4        https://bugs.webkit.org/show_bug.cgi?id=182643
     5        <rdar://problem/37394310>
     6
     7        Reviewed by Zalan Bujtas.
     8
     9        Deferring focus changes for accessibility has a number of benefits.
     10            1) Reduces the chance of calling into layout during layout.
     11            2) Coalesces multiple focus notifications that would be needlessly sent.
     12            3) Improves performance by not calling out to the accessibility notification machinery during layout.
     13
     14        In this patch, I also started making more AXObjectCache calls private. This will reduce the chance that clients
     15        will call into AXObjectCache during unexpected times.
     16
     17        * accessibility/AXObjectCache.cpp:
     18        (WebCore::AXObjectCache::deferFocusedUIElementChangeIfNeeded):
     19        (WebCore::conditionallyAddNodeToFilterList):
     20        (WebCore::filterVectorPairForRemoval):
     21        (WebCore::filterMapForRemoval):
     22        (WebCore::filterListForRemoval):
     23        (WebCore::AXObjectCache::prepareForDocumentDestruction):
     24        (WebCore::AXObjectCache::performDeferredCacheUpdate):
     25        * accessibility/AXObjectCache.h:
     26        * dom/Document.cpp:
     27        (WebCore::Document::setFocusedElement):
     28
    1292018-02-12  John Wilander  <wilander@apple.com>
    230
  • trunk/Source/WebCore/accessibility/AXObjectCache.cpp

    r228390 r228417  
    10161016   
    10171017    postNotification(getOrCreate(node), &document(), AXMenuListItemSelected);
     1018}
     1019   
     1020void AXObjectCache::deferFocusedUIElementChangeIfNeeded(Node* oldNode, Node* newNode)
     1021{
     1022    if (nodeAndRendererAreValid(newNode) && rendererNeedsDeferredUpdate(*newNode->renderer()))
     1023        m_deferredFocusedNodeChange.append({ oldNode, newNode });
     1024    else
     1025        handleFocusedUIElementChanged(oldNode, newNode);
    10181026}
    10191027   
     
    27782786}
    27792787
     2788static void conditionallyAddNodeToFilterList(Node* node, const Document& document, HashSet<Node*>& nodesToRemove)
     2789{
     2790    if (node && (!node->isConnected() || &node->document() == &document))
     2791        nodesToRemove.add(node);
     2792}
     2793   
     2794template<typename T>
     2795static void filterVectorPairForRemoval(const Vector<std::pair<T, T>>& list, const Document& document, HashSet<Node*>& nodesToRemove)
     2796{
     2797    for (auto& entry : list) {
     2798        conditionallyAddNodeToFilterList(entry.first, document, nodesToRemove);
     2799        conditionallyAddNodeToFilterList(entry.second, document, nodesToRemove);
     2800    }
     2801}
     2802   
    27802803template<typename T, typename U>
    27812804static void filterMapForRemoval(const HashMap<T, U>& list, const Document& document, HashSet<Node*>& nodesToRemove)
    27822805{
    2783     for (auto& entry : list) {
    2784         auto* node = entry.key;
    2785         if (node->isConnected() && &node->document() != &document)
    2786             continue;
    2787         nodesToRemove.add(node);
    2788     }
     2806    for (auto& entry : list)
     2807        conditionallyAddNodeToFilterList(entry.key, document, nodesToRemove);
    27892808}
    27902809
     
    27922811static void filterListForRemoval(const ListHashSet<T>& list, const Document& document, HashSet<Node*>& nodesToRemove)
    27932812{
    2794     for (auto* node : list) {
    2795         if (node->isConnected() && &node->document() != &document)
    2796             continue;
    2797         nodesToRemove.add(node);
    2798     }
     2813    for (auto* node : list)
     2814        conditionallyAddNodeToFilterList(node, document, nodesToRemove);
    27992815}
    28002816
     
    28092825    filterMapForRemoval(m_deferredTextFormControlValue, document, nodesToRemove);
    28102826    filterMapForRemoval(m_deferredAttributeChange, document, nodesToRemove);
     2827    filterVectorPairForRemoval(m_deferredFocusedNodeChange, document, nodesToRemove);
    28112828
    28122829    for (auto* node : nodesToRemove)
     
    28522869        handleAttributeChange(deferredAttributeChangeContext.value, deferredAttributeChangeContext.key);
    28532870    m_deferredAttributeChange.clear();
     2871   
     2872    for (auto& deferredFocusedChangeContext : m_deferredFocusedNodeChange)
     2873        handleFocusedUIElementChanged(deferredFocusedChangeContext.first, deferredFocusedChangeContext.second);
     2874    m_deferredFocusedNodeChange.clear();
    28542875}
    28552876   
  • trunk/Source/WebCore/accessibility/AXObjectCache.h

    r228390 r228417  
    169169    void childrenChanged(AccessibilityObject*);
    170170    void checkedStateChanged(Node*);
    171     void selectedChildrenChanged(Node*);
    172     void selectedChildrenChanged(RenderObject*);
    173     // Called by a node when text or a text equivalent (e.g. alt) attribute is changed.
    174     void textChanged(Node*);
    175171    // Called when a node has just been attached, so we can make sure we have the right subclass of AccessibilityObject.
    176172    void updateCacheAfterNodeIsAttached(Node*);
    177173
    178     void handleActiveDescendantChanged(Node*);
    179     void handleAriaRoleChanged(Node*);
    180     void handleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode);
     174    void deferFocusedUIElementChangeIfNeeded(Node* oldFocusedNode, Node* newFocusedNode);
    181175    void handleScrolledToAnchor(const Node* anchorNode);
    182     void handleAriaExpandedChange(Node*);
    183176    void handleScrollbarUpdate(ScrollView*);
    184177   
    185     void handleModalChange(Node*);
    186178    Node* modalNode();
    187179
     
    412404    void handleAttributeChange(const QualifiedName&, Element*);
    413405    bool shouldProcessAttributeChange(const QualifiedName&, Element*);
    414    
     406    void selectedChildrenChanged(Node*);
     407    void selectedChildrenChanged(RenderObject*);
     408    // Called by a node when text or a text equivalent (e.g. alt) attribute is changed.
     409    void textChanged(Node*);
     410    void handleActiveDescendantChanged(Node*);
     411    void handleAriaRoleChanged(Node*);
     412    void handleAriaExpandedChange(Node*);
     413    void handleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode);
     414
    415415    // aria-modal related
    416416    void findModalNodes();
    417417    void updateCurrentModalNode();
    418418    bool isNodeVisible(Node*) const;
     419    void handleModalChange(Node*);
    419420
    420421    Document& m_document;
     
    450451    HashMap<Element*, String> m_deferredTextFormControlValue;
    451452    HashMap<Element*, QualifiedName> m_deferredAttributeChange;
     453    Vector<std::pair<Node*, Node*>> m_deferredFocusedNodeChange;
    452454    bool m_isSynchronizingSelection { false };
    453455    bool m_performingDeferredCacheUpdate { false };
  • trunk/Source/WebCore/dom/Document.cpp

    r228390 r228417  
    39693969        // Create the AXObject cache in a focus change because GTK relies on it.
    39703970        if (AXObjectCache* cache = axObjectCache())
    3971             cache->handleFocusedUIElementChanged(oldFocusedElement.get(), newFocusedElement.get());
     3971            cache->deferFocusedUIElementChangeIfNeeded(oldFocusedElement.get(), newFocusedElement.get());
    39723972    }
    39733973
Note: See TracChangeset for help on using the changeset viewer.