diff --git a/atom/browser/api/atom_api_app.cc b/atom/browser/api/atom_api_app.cc index 41098f82e444..6e28530c3d95 100644 --- a/atom/browser/api/atom_api_app.cc +++ b/atom/browser/api/atom_api_app.cc @@ -873,6 +873,18 @@ bool App::IsAccessibilitySupportEnabled() { return ax_state->IsAccessibleBrowser(); } +void App::SetAccessibilitySupportEnabled(bool enabled) { + auto ax_state = content::BrowserAccessibilityState::GetInstance(); + + if (enabled) { + ax_state->OnScreenReaderDetected(); + } else { + ax_state->DisableAccessibility(); + } + + Browser::Get()->OnAccessibilitySupportChanged(); +} + Browser::LoginItemSettings App::GetLoginItemSettings(mate::Arguments* args) { Browser::LoginItemSettings options; args->GetNext(&options); @@ -1155,6 +1167,8 @@ void App::BuildPrototype( .SetMethod("relaunch", &App::Relaunch) .SetMethod("isAccessibilitySupportEnabled", &App::IsAccessibilitySupportEnabled) + .SetMethod("setAccessibilitySupportEnabled", + &App::SetAccessibilitySupportEnabled) .SetMethod("disableHardwareAcceleration", &App::DisableHardwareAcceleration) .SetMethod("disableDomainBlockingFor3DAPIs", diff --git a/atom/browser/api/atom_api_app.h b/atom/browser/api/atom_api_app.h index ce5d108e9786..05b304c9bfd5 100644 --- a/atom/browser/api/atom_api_app.h +++ b/atom/browser/api/atom_api_app.h @@ -171,6 +171,7 @@ class App : public AtomBrowserClient::Delegate, void DisableHardwareAcceleration(mate::Arguments* args); void DisableDomainBlockingFor3DAPIs(mate::Arguments* args); bool IsAccessibilitySupportEnabled(); + void SetAccessibilitySupportEnabled(bool enabled); Browser::LoginItemSettings GetLoginItemSettings(mate::Arguments* args); #if defined(USE_NSS_CERTS) void ImportCertificate(const base::DictionaryValue& options, diff --git a/atom/browser/mac/atom_application.mm b/atom/browser/mac/atom_application.mm index 4a0e18401664..52975e30c7a8 100644 --- a/atom/browser/mac/atom_application.mm +++ b/atom/browser/mac/atom_application.mm @@ -72,6 +72,9 @@ bool enableAccessibility = ([self voiceOverEnabled] && [value boolValue]); [self updateAccessibilityEnabled:enableAccessibility]; } + else if ([attribute isEqualToString:@"AXManualAccessibility"]) { + [self updateAccessibilityEnabled:[value boolValue]]; + } return [super accessibilitySetValue:value forAttribute:attribute]; } diff --git a/docs/api/app.md b/docs/api/app.md index 0fed6e5dacd1..298e2af811f7 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -890,6 +890,15 @@ technologies, such as screen readers, has been detected. See https://www.chromium.org/developers/design-documents/accessibility for more details. +### `app.setAccessibilitySupportEnabled(enabled)` _macOS_ _Windows_ + +* `enabled` Boolean - Enable or disable [accessibility tree](https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/the-accessibility-tree) rendering + +Manually enables Chrome's accessibility support, allowing to expose accessibility switch to users in application settings. https://www.chromium.org/developers/design-documents/accessibility for more +details. Disabled by default. + +**Note:** Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default. + ### `app.setAboutPanelOptions(options)` _macOS_ * `options` Object diff --git a/docs/tutorial/accessibility.md b/docs/tutorial/accessibility.md index d256ff5567d5..d2b6099bba54 100644 --- a/docs/tutorial/accessibility.md +++ b/docs/tutorial/accessibility.md @@ -8,7 +8,7 @@ Accessibility concerns in Electron applications are similar to those of websites These new features bring those auditing tools to your Electron app. You can choose to add audits to your tests with Spectron or use them within DevTools with Devtron. Read on for a summary of the tools or checkout our [accessibility documentation](https://electron.atom.io/docs/tutorial/accessibility) for more information. -### Spectron +## Spectron In the testing framework Spectron, you can now audit each window and `` tag in your application. For example: @@ -22,7 +22,7 @@ app.client.auditAccessibility().then(function (audit) { You can read more about this feature in [Spectron's documentation](https://github.com/electron/spectron#accessibility-testing). -### Devtron +## Devtron In Devtron, there is a new accessibility tab which will allow you to audit a page in your app, sort and filter the results. @@ -31,3 +31,32 @@ In Devtron, there is a new accessibility tab which will allow you to audit a pag Both of these tools are using the [Accessibility Developer Tools](https://github.com/GoogleChrome/accessibility-developer-tools) library built by Google for Chrome. You can learn more about the accessibility audit rules this library uses on that [repository's wiki](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules). If you know of other great accessibility tools for Electron, add them to the [accessibility documentation](https://electron.atom.io/docs/tutorial/accessibility) with a pull request. + +## Enabling Accessibility + +Electron applications keep accessibility disabled by default for performance reasons but there are multiple ways to enable it. + +### Inside Application + +By using [`app.setAccessibilitySupportEnabled(enabled)`](https://electron.atom.io/docs/api/app.md#appsetaccessibilitysupportenabledenabled-macos-windows), you can expose accessibility switch to users in the application preferences. User's system assistive utilities have priority over this setting and will override it. + +### Assistive Technology + +Electron application will enable accessibility automatically when it detects assistive technology (Windows) or VoiceOver (macOS). See Chrome's [accessibility documentation](https://www.chromium.org/developers/design-documents/accessibility#TOC-How-Chrome-detects-the-presence-of-Assistive-Technology) for more details. + +On macOS, thrid-party assistive technology can switch accessibility inside Electron applications by setting the attribute `AXManualAccessibility` programmatically: + +```objc +CFStringRef kAXManualAccessibility = CFSTR("AXManualAccessibility"); + ++ (void)enableAccessibility:(BOOL)enable inElectronApplication:(NSRunningApplication *)app +{ + AXUIElementRef appRef = AXUIElementCreateApplication(app.processIdentifier); + if (appRef == nil) + return; + + CFBooleanRef value = enable ? kCFBooleanTrue : kCFBooleanFalse; + AXUIElementSetAttributeValue(appRef, kAXManualAccessibility, value); + CFRelease(appRef); +} +```