Title: [270609] trunk/Source/WebCore
Revision
270609
Author
[email protected]
Date
2020-12-09 16:35:27 -0800 (Wed, 09 Dec 2020)

Log Message

Fix for focus tracking in isolated tree mode.
https://bugs.webkit.org/show_bug.cgi?id=219662

Reviewed by Chris Fleizach.

Covered by existing tests.

- AXIsolatedTree::setFocusedNodeID and applyPendingChanges now properly
handle the focused node ID update when the focused object changes.
- AccessibilityObject::setFocused sets focus and activates the
corresponding view. This was done in the wrapper baseAccessibilitySetFocus
method, but this is a more appropriate place for this core functionality.
- Some code cleanup, ASSERT checks of appropriate thread, and additional
logging.

* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::setFocused):
* accessibility/AccessibilityObject.h:
* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::setFocused):
* accessibility/AccessibilityScrollView.cpp:
(WebCore::AccessibilityScrollView::setFocused):
* accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
(-[WebAccessibilityObjectWrapper _accessibilitySetFocus:]):
* accessibility/isolatedtree/AXIsolatedObject.cpp:
(WebCore::AXIsolatedObject::page const):
(WebCore::AXIsolatedObject::document const):
(WebCore::AXIsolatedObject::documentFrameView const):
* accessibility/isolatedtree/AXIsolatedTree.cpp:
(WebCore::AXIsolatedTree::setFocusedNodeID):
(WebCore::AXIsolatedTree::applyPendingChanges):
* accessibility/mac/WebAccessibilityObjectWrapperBase.h:
* accessibility/mac/WebAccessibilityObjectWrapperBase.mm:
(-[WebAccessibilityObjectWrapperBase baseAccessibilitySetFocus:]):
Deleted, not needed since core functionality is now in AccessibilityObject::setFocused.
* accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(-[WebAccessibilityObjectWrapper accessibilityAttributeValue:]):
(-[WebAccessibilityObjectWrapper _accessibilitySetValue:forAttribute:]):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (270608 => 270609)


--- trunk/Source/WebCore/ChangeLog	2020-12-10 00:23:43 UTC (rev 270608)
+++ trunk/Source/WebCore/ChangeLog	2020-12-10 00:35:27 UTC (rev 270609)
@@ -1,3 +1,44 @@
+2020-12-09  Andres Gonzalez  <[email protected]>
+
+        Fix for focus tracking in isolated tree mode.
+        https://bugs.webkit.org/show_bug.cgi?id=219662
+
+        Reviewed by Chris Fleizach.
+
+        Covered by existing tests.
+
+        - AXIsolatedTree::setFocusedNodeID and applyPendingChanges now properly
+        handle the focused node ID update when the focused object changes.
+        - AccessibilityObject::setFocused sets focus and activates the
+        corresponding view. This was done in the wrapper baseAccessibilitySetFocus
+        method, but this is a more appropriate place for this core functionality.
+        - Some code cleanup, ASSERT checks of appropriate thread, and additional
+        logging.
+
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::setFocused):
+        * accessibility/AccessibilityObject.h:
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::setFocused):
+        * accessibility/AccessibilityScrollView.cpp:
+        (WebCore::AccessibilityScrollView::setFocused):
+        * accessibility/ios/WebAccessibilityObjectWrapperIOS.mm:
+        (-[WebAccessibilityObjectWrapper _accessibilitySetFocus:]):
+        * accessibility/isolatedtree/AXIsolatedObject.cpp:
+        (WebCore::AXIsolatedObject::page const):
+        (WebCore::AXIsolatedObject::document const):
+        (WebCore::AXIsolatedObject::documentFrameView const):
+        * accessibility/isolatedtree/AXIsolatedTree.cpp:
+        (WebCore::AXIsolatedTree::setFocusedNodeID):
+        (WebCore::AXIsolatedTree::applyPendingChanges):
+        * accessibility/mac/WebAccessibilityObjectWrapperBase.h:
+        * accessibility/mac/WebAccessibilityObjectWrapperBase.mm:
+        (-[WebAccessibilityObjectWrapperBase baseAccessibilitySetFocus:]):
+        Deleted, not needed since core functionality is now in AccessibilityObject::setFocused.
+        * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+        (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:]):
+        (-[WebAccessibilityObjectWrapper _accessibilitySetValue:forAttribute:]):
+
 2020-12-09  Said Abou-Hallawa  <[email protected]>
 
         [GPU Process]: Recording an in-process ImageBuffer drawing has to convert it to a NativeImage first

Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.cpp (270608 => 270609)


--- trunk/Source/WebCore/accessibility/AccessibilityObject.cpp	2020-12-10 00:23:43 UTC (rev 270608)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.cpp	2020-12-10 00:35:27 UTC (rev 270609)
@@ -2561,7 +2561,40 @@
     auto* axObjectCache = this->axObjectCache();
     return page && axObjectCache ? axObjectCache->focusedObjectForPage(page) : nullptr;
 }
-    
+
+void AccessibilityObject::setFocused(bool focus)
+{
+    if (focus) {
+        // Ensure that the view is focused and active, otherwise, any attempt to set focus to an object inside it will fail.
+        auto* document = this->document();
+        if (!document)
+            return;
+
+        auto* frame = document->frame();
+        if (frame && frame->selection().isFocusedAndActive())
+            return; // Nothing to do, already focused and active.
+
+        auto* page = document->page();
+        if (!page)
+            return;
+
+        ChromeClient& chromeClient = page->chrome().client();
+        chromeClient.focus();
+
+#if PLATFORM(COCOA)
+        auto* frameView = documentFrameView();
+        if (!frameView)
+            return;
+
+        // Legacy WebKit1 case.
+        if (frameView->platformWidget())
+            chromeClient.makeFirstResponder((NSResponder *)frameView->platformWidget());
+        else
+            chromeClient.assistiveTechnologyMakeFirstResponder();
+#endif
+    }
+}
+
 AccessibilitySortDirection AccessibilityObject::sortDirection() const
 {
     AccessibilityRole role = roleValue();

Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.h (270608 => 270609)


--- trunk/Source/WebCore/accessibility/AccessibilityObject.h	2020-12-10 00:23:43 UTC (rev 270608)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.h	2020-12-10 00:35:27 UTC (rev 270609)
@@ -457,7 +457,10 @@
     unsigned hierarchicalLevel() const override { return 0; }
     bool isInlineText() const override;
 
-    void setFocused(bool) override { }
+    // Ensures that the view is focused and active before attempting to set focus to an AccessibilityObject.
+    // Subclasses that override setFocused should call this base implementation first.
+    void setFocused(bool) override;
+
     void setSelectedText(const String&) override { }
     void setSelectedTextRange(const PlainTextRange&) override { }
     bool setValue(const String&) override { return false; }

Modified: trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp (270608 => 270609)


--- trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp	2020-12-10 00:23:43 UTC (rev 270608)
+++ trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp	2020-12-10 00:35:27 UTC (rev 270609)
@@ -1849,7 +1849,7 @@
 {
     if (!canSetFocusAttribute())
         return;
-    
+
     Document* document = this->document();
     Node* node = this->node();
 
@@ -1858,11 +1858,14 @@
         return;
     }
 
+    // Call the base class setFocused to ensure the view is focused and active.
+    AccessibilityObject::setFocused(on);
+
     // When a node is told to set focus, that can cause it to be deallocated, which means that doing
     // anything else inside this object will crash. To fix this, we added a RefPtr to protect this object
     // long enough for duration.
     RefPtr<AccessibilityObject> protectedThis(this);
-    
+
     // If this node is already the currently focused node, then calling focus() won't do anything.
     // That is a problem when focus is removed from the webpage to chrome, and then returns.
     // In these cases, we need to do what keyboard and mouse focus do, which is reset focus first.

Modified: trunk/Source/WebCore/accessibility/AccessibilityScrollView.cpp (270608 => 270609)


--- trunk/Source/WebCore/accessibility/AccessibilityScrollView.cpp	2020-12-10 00:23:43 UTC (rev 270608)
+++ trunk/Source/WebCore/accessibility/AccessibilityScrollView.cpp	2020-12-10 00:35:27 UTC (rev 270609)
@@ -104,9 +104,12 @@
     AccessibilityObject* webArea = webAreaObject();
     return webArea && webArea->isFocused();
 }
-    
+
 void AccessibilityScrollView::setFocused(bool focused)
 {
+    // Call the base class setFocused to ensure the view is focused and active.
+    AccessibilityObject::setFocused(focused);
+
     if (AccessibilityObject* webArea = webAreaObject())
         webArea->setFocused(focused);
 }

Modified: trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm (270608 => 270609)


--- trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm	2020-12-10 00:23:43 UTC (rev 270608)
+++ trunk/Source/WebCore/accessibility/ios/WebAccessibilityObjectWrapperIOS.mm	2020-12-10 00:35:27 UTC (rev 270609)
@@ -2081,7 +2081,8 @@
 
 - (void)_accessibilitySetFocus:(BOOL)focus
 {
-    [self baseAccessibilitySetFocus:focus];
+    if (auto* backingObject = self.axBackingObject)
+        backingObject->setFocused(focus);
 }
 
 - (void)accessibilityDecreaseSelection:(TextGranularity)granularity

Modified: trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp (270608 => 270609)


--- trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp	2020-12-10 00:23:43 UTC (rev 270608)
+++ trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedObject.cpp	2020-12-10 00:35:27 UTC (rev 270609)
@@ -1905,8 +1905,11 @@
 
 Page* AXIsolatedObject::page() const
 {
-    if (auto* object = associatedAXObject())
-        return object->page();
+    ASSERT(isMainThread());
+
+    if (auto* axObject = associatedAXObject())
+        return axObject->page();
+
     ASSERT_NOT_REACHED();
     return nullptr;
 }
@@ -1913,8 +1916,11 @@
 
 Document* AXIsolatedObject::document() const
 {
-    if (auto* object = associatedAXObject())
-        return object->document();
+    ASSERT(isMainThread());
+
+    if (auto* axObject = associatedAXObject())
+        return axObject->document();
+
     ASSERT_NOT_REACHED();
     return nullptr;
 }
@@ -1921,8 +1927,12 @@
 
 FrameView* AXIsolatedObject::documentFrameView() const
 {
-    if (auto* object = associatedAXObject())
-        return object->documentFrameView();
+    ASSERT(isMainThread());
+
+    if (auto* axObject = associatedAXObject())
+        return axObject->documentFrameView();
+
+    ASSERT_NOT_REACHED();
     return nullptr;
 }
 

Modified: trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedTree.cpp (270608 => 270609)


--- trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedTree.cpp	2020-12-10 00:23:43 UTC (rev 270608)
+++ trunk/Source/WebCore/accessibility/isolatedtree/AXIsolatedTree.cpp	2020-12-10 00:35:27 UTC (rev 270609)
@@ -388,8 +388,13 @@
     AXTRACE("AXIsolatedTree::setFocusedNodeID");
     AXLOG(makeString("axID ", axID));
     ASSERT(isMainThread());
+
     LockHolder locker { m_changeLogLock };
     m_pendingFocusedNodeID = axID;
+
+    AXPropertyMap propertyMap;
+    propertyMap.set(AXPropertyName::IsFocused, true);
+    m_pendingPropertyChanges.append({ axID, propertyMap });
 }
 
 void AXIsolatedTree::removeNode(AXID axID)
@@ -436,9 +441,18 @@
 
     LockHolder locker { m_changeLogLock };
 
-    AXLOG(makeString("focusedNodeID ", m_focusedNodeID, " pendingFocusedNodeID ", m_pendingFocusedNodeID));
-    m_focusedNodeID = m_pendingFocusedNodeID;
+    if (m_pendingFocusedNodeID != m_focusedNodeID) {
+        AXLOG(makeString("focusedNodeID ", m_focusedNodeID, " pendingFocusedNodeID ", m_pendingFocusedNodeID));
 
+        if (m_focusedNodeID != InvalidAXID) {
+            // Set the old focused object's IsFocused property to false.
+            AXPropertyMap propertyMap;
+            propertyMap.set(AXPropertyName::IsFocused, false);
+            m_pendingPropertyChanges.append({ m_focusedNodeID, propertyMap });
+        }
+        m_focusedNodeID = m_pendingFocusedNodeID;
+    }
+
     while (m_pendingNodeRemovals.size()) {
         auto axID = m_pendingNodeRemovals.takeLast();
         AXLOG(makeString("removing axID ", axID));

Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.h (270608 => 270609)


--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.h	2020-12-10 00:23:43 UTC (rev 270608)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.h	2020-12-10 00:35:27 UTC (rev 270609)
@@ -74,7 +74,6 @@
 - (NSString *)baseAccessibilityHelpText;
 - (NSArray<NSString *> *)baseAccessibilitySpeechHint;
 
-- (void)baseAccessibilitySetFocus:(BOOL)focus;
 - (NSString *)ariaLandmarkRoleDescription;
 
 - (id)attachmentView;

Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm (270608 => 270609)


--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm	2020-12-10 00:23:43 UTC (rev 270608)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperBase.mm	2020-12-10 00:35:27 UTC (rev 270609)
@@ -43,8 +43,6 @@
 #import "AccessibilityTableCell.h"
 #import "AccessibilityTableColumn.h"
 #import "AccessibilityTableRow.h"
-#import "Chrome.h"
-#import "ChromeClient.h"
 #import "ColorMac.h"
 #import "ContextMenuController.h"
 #import "Editing.h"
@@ -469,27 +467,6 @@
     return self.axBackingObject->ariaLandmarkRoleDescription();
 }
 
-- (void)baseAccessibilitySetFocus:(BOOL)focus
-{
-    // If focus is just set without making the view the first responder, then keyboard focus won't move to the right place.
-    if (focus && !self.axBackingObject->document()->frame()->selection().isFocusedAndActive()) {
-        FrameView* frameView = self.axBackingObject->documentFrameView();
-        Page* page = self.axBackingObject->page();
-        if (page && frameView) {
-            ChromeClient& chromeClient = page->chrome().client();
-            chromeClient.focus();
-
-            // Legacy WebKit1 case.
-            if (frameView->platformWidget())
-                chromeClient.makeFirstResponder(frameView->platformWidget());
-            else
-                chromeClient.assistiveTechnologyMakeFirstResponder();
-        }
-    }
-
-    self.axBackingObject->setFocused(focus);
-}
-
 - (NSString *)accessibilityPlatformMathSubscriptKey
 {
     ASSERT_NOT_REACHED();

Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm (270608 => 270609)


--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm	2020-12-10 00:23:43 UTC (rev 270608)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm	2020-12-10 00:35:27 UTC (rev 270609)
@@ -2139,9 +2139,12 @@
 ALLOW_DEPRECATED_IMPLEMENTATIONS_END
 {
     AXTRACE(makeString("WebAccessibilityObjectWrapper accessibilityAttributeValue:", String(attributeName)));
+
     auto* backingObject = self.updateObjectBackingStore;
-    if (!backingObject)
+    if (!backingObject) {
+        AXLOG("No backingObject!!!");
         return nil;
+    }
 
     if (backingObject->isDetachedFromParent()) {
         AXLOG("backingObject is detached from parent!!!");
@@ -3360,11 +3363,15 @@
 #endif
 }
 
-- (void)_accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName
+- (void)_accessibilitySetValue:(id)value forAttribute:(NSString *)attributeName
 {
+    AXTRACE(makeString("WebAccessibilityObjectWrapper _accessibilitySetValue: forAttribute:", String(attributeName)));
+
     auto* backingObject = self.updateObjectBackingStore;
-    if (!backingObject)
+    if (!backingObject) {
+        AXLOG("No backingObject!!!");
         return;
+    }
 
     AXTextMarkerRangeRef textMarkerRange = nil;
     NSNumber*               number = nil;
@@ -3392,7 +3399,7 @@
                 backingObject->setSelectedVisiblePositionRange(visiblePositionRangeForTextMarkerRange(backingObject->axObjectCache(), textMarkerRange));
         });
     } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) {
-        [self baseAccessibilitySetFocus:[number boolValue]];
+        backingObject->setFocused([number boolValue]);
     } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
         if (number && backingObject->canSetNumericValue())
             backingObject->setValue([number floatValue]);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to