2 /* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include "mozAccessible.h"
11 #include "LocalAccessible.h"
12 #include "DocAccessible.h"
13 #include "DocAccessibleParent.h"
14 #include "nsCocoaUtils.h"
15 #include "mozilla/a11y/PDocAccessible.h"
22 * Get a localized string from the a11y string bundle.
23 * Return nil if not found.
25 NSString* LocalizedString(const nsString& aString) {
28 Accessible::TranslateString(aString, text);
30 return text.IsEmpty() ? nil : nsCocoaUtils::ToNSString(text);
33 NSString* GetAccAttr(mozAccessible* aNativeAccessible, nsAtom* aAttrName) {
35 Accessible* acc = [aNativeAccessible geckoAccessible];
36 RefPtr<AccAttributes> attributes = acc->Attributes();
42 attributes->GetAttribute(aAttrName, result);
44 if (!result.IsEmpty()) {
45 return nsCocoaUtils::ToNSString(result);
51 bool DocumentExists(Accessible* aDoc, uintptr_t aDocPtr) {
52 if (reinterpret_cast<uintptr_t>(aDoc) == aDocPtr) {
56 if (aDoc->IsLocal()) {
57 DocAccessible* docAcc = aDoc->AsLocal()->AsDoc();
58 uint32_t docCount = docAcc->ChildDocumentCount();
59 for (uint32_t i = 0; i < docCount; i++) {
60 if (DocumentExists(docAcc->GetChildDocumentAt(i), aDocPtr)) {
65 DocAccessibleParent* docProxy = aDoc->AsRemote()->AsDoc();
66 size_t docCount = docProxy->ChildDocCount();
67 for (uint32_t i = 0; i < docCount; i++) {
68 if (DocumentExists(docProxy->ChildDocAt(i), aDocPtr)) {
77 static NSColor* ColorFromColor(const Color& aColor) {
78 return [NSColor colorWithCalibratedRed:NS_GET_R(aColor.mValue) / 255.0
79 green:NS_GET_G(aColor.mValue) / 255.0
80 blue:NS_GET_B(aColor.mValue) / 255.0
84 NSDictionary* StringAttributesFromAccAttributes(AccAttributes* aAttributes,
85 Accessible* aContainer) {
87 if (mozAccessible* mozAcc = GetNativeFromGeckoAccessible(aContainer)) {
88 // If we don't have attributes provided this is probably a control like
89 // a button or empty entry. Just provide the accessible as an
91 return @{@"AXAttachment" : mozAcc};
96 NSMutableDictionary* attrDict =
97 [NSMutableDictionary dictionaryWithCapacity:aAttributes->Count()];
98 NSMutableDictionary* fontAttrDict = [[NSMutableDictionary alloc] init];
99 [attrDict setObject:fontAttrDict forKey:@"AXFont"];
100 for (auto iter : *aAttributes) {
101 if (iter.Name() == nsGkAtoms::backgroundColor) {
102 if (Maybe<Color> value = iter.Value<Color>()) {
103 NSColor* color = ColorFromColor(*value);
104 [attrDict setObject:(__bridge id)color.CGColor
105 forKey:@"AXBackgroundColor"];
107 } else if (iter.Name() == nsGkAtoms::color) {
108 if (Maybe<Color> value = iter.Value<Color>()) {
109 NSColor* color = ColorFromColor(*value);
110 [attrDict setObject:(__bridge id)color.CGColor
111 forKey:@"AXForegroundColor"];
113 } else if (iter.Name() == nsGkAtoms::font_size) {
114 if (Maybe<FontSize> pointSize = iter.Value<FontSize>()) {
115 int32_t fontPixelSize = static_cast<int32_t>(pointSize->mValue * 4 / 3);
116 [fontAttrDict setObject:@(fontPixelSize) forKey:@"AXFontSize"];
118 } else if (iter.Name() == nsGkAtoms::font_family) {
119 nsAutoString fontFamily;
120 iter.ValueAsString(fontFamily);
121 [fontAttrDict setObject:nsCocoaUtils::ToNSString(fontFamily)
122 forKey:@"AXFontFamily"];
123 } else if (iter.Name() == nsGkAtoms::textUnderlineColor) {
124 [attrDict setObject:@1 forKey:@"AXUnderline"];
125 if (Maybe<Color> value = iter.Value<Color>()) {
126 NSColor* color = ColorFromColor(*value);
127 [attrDict setObject:(__bridge id)color.CGColor
128 forKey:@"AXUnderlineColor"];
130 } else if (iter.Name() == nsGkAtoms::invalid) {
131 // XXX: There is currently no attribute for grammar
132 if (auto value = iter.Value<RefPtr<nsAtom>>()) {
133 if (*value == nsGkAtoms::spelling) {
134 [attrDict setObject:@YES
135 forKey:NSAccessibilityMarkedMisspelledTextAttribute];
139 nsAutoString valueStr;
140 iter.ValueAsString(valueStr);
142 iter.NameAsString(keyStr);
143 [attrDict setObject:nsCocoaUtils::ToNSString(valueStr)
144 forKey:nsCocoaUtils::ToNSString(keyStr)];
148 mozAccessible* container = GetNativeFromGeckoAccessible(aContainer);
149 id<MOXAccessible> link =
150 [container moxFindAncestor:^BOOL(id<MOXAccessible> moxAcc, BOOL* stop) {
151 return [[moxAcc moxRole] isEqualToString:NSAccessibilityLinkRole];
154 [attrDict setObject:link forKey:@"AXLink"];
157 id<MOXAccessible> heading =
158 [container moxFindAncestor:^BOOL(id<MOXAccessible> moxAcc, BOOL* stop) {
159 return [[moxAcc moxRole] isEqualToString:@"AXHeading"];
162 [attrDict setObject:[heading moxValue] forKey:@"AXHeadingLevel"];
169 } // namespace mozilla