зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1248838 - ARIA owns change may fail, r=yzen
This commit is contained in:
Родитель
1139f832a4
Коммит
0b5d5b3e24
|
@ -2130,6 +2130,51 @@ Accessible::RemoveChild(Accessible* aChild)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Accessible::MoveChild(uint32_t aNewIndex, Accessible* aChild)
|
||||
{
|
||||
MOZ_ASSERT(aChild, "No child was given");
|
||||
MOZ_ASSERT(aChild->mParent == this, "A child from different subtree was given");
|
||||
MOZ_ASSERT(aChild->mIndexInParent != -1, "Unbound child was given");
|
||||
MOZ_ASSERT(static_cast<uint32_t>(aChild->mIndexInParent) != aNewIndex,
|
||||
"No move, same index");
|
||||
MOZ_ASSERT(aNewIndex <= mChildren.Length(), "Wrong new index was given");
|
||||
|
||||
#ifdef DEBUG
|
||||
// AutoTreeMutation should update group info.
|
||||
AssertInMutatingSubtree();
|
||||
#endif
|
||||
|
||||
mEmbeddedObjCollector = nullptr;
|
||||
mChildren.RemoveElementAt(aChild->mIndexInParent);
|
||||
|
||||
uint32_t startIdx = aNewIndex, endIdx = aChild->mIndexInParent;
|
||||
|
||||
// If the child is moved after its current position.
|
||||
if (static_cast<uint32_t>(aChild->mIndexInParent) < aNewIndex) {
|
||||
startIdx = aChild->mIndexInParent;
|
||||
|
||||
if (aNewIndex == mChildren.Length() + 1) {
|
||||
// The child is moved to the end.
|
||||
mChildren.AppendElement(aChild);
|
||||
endIdx = mChildren.Length() - 1;
|
||||
}
|
||||
else {
|
||||
mChildren.InsertElementAt(aNewIndex - 1, aChild);
|
||||
endIdx = aNewIndex;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The child is moved prior its current position.
|
||||
mChildren.InsertElementAt(aNewIndex, aChild);
|
||||
}
|
||||
|
||||
for (uint32_t idx = startIdx; idx <= endIdx; idx++) {
|
||||
mChildren[idx]->mIndexInParent = idx;
|
||||
mChildren[idx]->mInt.mIndexOfEmbeddedChild = -1;
|
||||
}
|
||||
}
|
||||
|
||||
Accessible*
|
||||
Accessible::GetChildAt(uint32_t aIndex) const
|
||||
{
|
||||
|
|
|
@ -396,6 +396,11 @@ public:
|
|||
virtual bool InsertChildAt(uint32_t aIndex, Accessible* aChild);
|
||||
virtual bool RemoveChild(Accessible* aChild);
|
||||
|
||||
/**
|
||||
* Reallocates the child withing its parent.
|
||||
*/
|
||||
void MoveChild(uint32_t aNewIndex, Accessible* aChild);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Accessible tree traverse methods
|
||||
|
||||
|
|
|
@ -2058,7 +2058,10 @@ DocAccessible::DoARIAOwnsRelocation(Accessible* aOwner)
|
|||
}
|
||||
|
||||
if (child->Parent() == aOwner) {
|
||||
MoveChild(child, insertIdx - 1);
|
||||
if (child->IsRelocated()) {
|
||||
children->RemoveElement(child);
|
||||
}
|
||||
MoveChild(child, insertIdx);
|
||||
children->InsertElementAt(arrayIdx, child);
|
||||
arrayIdx++;
|
||||
|
||||
|
@ -2141,9 +2144,7 @@ DocAccessible::MoveChild(Accessible* aChild, int32_t aIdxInParent)
|
|||
reorderEvent->AddSubMutationEvent(hideEvent);
|
||||
|
||||
AutoTreeMutation mut(parent);
|
||||
parent->RemoveChild(aChild);
|
||||
|
||||
parent->InsertChildAt(aIdxInParent, aChild);
|
||||
parent->MoveChild(aIdxInParent, aChild);
|
||||
aChild->SetRelocated(true);
|
||||
|
||||
FireDelayedEvent(hideEvent);
|
||||
|
@ -2174,6 +2175,7 @@ DocAccessible::PutChildrenBack(nsTArray<RefPtr<Accessible> >* aChildren,
|
|||
RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(owner);
|
||||
RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(child, false);
|
||||
reorderEvent->AddSubMutationEvent(hideEvent);
|
||||
FireDelayedEvent(hideEvent);
|
||||
|
||||
{
|
||||
AutoTreeMutation mut(owner);
|
||||
|
@ -2181,7 +2183,6 @@ DocAccessible::PutChildrenBack(nsTArray<RefPtr<Accessible> >* aChildren,
|
|||
child->SetRelocated(false);
|
||||
}
|
||||
|
||||
FireDelayedEvent(hideEvent);
|
||||
MaybeNotifyOfValueChange(owner);
|
||||
FireDelayedEvent(reorderEvent);
|
||||
}
|
||||
|
|
|
@ -110,6 +110,27 @@ function isLogged(aModule)
|
|||
return gAccRetrieval.isLogged(aModule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the accessible tree into console.
|
||||
*/
|
||||
function dumpTree(aId, aMsg)
|
||||
{
|
||||
function dumpTreeIntl(acc, indent)
|
||||
{
|
||||
dump(indent + prettyName(acc) + "\n");
|
||||
|
||||
var children = acc.children;
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var child = children.queryElementAt(i, nsIAccessible);
|
||||
dumpTreeIntl(child, indent + " ");
|
||||
}
|
||||
}
|
||||
|
||||
dump(aMsg + "\n");
|
||||
var root = getAccessible(aId);
|
||||
dumpTreeIntl(root, " ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the given function when document is loaded and focused. Preferable
|
||||
* to mochitests 'addLoadEvent' function -- additionally ensures state of the
|
||||
|
|
|
@ -23,19 +23,21 @@
|
|||
// Invokers
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function removeARIAOwns()
|
||||
function changeARIAOwns()
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getNode("t1_checkbox")),
|
||||
new invokerChecker(EVENT_HIDE, getNode("t1_button")),
|
||||
new invokerChecker(EVENT_SHOW, getNode("t1_button")),
|
||||
new invokerChecker(EVENT_HIDE, getNode("t1_subdiv")),
|
||||
new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
|
||||
new invokerChecker(EVENT_HIDE, getNode("t1_checkbox")),
|
||||
new invokerChecker(EVENT_SHOW, getNode("t1_checkbox")),
|
||||
new invokerChecker(EVENT_REORDER, getNode("t1_container"))
|
||||
];
|
||||
|
||||
this.invoke = function removeARIAOwns_invoke()
|
||||
this.invoke = function setARIAOwns_invoke()
|
||||
{
|
||||
// children are swapped
|
||||
// children are swapped by ARIA owns
|
||||
var tree =
|
||||
{ SECTION: [
|
||||
{ CHECKBUTTON: [
|
||||
|
@ -45,6 +47,41 @@
|
|||
] };
|
||||
testAccessibleTree("t1_container", tree);
|
||||
|
||||
getNode("t1_container").
|
||||
setAttribute("aria-owns", "t1_button t1_subdiv");
|
||||
}
|
||||
|
||||
this.finalCheck = function setARIAOwns_finalCheck()
|
||||
{
|
||||
// children are swapped again, button and subdiv are appended to
|
||||
// the children.
|
||||
var tree =
|
||||
{ SECTION: [
|
||||
{ CHECKBUTTON: [ ] }, // checkbox, native order
|
||||
{ PUSHBUTTON: [ ] }, // button, rearranged by ARIA own
|
||||
{ SECTION: [ ] } // subdiv from the subtree, ARIA owned
|
||||
] };
|
||||
testAccessibleTree("t1_container", tree);
|
||||
}
|
||||
|
||||
this.getID = function setARIAOwns_getID()
|
||||
{
|
||||
return "Change @aria-owns attribute";
|
||||
}
|
||||
}
|
||||
|
||||
function removeARIAOwns()
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getNode("t1_button")),
|
||||
new invokerChecker(EVENT_HIDE, getNode("t1_subdiv")),
|
||||
new invokerChecker(EVENT_SHOW, getNode("t1_button")),
|
||||
new invokerChecker(EVENT_SHOW, getNode("t1_subdiv")),
|
||||
new invokerChecker(EVENT_REORDER, getNode("t1_container"))
|
||||
];
|
||||
|
||||
this.invoke = function removeARIAOwns_invoke()
|
||||
{
|
||||
getNode("t1_container").removeAttribute("aria-owns");
|
||||
}
|
||||
|
||||
|
@ -418,6 +455,7 @@
|
|||
gQueue = new eventQueue();
|
||||
|
||||
// test1
|
||||
gQueue.push(new changeARIAOwns());
|
||||
gQueue.push(new removeARIAOwns());
|
||||
gQueue.push(new setARIAOwns());
|
||||
gQueue.push(new addIdToARIAOwns());
|
||||
|
|
Загрузка…
Ссылка в новой задаче