No accessibility events for re-focused object after ARIA dialog dismissed

NEW
Unassigned

Status

()

P2
normal
3 years ago
2 months ago

People

(Reporter: jdiggs, Unassigned)

Tracking

(Blocks: 3 bugs)

Trunk
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(firefox42 affected)

Details

Attachments

(3 attachments, 1 obsolete attachment)

(Reporter)

Description

3 years ago
Created attachment 8643065 [details]
test case: aria-modal-dialog.html

Steps to reproduce:
1. Load the attached test case in Firefox
2. Launch DOM inspector and listen for (at least) focus events
3. Tab to the "Display a dialog" link
4. Sanity check: Press Ctrl+O to open native "Open" dialog. Press Escape.
5. Press Return on "Display a dialog" link. Press Escape.

Expected results: After both steps 4 and 5, there would be a focus event for the "Display a dialog" link which just re-gained focus after each dialog was dismissed.

Actual results: After step 4, there is a focus event for the "Display a dialog" link which just re-gained focus. However, after step 5, there is not a focus event for the "Display a dialog" link.

There are also missing window: accessibility events which I'll provide steps for in a subsequent comment.

Impact: Screen readers don't know where the user is after the ARIA dialog is dismissed.
(Reporter)

Comment 1

3 years ago
Created attachment 8643072 [details]
at-spi2 accessible-event listener: listener.py

Steps to reproduce:
1. Launch the attached accessible-event listener in terminal
2. Perform the dialog opening and dismissing steps from the opening report

Results:
* When the native dialog gains focus, the Firefox main window emits a window:deactivate event. (Good)
* When the native dialog is dismissed, the Firefox main window emits a window:activate event. (Good)
* When the ARIA dialog gains focus, it emits a window:activate event. (Good) BUT the Firefox main window does not emit a window:deactivate event. (Not good; but workaroundable)
* When the ARIA dialog loses focus, it emits a window:deactivate event. (Good) BUT the Firefox main window does not emit a window:activate event. (BAD and hard to reliably work around, especially given the lack of focus events mentioned in the opening report. Basically, all Orca knows is that the user is no longer in the ARIA dialog. Orca has no clue where the user actually is because nothing claims to be the active window or the focused object.)
(Reporter)

Updated

3 years ago
Blocks: 1171559

Comment 2

3 years ago
Running the test case, I see that this apparently does not work as intended in the first place. In the Error Console, I see several of these errors:

attachment.cgi
Error
TypeError: okbutton is null
attachment.cgi
:39:3
Error
TypeError: pagebackground is null

So the intended logic doesn't kick in for me. The OK button doesn't gain focus when the dialog opens, and subsequently, the return to the other element doesn't work, either.
(Reporter)

Comment 3

3 years ago
Created attachment 8643128 [details]
new test case: aria-modal-dialog.html

Ok, this version of the test case corrects the errors. The focus event for the link is present, but the window events I mentioned in my comment are still missing and that really should be fixed. The original, in-the-wild test case is not for a link-triggered popup dialog, but for a time-triggered one. (I'll see if I can make another test case in which the window events are missing and the focus events are also missing.)
Attachment #8643065 - Attachment is obsolete: true
(Reporter)

Comment 4

3 years ago
Created attachment 8643137 [details]
timed-aria-modal-dialog.html

Steps to reproduce:
1. Enable native caret navigation in Firefox
2. Load the test case
3. Tab to the "Line 1" link
4. Press Down arrow to move focus off that link to the text with "Line 2"
5. Wait 5 seconds for the dialog to appear
6. Press Escape

Expected results: At least one of the following (preferably both):
a. A window activate event for the Firefox window
b. A focus event for the document frame

Actual results: I don't see a or b. As a result, if the Orca user happens to not be on a focusable object at the time the dialog pops up, Orca gets no events indicating what has focus/is active after the dialog is dismissed.

In addition: The caret is no longer in the document frame, so the user cannot Down Arrow to Line 3.

This may be bad authoring, but it happens in the wild. If you (Firefox) happen to know the user is back in the document and the Firefox window is the active window, emitting the corresponding signals would be appreciated. Thanks!

Comment 5

2 months ago
Really simple test case:
data:text/html,<div role="dialog"><button autofocus onClick="this.parentNode.removeChild(this);">Close</button></div><button>Dummy</button>
Clicking the close button removes the dialog and fires no focus event. Happens all the time in the wild, and in many implementations, this can happen even if there *was* something focused before the dialog was opened. For NVDA, this is even worse because if the user cursors around, they'll still see the dialog content, since it's in a separate buffer.

Stated generally, the problem is that if focus is on an element which is removed (and blur isn't called before removal), no focus event is fired.

I think this is due to bug 559561. I thought there was a general a11y bug for this, but if there is, I can't find it.

It doesn't seem like bug 559561 is going anywhere and that'll probably require a lot of DOM/layout expertise to fix. I think we should just try to work around this in a11y for now.

Eitan, I seem to recall you saying you deal with this in AccessFu somehow. I'm guessing you watch for removals and adjust the virtual cursor? How do you manage this efficiently? Can we borrow some ideas more generally here?

Setting to p2 because this is super annoying for ARIA dialogs all over the place, but might need to adjust if a workaround turns out to be too complex. Marco, appreciate your thoughts on priority also. Have you seen this too?
Blocks: 375743
Flags: needinfo?(mzehe)
Flags: needinfo?(eitan)
Priority: -- → P2

Comment 6

2 months ago
I always advise people to explicitly set focus to something after closing a dialog. Because browsers are in a habit of behaving inconsistently. So even if a button had focus and opened an ARIA dialog, which is only simulated anyway, the DOM doesn't remember where focus was before. Remember, ARIA dialogs aren't really dialogs for the browser. So, I tell people, if they make something close the dialog, make sure to set focus back to the control that opened it, or the control that makes most sense in the UX flow of the particular web application. And that generally works well. But as a web author, you have to consciously do that. And I think it's even documented like that in the authoring best practices.
Flags: needinfo?(mzehe)

Comment 7

2 months ago
(In reply to Marco Zehe (:MarcoZ) from comment #6)
> I always advise people to explicitly set focus to something after closing a
> dialog.

To clarify, I was more curious about what you see in the wild. I know what authors *should* do and I know the spec probably even *tells* them to do that. But in your experience, do real world sites actually follow that guidance? I've seen quite a lot in my time that don't, but maybe I'm an anomaly... and I can't think of specific examples right now, of course. :(

If our users are hitting this on a regular basis and we can alter behaviour to work around poor authoring without boiling the ocean, it makes sense to prioritise this. If, on the other hand, this kind of poor authoring is rare, this can e a p3 instead of a p2. (It's a p3 even aside from ARIA dialogs because focus should just never go to limbo at all.)
I think this is an implementation bug on our part. When a focused element is destroyed, the activeElement is reset to the <body> tag, just like if you did a blur() on the focused element. Except that in the former case we don't fire an event that the document was focused.

In accessfu we do weird dirty tricks where we listen for new dialogs and store the pre-dialog cursor position. When the dialog is dismissed we wait half a second to allow the web app to Do The Right Thing and explicitly set focus. If it doesn't we use the stored location, and hopefully it still exists.
Flags: needinfo?(eitan)
Of course, Joanie already knew this was a bug on our part 3 years ago :)

Comment 10

2 months ago
(In reply to Eitan Isaacson [:eeejay] from comment #8)
> I think this is an implementation bug on our part. When a focused element is
> destroyed, the activeElement is reset to the <body> tag, just like if you
> did a blur() on the focused element. Except that in the former case we don't
> fire an event that the document was focused.

I assumed this was because DOM isn't firing blur events for this case, which is apparently a DOM bug. See bug 559561. Are you saying there's more explicit a11y code for this case?

> In accessfu we do weird dirty tricks where we listen for new dialogs and
> store the pre-dialog cursor position. When the dialog is dismissed

How do you detect dialog dismissal?
(In reply to James Teh [:Jamie] from comment #10)
> (In reply to Eitan Isaacson [:eeejay] from comment #8)
> > I think this is an implementation bug on our part. When a focused element is
> > destroyed, the activeElement is reset to the <body> tag, just like if you
> > did a blur() on the focused element. Except that in the former case we don't
> > fire an event that the document was focused.
> 
> I assumed this was because DOM isn't firing blur events for this case, which
> is apparently a DOM bug. See bug 559561. Are you saying there's more
> explicit a11y code for this case?
> 

Yeah, not sure who is at fault. Looks like that bug got stuck because they want a destroyed element to send a blur event?
You had a similar bug open too: bug 1230420.

If this won't get resolved in DOM any time soon, I bet we can account for this in FocusManager.

> > In accessfu we do weird dirty tricks where we listen for new dialogs and
> > store the pre-dialog cursor position. When the dialog is dismissed
> 
> How do you detect dialog dismissal?

We listen for a hide event. If the vc position is defunct, or if it is in the subtree of the newly hidden accessible, we restore the pre-dialog position.

https://searchfox.org/mozilla-central/rev/97d488a17a848ce3bebbfc83dc916cf20b88451c/accessible/jsat/EventManager.jsm#338
You need to log in before you can comment on or make changes to this bug.