summaryrefslogtreecommitdiff
path: root/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp')
-rw-r--r--Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp60
1 files changed, 40 insertions, 20 deletions
diff --git a/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp b/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp
index 753f761e4..85e0c64d5 100644
--- a/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp
+++ b/Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp
@@ -30,7 +30,8 @@
#include "Range.h"
#include "TextIterator.h"
#include "WebKitAccessibleWrapperAtk.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/CString.h>
namespace WebCore {
@@ -75,7 +76,19 @@ void AXObjectCache::attachWrapper(AccessibilityObject* obj)
if (!document || document->childNeedsStyleRecalc())
return;
- // Don't emit the signal for objects that we already know won't be exposed directly.
+ // Don't emit the signal when the actual object being added is not going to be exposed.
+ if (obj->accessibilityIsIgnoredByDefault())
+ return;
+
+ // Don't emit the signal if the object being added is not -- or not yet -- rendered,
+ // which can occur in nested iframes. In these instances we don't want to ignore the
+ // child. But if an assistive technology is listening, AT-SPI2 will attempt to create
+ // and cache the state set for the child upon emission of the signal. If the object
+ // has not yet been rendered, this will result in a crash.
+ if (!obj->renderer())
+ return;
+
+ // Don't emit the signal for objects whose parents won't be exposed directly.
AccessibilityObject* coreParent = obj->parentObjectUnignored();
if (!coreParent || coreParent->accessibilityIsIgnoredByDefault())
return;
@@ -119,8 +132,8 @@ static void notifyChildrenSelectionChange(AccessibilityObject* object)
// focused object and its associated list object, as per previous
// calls to this function, in order to properly decide whether to
// emit some signals or not.
- DEFINE_STATIC_LOCAL(RefPtr<AccessibilityObject>, oldListObject, ());
- DEFINE_STATIC_LOCAL(RefPtr<AccessibilityObject>, oldFocusedObject, ());
+ static NeverDestroyed<RefPtr<AccessibilityObject>> oldListObject;
+ static NeverDestroyed<RefPtr<AccessibilityObject>> oldFocusedObject;
// Only list boxes and menu lists supported so far.
if (!object || !(object->isListBox() || object->isMenuList()))
@@ -128,21 +141,19 @@ static void notifyChildrenSelectionChange(AccessibilityObject* object)
// Only support HTML select elements so far (ARIA selectors not supported).
Node* node = object->node();
- if (!node || !isHTMLSelectElement(node))
+ if (!is<HTMLSelectElement>(node))
return;
// Emit signal from the listbox's point of view first.
g_signal_emit_by_name(object->wrapper(), "selection-changed");
// Find the item where the selection change was triggered from.
- HTMLSelectElement* select = toHTMLSelectElement(node);
- if (!select)
- return;
- int changedItemIndex = select->activeSelectionStartListIndex();
+ HTMLSelectElement& select = downcast<HTMLSelectElement>(*node);
+ int changedItemIndex = select.activeSelectionStartListIndex();
AccessibilityObject* listObject = getListObject(object);
if (!listObject) {
- oldListObject = 0;
+ oldListObject.get() = nullptr;
return;
}
@@ -154,11 +165,11 @@ static void notifyChildrenSelectionChange(AccessibilityObject* object)
// Ensure the current list object is the same than the old one so
// further comparisons make sense. Otherwise, just reset
// oldFocusedObject so it won't be taken into account.
- if (oldListObject != listObject)
- oldFocusedObject = 0;
+ if (oldListObject.get() != listObject)
+ oldFocusedObject.get() = nullptr;
- AtkObject* axItem = item ? item->wrapper() : 0;
- AtkObject* axOldFocusedObject = oldFocusedObject ? oldFocusedObject->wrapper() : 0;
+ AtkObject* axItem = item ? item->wrapper() : nullptr;
+ AtkObject* axOldFocusedObject = oldFocusedObject.get() ? oldFocusedObject.get()->wrapper() : nullptr;
// Old focused object just lost focus, so emit the events.
if (axOldFocusedObject && axItem != axOldFocusedObject) {
@@ -179,8 +190,8 @@ static void notifyChildrenSelectionChange(AccessibilityObject* object)
}
// Update pointers to the previously involved objects.
- oldListObject = listObject;
- oldFocusedObject = item;
+ oldListObject.get() = listObject;
+ oldFocusedObject.get() = item;
}
void AXObjectCache::postPlatformNotification(AccessibilityObject* coreObject, AXNotification notification)
@@ -191,7 +202,7 @@ void AXObjectCache::postPlatformNotification(AccessibilityObject* coreObject, AX
switch (notification) {
case AXCheckedStateChanged:
- if (!coreObject->isCheckboxOrRadio())
+ if (!coreObject->isCheckboxOrRadio() && !coreObject->isSwitch())
return;
atk_object_notify_state_change(axObject, ATK_STATE_CHECKED, coreObject->isChecked());
break;
@@ -212,7 +223,13 @@ void AXObjectCache::postPlatformNotification(AccessibilityObject* coreObject, AX
propertyValues.property_name = "accessible-value";
memset(&propertyValues.new_value, 0, sizeof(GValue));
+#if ATK_CHECK_VERSION(2,11,92)
+ double value;
+ atk_value_get_value_and_text(ATK_VALUE(axObject), &value, nullptr);
+ g_value_set_double(g_value_init(&propertyValues.new_value, G_TYPE_DOUBLE), value);
+#else
atk_value_get_current_value(ATK_VALUE(axObject), &propertyValues.new_value);
+#endif
g_signal_emit_by_name(ATK_OBJECT(axObject), "property-change::accessible-value", &propertyValues, NULL);
}
@@ -232,7 +249,7 @@ void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject* obje
if (!object || text.isEmpty())
return;
- AccessibilityObject* parentObject = object->parentObjectUnignored();
+ AccessibilityObject* parentObject = object->isNonNativeTextControl() ? object : object->parentObjectUnignored();
if (!parentObject)
return;
@@ -251,12 +268,15 @@ void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject* obje
// Select the right signal to be emitted
CString detail;
switch (textChange) {
- case AXObjectCache::AXTextInserted:
+ case AXTextInserted:
detail = "text-insert";
break;
- case AXObjectCache::AXTextDeleted:
+ case AXTextDeleted:
detail = "text-remove";
break;
+ case AXTextAttributesChanged:
+ detail = "text-attributes-changed";
+ break;
}
String textToEmit = text;