From ddfd2bc4bea7d016874b8be5ebc373219c72e2c7 Mon Sep 17 00:00:00 2001 From: Theo Julienne Date: Sun, 12 Apr 2015 10:44:27 -0700 Subject: [PATCH] [mac] Dynamically enable accessibility based on VoiceOver status --- atom/browser/mac/atom_application.mm | 21 +++++++++++++++++++++ atom/browser/native_window_mac.mm | 28 ++++++++++++++++++---------- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/atom/browser/mac/atom_application.mm b/atom/browser/mac/atom_application.mm index b84121c..7d1fd53 100644 --- a/atom/browser/mac/atom_application.mm +++ b/atom/browser/mac/atom_application.mm @@ -8,6 +8,8 @@ #include "base/strings/sys_string_conversions.h" #include "atom/browser/browser.h" +#include "content/public/browser/browser_accessibility_state.h" + @implementation AtomApplication + (AtomApplication*)sharedApplication { @@ -46,4 +48,23 @@ atom::Browser::Get()->OpenURL(base::SysNSStringToUTF8(url)); } +- (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"]) { + [self updateAccessibilityEnabled:[value boolValue]]; + } + return [super accessibilitySetValue:value forAttribute:attribute]; +} + +- (void)updateAccessibilityEnabled:(BOOL)enabled { + content::BrowserAccessibilityState *ax_state = content::BrowserAccessibilityState::GetInstance(); + + if (enabled) { + ax_state->OnScreenReaderDetected(); + } else { + ax_state->DisableAccessibility(); + } +} + @end diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 2480e22..05edf17 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -15,6 +15,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/browser_accessibility_state.h" #include "native_mate/dictionary.h" #include "vendor/brightray/browser/inspectable_web_contents.h" #include "vendor/brightray/browser/inspectable_web_contents_view.h" @@ -193,17 +194,24 @@ static const CGFloat kAtomWindowCornerRadius = 4.0; shell_->OpenDevTools(true); } -// Returns an empty array for AXChildren attribute, this will force the -// SpeechSynthesisServer to use its classical way of speaking the selected text: -// by invoking the "Command+C" for current application and then speak out -// what's in the clipboard. Otherwise the "Text to Speech" would always speak -// out window's title. -// This behavior is taken by both FireFox and Chrome, see also FireFox's bug on -// more of how SpeechSynthesisServer chose which text to read: -// https://bugzilla.mozilla.org/show_bug.cgi?id=674612 - (id)accessibilityAttributeValue:(NSString*)attribute { - if ([attribute isEqualToString:@"AXChildren"]) - return [NSArray array]; + if ([attribute isEqualToString:@"AXChildren"]) { + NSArray *children = [super accessibilityAttributeValue:attribute]; + + // Filter out objects that aren't the title bar buttons. + // This has the effect of removing the window title, which VoiceOver already sees. + // * when VoiceOver is disabled, this causes Cmd+C to be used for TTS but still + // leaves the buttons available in the accessibility tree. + // * when VoiceOver is enabled, the full accessibility tree is used. + // Without removing the title and with VO disabled, the TTS would always read the + // window title instead of using Cmd+C to get the selected text. + NSPredicate *predicate = [NSPredicate predicateWithFormat: + @"(self isKindOfClass: %@) OR (self.className == %@)", + [NSButtonCell class], @"RenderWidgetHostViewCocoa"]; + + return [children filteredArrayUsingPredicate:predicate]; + } + return [super accessibilityAttributeValue:attribute]; } -- 2.7.4