Bug 788389 - fire statechange event whenever checked state is changed not depending on focused state, r=tbsaunde

This commit is contained in:
Alexander Surkov 2013-08-02 12:42:36 -04:00
Родитель cba68435bc
Коммит 10affe6a86
7 изменённых файлов: 87 добавлений и 42 удалений

Просмотреть файл

@ -723,6 +723,15 @@ public:
*/
bool HasNumericValue() const;
/**
* Return true if the accessible state change is processed by handling proper
* DOM UI event, if otherwise then false. For example, HTMLCheckboxAccessible
* process nsIDocumentObserver::ContentStateChanged instead
* 'CheckboxStateChange' event.
*/
bool NeedsDOMUIEvent() const
{ return !(mStateFlags & eIgnoreDOMUIEvent); }
protected:
/**
@ -789,6 +798,7 @@ protected:
eSharedNode = 1 << 2, // accessible shares DOM node from another accessible
eNotNodeMapEntry = 1 << 3, // accessible shouldn't be in document node map
eHasNumericValue = 1 << 4, // accessible has a numeric value
eIgnoreDOMUIEvent = 1 << 5, // don't process DOM UI events for a11y events
eLastStateFlag = eHasNumericValue
};

Просмотреть файл

@ -1158,7 +1158,13 @@ DocAccessible::ContentStateChanged(nsIDocument* aDocument,
nsRefPtr<AccEvent> event =
new AccSelChangeEvent(widget, accessible, selChangeType);
FireDelayedEvent(event);
return;
}
nsRefPtr<AccEvent> event =
new AccStateChangeEvent(accessible, states::CHECKED,
aContent->AsElement()->State().HasState(NS_EVENT_STATE_CHECKED));
FireDelayedEvent(event);
}
if (aStateMask.HasState(NS_EVENT_STATE_INVALID)) {

Просмотреть файл

@ -21,7 +21,9 @@ public:
ProgressMeterAccessible(nsIContent* aContent, DocAccessible* aDoc) :
LeafAccessible(aContent, aDoc)
{
mStateFlags |= eHasNumericValue;
// Ignore 'ValueChange' DOM event in lieu of @value attribute change
// notifications.
mStateFlags |= eHasNumericValue | eIgnoreDOMUIEvent;
mType = eProgressType;
}

Просмотреть файл

@ -310,16 +310,13 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
if (eventType.EqualsLiteral("RadioStateChange")) {
uint64_t state = accessible->State();
// radiogroup in prefWindow is exposed as a list,
// and panebutton is exposed as XULListitem in A11y.
// XULListitemAccessible::GetStateInternal uses STATE_SELECTED in this case,
// so we need to check states::SELECTED also.
bool isEnabled = (state & (states::CHECKED | states::SELECTED)) != 0;
nsRefPtr<AccEvent> accEvent =
new AccStateChangeEvent(accessible, states::CHECKED, isEnabled);
nsEventShell::FireEvent(accEvent);
if (accessible->NeedsDOMUIEvent()) {
nsRefPtr<AccEvent> accEvent =
new AccStateChangeEvent(accessible, states::CHECKED, isEnabled);
nsEventShell::FireEvent(accEvent);
}
if (isEnabled) {
FocusMgr()->ActiveItemChanged(accessible);
@ -333,14 +330,14 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
}
if (eventType.EqualsLiteral("CheckboxStateChange")) {
uint64_t state = accessible->State();
if (accessible->NeedsDOMUIEvent()) {
uint64_t state = accessible->State();
bool isEnabled = !!(state & states::CHECKED);
bool isEnabled = !!(state & states::CHECKED);
nsRefPtr<AccEvent> accEvent =
new AccStateChangeEvent(accessible, states::CHECKED, isEnabled);
nsEventShell::FireEvent(accEvent);
nsRefPtr<AccEvent> accEvent =
new AccStateChangeEvent(accessible, states::CHECKED, isEnabled);
nsEventShell::FireEvent(accEvent);
}
return;
}
@ -455,14 +452,10 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
logging::ActiveItemChangeCausedBy("DOMMenuBarInactive", accessible);
#endif
}
else if (eventType.EqualsLiteral("ValueChange")) {
//We don't process 'ValueChange' events for progress meters since we listen
//@value attribute change for them.
if (!accessible->IsProgress()) {
targetDocument->FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
accessible);
}
else if (accessible->NeedsDOMUIEvent() &&
eventType.EqualsLiteral("ValueChange")) {
targetDocument->FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
accessible);
}
#ifdef DEBUG_DRAGDROPSTART
else if (eventType.EqualsLiteral("mouseover")) {

Просмотреть файл

@ -39,12 +39,6 @@ using namespace mozilla::a11y;
// HTMLCheckboxAccessible
////////////////////////////////////////////////////////////////////////////////
HTMLCheckboxAccessible::
HTMLCheckboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
LeafAccessible(aContent, aDoc)
{
}
role
HTMLCheckboxAccessible::NativeRole()
{
@ -119,12 +113,6 @@ HTMLCheckboxAccessible::IsWidget() const
// HTMLRadioButtonAccessible
////////////////////////////////////////////////////////////////////////////////
HTMLRadioButtonAccessible::
HTMLRadioButtonAccessible(nsIContent* aContent, DocAccessible* aDoc) :
RadioButtonAccessible(aContent, aDoc)
{
}
uint64_t
HTMLRadioButtonAccessible::NativeState()
{

Просмотреть файл

@ -26,7 +26,13 @@ class HTMLCheckboxAccessible : public LeafAccessible
public:
enum { eAction_Click = 0 };
HTMLCheckboxAccessible(nsIContent* aContent, DocAccessible* aDoc);
HTMLCheckboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
LeafAccessible(aContent, aDoc)
{
// Ignore "CheckboxStateChange" DOM event in lieu of document observer
// state change notification.
mStateFlags |= eIgnoreDOMUIEvent;
}
// nsIAccessible
NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName);
@ -51,7 +57,13 @@ class HTMLRadioButtonAccessible : public RadioButtonAccessible
{
public:
HTMLRadioButtonAccessible(nsIContent* aContent, DocAccessible* aDoc);
HTMLRadioButtonAccessible(nsIContent* aContent, DocAccessible* aDoc) :
RadioButtonAccessible(aContent, aDoc)
{
// Ignore "RadioStateChange" DOM event in lieu of document observer
// state change notification.
mStateFlags |= eIgnoreDOMUIEvent;
}
// Accessible
virtual uint64_t NativeState();

Просмотреть файл

@ -72,6 +72,26 @@
};
}
function changeCheckInput(aID, aIsChecked)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new stateChangeChecker(STATE_CHECKED, false, aIsChecked, this.DOMNode)
];
this.invoke = function changeCheckInput_invoke()
{
this.DOMNode.checked = aIsChecked;
}
this.getID = function changeCheckInput_getID()
{
return "change checked state to '" + aIsChecked + "' for " +
prettyName(aID);
}
}
function stateChangeOnFileInput(aID, aAttr, aValue,
aState, aIsExtraState, aIsEnabled)
{
@ -154,6 +174,12 @@
// invalid state change
gQueue.push(new invalidInput("email"));
// checked state change
gQueue.push(new changeCheckInput("checkbox", true));
gQueue.push(new changeCheckInput("checkbox", false));
gQueue.push(new changeCheckInput("radio", true));
gQueue.push(new changeCheckInput("radio", false));
// file input inherited state changes
gQueue.push(new stateChangeOnFileInput("file", "aria-busy", "true",
STATE_BUSY, false, true));
@ -180,17 +206,22 @@
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=564471"
title="Make state change events async">
Mozilla Bug 564471
</a><br>
Bug 564471
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=555728"
title="Fire a11y event based on HTML5 constraint validation">
Mozilla Bug 555728
Bug 555728
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=699017"
title="File input control should be propogate states to descendants">
Mozilla Bug 699017
Bug 699017
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=788389"
title="Fire statechange event whenever checked state is changed not depending on focused state">
Bug 788389
</a>
<p id="display"></p>
@ -204,6 +235,9 @@
<input id="email" type='email'>
<input id="checkbox" type="checkbox">
<input id="radio" type="radio">
<input id="file" type="file">
<div id="div"></div>