Commit d8bd058f authored by Adam Ettenberger's avatar Adam Ettenberger Committed by Commit Bot

Fire events for UIA_Value* and UIA_RangeValue* Properties

1. Adding or mapping generated events for relevant properties :
   - ENABLED_CHANGED     (IntAttribute::kRestriction)
   - READONLY_CHANGED    (IntAttribute::kRestriction)
   - VALUE_CHANGED       (FloatAttribute::kValueForRange)
   - VALUE_MAX_CHANGED   (FloatAttribute::kMaxValueForRange)
   - VALUE_MIN_CHANGED   (FloatAttribute::kMinValueForRange)
   - VALUE_STEP_CHANGED  (FloatAttribute::kStepValueForRange)

2. Firing UIA Property Changed events :
   - UIA_IsEnabledPropertyId
   - UIA_RangeValueIsReadOnlyPropertyId
   - UIA_RangeValueLargeChangePropertyId
   - UIA_RangeValueMaximumPropertyId
   - UIA_RangeValueMinimumPropertyId
   - UIA_RangeValueSmallChangePropertyId
   - UIA_RangeValueValuePropertyId
   - UIA_ValueIsReadOnlyPropertyId
   - UIA_ValueValuePropertyId

3. Ethan found a bug with AccessibilityEventRecorderUia which was
   causing event tests with multiple 'go()' calls to timeout.
   Cherry picked the fix from his CL :
   https://chromium-review.googlesource.com/c/chromium/src/+/1518407

Bug: 844149
Change-Id: Icf10385faf2ba84a49747298692bed409a862886
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1534286
Commit-Queue: Adam Ettenberger <adettenb@microsoft.com>
Reviewed-by: default avatarSean Topping <seantopping@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#644618}
parent 86e9f145
......@@ -196,6 +196,7 @@ api::automation::EventType ToAutomationEvent(
case ui::AXEventGenerator::Event::CLASS_NAME_CHANGED:
case ui::AXEventGenerator::Event::DESCRIBED_BY_CHANGED:
case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
case ui::AXEventGenerator::Event::ENABLED_CHANGED:
case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
case ui::AXEventGenerator::Event::KEY_SHORTCUTS_CHANGED:
......@@ -205,7 +206,11 @@ api::automation::EventType ToAutomationEvent(
case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
case ui::AXEventGenerator::Event::PLACEHOLDER_CHANGED:
case ui::AXEventGenerator::Event::POSITION_IN_SET_CHANGED:
case ui::AXEventGenerator::Event::READONLY_CHANGED:
case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
return api::automation::EVENT_TYPE_NONE;
}
......
......@@ -197,6 +197,7 @@ api::automation::EventType ToAutomationEvent(
case ui::AXEventGenerator::Event::CLASS_NAME_CHANGED:
case ui::AXEventGenerator::Event::DESCRIBED_BY_CHANGED:
case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
case ui::AXEventGenerator::Event::ENABLED_CHANGED:
case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
case ui::AXEventGenerator::Event::KEY_SHORTCUTS_CHANGED:
......@@ -206,7 +207,11 @@ api::automation::EventType ToAutomationEvent(
case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
case ui::AXEventGenerator::Event::PLACEHOLDER_CHANGED:
case ui::AXEventGenerator::Event::POSITION_IN_SET_CHANGED:
case ui::AXEventGenerator::Event::READONLY_CHANGED:
case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
return api::automation::EVENT_TYPE_NONE;
}
......
......@@ -225,15 +225,16 @@ void AccessibilityEventRecorderUia::Thread::ThreadMain() {
}
}
// Signal thread shutdown complete; this will wake the main thread to compile
// test results and compare against the expected results.
std::move(shutdown_complete_).Run();
// Cleanup
uia_->RemoveAllEventHandlers();
uia_event_handler_->CleanUp();
uia_event_handler_.Reset();
root_.Reset();
uia_.Reset();
// Signal thread shutdown complete; this will wake the main thread to compile
// test results and compare against the expected results.
std::move(shutdown_complete_).Run();
}
void AccessibilityEventRecorderUia::Thread::SendShutdownSignal() {
......
......@@ -1735,8 +1735,6 @@ void BrowserAccessibilityComWin::UpdateStep3FireEvents(
}
if (description() != old_win_attributes_->description)
FireNativeEvent(EVENT_OBJECT_DESCRIPTIONCHANGE);
if (value() != old_win_attributes_->value)
FireNativeEvent(EVENT_OBJECT_VALUECHANGE);
// Do not fire EVENT_OBJECT_STATECHANGE if the change was due to a focus
// change.
......
......@@ -205,6 +205,7 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
case ui::AXEventGenerator::Event::EXPANDED:
case ui::AXEventGenerator::Event::ENABLED_CHANGED:
case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
case ui::AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
......@@ -221,6 +222,7 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
case ui::AXEventGenerator::Event::PLACEHOLDER_CHANGED:
case ui::AXEventGenerator::Event::POSITION_IN_SET_CHANGED:
case ui::AXEventGenerator::Event::READONLY_CHANGED:
case ui::AXEventGenerator::Event::RELATED_NODE_CHANGED:
case ui::AXEventGenerator::Event::ROLE_CHANGED:
case ui::AXEventGenerator::Event::ROW_COUNT_CHANGED:
......@@ -228,6 +230,9 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
case ui::AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED:
case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
case ui::AXEventGenerator::Event::STATE_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
// There are some notifications that aren't meaningful on Android.
// It's okay to skip them.
break;
......
......@@ -378,6 +378,7 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
case ui::AXEventGenerator::Event::DESCRIBED_BY_CHANGED:
case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
case ui::AXEventGenerator::Event::ENABLED_CHANGED:
case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
case ui::AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
......@@ -391,12 +392,16 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
case ui::AXEventGenerator::Event::PLACEHOLDER_CHANGED:
case ui::AXEventGenerator::Event::POSITION_IN_SET_CHANGED:
case ui::AXEventGenerator::Event::READONLY_CHANGED:
case ui::AXEventGenerator::Event::RELATED_NODE_CHANGED:
case ui::AXEventGenerator::Event::ROLE_CHANGED:
case ui::AXEventGenerator::Event::SCROLL_POSITION_CHANGED:
case ui::AXEventGenerator::Event::SELECTED_CHANGED:
case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
case ui::AXEventGenerator::Event::STATE_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
// There are some notifications that aren't meaningful on Mac.
// It's okay to skip them.
return;
......
......@@ -20,6 +20,7 @@
#include "ui/accessibility/accessibility_switches.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/platform/ax_fragment_root_win.h"
#include "ui/accessibility/platform/ax_platform_node_delegate_utils_win.h"
#include "ui/base/win/atl_module.h"
namespace content {
......@@ -187,6 +188,9 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
FireWinAccessibilityEvent(IA2_EVENT_TEXT_CARET_MOVED, focus_object);
break;
}
case ui::AXEventGenerator::Event::ENABLED_CHANGED:
FireUiaPropertyChangedEvent(UIA_IsEnabledPropertyId, node);
break;
case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
FireUiaPropertyChangedEvent(UIA_FlowsToPropertyId, node);
break;
......@@ -240,6 +244,12 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
case ui::AXEventGenerator::Event::POSITION_IN_SET_CHANGED:
FireUiaPropertyChangedEvent(UIA_PositionInSetPropertyId, node);
break;
case ui::AXEventGenerator::Event::READONLY_CHANGED:
if (ui::IsRangeValueSupported(node->GetData()))
FireUiaPropertyChangedEvent(UIA_RangeValueIsReadOnlyPropertyId, node);
else if (ui::IsValuePatternSupported(node))
FireUiaPropertyChangedEvent(UIA_ValueIsReadOnlyPropertyId, node);
break;
case ui::AXEventGenerator::Event::ROLE_CHANGED:
FireUiaPropertyChangedEvent(UIA_AriaRolePropertyId, node);
break;
......@@ -256,7 +266,25 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
FireUiaPropertyChangedEvent(UIA_SizeOfSetPropertyId, node);
break;
case ui::AXEventGenerator::Event::VALUE_CHANGED:
FireUiaPropertyChangedEvent(UIA_ValueValuePropertyId, node);
FireWinAccessibilityEvent(EVENT_OBJECT_VALUECHANGE, node);
if (ui::IsRangeValueSupported(node->GetData()))
FireUiaPropertyChangedEvent(UIA_RangeValueValuePropertyId, node);
else if (ui::IsValuePatternSupported(node))
FireUiaPropertyChangedEvent(UIA_ValueValuePropertyId, node);
break;
case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
if (IsRangeValueSupported(node->GetData()))
FireUiaPropertyChangedEvent(UIA_RangeValueMaximumPropertyId, node);
break;
case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
if (IsRangeValueSupported(node->GetData()))
FireUiaPropertyChangedEvent(UIA_RangeValueMinimumPropertyId, node);
break;
case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
if (IsRangeValueSupported(node->GetData())) {
FireUiaPropertyChangedEvent(UIA_RangeValueSmallChangePropertyId, node);
FireUiaPropertyChangedEvent(UIA_RangeValueLargeChangePropertyId, node);
}
break;
case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED:
......
......@@ -578,4 +578,33 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
RunEventTest(FILE_PATH_LITERAL("button-click.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
RangeValueIsReadonlyChanged) {
RunEventTest(FILE_PATH_LITERAL("range-value-is-readonly-changed.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, RangeValueMaximumChanged) {
RunEventTest(FILE_PATH_LITERAL("range-value-maximum-changed.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, RangeValueMinimumChanged) {
RunEventTest(FILE_PATH_LITERAL("range-value-minimum-changed.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, RangeValueStepChanged) {
RunEventTest(FILE_PATH_LITERAL("range-value-step-changed.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, RangeValueValueChanged) {
RunEventTest(FILE_PATH_LITERAL("range-value-value-changed.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, ValueIsReadOnlyChanged) {
RunEventTest(FILE_PATH_LITERAL("value-is-readonly-changed.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, ValueValueChanged) {
RunEventTest(FILE_PATH_LITERAL("value-value-changed.html"));
}
} // namespace content
IsEnabled changed on role=slider
RangeValueIsReadOnly changed on role=slider
=== Start Continuation ===
IsEnabled changed on role=slider
RangeValueIsReadOnly changed on role=slider
=== Start Continuation ===
RangeValueIsReadOnly changed on role=slider
=== Start Continuation ===
RangeValueIsReadOnly changed on role=slider
=== Start Continuation ===
IsEnabled changed on role=slider
RangeValueIsReadOnly changed on role=slider
=== Start Continuation ===
IsEnabled changed on role=slider
RangeValueIsReadOnly changed on role=slider
EVENT_OBJECT_STATECHANGE on <input#range> role=ROLE_SYSTEM_SLIDER value="5" UNAVAILABLE IA2_STATE_HORIZONTAL
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#range> role=ROLE_SYSTEM_SLIDER value="5" FOCUSABLE IA2_STATE_HORIZONTAL
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#range> role=ROLE_SYSTEM_SLIDER value="5" FOCUSABLE IA2_STATE_HORIZONTAL
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#range> role=ROLE_SYSTEM_SLIDER value="5" FOCUSABLE IA2_STATE_HORIZONTAL
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#range> role=ROLE_SYSTEM_SLIDER value="5" UNAVAILABLE,FOCUSABLE IA2_STATE_HORIZONTAL
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#range> role=ROLE_SYSTEM_SLIDER value="5" FOCUSABLE IA2_STATE_HORIZONTAL
<!DOCTYPE html>
<input id="range" type="range" min="0" max="10" value="5">
<script>
var go_passes = [
() => document.querySelector('#range').setAttribute('disabled', true),
() => document.querySelector('#range').removeAttribute('disabled'),
() => document.querySelector('#range').setAttribute('aria-readonly', true),
() => document.querySelector('#range').setAttribute('aria-readonly', false),
() => document.querySelector('#range').setAttribute('aria-disabled', true),
() => document.querySelector('#range').setAttribute('aria-disabled', false),
];
var current_pass = 0;
function go() {
go_passes[current_pass++].call();
return current_pass < go_passes.length;
}
</script>
RangeValueMaximum changed on role=slider
=== Start Continuation ===
RangeValueMaximum changed on role=slider
=== Start Continuation ===
RangeValueMaximum changed on role=slider
=== Start Continuation ===
RangeValueMaximum changed on role=slider
<!DOCTYPE html>
<input id="max" type="range" min="0" max="10" value="5">
<script>
var go_passes = [
() => document.querySelector('#max').setAttribute('max', 20),
() => document.querySelector('#max').removeAttribute('max'),
() => document.querySelector('#max').setAttribute('aria-valuemax', 10),
() => document.querySelector('#max').removeAttribute('aria-valuemax'),
];
var current_pass = 0;
function go() {
go_passes[current_pass++].call();
return current_pass < go_passes.length;
}
</script>
RangeValueMinimum changed on role=slider
=== Start Continuation ===
RangeValueMinimum changed on role=slider
=== Start Continuation ===
RangeValueMinimum changed on role=slider
=== Start Continuation ===
RangeValueMinimum changed on role=slider
<!DOCTYPE html>
<input id="min" type="range" min="0" max="10" value="5">
<script>
var go_passes = [
() => document.querySelector('#min').setAttribute('min', 1),
() => document.querySelector('#min').removeAttribute('min'),
() => document.querySelector('#min').setAttribute('aria-valuemin', 1),
() => document.querySelector('#min').removeAttribute('aria-valuemin'),
];
var current_pass = 0;
function go() {
go_passes[current_pass++].call();
return current_pass < go_passes.length;
}
</script>
RangeValueLargeChange changed on role=slider
RangeValueSmallChange changed on role=slider
=== Start Continuation ===
RangeValueLargeChange changed on role=slider
RangeValueSmallChange changed on role=slider
=== Start Continuation ===
RangeValueLargeChange changed on role=slider
RangeValueSmallChange changed on role=slider
RangeValueValue changed on role=slider
=== Start Continuation ===
=== Start Continuation ===
EVENT_OBJECT_VALUECHANGE on <input#step> role=ROLE_SYSTEM_SLIDER value="3" FOCUSABLE IA2_STATE_HORIZONTAL
<!DOCTYPE html>
<input id="step" type="range" min="0" max="10" value="4" step="4">
<script>
var go_passes = [
() => document.querySelector('#step').setAttribute('step', 2),
() => document.querySelector('#step').removeAttribute('step'),
// This |step| value should also trigger a property changed event
// for UIA_RangeValueValuePropertyId
() => document.querySelector('#step').setAttribute('step', 3),
];
var current_pass = 0;
function go() {
go_passes[current_pass++].call();
return current_pass < go_passes.length;
}
</script>
RangeValueValue changed on role=slider
=== Start Continuation ===
RangeValueValue changed on role=slider
=== Start Continuation ===
RangeValueValue changed on role=slider
=== Start Continuation ===
RangeValueValue changed on role=slider
EVENT_OBJECT_VALUECHANGE on <input#value> role=ROLE_SYSTEM_SLIDER value="2" FOCUSABLE IA2_STATE_HORIZONTAL
=== Start Continuation ===
EVENT_OBJECT_VALUECHANGE on <input#value> role=ROLE_SYSTEM_SLIDER value="5" FOCUSABLE IA2_STATE_HORIZONTAL
=== Start Continuation ===
EVENT_OBJECT_VALUECHANGE on <input#value> role=ROLE_SYSTEM_SLIDER value="5" FOCUSABLE IA2_STATE_HORIZONTAL
=== Start Continuation ===
EVENT_OBJECT_VALUECHANGE on <input#value> role=ROLE_SYSTEM_SLIDER value="5" FOCUSABLE IA2_STATE_HORIZONTAL
<!DOCTYPE html>
<input id="value" type="range" min="0" max="10" value="1">
<script>
var go_passes = [
() => document.querySelector('#value').setAttribute('value', 2),
() => document.querySelector('#value').removeAttribute('value'),
() => document.querySelector('#value').setAttribute('aria-valuenow', 3),
() => document.querySelector('#value').removeAttribute('aria-valuenow'),
];
var current_pass = 0;
function go() {
go_passes[current_pass++].call();
return current_pass < go_passes.length;
}
</script>
IsEnabled changed on role=textbox
ValueIsReadOnly changed on role=textbox
=== Start Continuation ===
IsEnabled changed on role=textbox
ValueIsReadOnly changed on role=textbox
=== Start Continuation ===
ValueIsReadOnly changed on role=textbox
=== Start Continuation ===
ValueIsReadOnly changed on role=textbox
=== Start Continuation ===
ValueIsReadOnly changed on role=textbox
=== Start Continuation ===
ValueIsReadOnly changed on role=textbox
=== Start Continuation ===
IsEnabled changed on role=textbox
ValueIsReadOnly changed on role=textbox
=== Start Continuation ===
IsEnabled changed on role=textbox
ValueIsReadOnly changed on role=textbox
EVENT_OBJECT_STATECHANGE on <input#text> role=ROLE_SYSTEM_TEXT UNAVAILABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#text> role=ROLE_SYSTEM_TEXT FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#text> role=ROLE_SYSTEM_TEXT FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#text> role=ROLE_SYSTEM_TEXT FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#text> role=ROLE_SYSTEM_TEXT FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#text> role=ROLE_SYSTEM_TEXT FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#text> role=ROLE_SYSTEM_TEXT UNAVAILABLE,FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE
=== Start Continuation ===
EVENT_OBJECT_STATECHANGE on <input#text> role=ROLE_SYSTEM_TEXT FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE
<!DOCTYPE html>
<input id="text" type="text">
<script>
var go_passes = [
() => document.querySelector('#text').setAttribute('disabled', true),
() => document.querySelector('#text').removeAttribute('disabled'),
() => document.querySelector('#text').setAttribute('readonly', true),
() => document.querySelector('#text').removeAttribute('readonly'),
() => document.querySelector('#text').setAttribute('aria-readonly', true),
() => document.querySelector('#text').setAttribute('aria-readonly', false),
() => document.querySelector('#text').setAttribute('aria-disabled', true),
() => document.querySelector('#text').setAttribute('aria-disabled', false),
];
var current_pass = 0;
function go() {
go_passes[current_pass++].call();
return current_pass < go_passes.length;
}
</script>
ValueValue changed on role=textbox
=== Start Continuation ===
ValueValue changed on role=textbox
EVENT_OBJECT_VALUECHANGE on <input#value> role=ROLE_SYSTEM_TEXT value="new thing" FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE
IA2_EVENT_TEXT_INSERTED on <input#value> role=ROLE_SYSTEM_TEXT value="new thing" FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE new_text={'new ' start=0 end=4}
IA2_EVENT_TEXT_REMOVED on <input#value> role=ROLE_SYSTEM_TEXT value="new thing" FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE old_text={'some' start=0 end=4}
=== Start Continuation ===
EVENT_OBJECT_VALUECHANGE on <input#value> role=ROLE_SYSTEM_TEXT FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE
IA2_EVENT_TEXT_REMOVED on <input#value> role=ROLE_SYSTEM_TEXT FOCUSABLE IA2_STATE_EDITABLE,IA2_STATE_SELECTABLE_TEXT,IA2_STATE_SINGLE_LINE old_text={'new thing' start=0 end=9}
<!DOCTYPE html>
<input id="value" type="text" value="something">
<script>
var go_passes = [
() => document.querySelector('#value').setAttribute('value', 'new thing'),
() => document.querySelector('#value').removeAttribute('value'),
];
var current_pass = 0;
function go() {
go_passes[current_pass++].call();
return current_pass < go_passes.length;
}
</script>
......@@ -1243,7 +1243,13 @@ void AXObjectCacheImpl::HandleAttributeChangedWithCleanLayout(
MaybeNewRelationTarget(element, Get(element));
} else if (attr_name == kTabindexAttr) {
FocusableChangedWithCleanLayout(element);
} else if (attr_name == kDisabledAttr) {
} else if (attr_name == kDisabledAttr || attr_name == kReadonlyAttr) {
MarkElementDirty(element, false);
} else if (attr_name == kValueAttr) {
HandleValueChanged(element);
} else if (attr_name == kMinAttr || attr_name == kMaxAttr) {
MarkElementDirty(element, false);
} else if (attr_name == kStepAttr) {
MarkElementDirty(element, false);
}
......@@ -1255,7 +1261,7 @@ void AXObjectCacheImpl::HandleAttributeChangedWithCleanLayout(
HandleActiveDescendantChangedWithCleanLayout(element);
} else if (attr_name == kAriaValuenowAttr ||
attr_name == kAriaValuetextAttr) {
PostNotification(element, ax::mojom::Event::kValueChanged);
HandleValueChanged(element);
} else if (attr_name == kAriaLabelAttr || attr_name == kAriaLabeledbyAttr ||
attr_name == kAriaLabelledbyAttr) {
TextChangedWithCleanLayout(element);
......
......@@ -264,9 +264,22 @@ void AXEventGenerator::OnIntAttributeChanged(AXTree* tree,
case ax::mojom::IntAttribute::kPosInSet:
AddEvent(node, Event::POSITION_IN_SET_CHANGED);
break;
case ax::mojom::IntAttribute::kRestriction:
AddEvent(node, Event::STATE_CHANGED);
case ax::mojom::IntAttribute::kRestriction: {
bool was_enabled;
bool was_readonly;
GetRestrictionStates(static_cast<ax::mojom::Restriction>(old_value),
&was_enabled, &was_readonly);
bool is_enabled;
bool is_readonly;
GetRestrictionStates(static_cast<ax::mojom::Restriction>(new_value),
&is_enabled, &is_readonly);
if (was_enabled != is_enabled)
AddEvent(node, Event::ENABLED_CHANGED);
if (was_readonly != is_readonly)
AddEvent(node, Event::READONLY_CHANGED);
break;
}
case ax::mojom::IntAttribute::kScrollX:
case ax::mojom::IntAttribute::kScrollY:
AddEvent(node, Event::SCROLL_POSITION_CHANGED);
......@@ -291,10 +304,23 @@ void AXEventGenerator::OnFloatAttributeChanged(AXTree* tree,
float new_value) {
DCHECK_EQ(tree_, tree);
if (attr == ax::mojom::FloatAttribute::kValueForRange)
AddEvent(node, Event::VALUE_CHANGED);
else
AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
switch (attr) {
case ax::mojom::FloatAttribute::kMaxValueForRange:
AddEvent(node, Event::VALUE_MAX_CHANGED);
break;
case ax::mojom::FloatAttribute::kMinValueForRange:
AddEvent(node, Event::VALUE_MIN_CHANGED);
break;
case ax::mojom::FloatAttribute::kStepValueForRange:
AddEvent(node, Event::VALUE_STEP_CHANGED);
break;
case ax::mojom::FloatAttribute::kValueForRange:
AddEvent(node, Event::VALUE_CHANGED);
break;
default:
AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
break;
}
}
void AXEventGenerator::OnBoolAttributeChanged(AXTree* tree,
......@@ -515,4 +541,24 @@ bool AXEventGenerator::ShouldFireLoadEvents(AXNode* node) {
data.relative_bounds.bounds.height();
}
// static
void AXEventGenerator::GetRestrictionStates(ax::mojom::Restriction restriction,
bool* is_enabled,
bool* is_readonly) {
switch (restriction) {
case ax::mojom::Restriction::kDisabled:
*is_enabled = false;
*is_readonly = true;
break;
case ax::mojom::Restriction::kReadOnly:
*is_enabled = true;
*is_readonly = true;
break;
case ax::mojom::Restriction::kNone:
*is_enabled = true;
*is_readonly = false;
break;
}
}
} // namespace ui
......@@ -34,6 +34,7 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver {
DESCRIPTION_CHANGED,
DOCUMENT_SELECTION_CHANGED,
DOCUMENT_TITLE_CHANGED,
ENABLED_CHANGED,
EXPANDED,
FLOW_TO_CHANGED,
HIERARCHICAL_LEVEL_CHANGED,
......@@ -54,6 +55,7 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver {
PLACEHOLDER_CHANGED,
POSITION_IN_SET_CHANGED,
RELATED_NODE_CHANGED,
READONLY_CHANGED,
ROLE_CHANGED,
ROW_COUNT_CHANGED,
SCROLL_POSITION_CHANGED,
......@@ -62,6 +64,9 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver {
SET_SIZE_CHANGED,
STATE_CHANGED,
VALUE_CHANGED,
VALUE_MAX_CHANGED,
VALUE_MIN_CHANGED,
VALUE_STEP_CHANGED,
};
struct EventParams {
......@@ -194,6 +199,9 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver {
void FireActiveDescendantEvents();
void FireRelationSourceEvents(AXTree* tree, AXNode* target_node);
bool ShouldFireLoadEvents(AXNode* node);
static void GetRestrictionStates(ax::mojom::Restriction restriction,
bool* is_enabled,
bool* is_readonly);
AXTree* tree_ = nullptr; // Not owned.
std::map<AXNode*, std::set<EventParams>> tree_events_;
......
......@@ -53,6 +53,9 @@ std::string DumpEvents(AXEventGenerator* generator) {
case AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
event_name = "DOCUMENT_TITLE_CHANGED";
break;
case AXEventGenerator::Event::ENABLED_CHANGED:
event_name = "ENABLED_CHANGED";
break;
case AXEventGenerator::Event::EXPANDED:
event_name = "EXPANDED";
break;
......@@ -113,6 +116,9 @@ std::string DumpEvents(AXEventGenerator* generator) {
case AXEventGenerator::Event::RELATED_NODE_CHANGED:
event_name = "RELATED_NODE_CHANGED";
break;
case AXEventGenerator::Event::READONLY_CHANGED:
event_name = "READONLY_CHANGED";
break;
case AXEventGenerator::Event::ROLE_CHANGED:
event_name = "ROLE_CHANGED";
break;
......@@ -137,6 +143,15 @@ std::string DumpEvents(AXEventGenerator* generator) {
case AXEventGenerator::Event::VALUE_CHANGED:
event_name = "VALUE_CHANGED";
break;
case AXEventGenerator::Event::VALUE_MAX_CHANGED:
event_name = "VALUE_MAX_CHANGED";
break;
case AXEventGenerator::Event::VALUE_MIN_CHANGED:
event_name = "VALUE_MIN_CHANGED";
break;
case AXEventGenerator::Event::VALUE_STEP_CHANGED:
event_name = "VALUE_STEP_CHANGED";
break;
default:
NOTREACHED();
event_name = "UNKNOWN";
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment