Skip to content

Implement "Symbols" accessibility rotor#1431

Closed
dusek wants to merge 1 commit intotextmate:masterfrom
dusek:accessibility-rotor-symbols
Closed

Implement "Symbols" accessibility rotor#1431
dusek wants to merge 1 commit intotextmate:masterfrom
dusek:accessibility-rotor-symbols

Conversation

@dusek
Copy link
Contributor

@dusek dusek commented Dec 25, 2018

Accessibility rotors allow VoiceOver users to navigate content quickly by making possible navigation through select elements only.

In this case, we enable VoiceOver users to navigate efficiently through symbols.

The first way to invoke a rotor is a "global" one (does not take into account current position in text) and is invoked with VO-U. After pressing arrow left/right sufficient times to reach "Symbols", one is presented with a list analogical to the "Jump to symbols" TextMate feature invokable by Shift-Cmd-T. Arrow up and down then enable navigating through items, Return selects the result (and jumps to it), Esc cancels the interface without moving the cursor. Also filtering the list works by simply typing characters (implemented as case-insensitive substring search - consistent e.g. with Safari's "Headings" rotor).

The second way to use a rotor is a "local" one (navigates w.r.t. the current position in text) and is typically done through Trackpad Commander (turned on by VO + two finger "screw" gesture to the right on the Trackpad). Then one uses two-finger "screw" gesture (like (un)screwing the bottle lid from/to the bottle with thumb and index finger) to select "Symbols". When this is finally selected (the selection is persistent), the user can then use flick with one finger up or down gestures to move to the previous/next occurrence respectively.

I made a choice at one spot - I report the "symbol location - end of hardline" as the range of the symbol (that is e.g. what VoiceOver reads when navigating the elements). This seemed to work best for the user at least in the Objective-C code.

The APIs are 10.13+ only, so appropriate avaiability declarations are put in place to not cause warnings from the compiler. I was not surewhether some declaration like that is needed also for the OakTextView's informal category's conformance to the NSAccessibilityCustomRotorItemSearchDelegate protocol - the protocol is 10.13+ only too, but the compiler does not warn about conforming to it. Perhaps the Objective-C runtime is smart enough to take into account that the NSAccessibilityCustomRotorItemSearchDelegate symbol is (hopefully) weakly-linked and adds conformance to it (I assume using the class_addProtocol function) only when it is non-nil. I have however not tested whether the compiled app actually degrades gracefully (without crashing) on macOS 10.12 and earlier, though (for starters, I seem not to have access to a macOS Sierra image to create a VM).

I release the code to the public domain.

Screenshots

"Global" rotor for "Symbols"

screenshot 2018-12-25 at 17 17 49

"Global" rotor for "Symbols" with "blink" filter applied

screenshot 2018-12-25 at 17 18 29

After selecting item in "global" rotor for "Symbols"

screenshot 2018-12-25 at 17 19 13

"Local" rotor for "Symbols" offered

screenshot 2018-12-25 at 17 16 07

Accessibility rotors allow VoiceOver user to navigate content quickly
by making possible navigation through select elements only.

In this case, we enable VoiceOver users to navigate efficiently
through symbols.

The first way to invoke a rotor is a "global" one (does not take into
account current position in text) and is invoked with VO-U. After
pressing arrow left/right sufficient times to reach "Symbols", one is
presented with a list analogical to the "Jump to symbols" TextMate
feature invokable by Shift-Cmd-T. Arrow up and down then enable
navigating through items, Return selects the result (and jumps to it),
Esc cancels the interface without moving the cursor. Also filtering
the list works by simply typing characters (implemented as
case-insensitive substring search - consistent e.g. with Safari's
"Headings" rotor).

The second way to use a rotor is a "local" one (navigates w.r.t. the
current position in text) and is typically done through Trackpad
Commander (turned on by VO + two finger "screw" gesture to the right
on the Trackpad). Then one uses two-finger "screw" gesture (like
(un)screwing the bottle lid from/to the bottle with thumb and index
finger) to select "Symbols". When this is finally selected (the
selection is persistent), the user can then use flick with one finger
up or down gestures to move to the previous/next occurrence respectively.

I made a choice at one spot - I report the "symbol location - end of
hardline" as the range of the symbol (that is e.g. what VoiceOver
reads when navigating the elements). This seemed to work best for the
user at least in the Objective-C code.

The APIs are 10.13+ only, so appropriate avaiability declarations are
put in place to not cause warnings from the compiler. I was not sure
whether some declaration like that is needed also for the
OakTextView's informal category's conformance to the
`NSAccessibilityCustomRotorItemSearchDelegate` protocol - the protocol
is 10.13+ only too, but the compiler does not warn about conforming to
it. Perhaps the Objective-C runtime is smart enough to take into
account that the `NSAccessibilityCustomRotorItemSearchDelegate` symbol
is (hopefully) weakly-linked and adds conformance to it (I assume
using the `class_addProtocol` function) only when it is non-nil. I
have however not tested whether the compiled app actually degrades
gracefully (without crashing) on macOS 10.12 and earlier, though (for
starters, I seem not to have access to a macOS Sierra image to create
a VM).
@sorbits
Copy link
Member

sorbits commented Feb 21, 2019

Merged as 85d3af9, thanks!

For me, the first symbol in the file did not show up on VO-U so I had to insert these lines to workaround the lack of being passed NSNotFound.

For the previously implemented informal accessibility methods, I believe availability macros are unnecessary because our implementation does not reference any new (10.13+) symbols, contrary to this rotor stuff that involves new API (even in the method signature).

@sorbits sorbits closed this Feb 21, 2019
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.

2 participants