mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 807911 - whittle mutation events processing, r=tbsaunde
This commit is contained in:
parent
7556e76ede
commit
f15104b9ad
@ -214,7 +214,6 @@ AccStateChangeEvent::CreateXPCOMObject()
|
||||
// we are ready to fire the event and so we will no longer assert at that point
|
||||
// if the node was removed from the document. Either way, the AT won't work with
|
||||
// a defunct accessible so the behaviour should be equivalent.
|
||||
// XXX revisit this when coalescence is faster (eCoalesceFromSameSubtree)
|
||||
AccTextChangeEvent::
|
||||
AccTextChangeEvent(Accessible* aAccessible, int32_t aStart,
|
||||
const nsAString& aModifiedText, bool aIsInserted,
|
||||
@ -243,17 +242,23 @@ AccTextChangeEvent::CreateXPCOMObject()
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccMutationEvent
|
||||
// AccReorderEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccMutationEvent::
|
||||
AccMutationEvent(uint32_t aEventType, Accessible* aTarget,
|
||||
nsINode* aTargetNode) :
|
||||
AccEvent(aEventType, aTarget, eAutoDetect, eCoalesceFromSameSubtree)
|
||||
uint32_t
|
||||
AccReorderEvent::IsShowHideEventTarget(const Accessible* aTarget) const
|
||||
{
|
||||
mNode = aTargetNode;
|
||||
}
|
||||
uint32_t count = mDependentEvents.Length();
|
||||
for (uint32_t index = count - 1; index < count; index--) {
|
||||
if (mDependentEvents[index]->mAccessible == aTarget &&
|
||||
mDependentEvents[index]->mEventType == nsIAccessibleEvent::EVENT_SHOW ||
|
||||
mDependentEvents[index]->mEventType == nsIAccessibleEvent::EVENT_HIDE) {
|
||||
return mDependentEvents[index]->mEventType;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccHideEvent
|
||||
@ -263,7 +268,6 @@ AccHideEvent::
|
||||
AccHideEvent(Accessible* aTarget, nsINode* aTargetNode) :
|
||||
AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget, aTargetNode)
|
||||
{
|
||||
mParent = mAccessible->Parent();
|
||||
mNextSibling = mAccessible->NextSibling();
|
||||
mPrevSibling = mAccessible->PrevSibling();
|
||||
}
|
||||
|
@ -38,10 +38,13 @@ public:
|
||||
// This event will always be emitted.
|
||||
eAllowDupes,
|
||||
|
||||
// eCoalesceFromSameSubtree : For events of the same type from the same
|
||||
// subtree or the same node, only the umbrella event on the ancestor
|
||||
// will be emitted.
|
||||
eCoalesceFromSameSubtree,
|
||||
// eCoalesceReorder : For reorder events from the same subtree or the same
|
||||
// node, only the umbrella event on the ancestor will be emitted.
|
||||
eCoalesceReorder,
|
||||
|
||||
// eCoalesceMutationTextChange : coalesce text change events caused by
|
||||
// tree mutations of the same tree level.
|
||||
eCoalesceMutationTextChange,
|
||||
|
||||
// eCoalesceOfSameType : For events of the same type, only the newest event
|
||||
// will be processed.
|
||||
@ -90,6 +93,7 @@ public:
|
||||
eStateChangeEvent,
|
||||
eTextChangeEvent,
|
||||
eMutationEvent,
|
||||
eReorderEvent,
|
||||
eHideEvent,
|
||||
eShowEvent,
|
||||
eCaretMoveEvent,
|
||||
@ -129,6 +133,7 @@ protected:
|
||||
nsCOMPtr<nsINode> mNode;
|
||||
|
||||
friend class NotificationController;
|
||||
friend class AccReorderEvent;
|
||||
};
|
||||
|
||||
|
||||
@ -197,6 +202,7 @@ private:
|
||||
nsString mModifiedText;
|
||||
|
||||
friend class NotificationController;
|
||||
friend class AccReorderEvent;
|
||||
};
|
||||
|
||||
|
||||
@ -207,7 +213,15 @@ class AccMutationEvent: public AccEvent
|
||||
{
|
||||
public:
|
||||
AccMutationEvent(uint32_t aEventType, Accessible* aTarget,
|
||||
nsINode* aTargetNode);
|
||||
nsINode* aTargetNode) :
|
||||
AccEvent(aEventType, aTarget, eAutoDetect, eCoalesceMutationTextChange)
|
||||
{
|
||||
// Don't coalesce these since they are coalesced by reorder event. Coalesce
|
||||
// contained text change events.
|
||||
mNode = aTargetNode;
|
||||
mParent = mAccessible->Parent();
|
||||
}
|
||||
virtual ~AccMutationEvent() { };
|
||||
|
||||
// Event
|
||||
static const EventGroup kEventGroup = eMutationEvent;
|
||||
@ -221,6 +235,7 @@ public:
|
||||
bool IsHide() const { return mEventType == nsIAccessibleEvent::EVENT_HIDE; }
|
||||
|
||||
protected:
|
||||
nsRefPtr<Accessible> mParent;
|
||||
nsRefPtr<AccTextChangeEvent> mTextChangeEvent;
|
||||
|
||||
friend class NotificationController;
|
||||
@ -250,7 +265,6 @@ public:
|
||||
Accessible* TargetPrevSibling() const { return mPrevSibling; }
|
||||
|
||||
protected:
|
||||
nsRefPtr<Accessible> mParent;
|
||||
nsRefPtr<Accessible> mNextSibling;
|
||||
nsRefPtr<Accessible> mPrevSibling;
|
||||
|
||||
@ -275,6 +289,57 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class for reorder accessible event. Takes care about
|
||||
*/
|
||||
class AccReorderEvent : public AccEvent
|
||||
{
|
||||
public:
|
||||
AccReorderEvent(Accessible* aTarget) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_REORDER, aTarget,
|
||||
eAutoDetect, eCoalesceReorder) { }
|
||||
virtual ~AccReorderEvent() { };
|
||||
|
||||
// Event
|
||||
static const EventGroup kEventGroup = eReorderEvent;
|
||||
virtual unsigned int GetEventGroups() const
|
||||
{
|
||||
return AccEvent::GetEventGroups() | (1U << eReorderEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get connected with mutation event.
|
||||
*/
|
||||
void AddSubMutationEvent(AccMutationEvent* aEvent)
|
||||
{ mDependentEvents.AppendElement(aEvent); }
|
||||
|
||||
/**
|
||||
* Do not emit the reorder event and its connected mutation events.
|
||||
*/
|
||||
void DoNotEmitAll()
|
||||
{
|
||||
mEventRule = AccEvent::eDoNotEmit;
|
||||
uint32_t eventsCount = mDependentEvents.Length();
|
||||
for (uint32_t idx = 0; idx < eventsCount; idx++)
|
||||
mDependentEvents[idx]->mEventRule = AccEvent::eDoNotEmit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given accessible is a target of connected mutation
|
||||
* event.
|
||||
*/
|
||||
uint32_t IsShowHideEventTarget(const Accessible* aTarget) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Show and hide events causing this reorder event.
|
||||
*/
|
||||
nsTArray<AccMutationEvent*> mDependentEvents;
|
||||
|
||||
friend class NotificationController;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible caret move event.
|
||||
*/
|
||||
|
@ -110,6 +110,10 @@ NotificationController::Shutdown()
|
||||
void
|
||||
NotificationController::QueueEvent(AccEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(aEvent->mAccessible && aEvent->mAccessible->IsApplication() ||
|
||||
aEvent->GetDocAccessible() == mDocument,
|
||||
"Queued event belongs to another document!");
|
||||
|
||||
if (!mEvents.AppendElement(aEvent))
|
||||
return;
|
||||
|
||||
@ -298,44 +302,9 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
||||
// process it synchronously.
|
||||
mObservingState = eRefreshObserving;
|
||||
|
||||
// Process only currently queued events.
|
||||
nsTArray<nsRefPtr<AccEvent> > events;
|
||||
events.SwapElements(mEvents);
|
||||
|
||||
uint32_t eventCount = events.Length();
|
||||
#ifdef A11Y_LOG
|
||||
if (eventCount > 0 && logging::IsEnabled(logging::eEvents)) {
|
||||
logging::MsgBegin("EVENTS", "events processing");
|
||||
logging::Address("document", mDocument);
|
||||
logging::MsgEnd();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint32_t idx = 0; idx < eventCount; idx++) {
|
||||
AccEvent* accEvent = events[idx];
|
||||
if (accEvent->mEventRule != AccEvent::eDoNotEmit) {
|
||||
Accessible* target = accEvent->GetAccessible();
|
||||
if (!target || target->IsDefunct())
|
||||
continue;
|
||||
|
||||
// Dispatch the focus event if target is still focused.
|
||||
if (accEvent->mEventType == nsIAccessibleEvent::EVENT_FOCUS) {
|
||||
FocusMgr()->ProcessFocusEvent(accEvent);
|
||||
continue;
|
||||
}
|
||||
|
||||
mDocument->ProcessPendingEvent(accEvent);
|
||||
|
||||
// Fire text change event caused by tree mutation.
|
||||
AccMutationEvent* showOrHideEvent = downcast_accEvent(accEvent);
|
||||
if (showOrHideEvent) {
|
||||
if (showOrHideEvent->mTextChangeEvent)
|
||||
mDocument->ProcessPendingEvent(showOrHideEvent->mTextChangeEvent);
|
||||
}
|
||||
}
|
||||
if (!mDocument)
|
||||
return;
|
||||
}
|
||||
ProcessEventQueue();
|
||||
if (!mDocument)
|
||||
return;
|
||||
|
||||
// Stop further processing if there are no new notifications of any kind or
|
||||
// events and document load is processed.
|
||||
@ -348,9 +317,6 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NotificationController: event queue
|
||||
|
||||
void
|
||||
NotificationController::CoalesceEvents()
|
||||
{
|
||||
@ -359,113 +325,54 @@ NotificationController::CoalesceEvents()
|
||||
AccEvent* tailEvent = mEvents[tail];
|
||||
|
||||
switch(tailEvent->mEventRule) {
|
||||
case AccEvent::eCoalesceFromSameSubtree:
|
||||
case AccEvent::eCoalesceReorder:
|
||||
CoalesceReorderEvents(tailEvent);
|
||||
break; // case eCoalesceReorder
|
||||
|
||||
case AccEvent::eCoalesceMutationTextChange:
|
||||
{
|
||||
// No node means this is application accessible (which is a subject of
|
||||
// reorder events), we do not coalesce events for it currently.
|
||||
if (!tailEvent->mNode)
|
||||
return;
|
||||
|
||||
for (int32_t index = tail - 1; index >= 0; index--) {
|
||||
for (uint32_t index = tail - 1; index < tail; index--) {
|
||||
AccEvent* thisEvent = mEvents[index];
|
||||
|
||||
if (thisEvent->mEventType != tailEvent->mEventType)
|
||||
continue; // Different type
|
||||
|
||||
// Skip event for application accessible since no coalescence for it
|
||||
// is supported. Ignore events from different documents since we don't
|
||||
// coalesce them.
|
||||
if (!thisEvent->mNode ||
|
||||
thisEvent->mNode->OwnerDoc() != tailEvent->mNode->OwnerDoc())
|
||||
if (thisEvent->mEventRule != tailEvent->mEventRule)
|
||||
continue;
|
||||
|
||||
// Coalesce earlier event for the same target.
|
||||
if (thisEvent->mNode == tailEvent->mNode) {
|
||||
// We don't currently coalesce text change events from show/hide events.
|
||||
if (thisEvent->mEventType != tailEvent->mEventType)
|
||||
continue;
|
||||
|
||||
// Show events may be duped because of reinsertion (removal is ignored
|
||||
// because initial insertion is not processed). Ignore initial
|
||||
// insertion.
|
||||
if (thisEvent->mAccessible == tailEvent->mAccessible)
|
||||
thisEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
// If event queue contains an event of the same type and having target
|
||||
// that is sibling of target of newly appended event then apply its
|
||||
// event rule to the newly appended event.
|
||||
AccMutationEvent* tailMutationEvent = downcast_accEvent(tailEvent);
|
||||
AccMutationEvent* thisMutationEvent = downcast_accEvent(thisEvent);
|
||||
if (tailMutationEvent->mParent != thisMutationEvent->mParent)
|
||||
continue;
|
||||
|
||||
// Coalesce hide and show events for sibling targets.
|
||||
if (tailEvent->mEventType == nsIAccessibleEvent::EVENT_HIDE) {
|
||||
// Coalesce text change events for hide and show events.
|
||||
if (thisMutationEvent->IsHide()) {
|
||||
AccHideEvent* tailHideEvent = downcast_accEvent(tailEvent);
|
||||
AccHideEvent* thisHideEvent = downcast_accEvent(thisEvent);
|
||||
if (thisHideEvent->mParent == tailHideEvent->mParent) {
|
||||
tailEvent->mEventRule = thisEvent->mEventRule;
|
||||
|
||||
// Coalesce text change events for hide events.
|
||||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
|
||||
CoalesceTextChangeEventsFor(tailHideEvent, thisHideEvent);
|
||||
|
||||
return;
|
||||
}
|
||||
} else if (tailEvent->mEventType == nsIAccessibleEvent::EVENT_SHOW) {
|
||||
if (thisEvent->mAccessible->Parent() ==
|
||||
tailEvent->mAccessible->Parent()) {
|
||||
tailEvent->mEventRule = thisEvent->mEventRule;
|
||||
|
||||
// Coalesce text change events for show events.
|
||||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit) {
|
||||
AccShowEvent* tailShowEvent = downcast_accEvent(tailEvent);
|
||||
AccShowEvent* thisShowEvent = downcast_accEvent(thisEvent);
|
||||
CoalesceTextChangeEventsFor(tailShowEvent, thisShowEvent);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
CoalesceTextChangeEventsFor(tailHideEvent, thisHideEvent);
|
||||
break;
|
||||
}
|
||||
|
||||
// Ignore events unattached from DOM since we don't coalesce them.
|
||||
if (!thisEvent->mNode->IsInDoc())
|
||||
continue;
|
||||
|
||||
// Coalesce events by sibling targets (this is a case for reorder
|
||||
// events).
|
||||
if (thisEvent->mNode->GetParentNode() ==
|
||||
tailEvent->mNode->GetParentNode()) {
|
||||
tailEvent->mEventRule = thisEvent->mEventRule;
|
||||
return;
|
||||
}
|
||||
|
||||
// This and tail events can be anywhere in the tree, make assumptions
|
||||
// for mutation events.
|
||||
|
||||
// Coalesce tail event if tail node is descendant of this node. Stop
|
||||
// processing if tail event is coalesced since all possible descendants
|
||||
// of this node was coalesced before.
|
||||
// Note: more older hide event target (thisNode) can't contain recent
|
||||
// hide event target (tailNode), i.e. be ancestor of tailNode. Skip
|
||||
// this check for hide events.
|
||||
if (tailEvent->mEventType != nsIAccessibleEvent::EVENT_HIDE &&
|
||||
nsCoreUtils::IsAncestorOf(thisEvent->mNode, tailEvent->mNode)) {
|
||||
tailEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
// If this node is a descendant of tail node then coalesce this event,
|
||||
// check other events in the queue. Do not emit thisEvent, also apply
|
||||
// this result to sibling nodes of thisNode.
|
||||
if (nsCoreUtils::IsAncestorOf(tailEvent->mNode, thisEvent->mNode)) {
|
||||
thisEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
ApplyToSiblings(0, index, thisEvent->mEventType,
|
||||
thisEvent->mNode, AccEvent::eDoNotEmit);
|
||||
continue;
|
||||
}
|
||||
|
||||
} // for (index)
|
||||
|
||||
} break; // case eCoalesceFromSameSubtree
|
||||
AccShowEvent* tailShowEvent = downcast_accEvent(tailEvent);
|
||||
AccShowEvent* thisShowEvent = downcast_accEvent(thisEvent);
|
||||
CoalesceTextChangeEventsFor(tailShowEvent, thisShowEvent);
|
||||
break;
|
||||
}
|
||||
} break; // case eCoalesceMutationTextChange
|
||||
|
||||
case AccEvent::eCoalesceOfSameType:
|
||||
{
|
||||
// Coalesce old events by newer event.
|
||||
for (int32_t index = tail - 1; index >= 0; index--) {
|
||||
for (uint32_t index = tail - 1; index < tail; index--) {
|
||||
AccEvent* accEvent = mEvents[index];
|
||||
if (accEvent->mEventType == tailEvent->mEventType &&
|
||||
accEvent->mEventRule == tailEvent->mEventRule) {
|
||||
accEvent->mEventRule == tailEvent->mEventRule) {
|
||||
accEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
@ -476,7 +383,7 @@ NotificationController::CoalesceEvents()
|
||||
{
|
||||
// Check for repeat events, coalesce newly appended event by more older
|
||||
// event.
|
||||
for (int32_t index = tail - 1; index >= 0; index--) {
|
||||
for (uint32_t index = tail - 1; index < tail; index--) {
|
||||
AccEvent* accEvent = mEvents[index];
|
||||
if (accEvent->mEventType == tailEvent->mEventType &&
|
||||
accEvent->mEventRule == tailEvent->mEventRule &&
|
||||
@ -513,18 +420,92 @@ NotificationController::CoalesceEvents()
|
||||
}
|
||||
|
||||
void
|
||||
NotificationController::ApplyToSiblings(uint32_t aStart, uint32_t aEnd,
|
||||
uint32_t aEventType, nsINode* aNode,
|
||||
AccEvent::EEventRule aEventRule)
|
||||
NotificationController::CoalesceReorderEvents(AccEvent* aTailEvent)
|
||||
{
|
||||
for (uint32_t index = aStart; index < aEnd; index ++) {
|
||||
AccEvent* accEvent = mEvents[index];
|
||||
if (accEvent->mEventType == aEventType &&
|
||||
accEvent->mEventRule != AccEvent::eDoNotEmit && accEvent->mNode &&
|
||||
accEvent->mNode->GetParentNode() == aNode->GetParentNode()) {
|
||||
accEvent->mEventRule = aEventRule;
|
||||
uint32_t count = mEvents.Length();
|
||||
for (uint32_t index = count - 2; index < count; index--) {
|
||||
AccEvent* thisEvent = mEvents[index];
|
||||
|
||||
// Skip events of different types and targeted to application accessible.
|
||||
if (thisEvent->mEventType != aTailEvent->mEventType ||
|
||||
thisEvent->mAccessible->IsApplication())
|
||||
continue;
|
||||
|
||||
// If thisEvent target is not in document longer, i.e. if it was
|
||||
// removed from the tree then do not emit the event.
|
||||
if (!thisEvent->mAccessible->IsDoc() &&
|
||||
!thisEvent->mAccessible->IsInDocument()) {
|
||||
thisEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Coalesce earlier event of the same target.
|
||||
if (thisEvent->mAccessible == aTailEvent->mAccessible) {
|
||||
if (thisEvent->mEventRule == AccEvent::eDoNotEmit) {
|
||||
AccReorderEvent* tailReorder = downcast_accEvent(aTailEvent);
|
||||
tailReorder->DoNotEmitAll();
|
||||
} else {
|
||||
thisEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If tailEvent contains thisEvent
|
||||
// then
|
||||
// if show of tailEvent contains a grand parent of thisEvent
|
||||
// then assert
|
||||
// else if hide of tailEvent contains a grand parent of thisEvent
|
||||
// then ignore thisEvent and its show and hide events
|
||||
// otherwise ignore thisEvent but not its show and hide events
|
||||
Accessible* thisParent = thisEvent->mAccessible;
|
||||
while (thisParent && thisParent != mDocument) {
|
||||
if (thisParent->Parent() == aTailEvent->mAccessible) {
|
||||
AccReorderEvent* tailReorder = downcast_accEvent(aTailEvent);
|
||||
uint32_t eventType = tailReorder->IsShowHideEventTarget(thisParent);
|
||||
|
||||
if (eventType == nsIAccessibleEvent::EVENT_SHOW) {
|
||||
NS_ERROR("Accessible tree was created after it was modified! Huh?");
|
||||
} else if (eventType == nsIAccessibleEvent::EVENT_HIDE) {
|
||||
AccReorderEvent* thisReorder = downcast_accEvent(thisEvent);
|
||||
thisReorder->DoNotEmitAll();
|
||||
} else {
|
||||
thisEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
thisParent = thisParent->Parent();
|
||||
}
|
||||
|
||||
// If tailEvent is contained by thisEvent
|
||||
// then
|
||||
// if show of thisEvent contains the tailEvent
|
||||
// then ignore tailEvent
|
||||
// if hide of thisEvent contains the tailEvent
|
||||
// then assert
|
||||
// otherwise ignore tailEvent but not its show and hide events
|
||||
Accessible* tailParent = aTailEvent->mAccessible;
|
||||
while (tailParent && tailParent != mDocument) {
|
||||
if (tailParent->Parent() == thisEvent->mAccessible) {
|
||||
AccReorderEvent* thisReorder = downcast_accEvent(thisEvent);
|
||||
AccReorderEvent* tailReorder = downcast_accEvent(aTailEvent);
|
||||
uint32_t eventType = thisReorder->IsShowHideEventTarget(tailParent);
|
||||
if (eventType == nsIAccessibleEvent::EVENT_SHOW)
|
||||
tailReorder->DoNotEmitAll();
|
||||
else if (eventType == nsIAccessibleEvent::EVENT_HIDE)
|
||||
NS_ERROR("Accessible tree was modified after it was removed! Huh?");
|
||||
else
|
||||
aTailEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tailParent = tailParent->Parent();
|
||||
}
|
||||
|
||||
} // for (index)
|
||||
}
|
||||
|
||||
void
|
||||
@ -544,7 +525,7 @@ NotificationController::CoalesceSelChangeEvents(AccSelChangeEvent* aTailEvent,
|
||||
// Do not emit any preceding selection events for same widget if they
|
||||
// weren't coalesced yet.
|
||||
if (aThisEvent->mEventType != nsIAccessibleEvent::EVENT_SELECTION_WITHIN) {
|
||||
for (int32_t jdx = aThisIndex - 1; jdx >= 0; jdx--) {
|
||||
for (uint32_t jdx = aThisIndex - 1; jdx < aThisIndex; jdx--) {
|
||||
AccEvent* prevEvent = mEvents[jdx];
|
||||
if (prevEvent->mEventRule == aTailEvent->mEventRule) {
|
||||
AccSelChangeEvent* prevSelChangeEvent =
|
||||
@ -692,6 +673,76 @@ NotificationController::CreateTextChangeEventFor(AccMutationEvent* aEvent)
|
||||
aEvent->mIsFromUserInput ? eFromUserInput : eNoUserInput);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NotificationController: event queue
|
||||
|
||||
void
|
||||
NotificationController::ProcessEventQueue()
|
||||
{
|
||||
// Process only currently queued events.
|
||||
nsTArray<nsRefPtr<AccEvent> > events;
|
||||
events.SwapElements(mEvents);
|
||||
|
||||
uint32_t eventCount = events.Length();
|
||||
#ifdef A11Y_LOG
|
||||
if (eventCount > 0 && logging::IsEnabled(logging::eEvents)) {
|
||||
logging::MsgBegin("EVENTS", "events processing");
|
||||
logging::Address("document", mDocument);
|
||||
logging::MsgEnd();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint32_t idx = 0; idx < eventCount; idx++) {
|
||||
AccEvent* event = events[idx];
|
||||
if (event->mEventRule != AccEvent::eDoNotEmit) {
|
||||
Accessible* target = event->GetAccessible();
|
||||
if (!target || target->IsDefunct())
|
||||
continue;
|
||||
|
||||
// Dispatch the focus event if target is still focused.
|
||||
if (event->mEventType == nsIAccessibleEvent::EVENT_FOCUS) {
|
||||
FocusMgr()->ProcessFocusEvent(event);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Dispatch caret moved and text selection change events.
|
||||
if (event->mEventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED) {
|
||||
HyperTextAccessible* hyperText = target->AsHyperText();
|
||||
int32_t caretOffset = -1;
|
||||
if (hyperText &&
|
||||
NS_SUCCEEDED(hyperText->GetCaretOffset(&caretOffset))) {
|
||||
nsRefPtr<AccEvent> caretMoveEvent =
|
||||
new AccCaretMoveEvent(hyperText, caretOffset);
|
||||
nsEventShell::FireEvent(caretMoveEvent);
|
||||
|
||||
// There's a selection so fire selection change as well.
|
||||
int32_t selectionCount;
|
||||
hyperText->GetSelectionCount(&selectionCount);
|
||||
if (selectionCount)
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED,
|
||||
hyperText);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
nsEventShell::FireEvent(event);
|
||||
|
||||
// Fire text change events.
|
||||
AccMutationEvent* mutationEvent = downcast_accEvent(event);
|
||||
if (mutationEvent) {
|
||||
if (mutationEvent->mTextChangeEvent)
|
||||
nsEventShell::FireEvent(mutationEvent->mTextChangeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
if (event->mEventType == nsIAccessibleEvent::EVENT_HIDE)
|
||||
mDocument->ShutdownChildrenInSubtree(event->mAccessible);
|
||||
|
||||
if (!mDocument)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Notification controller: text leaf accessible text update
|
||||
|
||||
|
@ -201,18 +201,9 @@ private:
|
||||
void CoalesceEvents();
|
||||
|
||||
/**
|
||||
* Apply aEventRule to same type event that from sibling nodes of aDOMNode.
|
||||
* @param aEventsToFire array of pending events
|
||||
* @param aStart start index of pending events to be scanned
|
||||
* @param aEnd end index to be scanned (not included)
|
||||
* @param aEventType target event type
|
||||
* @param aDOMNode target are siblings of this node
|
||||
* @param aEventRule the event rule to be applied
|
||||
* (should be eDoNotEmit or eAllowDupes)
|
||||
* Coalesce events from the same subtree.
|
||||
*/
|
||||
void ApplyToSiblings(uint32_t aStart, uint32_t aEnd,
|
||||
uint32_t aEventType, nsINode* aNode,
|
||||
AccEvent::EEventRule aEventRule);
|
||||
void CoalesceReorderEvents(AccEvent* aTailEvent);
|
||||
|
||||
/**
|
||||
* Coalesce two selection change events within the same select control.
|
||||
@ -230,11 +221,18 @@ private:
|
||||
AccShowEvent* aThisEvent);
|
||||
|
||||
/**
|
||||
* Create text change event caused by hide or show event. When a node is
|
||||
* hidden/removed or shown/appended, the text in an ancestor hyper text will
|
||||
* lose or get new characters.
|
||||
* Create text change event caused by hide or show event. When a node is
|
||||
* hidden/removed or shown/appended, the text in an ancestor hyper text will
|
||||
* lose or get new characters.
|
||||
*/
|
||||
void CreateTextChangeEventFor(AccMutationEvent* aEvent);
|
||||
|
||||
// Event queue processing
|
||||
|
||||
/**
|
||||
* Process events from the queue and fires events.
|
||||
*/
|
||||
void CreateTextChangeEventFor(AccMutationEvent* aEvent);
|
||||
void ProcessEventQueue();
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -398,9 +398,10 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
|
||||
// the tree. The reorder event is delivered after the document tree is
|
||||
// constructed because event processing and tree construction are done by
|
||||
// the same document.
|
||||
// Note: don't use AccReorderEvent to avoid coalsecense and special reorder
|
||||
// events processing.
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, ApplicationAcc(),
|
||||
eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, ApplicationAcc());
|
||||
docAcc->FireDelayedAccessibleEvent(reorderEvent);
|
||||
|
||||
} else {
|
||||
|
@ -49,7 +49,7 @@ DocAccessible::MaybeNotifyOfValueChange(Accessible* aAccessible)
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible,
|
||||
eAutoDetect, AccEvent::eRemoveDupes);
|
||||
FireDelayedAccessibleEvent(valueChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1572,9 +1572,7 @@ DocAccessible::DoInitialUpdate()
|
||||
// this document may be fired prior to this reorder event. If this is
|
||||
// a problem then consider to keep event processing per tab document.
|
||||
if (!IsRoot()) {
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, Parent(), eAutoDetect,
|
||||
AccEvent::eCoalesceFromSameSubtree);
|
||||
nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(Parent());
|
||||
ParentDocument()->FireDelayedAccessibleEvent(reorderEvent);
|
||||
}
|
||||
}
|
||||
@ -1785,75 +1783,53 @@ DocAccessible::FireDelayedAccessibleEvent(AccEvent* aEvent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
DocAccessible::ProcessPendingEvent(AccEvent* aEvent)
|
||||
{
|
||||
uint32_t eventType = aEvent->GetEventType();
|
||||
if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED) {
|
||||
HyperTextAccessible* hyperText = aEvent->GetAccessible()->AsHyperText();
|
||||
int32_t caretOffset;
|
||||
if (hyperText &&
|
||||
NS_SUCCEEDED(hyperText->GetCaretOffset(&caretOffset))) {
|
||||
nsRefPtr<AccEvent> caretMoveEvent =
|
||||
new AccCaretMoveEvent(hyperText, caretOffset);
|
||||
nsEventShell::FireEvent(caretMoveEvent);
|
||||
|
||||
int32_t selectionCount;
|
||||
hyperText->GetSelectionCount(&selectionCount);
|
||||
if (selectionCount) { // There's a selection so fire selection change as well
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED,
|
||||
hyperText);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsEventShell::FireEvent(aEvent);
|
||||
|
||||
// Post event processing
|
||||
if (eventType == nsIAccessibleEvent::EVENT_HIDE)
|
||||
ShutdownChildrenInSubtree(aEvent->GetAccessible());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DocAccessible::ProcessContentInserted(Accessible* aContainer,
|
||||
const nsTArray<nsCOMPtr<nsIContent> >* aInsertedContent)
|
||||
{
|
||||
// Process the notification if the container accessible is still in tree.
|
||||
// Process insertions if the container accessible is still in tree.
|
||||
if (!HasAccessible(aContainer->GetNode()))
|
||||
return;
|
||||
|
||||
if (aContainer == this) {
|
||||
// If new root content has been inserted then update it.
|
||||
nsIContent* rootContent = nsCoreUtils::GetRoleContent(mDocument);
|
||||
if (rootContent != mContent)
|
||||
mContent = rootContent;
|
||||
bool containerNotUpdated = true;
|
||||
|
||||
// Continue to update the tree even if we don't have root content.
|
||||
// For example, elements may be inserted under the document element while
|
||||
// there is no HTML body element.
|
||||
}
|
||||
|
||||
// XXX: Invalidate parent-child relations for container accessible and its
|
||||
// children because there's no good way to find insertion point of new child
|
||||
// accessibles into accessible tree. We need to invalidate children even
|
||||
// there's no inserted accessibles in the end because accessible children
|
||||
// are created while parent recaches child accessibles.
|
||||
aContainer->UpdateChildren();
|
||||
|
||||
// The container might be changed, for example, because of the subsequent
|
||||
// overlapping content insertion (i.e. other content was inserted between this
|
||||
// inserted content and its container or the content was reinserted into
|
||||
// different container of unrelated part of tree). These cases result in
|
||||
// double processing, however generated events are coalesced and we don't
|
||||
// harm an AT.
|
||||
// Theoretically the element might be not in tree at all at this point what
|
||||
// means there's no container.
|
||||
for (uint32_t idx = 0; idx < aInsertedContent->Length(); idx++) {
|
||||
Accessible* directContainer =
|
||||
// The container might be changed, for example, because of the subsequent
|
||||
// overlapping content insertion (i.e. other content was inserted between
|
||||
// this inserted content and its container or the content was reinserted
|
||||
// into different container of unrelated part of tree). To avoid a double
|
||||
// processing of the content insertion ignore this insertion notification.
|
||||
// Note, the inserted content might be not in tree at all at this point what
|
||||
// means there's no container. Ignore the insertion too.
|
||||
|
||||
Accessible* presentContainer =
|
||||
GetContainerAccessible(aInsertedContent->ElementAt(idx));
|
||||
if (directContainer)
|
||||
UpdateTree(directContainer, aInsertedContent->ElementAt(idx), true);
|
||||
if (presentContainer != aContainer)
|
||||
continue;
|
||||
|
||||
if (containerNotUpdated) {
|
||||
containerNotUpdated = false;
|
||||
|
||||
if (aContainer == this) {
|
||||
// If new root content has been inserted then update it.
|
||||
nsIContent* rootContent = nsCoreUtils::GetRoleContent(mDocument);
|
||||
if (rootContent != mContent)
|
||||
mContent = rootContent;
|
||||
|
||||
// Continue to update the tree even if we don't have root content.
|
||||
// For example, elements may be inserted under the document element while
|
||||
// there is no HTML body element.
|
||||
}
|
||||
|
||||
// XXX: Invalidate parent-child relations for container accessible and its
|
||||
// children because there's no good way to find insertion point of new child
|
||||
// accessibles into accessible tree. We need to invalidate children even
|
||||
// there's no inserted accessibles in the end because accessible children
|
||||
// are created while parent recaches child accessibles.
|
||||
aContainer->UpdateChildren();
|
||||
}
|
||||
|
||||
UpdateTree(aContainer, aInsertedContent->ElementAt(idx), true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1880,15 +1856,17 @@ DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode,
|
||||
}
|
||||
#endif
|
||||
|
||||
nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(aContainer);
|
||||
|
||||
if (child) {
|
||||
updateFlags |= UpdateTreeInternal(child, aIsInsert);
|
||||
updateFlags |= UpdateTreeInternal(child, aIsInsert, reorderEvent);
|
||||
|
||||
} else {
|
||||
nsAccTreeWalker walker(this, aChildNode,
|
||||
aContainer->CanHaveAnonChildren(), true);
|
||||
|
||||
while ((child = walker.NextChild()))
|
||||
updateFlags |= UpdateTreeInternal(child, aIsInsert);
|
||||
updateFlags |= UpdateTreeInternal(child, aIsInsert, reorderEvent);
|
||||
}
|
||||
|
||||
// Content insertion/removal is not cause of accessible tree change.
|
||||
@ -1903,8 +1881,9 @@ DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode,
|
||||
Accessible* ancestor = aContainer;
|
||||
while (ancestor) {
|
||||
if (ancestor->ARIARole() == roles::ALERT) {
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_ALERT,
|
||||
ancestor->GetNode());
|
||||
nsRefPtr<AccEvent> alertEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_ALERT, ancestor);
|
||||
FireDelayedAccessibleEvent(alertEvent);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1920,15 +1899,12 @@ DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode,
|
||||
|
||||
// Fire reorder event so the MSAA clients know the children have changed. Also
|
||||
// the event is used internally by MSAA layer.
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, aContainer->GetNode(),
|
||||
eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
|
||||
if (reorderEvent)
|
||||
FireDelayedAccessibleEvent(reorderEvent);
|
||||
FireDelayedAccessibleEvent(reorderEvent);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert)
|
||||
DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
|
||||
AccReorderEvent* aReorderEvent)
|
||||
{
|
||||
uint32_t updateFlags = eAccessible;
|
||||
|
||||
@ -1950,34 +1926,34 @@ DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert)
|
||||
if (aChild->ARIARole() == roles::MENUPOPUP) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END, aChild);
|
||||
|
||||
if (event)
|
||||
FireDelayedAccessibleEvent(event);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Fire show/hide event.
|
||||
nsRefPtr<AccEvent> event;
|
||||
nsRefPtr<AccMutationEvent> event;
|
||||
if (aIsInsert)
|
||||
event = new AccShowEvent(aChild, node);
|
||||
else
|
||||
event = new AccHideEvent(aChild, node);
|
||||
|
||||
if (event)
|
||||
FireDelayedAccessibleEvent(event);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
aReorderEvent->AddSubMutationEvent(event);
|
||||
|
||||
if (aIsInsert) {
|
||||
roles::Role ariaRole = aChild->ARIARole();
|
||||
if (ariaRole == roles::MENUPOPUP) {
|
||||
// Fire EVENT_MENUPOPUP_START if ARIA menu appears.
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
|
||||
node, AccEvent::eRemoveDupes);
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aChild);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
|
||||
} else if (ariaRole == roles::ALERT) {
|
||||
// Fire EVENT_ALERT if ARIA alert appears.
|
||||
updateFlags = eAlertAccessible;
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_ALERT, node,
|
||||
AccEvent::eRemoveDupes);
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_ALERT, aChild);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
|
||||
// If focused node has been shown then it means its frame was recreated
|
||||
|
@ -427,12 +427,6 @@ protected:
|
||||
*/
|
||||
void ARIAActiveDescendantChanged(nsIContent* aElm);
|
||||
|
||||
/**
|
||||
* Process the event when the queue of pending events is untwisted. Fire
|
||||
* accessible events as result of the processing.
|
||||
*/
|
||||
void ProcessPendingEvent(AccEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Update the accessible tree for inserted content.
|
||||
*/
|
||||
@ -464,7 +458,8 @@ protected:
|
||||
eAlertAccessible = 2
|
||||
};
|
||||
|
||||
uint32_t UpdateTreeInternal(Accessible* aChild, bool aIsInsert);
|
||||
uint32_t UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
|
||||
AccReorderEvent* aReorderEvent);
|
||||
|
||||
/**
|
||||
* Create accessible tree.
|
||||
|
@ -85,6 +85,7 @@ HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
||||
return;
|
||||
|
||||
bool doReorderEvent = false;
|
||||
nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(this);
|
||||
|
||||
// Remove areas that are not a valid part of the image map anymore.
|
||||
for (int32_t childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) {
|
||||
@ -93,8 +94,9 @@ HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
||||
continue;
|
||||
|
||||
if (aDoFireEvents) {
|
||||
nsRefPtr<AccEvent> event = new AccHideEvent(area, area->GetContent());
|
||||
nsRefPtr<AccHideEvent> event = new AccHideEvent(area, area->GetContent());
|
||||
mDoc->FireDelayedAccessibleEvent(event);
|
||||
reorderEvent->AddSubMutationEvent(event);
|
||||
doReorderEvent = true;
|
||||
}
|
||||
|
||||
@ -118,20 +120,17 @@ HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
||||
}
|
||||
|
||||
if (aDoFireEvents) {
|
||||
nsRefPtr<AccEvent> event = new AccShowEvent(area, areaContent);
|
||||
nsRefPtr<AccShowEvent> event = new AccShowEvent(area, areaContent);
|
||||
mDoc->FireDelayedAccessibleEvent(event);
|
||||
reorderEvent->AddSubMutationEvent(event);
|
||||
doReorderEvent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fire reorder event if needed.
|
||||
if (doReorderEvent) {
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, mContent,
|
||||
eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
|
||||
if (doReorderEvent)
|
||||
mDoc->FireDelayedAccessibleEvent(reorderEvent);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -662,11 +662,8 @@ XULTreeAccessible::TreeViewChanged(nsITreeView* aView)
|
||||
// Fire reorder event on tree accessible on accessible tree (do not fire
|
||||
// show/hide events on tree items because it can be expensive to fire them for
|
||||
// each tree item.
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, this, eAutoDetect,
|
||||
AccEvent::eCoalesceFromSameSubtree);
|
||||
if (reorderEvent)
|
||||
Document()->FireDelayedAccessibleEvent(reorderEvent);
|
||||
nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(this);
|
||||
Document()->FireDelayedAccessibleEvent(reorderEvent);
|
||||
|
||||
// Clear cache.
|
||||
ClearCache(mAccessibleCache);
|
||||
|
@ -503,9 +503,11 @@ function eventQueue(aEventType)
|
||||
{
|
||||
// Create unified event sequence concatenating expected and unexpected
|
||||
// events.
|
||||
this.mEventSeq = ("eventSeq" in aInvoker) ?
|
||||
aInvoker.eventSeq :
|
||||
[ new invokerChecker(this.mDefEventType, aInvoker.DOMNode) ];
|
||||
this.mEventSeq = ("eventSeq" in aInvoker) ? aInvoker.eventSeq : [ ];
|
||||
if (!this.mEventSeq.length && this.mDefEventType) {
|
||||
this.mEventSeq.push(new invokerChecker(this.mDefEventType,
|
||||
aInvoker.DOMNode));
|
||||
}
|
||||
|
||||
var len = this.mEventSeq.length;
|
||||
for (var idx = 0; idx < len; idx++) {
|
||||
|
@ -67,7 +67,7 @@
|
||||
|
||||
this.getID = function showMenu_getID()
|
||||
{
|
||||
return "Show ARIA menu " + aMenuID + " by " +
|
||||
return "Show ARIA menu '" + aMenuID + "' by " +
|
||||
(aHow == kViaDisplayStyle ? "display" : "visibility") +
|
||||
" style tricks";
|
||||
};
|
||||
@ -150,7 +150,6 @@
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debuging
|
||||
//gA11yEventDumpToConsole = true; // debuging
|
||||
|
||||
function doTests()
|
||||
|
@ -326,7 +326,7 @@
|
||||
// Do tests.
|
||||
|
||||
var gQueue = null;
|
||||
// var gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true; // debug stuff
|
||||
|
||||
function doTests()
|
||||
{
|
||||
|
@ -242,8 +242,8 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger content insertion, removal and insertion of the same element
|
||||
* for the same parent.
|
||||
* Trigger content insertion (flush layout), removal and insertion of
|
||||
* the same element for the same parent.
|
||||
*/
|
||||
function test1(aContainerID)
|
||||
{
|
||||
@ -266,13 +266,14 @@
|
||||
|
||||
this.getID = function test1_getID()
|
||||
{
|
||||
return "test1";
|
||||
return "fuzzy test #1: content insertion (flush layout), removal and" +
|
||||
"reinsertion";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger content insertion, removal and insertion of the same element
|
||||
* for the different parents.
|
||||
* Trigger content insertion (flush layout), removal and insertion of
|
||||
* the same element for the different parents.
|
||||
*/
|
||||
function test2(aContainerID, aTmpContainerID)
|
||||
{
|
||||
@ -302,7 +303,36 @@
|
||||
|
||||
this.getID = function test2_getID()
|
||||
{
|
||||
return "test2";
|
||||
return "fuzzy test #2: content insertion (flush layout), removal and" +
|
||||
"reinsertion under another container";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Content insertion (flush layout) and then removal (nothing was changed).
|
||||
*/
|
||||
function test3(aContainerID)
|
||||
{
|
||||
this.divNode = document.createElement("div");
|
||||
this.divNode.setAttribute("id", "div-test3");
|
||||
this.containerNode = getNode(aContainerID);
|
||||
|
||||
this.unexpectedEventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, this.divNode),
|
||||
new invokerChecker(EVENT_HIDE, this.divNode),
|
||||
new invokerChecker(EVENT_REORDER, this.containerNode)
|
||||
];
|
||||
|
||||
this.invoke = function test3_invoke()
|
||||
{
|
||||
this.containerNode.appendChild(this.divNode);
|
||||
getComputedStyle(this.divNode, "").color;
|
||||
this.containerNode.removeChild(this.divNode);
|
||||
}
|
||||
|
||||
this.getID = function test3_getID()
|
||||
{
|
||||
return "fuzzy test #3: content insertion (flush layout) and removal";
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,8 +373,7 @@
|
||||
* Do tests.
|
||||
*/
|
||||
var gQueue = null;
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
//gA11yEventDumpToConsole = true; // debug stuff
|
||||
|
||||
function doTests()
|
||||
{
|
||||
@ -427,6 +456,7 @@
|
||||
gQueue.push(new test1("testContainer"));
|
||||
gQueue.push(new test2("testContainer", "testContainer2"));
|
||||
gQueue.push(new test2("testContainer", "testNestedContainer"));
|
||||
gQueue.push(new test3("testContainer"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user