1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/mac/mozActionElements.mm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,377 @@ 1.4 +/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#import "mozActionElements.h" 1.10 + 1.11 +#import "MacUtils.h" 1.12 +#include "Accessible-inl.h" 1.13 +#include "DocAccessible.h" 1.14 +#include "XULTabAccessible.h" 1.15 + 1.16 +#include "nsDeckFrame.h" 1.17 +#include "nsObjCExceptions.h" 1.18 + 1.19 +using namespace mozilla::a11y; 1.20 + 1.21 +enum CheckboxValue { 1.22 + // these constants correspond to the values in the OS 1.23 + kUnchecked = 0, 1.24 + kChecked = 1, 1.25 + kMixed = 2 1.26 +}; 1.27 + 1.28 +@implementation mozButtonAccessible 1.29 + 1.30 +- (NSArray*)accessibilityAttributeNames 1.31 +{ 1.32 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; 1.33 + 1.34 + static NSArray *attributes = nil; 1.35 + if (!attributes) { 1.36 + attributes = [[NSArray alloc] initWithObjects:NSAccessibilityParentAttribute, // required 1.37 + NSAccessibilityRoleAttribute, // required 1.38 + NSAccessibilityRoleDescriptionAttribute, 1.39 + NSAccessibilityPositionAttribute, // required 1.40 + NSAccessibilitySizeAttribute, // required 1.41 + NSAccessibilityWindowAttribute, // required 1.42 + NSAccessibilityPositionAttribute, // required 1.43 + NSAccessibilityTopLevelUIElementAttribute, // required 1.44 + NSAccessibilityHelpAttribute, 1.45 + NSAccessibilityEnabledAttribute, // required 1.46 + NSAccessibilityFocusedAttribute, // required 1.47 + NSAccessibilityTitleAttribute, // required 1.48 + NSAccessibilityDescriptionAttribute, 1.49 +#if DEBUG 1.50 + @"AXMozDescription", 1.51 +#endif 1.52 + nil]; 1.53 + } 1.54 + return attributes; 1.55 + 1.56 + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; 1.57 +} 1.58 + 1.59 +- (id)accessibilityAttributeValue:(NSString *)attribute 1.60 +{ 1.61 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; 1.62 + 1.63 + if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) 1.64 + return nil; 1.65 + if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) { 1.66 + if ([self isTab]) 1.67 + return utils::LocalizedString(NS_LITERAL_STRING("tab")); 1.68 + 1.69 + return NSAccessibilityRoleDescription([self role], nil); 1.70 + } 1.71 + 1.72 + return [super accessibilityAttributeValue:attribute]; 1.73 + 1.74 + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; 1.75 +} 1.76 + 1.77 +- (BOOL)accessibilityIsIgnored 1.78 +{ 1.79 + return !mGeckoAccessible; 1.80 +} 1.81 + 1.82 +- (NSArray*)accessibilityActionNames 1.83 +{ 1.84 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; 1.85 + 1.86 + if ([self isEnabled]) 1.87 + return [NSArray arrayWithObject:NSAccessibilityPressAction]; 1.88 + 1.89 + return nil; 1.90 + 1.91 + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; 1.92 +} 1.93 + 1.94 +- (NSString*)accessibilityActionDescription:(NSString*)action 1.95 +{ 1.96 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; 1.97 + 1.98 + if ([action isEqualToString:NSAccessibilityPressAction]) { 1.99 + if ([self isTab]) 1.100 + return utils::LocalizedString(NS_LITERAL_STRING("switch")); 1.101 + 1.102 + return @"press button"; // XXX: localize this later? 1.103 + } 1.104 + 1.105 + return nil; 1.106 + 1.107 + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; 1.108 +} 1.109 + 1.110 +- (void)accessibilityPerformAction:(NSString*)action 1.111 +{ 1.112 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; 1.113 + 1.114 + if ([action isEqualToString:NSAccessibilityPressAction]) 1.115 + [self click]; 1.116 + 1.117 + NS_OBJC_END_TRY_ABORT_BLOCK; 1.118 +} 1.119 + 1.120 +- (void)click 1.121 +{ 1.122 + // both buttons and checkboxes have only one action. we should really stop using arbitrary 1.123 + // arrays with actions, and define constants for these actions. 1.124 + mGeckoAccessible->DoAction(0); 1.125 +} 1.126 + 1.127 +- (BOOL)isTab 1.128 +{ 1.129 + return (mGeckoAccessible && (mGeckoAccessible->Role() == roles::PAGETAB)); 1.130 +} 1.131 + 1.132 +@end 1.133 + 1.134 +@implementation mozCheckboxAccessible 1.135 + 1.136 +- (NSString*)accessibilityActionDescription:(NSString*)action 1.137 +{ 1.138 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; 1.139 + 1.140 + if ([action isEqualToString:NSAccessibilityPressAction]) { 1.141 + if ([self isChecked] != kUnchecked) 1.142 + return @"uncheck checkbox"; // XXX: localize this later? 1.143 + 1.144 + return @"check checkbox"; // XXX: localize this later? 1.145 + } 1.146 + 1.147 + return nil; 1.148 + 1.149 + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; 1.150 +} 1.151 + 1.152 +- (int)isChecked 1.153 +{ 1.154 + uint64_t state = mGeckoAccessible->NativeState(); 1.155 + 1.156 + // check if we're checked or in a mixed state 1.157 + if (state & states::CHECKED) { 1.158 + return (state & states::MIXED) ? kMixed : kChecked; 1.159 + } 1.160 + 1.161 + return kUnchecked; 1.162 +} 1.163 + 1.164 +- (id)value 1.165 +{ 1.166 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; 1.167 + 1.168 + return [NSNumber numberWithInt:[self isChecked]]; 1.169 + 1.170 + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; 1.171 +} 1.172 + 1.173 +@end 1.174 + 1.175 +@implementation mozPopupButtonAccessible 1.176 + 1.177 +- (NSArray *)accessibilityAttributeNames 1.178 +{ 1.179 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; 1.180 + 1.181 + static NSArray *attributes = nil; 1.182 + 1.183 + if (!attributes) { 1.184 + attributes = [[NSArray alloc] initWithObjects:NSAccessibilityParentAttribute, // required 1.185 + NSAccessibilityPositionAttribute, // required 1.186 + NSAccessibilityRoleAttribute, // required 1.187 + NSAccessibilitySizeAttribute, // required 1.188 + NSAccessibilityWindowAttribute, // required 1.189 + NSAccessibilityTopLevelUIElementAttribute, // required 1.190 + NSAccessibilityHelpAttribute, 1.191 + NSAccessibilityEnabledAttribute, // required 1.192 + NSAccessibilityFocusedAttribute, // required 1.193 + NSAccessibilityTitleAttribute, // required for popupmenus, and for menubuttons with a title 1.194 + NSAccessibilityChildrenAttribute, // required 1.195 + NSAccessibilityDescriptionAttribute, // required if it has no title attr 1.196 +#if DEBUG 1.197 + @"AXMozDescription", 1.198 +#endif 1.199 + nil]; 1.200 + } 1.201 + return attributes; 1.202 + 1.203 + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; 1.204 +} 1.205 + 1.206 +- (id)accessibilityAttributeValue:(NSString *)attribute 1.207 +{ 1.208 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; 1.209 + 1.210 + if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { 1.211 + return [super children]; 1.212 + } 1.213 + return [super accessibilityAttributeValue:attribute]; 1.214 + 1.215 + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; 1.216 +} 1.217 + 1.218 +- (NSArray *)accessibilityActionNames 1.219 +{ 1.220 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; 1.221 + 1.222 + if ([self isEnabled]) { 1.223 + return [NSArray arrayWithObjects:NSAccessibilityPressAction, 1.224 + NSAccessibilityShowMenuAction, 1.225 + nil]; 1.226 + } 1.227 + return nil; 1.228 + 1.229 + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; 1.230 +} 1.231 + 1.232 +- (NSString *)accessibilityActionDescription:(NSString *)action 1.233 +{ 1.234 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; 1.235 + 1.236 + if ([action isEqualToString:NSAccessibilityShowMenuAction]) 1.237 + return @"show menu"; 1.238 + return [super accessibilityActionDescription:action]; 1.239 + 1.240 + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; 1.241 +} 1.242 + 1.243 +- (void)accessibilityPerformAction:(NSString *)action 1.244 +{ 1.245 + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; 1.246 + 1.247 + // both the ShowMenu and Click action do the same thing. 1.248 + if ([self isEnabled]) { 1.249 + // TODO: this should bring up the menu, but currently doesn't. 1.250 + // once msaa and atk have merged better, they will implement 1.251 + // the action needed to show the menu. 1.252 + [super click]; 1.253 + } 1.254 + 1.255 + NS_OBJC_END_TRY_ABORT_BLOCK; 1.256 +} 1.257 + 1.258 +@end 1.259 + 1.260 +@implementation mozTabsAccessible 1.261 + 1.262 +- (void)dealloc 1.263 +{ 1.264 + [mTabs release]; 1.265 + 1.266 + [super dealloc]; 1.267 +} 1.268 + 1.269 +- (NSArray*)accessibilityAttributeNames 1.270 +{ 1.271 + // standard attributes that are shared and supported by root accessible (AXMain) elements. 1.272 + static NSMutableArray* attributes = nil; 1.273 + 1.274 + if (!attributes) { 1.275 + attributes = [[super accessibilityAttributeNames] mutableCopy]; 1.276 + [attributes addObject:NSAccessibilityContentsAttribute]; 1.277 + [attributes addObject:NSAccessibilityTabsAttribute]; 1.278 + } 1.279 + 1.280 + return attributes; 1.281 +} 1.282 + 1.283 +- (id)accessibilityAttributeValue:(NSString *)attribute 1.284 +{ 1.285 + if ([attribute isEqualToString:NSAccessibilityContentsAttribute]) 1.286 + return [super children]; 1.287 + if ([attribute isEqualToString:NSAccessibilityTabsAttribute]) 1.288 + return [self tabs]; 1.289 + 1.290 + return [super accessibilityAttributeValue:attribute]; 1.291 +} 1.292 + 1.293 +/** 1.294 + * Returns the selected tab (the mozAccessible) 1.295 + */ 1.296 +- (id)value 1.297 +{ 1.298 + if (!mGeckoAccessible) 1.299 + return nil; 1.300 + 1.301 + Accessible* accessible = mGeckoAccessible->GetSelectedItem(0); 1.302 + if (!accessible) 1.303 + return nil; 1.304 + 1.305 + mozAccessible* nativeAcc = nil; 1.306 + nsresult rv = accessible->GetNativeInterface((void**)&nativeAcc); 1.307 + NS_ENSURE_SUCCESS(rv, nil); 1.308 + 1.309 + return nativeAcc; 1.310 +} 1.311 + 1.312 +/** 1.313 + * Return the mozAccessibles that are the tabs. 1.314 + */ 1.315 +- (id)tabs 1.316 +{ 1.317 + if (mTabs) 1.318 + return mTabs; 1.319 + 1.320 + NSArray* children = [self children]; 1.321 + NSEnumerator* enumerator = [children objectEnumerator]; 1.322 + mTabs = [[NSMutableArray alloc] init]; 1.323 + 1.324 + id obj; 1.325 + while ((obj = [enumerator nextObject])) 1.326 + if ([obj isTab]) 1.327 + [mTabs addObject:obj]; 1.328 + 1.329 + return mTabs; 1.330 +} 1.331 + 1.332 +- (void)invalidateChildren 1.333 +{ 1.334 + [super invalidateChildren]; 1.335 + 1.336 + [mTabs release]; 1.337 + mTabs = nil; 1.338 +} 1.339 + 1.340 +@end 1.341 + 1.342 +@implementation mozPaneAccessible 1.343 + 1.344 +- (NSUInteger)accessibilityArrayAttributeCount:(NSString*)attribute 1.345 +{ 1.346 + if (!mGeckoAccessible) 1.347 + return 0; 1.348 + 1.349 + // By default this calls -[[mozAccessible children] count]. 1.350 + // Since we don't cache mChildren. This is faster. 1.351 + if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) 1.352 + return mGeckoAccessible->ChildCount() ? 1 : 0; 1.353 + 1.354 + return [super accessibilityArrayAttributeCount:attribute]; 1.355 +} 1.356 + 1.357 +- (NSArray*)children 1.358 +{ 1.359 + if (!mGeckoAccessible) 1.360 + return nil; 1.361 + 1.362 + nsDeckFrame* deckFrame = do_QueryFrame(mGeckoAccessible->GetFrame()); 1.363 + nsIFrame* selectedFrame = deckFrame ? deckFrame->GetSelectedBox() : nullptr; 1.364 + 1.365 + Accessible* selectedAcc = nullptr; 1.366 + if (selectedFrame) { 1.367 + nsINode* node = selectedFrame->GetContent(); 1.368 + selectedAcc = mGeckoAccessible->Document()->GetAccessible(node); 1.369 + } 1.370 + 1.371 + if (selectedAcc) { 1.372 + mozAccessible *curNative = GetNativeFromGeckoAccessible(selectedAcc); 1.373 + if (curNative) 1.374 + return [NSArray arrayWithObjects:GetObjectOrRepresentedView(curNative), nil]; 1.375 + } 1.376 + 1.377 + return nil; 1.378 +} 1.379 + 1.380 +@end