dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.1k stars 1.17k forks source link

[Proposal] Allow focus on disabled controls #7749

Open batzen opened 1 year ago

batzen commented 1 year ago

Problem

I always wondered, and was recently remembered by it again in https://github.com/fluentribbon/Fluent.Ribbon/issues/1121 by @cbra-caa, why focus on disabled controls is completely blocked. IMHO this reduces accessibility as people with disabilities are completely blocked from accessing disabled controls using the keyboard.

Proposal

I propose that we, optionally, allow focus on disabled controls. That way application developers could add accessibility options to their applications to allow focus on disabled controls.

Implementation

To implement this we could add a new property like FocusableWhenNotEnabled which would unblock focus on disabled controls.

I will give this a try and create a PR in the near future to explore which areas of WPF would have to be modified to make this possible.

If anyone has suggestions, concerns or any other kind of feedback regarding this i would be happy to hear from you.

Symbai commented 1 year ago

IMHO this reduces accessibility as people with disabilities are completely blocked from accessing disabled controls using the keyboard.

Can you tell us the reason WHY they need accessing disabling controls? The reason to disable a control is to prevent end user doing anything with it. It allows to skip controls using the keyboard navigation. This is often a wanted behavior on form pages. So quite the opposite of what you want. I'm aware you want an optional flag and not a breaking change, still I am trying to explain WHY focus is blocked. A question you've asked. Now you would need to explain WHY focus shouldn't be blocked. Whats the benefit? And why is making a control readonly for example not a suitable solution for such a special use case?

miloush commented 1 year ago

I am not categorically against exploring this idea from technical point of view but I would like to hear from people with disabilities that this is actually an issue or that the proposed solution would be an improvement. And if this was the case, then perhaps this should go even higher than WPF - Windows, or have an accessibility standard updated. There is enough of people with disabilities that we don't need to be basing these decisions on "IMHO".

With that said, I am afraid this would be a bit more complex task than you suggest, it's not only about enabling focus on disabled controls, it is retemplating everything for this state. You would suddenly have a new state possible (disabled+focused) and then 3rd party controls might not get updated and then it will be a mess on a window...

batzen commented 1 year ago

Can you tell us the reason WHY they need accessing disabling controls? The reason to disable a control is to prevent end user doing anything with it. It allows to skip controls using the keyboard navigation. This is often a wanted behavior on form pages. So quite the opposite of what you want. I'm aware you want an optional flag and not a breaking change, still I am trying to explain WHY focus is blocked. A question you've asked. Now you would need to explain WHY focus shouldn't be blocked. Whats the benefit? And why is making a control readonly for example not a suitable solution for such a special use case?

Yes, IsReadOnly could be used for some controls, but only for some. Things like CheckBox, ToggleButton, RadioButton, ListBox etc. don't have that property which makes it impossible to reach such controls with the keyboard. It's all about being able to discover/reach something. Question for you: How is a blind person supposed to even know a control exists if there is no way to reach it?

And yes, i am totally aware that some screen readers have a mode that allows you to traverse the automation tree, but that has to be turned on explicitly and you have to know that there is something you can't reach.

And if this was the case, then perhaps this should go even higher than WPF - Windows, or have an accessibility standard updated.

I guess that ship has already sailed, as, and that might catch you by surprise (as it did for me), newer Office versions allow focus on disabled controls.

With that said, I am afraid this would be a bit more complex task than you suggest, it's not only about enabling focus on disabled controls, it is retemplating everything for this state. You would suddenly have a new state possible (disabled+focused) and then 3rd party controls might not get updated and then it will be a mess on a window...

It would require work, but not for everything, not for everyone and not all of a sudden, but only if the developer decides to enable the feature for certain things. That's still way better than completely blocking the focus at the framework level.

Symbai commented 1 year ago

Question for you: How is a blind person supposed to even know a control exists if there is no way to reach it?

You wrote "keyboard navigation". How is a blind person supposed to know a control exist only by keyboard navigating to it? I thought they use screen readers. Do screen readers skip disabled controls (honest question, I never used them)? And what do screen readers do when they read out a disabled control, do they mention its disabled? Whats the benefit of a (blind) person knowing something exist but this person cannot use it?

We're speaking about an edge case scenario already. I am just trying to find out how edge case it really is. It sounds like that if it is really needed, it can be workaround somehow. For example by enabling a mode for handicapped people which shows a textblock next to these controls which can be read by screen readers. You said it yourself, you want an opt in. Which means the developers must know they have users like that and they must be willing to support them. Even if this isn't the ideal solution where it only takes flipping a switch, it could still be a solution.

batzen commented 1 year ago

I assumed you knew how screen readers work, sorry.

Screen readers mostly, not only but most of the time, work by tracking the focus. If something can't receive focus it's "invisible" for the user (if the user is completely blind). Let's assume a completely blind person for the remaining explanation, for simplicity.

So to discover what the current screen contains the user tabs through the UI. Things that can't be focused are invisible. This includes TextBlock, which by default is not focusable.

How is a blind person supposed to know a control exist only by keyboard navigating to it?

Well that's the way it is. They have to tab through. What should the alternative be? Some screen readers have the ability to enter a special mode that allows discovery of non focusable controls, but it just traverses the automation tree instead of the visual tree and that returns way more controls than needed. For example Label, nested controls etc.. Whereas without that mode there is no need to read out labels as controls already should have information providing a sensible name to the screen reader (most likely the label).

Do screen readers skip disabled controls (honest question, I never used them)?

Yes they do. If they didn't skip them, we wouldn't have this conversation. ;-)

And what do screen readers do when they read out a disabled control, do they mention its disabled?

Disabled state is announced by the screen reader.

Whats the benefit of a (blind) person knowing something exist but this person cannot use it?

It can be read to them. And they know it exists. For example a button that is disabled still can provide information on the reason why it's disabled like "Save is not available as you don't have the required permissions."

We're speaking about an edge case scenario already.

Uh.

For example by enabling a mode for handicapped people which shows a textblock next to these controls which can be read by screen readers.

That requires much more work when developing the application as you have to take it into account in your whole layout and duplicate everything as a TextBlock. Developing accessible applications is already quite expensive and requires a lot of thought and work.

IMHO it feels quite strange to me that you admit to have zero knowledge about screen readers and accessibility and yet oppose a proposal to ease development for increased accessibility, by arguing that it's just an edge case. Please don't take this personally, it just feels strange.

Symbai commented 1 year ago

yet oppose a proposal to ease development for increased accessibility, by arguing that it's just an edge case.

I never opposed this proposal. I only asked questions. It is a fact that its an edge case scenario when we talk about handicapped people because they are a minority, its not an argument. And that you mention its quite expensive and requires a lot of additional work just underlines the statement. It is only you who put "edge case scenario" on the same level as "not important", I never said that and I never meant that. I am just trying to understand why you want something that sounds like it can be workaround. Because then I and others can understand if there is really a problem and how important this problem actually is. If there isn't a workaround, it is a problem and a huge one. If it can be workaround with a moderate amount of work, it is a problem but a small one and so on. This is important because there are A LOT of other important things, A LOT developers are waiting for already. Things where they cannot use workarounds.

batzen commented 1 year ago

So your point is NOTHING should be fixed/improved as long as there is a workaround?

Symbai commented 1 year ago

I have not said anything like that. Actually I said quite the opposite of it, for example in the following line:

If it can be workaround with a moderate amount of work, it is a problem but a small one and so on.

When its a problem it must be fixed, I thought that this logical step doesn't have to mentioned. But problems here on github are categorized based on their priority, common standard. And issues where workaround exists have lower priority (which I meant with small problem) than issues which don't have workarounds, also a common standard. There are of course also other factors which effects the priority. Which I only mention before there is another misinterpretation of my lines by trying to read things out I haven't said.

lindexi commented 1 year ago

@batzen I agree with your point of view, because I think focusable and control's disable state can be two independent states.

cbra-caa commented 1 year ago

Just to add my perspective to this, as I do not see it as an edge case:

We need to make the controls accessible for keyboard focus, even when they are disabled, otherwise the mental map of the application changes every time a CanExecute is switched. Imagine working in a program where every time you make a new selection, buttons 'randomly' appear/disappear, it makes creating a mental map of related actions almost impossible. And this is not only for the sake of the blind. People with sight-problems will still see the program but might opt to use a screen reader to assist in them in reading information from controls. In this case they can still make out the button, and where they are, but will be unable to step into it. The same problem exists for people who might have impaired motor skills, causing them to not reliably be able use the mouse, thus needing to navigate with the keyboard. For these the tooltip will be blocked - which is not the case for people using the mouse.

The guiding principle for accessibility development is that all users should have the same options regardless of what interaction scheme they are using. https://www.w3.org/WAI/WCAG22/Understanding/compatible.html

The main problem right now is that the pattern for developing accessible applications is to utilize the AutomationPeer framework. So any solution that requires us to replace one control for another, to provide a focus point for the screen reader to interact with, will be an Anti Pattern where an inappropriate peer will be returned.

As to the question of styling, currently the way Office is handling it, is having it match the 'Disabled' style with the FocusVisualStyle shown.

Finally, since this is now a feature of the Office package and the Windows explorer, it is what users will be expecting from all other products on the Windows client, thus we need to make it as available to developers as possible. https://www.microsoft.com/en/trust-center/compliance/accessibility#accessibility

batzen commented 1 year ago

The proposal and the draft implementation in the PR are about an optional setting, which breaking changes does that cause in any application?

So is everyone else.

That's definitely not the case as you can see the disabled controls.

There is also a significant performance penalty to doing what you are asking.

How do you come to the conclusion that checking an additional bool property has a significant impact on performance?

batzen commented 1 year ago

Someone else has already explained that this would cause new states that need to be handled, among other things, you seem to just being ignoring their input.

I never pretended there weren't any new states. But every app could decide, on a per control or even per control instance basis, if it wants to allow the new state.

batzen commented 1 year ago

I hid my last two comments as HypsyNZ decided to delete his comments, thus making mine "outdated".

batzen commented 1 year ago

So if I set Focusable=false and Disabled=true what do you expect the behavior to be if you set FocusableWhenNotEnabled=true and how would you implement it.

If Focusable is false it takes precedence. That should of course made be clear in the documentation. Focusable alone already has no meaning as the control has to be visible and, currently, not be disabled.

It seems like you explicitly want to cause undefined behavior.

Of course not. Maybe you should just have a look at the PR.

batzen commented 1 year ago

You have literally just cloned the IsEnabled property and unless I am missing something this doesn't make anything focusable or change the focusable property?

It makes controls focusable that have IsEnabled=False, when they also have Focusable=True and IsVisible=True. Without proposed changes: Focusable=True, IsVisible=True, IsEnabled=True = Focus allowed Focusable=True, IsVisible=True, IsEnabled=False = Focus blocked Focusable=False, IsVisible=True, IsEnabled=True = Focus blocked Focusable=True, IsVisible=False, IsEnabled=True = Focus blocked

With proposed changes: Focusable=True, IsVisible=True, IsEnabled=True, FocusableWhenNotEnabled=False = Focus allowed Focusable=True, IsVisible=True, IsEnabled=False, FocusableWhenNotEnabled=True = Focus allowed Focusable=False, IsVisible=True, IsEnabled=True, FocusableWhenNotEnabled=True = Focus blocked Focusable=True, IsVisible=False, IsEnabled=True, FocusableWhenNotEnabled=True = Focus blocked

The meaning of neither Focusable nor IsVisible is changed. As FocusableWhenNotEnabled defaults to False there is no change in behavior for anyone not setting it to True.