Bug 414302 - Incorrect selection events in HTML, XUL and ARIA, r=tbsaunde, f=marcoz

This commit is contained in:
Alexander Surkov
2011-11-01 08:52:27 +08:00
parent 4eca91e4dc
commit 18c1af0852
17 changed files with 663 additions and 150 deletions

View File

@@ -51,6 +51,10 @@
using namespace mozilla::a11y;
// Defines the number of selection add/remove events in the queue when they
// aren't packed into single selection within event.
const unsigned int kSelChangeCountToPack = 5;
////////////////////////////////////////////////////////////////////////////////
// NotificationCollector
////////////////////////////////////////////////////////////////////////////////
@@ -491,6 +495,26 @@ NotificationController::CoalesceEvents()
}
} break; // case eRemoveDupes
case AccEvent::eCoalesceSelectionChange:
{
AccSelChangeEvent* tailSelChangeEvent = downcast_accEvent(tailEvent);
PRInt32 index = tail - 1;
for (; index >= 0; index--) {
AccEvent* thisEvent = mEvents[index];
if (thisEvent->mEventRule == tailEvent->mEventRule) {
AccSelChangeEvent* thisSelChangeEvent =
downcast_accEvent(thisEvent);
// Coalesce selection change events within same control.
if (tailSelChangeEvent->mWidget == thisSelChangeEvent->mWidget) {
CoalesceSelChangeEvents(tailSelChangeEvent, thisSelChangeEvent, index);
return;
}
}
}
} break; // eCoalesceSelectionChange
default:
break; // case eAllowDupes, eDoNotEmit
} // switch
@@ -511,6 +535,86 @@ NotificationController::ApplyToSiblings(PRUint32 aStart, PRUint32 aEnd,
}
}
void
NotificationController::CoalesceSelChangeEvents(AccSelChangeEvent* aTailEvent,
AccSelChangeEvent* aThisEvent,
PRInt32 aThisIndex)
{
aTailEvent->mPreceedingCount = aThisEvent->mPreceedingCount + 1;
// Pack all preceding events into single selection within event
// when we receive too much selection add/remove events.
if (aTailEvent->mPreceedingCount >= kSelChangeCountToPack) {
aTailEvent->mEventType = nsIAccessibleEvent::EVENT_SELECTION_WITHIN;
aTailEvent->mAccessible = aTailEvent->mWidget;
aThisEvent->mEventRule = AccEvent::eDoNotEmit;
// Do not emit any preceding selection events for same widget if they
// weren't coalesced yet.
if (aThisEvent->mEventType != nsIAccessibleEvent::EVENT_SELECTION_WITHIN) {
for (PRInt32 jdx = aThisIndex - 1; jdx >= 0; jdx--) {
AccEvent* prevEvent = mEvents[jdx];
if (prevEvent->mEventRule == aTailEvent->mEventRule) {
AccSelChangeEvent* prevSelChangeEvent =
downcast_accEvent(prevEvent);
if (prevSelChangeEvent->mWidget == aTailEvent->mWidget)
prevSelChangeEvent->mEventRule = AccEvent::eDoNotEmit;
}
}
}
return;
}
// Pack sequential selection remove and selection add events into
// single selection change event.
if (aTailEvent->mPreceedingCount == 1 &&
aTailEvent->mItem != aThisEvent->mItem) {
if (aTailEvent->mSelChangeType == AccSelChangeEvent::eSelectionAdd &&
aThisEvent->mSelChangeType == AccSelChangeEvent::eSelectionRemove) {
aThisEvent->mEventRule = AccEvent::eDoNotEmit;
aTailEvent->mEventType = nsIAccessibleEvent::EVENT_SELECTION;
aTailEvent->mPackedEvent = aThisEvent;
return;
}
if (aThisEvent->mSelChangeType == AccSelChangeEvent::eSelectionAdd &&
aTailEvent->mSelChangeType == AccSelChangeEvent::eSelectionRemove) {
aTailEvent->mEventRule = AccEvent::eDoNotEmit;
aThisEvent->mEventType = nsIAccessibleEvent::EVENT_SELECTION;
aThisEvent->mPackedEvent = aThisEvent;
return;
}
}
// Unpack the packed selection change event because we've got one
// more selection add/remove.
if (aThisEvent->mEventType == nsIAccessibleEvent::EVENT_SELECTION) {
if (aThisEvent->mPackedEvent) {
aThisEvent->mPackedEvent->mEventType =
aThisEvent->mPackedEvent->mSelChangeType == AccSelChangeEvent::eSelectionAdd ?
nsIAccessibleEvent::EVENT_SELECTION_ADD :
nsIAccessibleEvent::EVENT_SELECTION_REMOVE;
aThisEvent->mPackedEvent->mEventRule =
AccEvent::eCoalesceSelectionChange;
aThisEvent->mPackedEvent = nsnull;
}
aThisEvent->mEventType =
aThisEvent->mSelChangeType == AccSelChangeEvent::eSelectionAdd ?
nsIAccessibleEvent::EVENT_SELECTION_ADD :
nsIAccessibleEvent::EVENT_SELECTION_REMOVE;
return;
}
// Convert into selection add since control has single selection but other
// selection events for this control are queued.
if (aTailEvent->mEventType == nsIAccessibleEvent::EVENT_SELECTION)
aTailEvent->mEventType = nsIAccessibleEvent::EVENT_SELECTION_ADD;
}
void
NotificationController::CoalesceTextChangeEventsFor(AccHideEvent* aTailEvent,
AccHideEvent* aThisEvent)