Bug 414302 - Incorrect selection events in HTML, XUL and ARIA, r=tbsaunde, f=marcoz
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user