Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial accessibility #576

Merged
merged 9 commits into from Jun 9, 2022
Merged

Initial accessibility #576

merged 9 commits into from Jun 9, 2022

Conversation

AZSlow3
Copy link
Contributor

@AZSlow3 AZSlow3 commented May 13, 2022

Resource file modification to make ReaLearn usable with screen readers.
(only rc file is updated, tested on Windows only)

Pre-words.
REAPER is primary DAW for visually impaired and blind musicians. But the number of accessible plug-ins and scripts is limited. Some developers support accessibility long time (Cockos), some have started to move in that direction recently (NI, iZotope, JUCE), other are "friendly", but don't have time/resources and yet there are many who simply ignore the problem.

There is (relatively) big REAPER community (RWP) which tries to improve the situation using all possible directions. I am (sighted) programmer which tries to help, with dedicated own projects (SIBIAC, AOSC), commiting to REAPER accessibility project (OSARA) and looking around what else can be done.

I am using ReaLearn myself (btw thanks!), and I think with limited effort (thanks to standard controls in UI) it is possible to make this plug-in natively accessible.
This pr is just the first step, but even that allows using the plug-in accessible way. Several more changes (in the code) are required to make the process convenient (primary fixing the order in which dynamic controls are created and explicitly moving focus in case current control is going to be disabled). If you agree, I will (slowly) move on, also I will try to find beta testers.

In case you want understand what it is all about, under Windows press Ctrl+Win+Enter to turn on Narrator. Navigate with Tab (between some controls with arrows) and listen what is reported. To press a button use Shift+Space (Space alone as you know is intercepted by REAPER). Apple also has build-in screen reader, but I don't have Apple and so I have no idea how to use it. REAPER under Linux is currently not accessible, so that platform is out of interest at the moment.

Resource file modification to make ReaLearn usable with screen readers.
(only rc file is updated, tested on Windows only)
@helgoboss
Copy link
Owner

Awesome, thanks. I still need to review the changes and see if they cause any issues, e.g. when using SWELL to make it work on macOS and Linux.

Several more changes (in the code) are required to make the process convenient (primary fixing the order in which dynamic controls are created and explicitly moving focus in case current control is going to be disabled)

ReaLearn doesn't create dynamic controls, it only shows/hides existing ones. How would this be approached?

I have forgotten shared group mapping panel.
@AZSlow3
Copy link
Contributor Author

AZSlow3 commented May 16, 2022

Once I start modifying the code, I will check SWELL is happy with the changes under Linux. Unfortunately I don't have macOS.

I better describe in details what I am doing, it is easy to break accessibility, so all GUI modifications should be done with that in mind.

  1. all sub panels should have DS_CONTROL (Misc/Control) flag set. Without it parent dialog will not include elements inside sub panel into tabstop order.
  2. all controlling widgets should have WS_TABSTOP (Misc/Tabstop) flag set OR be in a part of a group (some previous control should have WS_GROUP (Misc/Group) flag set). Group will work nicely only in case no controls in the group are consuming arrows (f.e. combo-box consumes arrows) and there is no non tabstop control in-between. I use groups at some places for buttons, to reduce the number of tabs needed to navigate throw huge number of elements. A group ends when another group starts (so, a widget with WS_GROUP flag stop current group and start new one)
  3. the order of tabstops is the order of widget creation, f.e. in rc file or sub panel insertion place (in existing list of controls).
  4. all controlling elements should have meaningful textual names or at least have to be self explaining by type after following named control (f.e. unnamed checkbox immediately after "Modifier A" combo is as good as current presentation for sighted users).
    4.1 for controls with static and not empty text, this text is used as the name. F.e. buttons and check-boxes.
    4.2 for controls with dynamic text (combo, edit, etc.) and for controls with static empty text there should be not empty label (TEXT) control immediately before.
    4.3. when (4.1) and (4.2) don't define the name (and it is not set with special accessibility API), the control is "unnamed".
    4.4 only one previous label is used for the name
    4.5 group boxes (GROUPBOX) names are announced once entered, that can be used as an addition or replacement (for 4.4). Important that box coordinates and control coordinates should overlap, group announcements are really box based (so not WS_GROUP based). F.e. I use that for "Source min/max".
    4.6 all labels (TEXT) which could not be identified as following control names are used as a (potentially lengthy) overall dialog or sub panel name. In the order these labels are defined. F.e. lower 2 labels in the main panel. I don't think that can be avoided without direct accessibility API calls (and I am even not sure that is possible at all, screen readers try to get as much as possible from "broken" from accessibility perspective applications, even when API prescribe something)
  5. in general, informational text should be edits (EDITTEXT), in tabstop order and complete text selected once focused. Even when the text is "static" (so read-only). While it is technically allowed to set WS_TABSTOP for labels, that is not working well with screen readers (and declared as a "bad style" by MS). F.e. real "Value" label for FX parameter and other places should be such (not changed yet).

So in my todo list for code changes:
a. show/hide group boxes for target, jump and step/size min/max (defined as for source min/max)
b. find the way to insert sub panels into main panel in reasonable order. Currently main panel (status and tags button), then mappings the last to the first, then header. That is not what users expect, especially reversed order of mappings.
c. find some solution for Up and Down buttons. The labels are replaced with symbols (arrows) and so these buttons get no names in screen reader. Down button is too small to fit hidden group box. Shortcuts in fact could be even more useful, but the list has no "current" element to do that. So I have no good ideas so far.
d. may be convert dynamic label in the mapping dialog to read-only edits.

Other that these relatively minor changes, everything sounds good for me. Several users have replied they are willing to test.

Spotted by SWELL under Linux
Works at Linux as intended, for some reason does not completely work on Windows. But in both cases the order is reasonable now.
@AZSlow3
Copy link
Contributor Author

AZSlow3 commented May 18, 2022

I have somehow solved tab order problem (one call is not working on Windows... but the result is still ok there).

Primary fix was in Window.move_to(). Without explicitly forbidding ZORDER change, "null" in the second parameter is interpreted as HWND_TOP, request to change tab order.

Group elements are behind sliders, included into visibility
controlling code. Tested on Windows and Linux.
This time with rc_mac_dlg and bindings generated under Linux.
@AZSlow3
Copy link
Contributor Author

AZSlow3 commented May 18, 2022

So, I will publish custom Windows build on RWP mailing list and wait reaction.
Up and Down buttons problem is still unsolved, the same for loosing focus on delete. The second can be done with existing bindings, but that will be more intrusive then current PR.
I don't think button problems can be solved without accessibility API. WDL has some code which can do the trick, but in its verbatim form it is WDL custom controls specific.

I think I am done for now, till someone spot a bug. Please check it works on MacOS when you have time. I guess some of potential users will wait at least till some pre-release is published by you.

@helgoboss
Copy link
Owner

Great PR, thanks a lot.

@helgoboss
Copy link
Owner

I just had a quick test on macOS and everything seems to work. Really nice work! I'll boot up my Windows machine later today and make a test there including the narrator. But you tested that already so I think that should be fine. So I guess we can merge this today.

@AZSlow3
Copy link
Contributor Author

AZSlow3 commented Jun 9, 2022

Please don't merge yet. There is at least one problem with panels order...

@helgoboss
Copy link
Owner

Okay.

Since in the Mapping window the focus is positioned correctly in Linux and Windows, not that I understand why, default order is working better.
@AZSlow3
Copy link
Contributor Author

AZSlow3 commented Jun 9, 2022

At least there are no known for me general problems now. The last change was just removing explicit ordering for the Mapping Header, it was bugging on Linux. I think in its current state this PR is safe for merging.

@helgoboss helgoboss merged commit 5c60461 into helgoboss:master Jun 9, 2022
@helgoboss
Copy link
Owner

Realized a bit too late that there's one issue. The source and target intervals have some second label:

image

@AZSlow3
Copy link
Contributor Author

AZSlow3 commented Jun 10, 2022

Ah... sorry. I don't have that on Windows and Linux.

The problem with original labels they are not groups. So visually they are "in the near", but screen readers are not so smart.
So I put extra "groups", which technically should be behind the control and so not visible. It seems like this trick does not work
with Mac SWELL...

There are just 2 ways to achieve good results:

  1. Make original "Source" and "Target" groups. Visual layout should be modified in this case, Windows/SWELL are not flexible in groups visualization. From my own experience I must admit at the beginning I was not sure about many controls in the Glue, I mean in which logical "group" they are. With Source Min/Max there is visually no problem, but f.e. to what "Value sequence" and "reverse" apply can be understood after reading the documentation only. So putting all controls is groups can be not bad idea even for sighted users (especially for beginners).
  2. Make accessibility specific overwrite for particular controls, so set different from the window text accessibility name explicitly. F.e. "Source min" instead of "min". That is not trivial and even if achieved will pollute the source. I guess for move mapping buttons that is the only reasonable way (till the buttons are somehow made image buttons with not shown but specified text, I have not checked yet what SWELL has for such cases).

I don't have good proposal to solve the problem without changes. Without these extra groups it will be very difficult to work accessible way. But extra labels on Mac are clear "no go". Can you check what will happened if the group is behind edit controls? it will be announced at less convenient place, but I think that still will give sufficient hint for what Min/Max in the near are.

@helgoboss
Copy link
Owner

Thanks for your suggestions. Another way would be to remove those extra groups on macOS. I'm actually just working on a little build-time helper that allows me to generate the RC file from a simplified data structure. Then it would be very easy to just not add the groups on macOS.

The reason I write this helper is that I'm not very satisfied having to use a resource editor to adjust the GUI layout. Yesterday I wanted to put all control elements a bit closer together and realized it's such tedious work if the resource editor doesn't provide specific support for it. When generating the RC file with code, this becomes trivial because one can just use variables and use scaling factors. Also it could be easier to enforce the accessibility requirements which you mentioned. It would be very easy to forget them when editing such a big dialog with a visual editor. Plus, I don't know any cross-platform resource editor.

@AZSlow3
Copy link
Contributor Author

AZSlow3 commented Jun 10, 2022

I have edited RC file as text to order things properly. Since you have controls under each other and it seems like current VS editor has no ways to order controls usable way (I mean I have not found something like Tab order Wisard in ResEdit), I think any solution will be better then VS editor...

@helgoboss
Copy link
Owner

@AZSlow3 FYI, it's done. The canonical source of truth for the dialogs is now here: https://github.com/helgoboss/realearn/blob/master/dialogs/src/lib.rs

So from now on, one needs to modify the Rust code instead of modifying the rc file directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants