electron/atom/browser/mac/atom_application.mm
Ivan Mir 94dd068e15 Special attribute for macOS accessibility #7206
In the linked issue we were discussing that Electron apps are inaccessible unless VoiceOver is enabled. While it's a working solution for users with vision impairment, all other users and apps that require accessibility can't interact with Electron-based software because they don't keep VoiceOver running.

I suggest adding `AXManualAccessibility` for programmatically enabling it in Electron apps. The reason for a new attribute is that `AXEnhancedUserInterface` is already reserved by VoiceOver.

Adding this attribute will allow both Electron developers and 3rd party developers to enable and disable accessibility from their code by calling `accessibilitySetValue:forAttribute:` on the application.

It will be also possible to create a small utility app to switch accessibility in Electron-based apps until there's a native UI solution (like the accessibility settings page in Chrome).
2017-08-19 17:18:12 -03:00

97 lines
2.9 KiB
Text

// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#import "atom/browser/mac/atom_application.h"
#include "atom/browser/browser.h"
#include "base/auto_reset.h"
#include "base/strings/sys_string_conversions.h"
#include "content/public/browser/browser_accessibility_state.h"
@implementation AtomApplication
+ (AtomApplication*)sharedApplication {
return (AtomApplication*)[super sharedApplication];
}
- (BOOL)isHandlingSendEvent {
return handlingSendEvent_;
}
- (void)sendEvent:(NSEvent*)event {
base::AutoReset<BOOL> scoper(&handlingSendEvent_, YES);
[super sendEvent:event];
}
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
handlingSendEvent_ = handlingSendEvent;
}
- (void)setCurrentActivity:(NSString*)type
withUserInfo:(NSDictionary*)userInfo
withWebpageURL:(NSURL*)webpageURL {
currentActivity_ = base::scoped_nsobject<NSUserActivity>(
[[NSUserActivity alloc] initWithActivityType:type]);
[currentActivity_ setUserInfo:userInfo];
[currentActivity_ setWebpageURL:webpageURL];
[currentActivity_ becomeCurrent];
}
- (NSUserActivity*)getCurrentActivity {
return currentActivity_.get();
}
- (void)awakeFromNib {
[[NSAppleEventManager sharedAppleEventManager]
setEventHandler:self
andSelector:@selector(handleURLEvent:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
}
- (void)handleURLEvent:(NSAppleEventDescriptor*)event
withReplyEvent:(NSAppleEventDescriptor*)replyEvent {
NSString* url = [
[event paramDescriptorForKeyword:keyDirectObject] stringValue];
atom::Browser::Get()->OpenURL(base::SysNSStringToUTF8(url));
}
- (bool)voiceOverEnabled {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults addSuiteNamed:@"com.apple.universalaccess"];
[defaults synchronize];
return [defaults boolForKey:@"voiceOverOnOffKey"];
}
- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
// Undocumented attribute that VoiceOver happens to set while running.
// Chromium uses this too, even though it's not exactly right.
if ([attribute isEqualToString:@"AXEnhancedUserInterface"]) {
bool enableAccessibility = ([self voiceOverEnabled] && [value boolValue]);
[self updateAccessibilityEnabled:enableAccessibility];
}
else if ([attribute isEqualToString:@"AXManualAccessibility"]) {
[self updateAccessibilityEnabled:[value boolValue]];
}
return [super accessibilitySetValue:value forAttribute:attribute];
}
- (void)updateAccessibilityEnabled:(BOOL)enabled {
auto ax_state = content::BrowserAccessibilityState::GetInstance();
if (enabled) {
ax_state->OnScreenReaderDetected();
} else {
ax_state->DisableAccessibility();
}
atom::Browser::Get()->OnAccessibilitySupportChanged();
}
- (void)orderFrontStandardAboutPanel:(id)sender {
atom::Browser::Get()->ShowAboutPanel();
}
@end