Bug 1694573 part 5: Make LocalAccessible call Platform*Event. Remove most of the platform HandleAccEvent overrides. r=eeejay

Mac and Android still override HandleAccEvent for platform specific behaviour other than firing the event.
The Android behaviour can be unified properly in future work.

ATK is the platform layer with the most churn because there were inconsistencies in the way local and remote events were handled.
I'm reasonably sure these were unintentional inconsistencies, so I've done my best to unify them.

Differential Revision: https://phabricator.services.mozilla.com/D183704
This commit is contained in:
James Teh 2023-07-19 02:56:54 +00:00
parent 4458083853
commit 7c63b7fc05
10 changed files with 175 additions and 566 deletions

View File

@ -99,113 +99,6 @@ nsresult AccessibleWrap::HandleAccEvent(AccEvent* aEvent) {
accessible->HandleLiveRegionEvent(aEvent);
if (IPCAccessibilityActive()) {
return NS_OK;
}
// The accessible can become defunct if we have an xpcom event listener
// which decides it would be fun to change the DOM and flush layout.
if (accessible->IsDefunct() || !accessible->IsBoundToParent()) {
return NS_OK;
}
if (doc) {
if (!doc->DocumentNode()->IsContentDocument()) {
return NS_OK;
}
}
RefPtr<SessionAccessibility> sessionAcc =
SessionAccessibility::GetInstanceFor(accessible);
if (!sessionAcc) {
return NS_OK;
}
switch (aEvent->GetEventType()) {
case nsIAccessibleEvent::EVENT_FOCUS:
sessionAcc->SendFocusEvent(accessible);
break;
case nsIAccessibleEvent::EVENT_VIRTUALCURSOR_CHANGED: {
AccVCChangeEvent* vcEvent = downcast_accEvent(aEvent);
if (!vcEvent->IsFromUserInput()) {
break;
}
RefPtr<AccessibleWrap> newPosition =
static_cast<AccessibleWrap*>(vcEvent->NewAccessible());
if (sessionAcc && newPosition) {
if (vcEvent->Reason() == nsIAccessiblePivot::REASON_POINT) {
sessionAcc->SendHoverEnterEvent(newPosition);
} else {
sessionAcc->SendAccessibilityFocusedEvent(newPosition);
}
}
break;
}
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
AccCaretMoveEvent* event = downcast_accEvent(aEvent);
sessionAcc->SendTextSelectionChangedEvent(accessible,
event->GetCaretOffset());
break;
}
case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
case nsIAccessibleEvent::EVENT_TEXT_REMOVED: {
AccTextChangeEvent* event = downcast_accEvent(aEvent);
sessionAcc->SendTextChangedEvent(
accessible, event->ModifiedText(), event->GetStartOffset(),
event->GetLength(), event->IsTextInserted(),
event->IsFromUserInput());
break;
}
case nsIAccessibleEvent::EVENT_STATE_CHANGE: {
AccStateChangeEvent* event = downcast_accEvent(aEvent);
auto state = event->GetState();
if (state & states::CHECKED) {
sessionAcc->SendClickedEvent(
accessible, java::SessionAccessibility::FLAG_CHECKABLE |
(event->IsStateEnabled()
? java::SessionAccessibility::FLAG_CHECKED
: 0));
}
if (state & states::EXPANDED) {
sessionAcc->SendClickedEvent(
accessible, java::SessionAccessibility::FLAG_EXPANDABLE |
(event->IsStateEnabled()
? java::SessionAccessibility::FLAG_EXPANDED
: 0));
}
if (state & states::SELECTED) {
sessionAcc->SendSelectedEvent(accessible, event->IsStateEnabled());
}
if (state & states::BUSY) {
sessionAcc->SendWindowStateChangedEvent(accessible);
}
break;
}
case nsIAccessibleEvent::EVENT_SCROLLING: {
AccScrollingEvent* event = downcast_accEvent(aEvent);
sessionAcc->SendScrollingEvent(accessible, event->ScrollX(),
event->ScrollY(), event->MaxScrollX(),
event->MaxScrollY());
break;
}
case nsIAccessibleEvent::EVENT_ANNOUNCEMENT: {
AccAnnouncementEvent* event = downcast_accEvent(aEvent);
sessionAcc->SendAnnouncementEvent(accessible, event->Announcement(),
event->Priority());
break;
}
case nsIAccessibleEvent::EVENT_REORDER: {
sessionAcc->SendWindowContentChangedEvent();
break;
}
default:
break;
}
return NS_OK;
}

View File

@ -950,286 +950,6 @@ void a11y::ProxyDestroyed(RemoteAccessible* aProxy) {
aProxy->SetWrapper(0);
}
nsresult AccessibleWrap::HandleAccEvent(AccEvent* aEvent) {
nsresult rv = LocalAccessible::HandleAccEvent(aEvent);
NS_ENSURE_SUCCESS(rv, rv);
if (IPCAccessibilityActive()) {
return NS_OK;
}
LocalAccessible* accessible = aEvent->GetAccessible();
NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);
// The accessible can become defunct if we have an xpcom event listener
// which decides it would be fun to change the DOM and flush layout.
if (accessible->IsDefunct()) return NS_OK;
uint32_t type = aEvent->GetEventType();
AtkObject* atkObj = AccessibleWrap::GetAtkObject(accessible);
// We don't create ATK objects for plain text leaves, just return NS_OK in
// such case.
if (!atkObj) {
NS_ASSERTION(type == nsIAccessibleEvent::EVENT_SHOW ||
type == nsIAccessibleEvent::EVENT_HIDE,
"Event other than SHOW and HIDE fired for plain text leaves");
return NS_OK;
}
AccessibleWrap* accWrap = GetAccessibleWrap(atkObj);
if (!accWrap) {
return NS_OK; // Node is shut down
}
switch (type) {
case nsIAccessibleEvent::EVENT_STATE_CHANGE: {
AccStateChangeEvent* event = downcast_accEvent(aEvent);
MAI_ATK_OBJECT(atkObj)->FireStateChangeEvent(event->GetState(),
event->IsStateEnabled());
break;
}
case nsIAccessibleEvent::EVENT_TEXT_REMOVED:
case nsIAccessibleEvent::EVENT_TEXT_INSERTED: {
AccTextChangeEvent* event = downcast_accEvent(aEvent);
NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
MAI_ATK_OBJECT(atkObj)->FireTextChangeEvent(
event->ModifiedText(), event->GetStartOffset(), event->GetLength(),
event->IsTextInserted(), event->IsFromUserInput());
return NS_OK;
}
case nsIAccessibleEvent::EVENT_FOCUS: {
a11y::RootAccessible* rootAccWrap = accWrap->RootAccessible();
if (rootAccWrap && rootAccWrap->IsActivated()) {
atk_focus_tracker_notify(atkObj);
// Fire state change event for focus
atk_object_notify_state_change(atkObj, ATK_STATE_FOCUSED, true);
return NS_OK;
}
} break;
case nsIAccessibleEvent::EVENT_NAME_CHANGE: {
nsAutoString newName;
accessible->Name(newName);
MaybeFireNameChange(atkObj, newName);
break;
}
case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
case nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE:
if (accessible->HasNumericValue()) {
// Make sure this is a numeric value. Don't fire for string value
// changes (e.g. text editing) ATK values are always numeric.
g_object_notify((GObject*)atkObj, "accessible-value");
}
break;
case nsIAccessibleEvent::EVENT_SELECTION:
case nsIAccessibleEvent::EVENT_SELECTION_ADD:
case nsIAccessibleEvent::EVENT_SELECTION_REMOVE: {
// XXX: dupe events may be fired
AccSelChangeEvent* selChangeEvent = downcast_accEvent(aEvent);
g_signal_emit_by_name(
AccessibleWrap::GetAtkObject(selChangeEvent->Widget()),
"selection_changed");
break;
}
case nsIAccessibleEvent::EVENT_SELECTION_WITHIN: {
g_signal_emit_by_name(atkObj, "selection_changed");
break;
}
case nsIAccessibleEvent::EVENT_ALERT:
// A hack using state change showing events as alert events.
atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, true);
break;
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
g_signal_emit_by_name(atkObj, "text_selection_changed");
break;
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
AccCaretMoveEvent* caretMoveEvent = downcast_accEvent(aEvent);
NS_ASSERTION(caretMoveEvent, "Event needs event data");
if (!caretMoveEvent) break;
int32_t caretOffset = caretMoveEvent->GetCaretOffset();
g_signal_emit_by_name(atkObj, "text_caret_moved", caretOffset);
} break;
case nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED:
g_signal_emit_by_name(atkObj, "text-attributes-changed");
break;
case nsIAccessibleEvent::EVENT_TABLE_MODEL_CHANGED:
g_signal_emit_by_name(atkObj, "model_changed");
break;
case nsIAccessibleEvent::EVENT_TABLE_ROW_INSERT: {
AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
int32_t rowIndex = tableEvent->GetIndex();
int32_t numRows = tableEvent->GetCount();
g_signal_emit_by_name(atkObj, "row_inserted", rowIndex, numRows);
} break;
case nsIAccessibleEvent::EVENT_TABLE_ROW_DELETE: {
AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
int32_t rowIndex = tableEvent->GetIndex();
int32_t numRows = tableEvent->GetCount();
g_signal_emit_by_name(atkObj, "row_deleted", rowIndex, numRows);
} break;
case nsIAccessibleEvent::EVENT_TABLE_ROW_REORDER: {
g_signal_emit_by_name(atkObj, "row_reordered");
break;
}
case nsIAccessibleEvent::EVENT_TABLE_COLUMN_INSERT: {
AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
int32_t colIndex = tableEvent->GetIndex();
int32_t numCols = tableEvent->GetCount();
g_signal_emit_by_name(atkObj, "column_inserted", colIndex, numCols);
} break;
case nsIAccessibleEvent::EVENT_TABLE_COLUMN_DELETE: {
AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
int32_t colIndex = tableEvent->GetIndex();
int32_t numCols = tableEvent->GetCount();
g_signal_emit_by_name(atkObj, "column_deleted", colIndex, numCols);
} break;
case nsIAccessibleEvent::EVENT_TABLE_COLUMN_REORDER:
g_signal_emit_by_name(atkObj, "column_reordered");
break;
case nsIAccessibleEvent::EVENT_SECTION_CHANGED:
g_signal_emit_by_name(atkObj, "visible_data_changed");
break;
case nsIAccessibleEvent::EVENT_SHOW: {
AccMutationEvent* event = downcast_accEvent(aEvent);
LocalAccessible* parentAcc =
event ? event->LocalParent() : accessible->LocalParent();
AtkObject* parent = AccessibleWrap::GetAtkObject(parentAcc);
NS_ENSURE_STATE(parent);
auto obj = reinterpret_cast<MaiAtkObject*>(atkObj);
obj->FireAtkShowHideEvent(parent, true, aEvent->IsFromUserInput());
return NS_OK;
}
case nsIAccessibleEvent::EVENT_HIDE: {
// XXX - Handle native dialog accessibles.
if (!accessible->IsRoot() && accessible->HasARIARole() &&
accessible->ARIARole() == roles::DIALOG) {
guint id = g_signal_lookup("deactivate", MAI_TYPE_ATK_OBJECT);
g_signal_emit(atkObj, id, 0);
}
AccMutationEvent* event = downcast_accEvent(aEvent);
LocalAccessible* parentAcc =
event ? event->LocalParent() : accessible->LocalParent();
AtkObject* parent = AccessibleWrap::GetAtkObject(parentAcc);
NS_ENSURE_STATE(parent);
auto obj = reinterpret_cast<MaiAtkObject*>(atkObj);
obj->FireAtkShowHideEvent(parent, false, aEvent->IsFromUserInput());
return NS_OK;
}
/*
* Because dealing with menu is very different between nsIAccessible
* and ATK, and the menu activity is important, specially transfer the
* following two event.
* Need more verification by AT test.
*/
case nsIAccessibleEvent::EVENT_MENU_START:
case nsIAccessibleEvent::EVENT_MENU_END:
break;
case nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE: {
guint id = g_signal_lookup("activate", MAI_TYPE_ATK_OBJECT);
g_signal_emit(atkObj, id, 0);
// Always fire a current focus event after activation.
FocusMgr()->ForceFocusEvent();
} break;
case nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE: {
guint id = g_signal_lookup("deactivate", MAI_TYPE_ATK_OBJECT);
g_signal_emit(atkObj, id, 0);
} break;
case nsIAccessibleEvent::EVENT_WINDOW_MAXIMIZE: {
guint id = g_signal_lookup("maximize", MAI_TYPE_ATK_OBJECT);
g_signal_emit(atkObj, id, 0);
} break;
case nsIAccessibleEvent::EVENT_WINDOW_MINIMIZE: {
guint id = g_signal_lookup("minimize", MAI_TYPE_ATK_OBJECT);
g_signal_emit(atkObj, id, 0);
} break;
case nsIAccessibleEvent::EVENT_WINDOW_RESTORE: {
guint id = g_signal_lookup("restore", MAI_TYPE_ATK_OBJECT);
g_signal_emit(atkObj, id, 0);
} break;
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
if (accessible->IsDoc()) {
g_signal_emit_by_name(atkObj, "load_complete");
}
// XXX - Handle native dialog accessibles.
if (!accessible->IsRoot() && accessible->HasARIARole() &&
accessible->ARIARole() == roles::DIALOG) {
guint id = g_signal_lookup("activate", MAI_TYPE_ATK_OBJECT);
g_signal_emit(atkObj, id, 0);
}
break;
case nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD:
if (accessible->IsDoc()) {
g_signal_emit_by_name(atkObj, "reload");
}
break;
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED:
if (accessible->IsDoc()) {
g_signal_emit_by_name(atkObj, "load_stopped");
}
break;
case nsIAccessibleEvent::EVENT_MENUPOPUP_START:
atk_focus_tracker_notify(atkObj); // fire extra focus event
atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, true);
atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, true);
break;
case nsIAccessibleEvent::EVENT_MENUPOPUP_END:
atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, false);
atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, false);
break;
}
return NS_OK;
}
void a11y::PlatformEvent(Accessible* aTarget, uint32_t aEventType) {
AtkObject* wrapper = GetWrapperFor(aTarget);
@ -1238,6 +958,12 @@ void a11y::PlatformEvent(Accessible* aTarget, uint32_t aEventType) {
if (aTarget->IsDoc()) {
g_signal_emit_by_name(wrapper, "load_complete");
}
// XXX - Handle native dialog accessibles.
if (!aTarget->IsRoot() && aTarget->HasARIARole() &&
aTarget->Role() == roles::DIALOG) {
guint id = g_signal_lookup("activate", MAI_TYPE_ATK_OBJECT);
g_signal_emit(wrapper, id, 0);
}
break;
case nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD:
if (aTarget->IsDoc()) {
@ -1263,7 +989,12 @@ void a11y::PlatformEvent(Accessible* aTarget, uint32_t aEventType) {
atk_object_notify_state_change(wrapper, ATK_STATE_SHOWING, true);
break;
case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
g_object_notify((GObject*)wrapper, "accessible-value");
case nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE:
if (aTarget->HasNumericValue()) {
// Make sure this is a numeric value. Don't fire for string value
// changes (e.g. text editing) ATK values are always numeric.
g_object_notify((GObject*)wrapper, "accessible-value");
}
break;
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
g_signal_emit_by_name(wrapper, "text_selection_changed");
@ -1274,6 +1005,39 @@ void a11y::PlatformEvent(Accessible* aTarget, uint32_t aEventType) {
case nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED:
g_signal_emit_by_name(wrapper, "text-attributes-changed");
break;
case nsIAccessibleEvent::EVENT_NAME_CHANGE: {
nsAutoString newName;
aTarget->Name(newName);
MaybeFireNameChange(wrapper, newName);
break;
}
case nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE: {
guint id = g_signal_lookup("activate", MAI_TYPE_ATK_OBJECT);
g_signal_emit(wrapper, id, 0);
// Always fire a current focus event after activation.
FocusMgr()->ForceFocusEvent();
break;
}
case nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE: {
guint id = g_signal_lookup("deactivate", MAI_TYPE_ATK_OBJECT);
g_signal_emit(wrapper, id, 0);
break;
}
case nsIAccessibleEvent::EVENT_WINDOW_MAXIMIZE: {
guint id = g_signal_lookup("maximize", MAI_TYPE_ATK_OBJECT);
g_signal_emit(wrapper, id, 0);
break;
}
case nsIAccessibleEvent::EVENT_WINDOW_MINIMIZE: {
guint id = g_signal_lookup("minimize", MAI_TYPE_ATK_OBJECT);
g_signal_emit(wrapper, id, 0);
break;
}
case nsIAccessibleEvent::EVENT_WINDOW_RESTORE: {
guint id = g_signal_lookup("restore", MAI_TYPE_ATK_OBJECT);
g_signal_emit(wrapper, id, 0);
break;
}
}
}
@ -1287,6 +1051,15 @@ void a11y::PlatformFocusEvent(Accessible* aTarget,
const LayoutDeviceIntRect& aCaretRect) {
AtkObject* wrapper = GetWrapperFor(aTarget);
// XXX Do we really need this check? If so, do we need a similar check for
// RemoteAccessible?
if (LocalAccessible* localTarget = aTarget->AsLocal()) {
a11y::RootAccessible* rootAcc = localTarget->RootAccessible();
if (!rootAcc || !rootAcc->IsActivated()) {
return;
}
}
atk_focus_tracker_notify(wrapper);
atk_object_notify_state_change(wrapper, ATK_STATE_FOCUSED, true);
}
@ -1372,7 +1145,17 @@ void MaiAtkObject::FireTextChangeEvent(const nsAString& aStr, int32_t aStart,
void a11y::PlatformShowHideEvent(Accessible* aTarget, Accessible* aParent,
bool aInsert, bool aFromUser) {
MaiAtkObject* obj = MAI_ATK_OBJECT(GetWrapperFor(aTarget));
AtkObject* atkObj = GetWrapperFor(aTarget);
if (!aInsert) {
// XXX - Handle native dialog accessibles.
if (!aTarget->IsRoot() && aTarget->HasARIARole() &&
aTarget->Role() == roles::DIALOG) {
guint id = g_signal_lookup("deactivate", MAI_TYPE_ATK_OBJECT);
g_signal_emit(atkObj, id, 0);
}
}
MaiAtkObject* obj = MAI_ATK_OBJECT(atkObj);
obj->FireAtkShowHideEvent(GetWrapperFor(aParent), aInsert, aFromUser);
}

View File

@ -58,7 +58,6 @@ class AccessibleWrap : public LocalAccessible {
// return the atk object for this AccessibleWrap
virtual void GetNativeInterface(void** aOutAccessible) override;
virtual nsresult HandleAccEvent(AccEvent* aEvent) override;
AtkObject* GetAtkObject(void);
static AtkObject* GetAtkObject(LocalAccessible* aAccessible);

View File

@ -13,6 +13,7 @@
#include "DocAccessible-inl.h"
#include "mozilla/a11y/AccAttributes.h"
#include "mozilla/a11y/DocAccessibleChild.h"
#include "mozilla/a11y/Platform.h"
#include "nsAccUtils.h"
#include "nsAccessibilityService.h"
#include "ApplicationAccessible.h"
@ -994,6 +995,115 @@ nsresult LocalAccessible::HandleAccEvent(AccEvent* aEvent) {
nsCoreUtils::DispatchAccEvent(MakeXPCEvent(aEvent));
}
if (IPCAccessibilityActive()) {
return NS_OK;
}
if (IsDefunct()) {
// This could happen if there is an XPCOM observer, since script might run
// which mutates the tree.
return NS_OK;
}
LocalAccessible* target = aEvent->GetAccessible();
switch (aEvent->GetEventType()) {
case nsIAccessibleEvent::EVENT_SHOW:
PlatformShowHideEvent(target, target->LocalParent(), true,
aEvent->IsFromUserInput());
break;
case nsIAccessibleEvent::EVENT_HIDE:
PlatformShowHideEvent(target, target->LocalParent(), false,
aEvent->IsFromUserInput());
break;
case nsIAccessibleEvent::EVENT_STATE_CHANGE: {
AccStateChangeEvent* event = downcast_accEvent(aEvent);
PlatformStateChangeEvent(target, event->GetState(),
event->IsStateEnabled());
break;
}
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
AccCaretMoveEvent* event = downcast_accEvent(aEvent);
LayoutDeviceIntRect rect;
// The caret rect is only used on Windows, so just pass an empty rect on
// other platforms.
// XXX We pass an empty rect on Windows as well because
// AccessibleWrap::UpdateSystemCaretFor currently needs to call
// HyperTextAccessible::GetCaretRect again to get the widget and there's
// no point calling it twice.
PlatformCaretMoveEvent(target, event->GetCaretOffset(),
event->IsSelectionCollapsed(),
event->GetGranularity(), rect);
break;
}
case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
case nsIAccessibleEvent::EVENT_TEXT_REMOVED: {
AccTextChangeEvent* event = downcast_accEvent(aEvent);
const nsString& text = event->ModifiedText();
PlatformTextChangeEvent(target, text, event->GetStartOffset(),
event->GetLength(), event->IsTextInserted(),
event->IsFromUserInput());
break;
}
case nsIAccessibleEvent::EVENT_SELECTION:
case nsIAccessibleEvent::EVENT_SELECTION_ADD:
case nsIAccessibleEvent::EVENT_SELECTION_REMOVE: {
AccSelChangeEvent* selEvent = downcast_accEvent(aEvent);
PlatformSelectionEvent(target, selEvent->Widget(),
aEvent->GetEventType());
break;
}
case nsIAccessibleEvent::EVENT_VIRTUALCURSOR_CHANGED: {
#ifdef ANDROID
AccVCChangeEvent* vcEvent = downcast_accEvent(aEvent);
PlatformVirtualCursorChangeEvent(
target, vcEvent->OldAccessible(), vcEvent->NewAccessible(),
vcEvent->Reason(), vcEvent->IsFromUserInput());
#endif
break;
}
case nsIAccessibleEvent::EVENT_FOCUS: {
LayoutDeviceIntRect rect;
// The caret rect is only used on Windows, so just pass an empty rect on
// other platforms.
#ifdef XP_WIN
if (HyperTextAccessible* text = target->AsHyperText()) {
nsIWidget* widget = nullptr;
rect = text->GetCaretRect(&widget);
}
#endif
PlatformFocusEvent(target, rect);
break;
}
#if defined(ANDROID)
case nsIAccessibleEvent::EVENT_SCROLLING_END:
case nsIAccessibleEvent::EVENT_SCROLLING: {
AccScrollingEvent* scrollingEvent = downcast_accEvent(aEvent);
PlatformScrollingEvent(
target, aEvent->GetEventType(), scrollingEvent->ScrollX(),
scrollingEvent->ScrollY(), scrollingEvent->MaxScrollX(),
scrollingEvent->MaxScrollY());
break;
}
case nsIAccessibleEvent::EVENT_ANNOUNCEMENT: {
AccAnnouncementEvent* announcementEvent = downcast_accEvent(aEvent);
PlatformAnnouncementEvent(target, announcementEvent->Announcement(),
announcementEvent->Priority());
break;
}
#endif // defined(ANDROID)
#if defined(MOZ_WIDGET_COCOA)
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED: {
AccTextSelChangeEvent* textSelChangeEvent = downcast_accEvent(aEvent);
AutoTArray<TextRange, 1> ranges;
textSelChangeEvent->SelectionRanges(&ranges);
PlatformTextSelectionChangeEvent(target, ranges);
break;
}
#endif // defined(MOZ_WIDGET_COCOA)
default:
PlatformEvent(target, aEvent->GetEventType());
}
return NS_OK;
}

View File

@ -158,129 +158,6 @@ nsresult AccessibleWrap::HandleAccEvent(AccEvent* aEvent) {
doc->ProcessNewLiveRegions();
}
if (IPCAccessibilityActive()) {
return NS_OK;
}
LocalAccessible* eventTarget = nullptr;
switch (eventType) {
case nsIAccessibleEvent::EVENT_SELECTION:
case nsIAccessibleEvent::EVENT_SELECTION_ADD:
case nsIAccessibleEvent::EVENT_SELECTION_REMOVE: {
AccSelChangeEvent* selEvent = downcast_accEvent(aEvent);
// The "widget" is the selected widget's container. In OSX
// it is the target of the selection changed event.
eventTarget = selEvent->Widget();
break;
}
case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
case nsIAccessibleEvent::EVENT_TEXT_REMOVED: {
LocalAccessible* acc = aEvent->GetAccessible();
// If there is a text input ancestor, use it as the event source.
while (acc && GetTypeFromRole(acc->Role()) != [mozTextAccessible class]) {
acc = acc->LocalParent();
}
eventTarget = acc ? acc : aEvent->GetAccessible();
break;
}
default:
eventTarget = aEvent->GetAccessible();
break;
}
mozAccessible* nativeAcc = nil;
eventTarget->GetNativeInterface((void**)&nativeAcc);
if (!nativeAcc) {
return NS_ERROR_FAILURE;
}
switch (eventType) {
case nsIAccessibleEvent::EVENT_STATE_CHANGE: {
AccStateChangeEvent* event = downcast_accEvent(aEvent);
[nativeAcc stateChanged:event->GetState()
isEnabled:event->IsStateEnabled()];
break;
}
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED: {
MOXTextMarkerDelegate* delegate =
[MOXTextMarkerDelegate getOrCreateForDoc:aEvent->Document()];
AccTextSelChangeEvent* event = downcast_accEvent(aEvent);
AutoTArray<TextRange, 1> ranges;
event->SelectionRanges(&ranges);
if (ranges.Length()) {
// Cache selection in delegate.
[delegate setSelectionFrom:ranges[0].StartContainer()
at:ranges[0].StartOffset()
to:ranges[0].EndContainer()
at:ranges[0].EndOffset()];
}
[nativeAcc handleAccessibleEvent:eventType];
break;
}
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
AccCaretMoveEvent* event = downcast_accEvent(aEvent);
int32_t caretOffset = event->GetCaretOffset();
MOXTextMarkerDelegate* delegate =
[MOXTextMarkerDelegate getOrCreateForDoc:aEvent->Document()];
[delegate setCaretOffset:eventTarget
at:caretOffset
moveGranularity:event->GetGranularity()];
if (event->IsSelectionCollapsed()) {
// If the selection is collapsed, invalidate our text selection cache.
[delegate setSelectionFrom:eventTarget
at:caretOffset
to:eventTarget
at:caretOffset];
}
if (mozTextAccessible* textAcc = static_cast<mozTextAccessible*>(
[nativeAcc moxEditableAncestor])) {
[textAcc
handleAccessibleEvent:nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED];
} else {
[nativeAcc
handleAccessibleEvent:nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED];
}
break;
}
case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
case nsIAccessibleEvent::EVENT_TEXT_REMOVED: {
AccTextChangeEvent* tcEvent = downcast_accEvent(aEvent);
[nativeAcc handleAccessibleTextChangeEvent:nsCocoaUtils::ToNSString(
tcEvent->ModifiedText())
inserted:tcEvent->IsTextInserted()
inContainer:aEvent->GetAccessible()
at:tcEvent->GetStartOffset()];
break;
}
case nsIAccessibleEvent::EVENT_ALERT:
case nsIAccessibleEvent::EVENT_FOCUS:
case nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE:
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
case nsIAccessibleEvent::EVENT_MENUPOPUP_START:
case nsIAccessibleEvent::EVENT_MENUPOPUP_END:
case nsIAccessibleEvent::EVENT_REORDER:
case nsIAccessibleEvent::EVENT_SELECTION:
case nsIAccessibleEvent::EVENT_SELECTION_ADD:
case nsIAccessibleEvent::EVENT_SELECTION_REMOVE:
case nsIAccessibleEvent::EVENT_LIVE_REGION_ADDED:
case nsIAccessibleEvent::EVENT_LIVE_REGION_REMOVED:
case nsIAccessibleEvent::EVENT_NAME_CHANGE:
case nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED:
[nativeAcc handleAccessibleEvent:eventType];
break;
default:
break;
}
return NS_OK;
NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);

View File

@ -89,7 +89,6 @@ void PlatformEvent(Accessible* aTarget, uint32_t aEventType) {
if (aEventType != nsIAccessibleEvent::EVENT_ALERT &&
aEventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE &&
aEventType != nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE &&
aEventType != nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED &&
aEventType != nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE &&
aEventType != nsIAccessibleEvent::EVENT_REORDER &&
aEventType != nsIAccessibleEvent::EVENT_LIVE_REGION_ADDED &&

View File

@ -59,35 +59,6 @@ void AccessibleWrap::GetNativeInterface(void** aOutAccessible) {
return result.forget(aOutAccessible);
}
////////////////////////////////////////////////////////////////////////////////
// LocalAccessible
nsresult AccessibleWrap::HandleAccEvent(AccEvent* aEvent) {
nsresult rv = LocalAccessible::HandleAccEvent(aEvent);
NS_ENSURE_SUCCESS(rv, rv);
if (IPCAccessibilityActive()) {
return NS_OK;
}
uint32_t eventType = aEvent->GetEventType();
// Means we're not active.
NS_ENSURE_TRUE(!IsDefunct(), NS_ERROR_FAILURE);
LocalAccessible* accessible = aEvent->GetAccessible();
if (!accessible) return NS_OK;
if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED ||
eventType == nsIAccessibleEvent::EVENT_FOCUS) {
UpdateSystemCaretFor(accessible);
}
MsaaAccessible::FireWinEvent(accessible, eventType);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// AccessibleWrap

View File

@ -34,7 +34,6 @@ class AccessibleWrap : public LocalAccessible {
public:
// LocalAccessible
virtual nsresult HandleAccEvent(AccEvent* aEvent) override;
virtual void Shutdown() override;
// Helper methods

View File

@ -17,22 +17,3 @@ using namespace mozilla;
using namespace mozilla::a11y;
NS_IMPL_ISUPPORTS_INHERITED0(HyperTextAccessibleWrap, HyperTextAccessible)
nsresult HyperTextAccessibleWrap::HandleAccEvent(AccEvent* aEvent) {
uint32_t eventType = aEvent->GetEventType();
if (eventType == nsIAccessibleEvent::EVENT_TEXT_REMOVED ||
eventType == nsIAccessibleEvent::EVENT_TEXT_INSERTED) {
LocalAccessible* accessible = aEvent->GetAccessible();
if (accessible && accessible->IsHyperText()) {
AccTextChangeEvent* event = downcast_accEvent(aEvent);
HyperTextAccessibleWrap* text =
static_cast<HyperTextAccessibleWrap*>(accessible->AsHyperText());
ia2AccessibleText::UpdateTextChangeData(
text, event->IsTextInserted(), event->ModifiedText(),
event->GetStartOffset(), event->GetLength());
}
}
return HyperTextAccessible::HandleAccEvent(aEvent);
}

View File

@ -21,9 +21,6 @@ class HyperTextAccessibleWrap : public HyperTextAccessible {
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// LocalAccessible
virtual nsresult HandleAccEvent(AccEvent* aEvent);
protected:
~HyperTextAccessibleWrap() {}
};