nvaccess / nvda

NVDA, the free and open source Screen Reader for Microsoft Windows
https://www.nvaccess.org/
Other
2.12k stars 637 forks source link

Limit list item quick navigation to current list #8193

Open LeonarddeR opened 6 years ago

LeonarddeR commented 6 years ago

Original idea by @bramd

Description of proposal

The current quick navigation command for list items jumps from list item to list item, thereby ignoring list boundaries. For example:

Piece of text

  1. New list

When using the quick navigation command for list items, every single list item will be navigated. I propose that the list item quicknav command doesn't pass list boundaries (i.e. when First level, 3 has focus in the above example, pressing "i" should report "No next item in current list" rather than jump to New list

Thoughts are welcome. Also, I'd like to invite @bramd to give more information about possible use cases.

DrSooom commented 6 years ago

See: #5906, #6815, #7804, #8103

I was thinking about this quite a while and found no satisfied solution. We can change the behaviour for I and Shift+I in that case that you have to press it twice to move up/back into a parent list, but in the end this could confuse more than it helps.

So, I'm asking me if it is possible to use tones (and speech) to present the level of the list similar to the line indentation (#5906). If the "lists"-checkbox in the document settings is enabled, "clst" could be displayed on the braille display as well. "" represents the level of the child list – to be exactly the distance between the current child list and the highest parent list. And if a list contains one or more child lists, "lst+" instead of "lst" could be shown – and of course spoken by NVDA as well.

Regarding to this tone feedback the user immediately knows on which list level the cursor currently is. So because of that changing the behaviours of I, L and Comma for lists isn't required anymore.

JulienCochuyt commented 5 years ago

As proposed in https://github.com/nvaccess/nvda/issues/9227#issuecomment-547291343 I'd propose to further extend this limitation to headers. Eg. pressing 2 would only move to the next H2 within the limits of the same H1. UX could go something like "no next/previous X in current Y, press again to search outside"

This could even later be extended to radio buttons groups and tab headers lists, effectively turning "i" to "items", not only "list items": Eg. have "r" move to the radio buttons group (ideally to the selected element) and "i" to individual radio buttons within the group.

@lukaszgo1 wrote in https://github.com/nvaccess/nvda/issues/9227#issuecomment-547432289

JAWS developers used this approach a few years ago. From user perspective this was very confusing. The final argument against this is the fact that Vispero changed this behavior to make it like NVDA. It looks like it had its problems.

What was their UX back then? (I'm apparently specialized in NVDA for too long) Did they include the proposed easy bypass mechanism of pressing twice and informative announcements? We included ability to restrict both quick nav and tab nav to a given zone in WebAccess with quite good user feedback so far. (zones there are quite similar to regions but can be set to encompass any node's subtree)

Also, this new behavior could be configurable, preferably IMHO active by default.

LeonarddeR commented 5 years ago

These are lovely ideas!

JulienCochuyt commented 5 years ago

@leonardder wrote:

These are lovely ideas!

Thanks for your enthusiasm!

The logic could be implemented either:

I'd go for the central approach, but what do you think?

LeonarddeR commented 5 years ago

I Understand that you prefer the global approach, however especcially for UIA, i'm afraid the performance impact will be major if not done in the tree interceptor directly. UIA quicknav is still far from ideal.

JulienCochuyt commented 5 years ago

@leonardder wrote:

I Understand that you prefer the global approach, however especcially for UIA, i'm afraid the performance impact will be major if not done in the tree interceptor directly. UIA quicknav is still far from ideal.

Having a look at UIABrowseMode.UIAHeadingQuicknavIterator I think I understand your concerns.

The advantage of the central approach was that the new constraints could easily be expressed in new arguments to the BrowseModeTreeInterceptor.addQuickNav, something like limit=("next", "heading1") for a heading2 or limit=("up", "list") for a listitem.

Maybe a mixture of both approaches could do the trick. In BrowseModeTreeInterceptor._quickNavScript:

DrSooom commented 5 years ago

@JulienCochuyt: The hierarchies of headlines are different to lists. Therefore I would separate them from this issue. It could get too complex if we're putting all into one single PR.

I also like your idea for headlines, but I want to have an option how the new "border" is announced by NVDA. I would prefer just a short beep tone and others could prefer speech output. Well, and it should be clear, that this new quick navigation behavior must be able to be enabled or disabled by the end user. Not all websites care about a useful and understandable headline hierarchy.

lukaszgo1 commented 5 years ago

@JulienCochuyt wrote:

As proposed in #9227 (comment) I'd propose to further extend this limitation to headers. Eg. pressing 2 would only move to the next H2 within the limits of the same H1. UX could go something like "no next/previous X in current Y, press again to search outside"

While I understand doing it for list items I do not see What would it improve for an end user in case of headings.

What was their UX back then? (I'm apparently specialized in NVDA for too long) Did they include the proposed easy bypass mechanism of pressing twice and informative announcements?

My bad, I've completely missed the part about being able to jump to the next element outside of the region by pressing twice. No they do not, the only way in which it was possible to move to say the next h2 outside of the current h1, was to move first to the next 1 annd the to h2.

Also, this new behavior could be configurable, preferably IMHO active by default.

It has to be, mainly because they would be no other screen reader with such mode of navigation and for people migrating to NVDA it would be really confusing I think.

JulienCochuyt commented 5 years ago

@DrSooom wrote:

@JulienCochuyt: The hierarchies of headlines are different to lists. Therefore I would separate them from this issue. It could get too complex if we're putting all into one single PR.

This feature is actually quite simple to implement and both lists and headings would share here a great portion of the needed code. The shared part is actually so important that splitting would lead to either:

Furthermore, I guess both features will probably meet the same opponents and advocates, thus I guess that for once there is good reasons for grouping.

JulienCochuyt commented 5 years ago

@lukaszgo1 wrote:

While I understand doing it for list items I do not see What would it improve for an end user in case of headings.

Consider a very long document, with dozens of nested headings, in which you'd want to skip whole parts but could not tell which ones to skip until reading the first few paragraphs. In this context, if you are reading the first few paragraphs under a level 2 heading and realize you want to skip until the next one, you could currently either:

LeonarddeR commented 5 years ago
* If `self._iterNodesByTypes.implementsLimit`, pass the limit parameter and catch a dedicated exception to trigger the specialized message. The function attribute would spare coupling `browseMode` with `VirtualBuffer` and the dedicated exception would allow to avoid coupling `UIABrowseMode` with `ui.message`

Just to make sure, are you suggesting that some implementations of _iterNodesByType would implement limit and others don't? I think that could be confusing for users.

* otherwise, check the boundaries in a generic way. This would leave all other implementations in the same place.

I agree that there should be a fallback for generic checking, but thinking more and more about this, may be _quickNavScript isn't the best place for this. Could a base implementation of _iterNodesByType in BrowseModeTreeInterceptor be of any help in this, or alternatively, a helper method that has either a generic implementation or for UIA, a specific implementation?

JulienCochuyt commented 5 years ago

@leonardder wrote:

* If `self._iterNodesByTypes.implementsLimit`, pass the limit parameter and catch a dedicated exception to trigger the specialized message. The function attribute would spare coupling `browseMode` with `VirtualBuffer` and the dedicated exception would allow to avoid coupling `UIABrowseMode` with `ui.message`

Just to make sure, are you suggesting that some implementations of _iterNodesByType would implement limit and others don't? I think that could be confusing for users.

Yes indeed. With a proper explanation in the docstring of _iterNodesByType as well as a comment everywhere the function attribute is set. My motivation was to limit API impact as much as possible. (Disclaimer: Yes, this is mostly for ease of maintenance on WebAccess…)

* otherwise, check the boundaries in a generic way. This would leave all other implementations in the same place.

I agree that there should be a fallback for generic checking, but thinking more and more about this, may be _quickNavScript isn't the best place for this. Could a base implementation of _iterNodesByType in BrowseModeTreeInterceptor be of any help in this, or alternatively, a helper method that has either a generic implementation or for UIA, a specific implementation?

The UIA and Edge implementations are quite special in that they require the boundary check to be performed along with the regular search in order not to badly impact performance. Thus, an external helper would not… help much IMHO.

Though, a base BrowseModeTreeInterceptor.iterNodesByType (without the leading underscore and with the limit kwarg) could implement the generic boundary, and call the existing _iterNodesByType implementations without much API impact. UIA and Edge would then override the outer iterNodesByType and not the inner _iterNodesByType.

Would you prefer this approach?

Maybe would it be clearer with a draft prototype…

LeonarddeR commented 5 years ago

Though, a base BrowseModeTreeInterceptor.iterNodesByType (without the leading underscore and with the limit kwarg) could implement the generic boundary, and call the existing _iterNodesByType implementations without much API impact. UIA and Edge would then override the outer iterNodesByType and not the inner _iterNodesByType.

Would you prefer this approach?

Yes, I really like that idea actually. Probably best to have @michaelDCurran's opinion before creating a draft, though.

michaelDCurran commented 5 years ago

I agree with the implementation proposal, and I agree that headings and lists could share the same code. I totally agree we should do this by default for list items, but I'm not totally convinced yet for headings. How about for the initial pr, support for list items is implemented, but in an abstract way such that it is very easy and clear to then add headings at a later date.

DrSooom commented 4 years ago

Based on @feerrenrut's comment in issue #11069 and after reading the whole issue comments here I currently have no idea which behavior in which situations is wanted. Therefore here some questions – some suggestions are already mentioned above by different users, but nothing is fixed:

Headlines:

H, Shift+H, 1 to 6 and Shift+1 to Shift+6 jump in NVDA 2019.2.1 between h1 and h6 headlines. The numbers skips headlines on other headline levels.

  1. Should this behavior be changed for H and Shift+H?
  2. Should we add an option to stop jumping when skipping a headline on a different headline level?
  3. If so, which speech, braille and beep feedback is wanted before an additional press of 1 to 6 and Shit+1 to Shift+6 is performed to reach the next respectively the previous headline in the same headline level?

Lists:

L, Shift+L, I and Shift+I are using in NVDA 2019.2.1 to jump between lists and list items. Shift+Comma and Comma are used to jump to the beginning of a container (in this case a list) and outside of the current container in top-bottom-order.

  1. Is a list level feedback like I described here wanted?
  2. Should the behavior of Comma and Shift+Comma be changed?
  3. Should the behavior of L and Shift+L be changed to the one which is currently used for 1 to 6 and Shift+1 to Shift+6 – skipping lists which aren't on the same list level?
  4. If so, which speech, braille and beep feedback is wanted before an additional press of l and Shit+L is performed to reach the next respectively the previous list in the same list level?
  5. Same question like No. 6 but for I and Shift+I.
  6. If so, which speech, braille and beep feedback is wanted before an additional press of l and Shit+I is performed to reach the next respectively the previous list item in the same list level?

General questions:

  1. Which behaviors should be defined as default?
  2. Which behaviors should be make configurable by the end user?
  3. Should the end user have the option to set up speech, braille and beep feedback for which kind of feedback separately?

Notes:

Adriani90 commented 4 years ago

@DrSooom I respectfully disagree with this approach. This makes things much too complicated. An enduser will know automatically when pressing 1, 2 or 3 or shift+1, +2or +3 between which heading levels NVDA will jump. We do not need extranious feedback here and it is clear that pressing 2 twice will skip all the other higher or lower heading levels as before. I would not change the behavior of h and shift+h, this is consistent with all other quick navigation keys and this should be definitely stay as is.

Regarding lists, I would recomment a similar approach like we already have for headings. For example nvda+shift+l could change numbers navigation from heading levels to list levels, nvda+shift+h would change the behavior of pressing numbers in browse mode from list levels back to heading levels. This is much simpler and would not overwelm anyone.

Another alternative would be to assign ctrl+numbers and ctrl+shift+ numbers to list level navigation but the key strokes are not very confortable for people with motoric disabilities.

To be honnest, I don't see a use case for which it would be useful to limit the navigation to current list. Lists are usually not that huge compared to tables for example. cc: @feerrenrut

feerrenrut commented 4 years ago

Sorry @DrSooom but this doesn't really help. This only makes this issue more uncertain, when it was basically all but agreed upon

I don't see a use case for which it would be useful to limit the navigation to current list.

@Adriani90 the reason this is important is that (good) lists and headings are often highly contextual and hierarchical. The information in sub-elements relate to the parent. In my opinion this should go further than just limiting to the list, it should limit to siblings at the current level. A good description of why is given by @JulienCochuyt in https://github.com/nvaccess/nvda/issues/8193#issuecomment-547623386

My preference is to make the UI very simple:

The goal: navigate hierarchical information structures where context is important.

I would prefer to avoid another conversation about which shortcut to use, let's first agree on the behavior. A PR can introduce the command with no default gesture. If we can get agreement on a default gesture, then a subsequent PR can assign that.

DrSooom commented 4 years ago

Another suggestion:

Notes: