Bug 1869092 - Fix timeouts in browser_PanelMultiView.js. r=twisniewski,test-only
[gecko.git] / accessible / mac / mozActionElements.mm
blobf39f2c8ad5cd7353688f64882f2ec3d45d70d080
1 /* clang-format off */
2 /* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 /* clang-format on */
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/. */
8 #import "mozActionElements.h"
10 #import "MacUtils.h"
11 #include "LocalAccessible-inl.h"
12 #include "DocAccessible.h"
13 #include "XULTabAccessible.h"
14 #include "HTMLFormControlAccessible.h"
16 #include "nsCocoaUtils.h"
17 #include "mozilla/FloatingPoint.h"
19 using namespace mozilla::a11y;
21 @implementation mozButtonAccessible
23 - (NSNumber*)moxHasPopup {
24   return @([self stateWithMask:states::HASPOPUP] != 0);
27 - (NSString*)moxPopupValue {
28   if ([self stateWithMask:states::HASPOPUP] != 0) {
29     return utils::GetAccAttr(self, nsGkAtoms::aria_haspopup);
30   }
32   return nil;
35 @end
37 @implementation mozPopupButtonAccessible
39 - (NSString*)moxTitle {
40   // Popup buttons don't have titles.
41   return @"";
44 - (BOOL)moxBlockSelector:(SEL)selector {
45   if (selector == @selector(moxHasPopup)) {
46     return YES;
47   }
49   return [super moxBlockSelector:selector];
52 - (NSArray*)moxChildren {
53   if ([self stateWithMask:states::EXPANDED] == 0) {
54     // If the popup button is collapsed don't return its children.
55     return @[];
56   }
58   return [super moxChildren];
61 - (void)stateChanged:(uint64_t)state isEnabled:(BOOL)enabled {
62   [super stateChanged:state isEnabled:enabled];
64   if (state == states::EXPANDED) {
65     // If the EXPANDED state is updated, fire AXMenu events on the
66     // popups child which is the actual menu.
67     if (mozAccessible* popup = (mozAccessible*)[self childAt:0]) {
68       [popup moxPostNotification:(enabled ? @"AXMenuOpened" : @"AXMenuClosed")];
69     }
70   }
73 @end
75 @implementation mozRadioButtonAccessible
77 - (NSArray*)moxLinkedUIElements {
78   return [[self getRelationsByType:RelationType::MEMBER_OF]
79       arrayByAddingObjectsFromArray:[super moxLinkedUIElements]];
82 @end
84 @implementation mozCheckboxAccessible
86 - (int)isChecked {
87   // check if we're checked or in a mixed state
88   uint64_t state =
89       [self stateWithMask:(states::CHECKED | states::PRESSED | states::MIXED)];
90   if (state & (states::CHECKED | states::PRESSED)) {
91     return kChecked;
92   }
94   if (state & states::MIXED) {
95     return kMixed;
96   }
98   return kUnchecked;
101 - (id)moxValue {
102   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
104   return [NSNumber numberWithInt:[self isChecked]];
106   NS_OBJC_END_TRY_BLOCK_RETURN(nil);
109 - (void)stateChanged:(uint64_t)state isEnabled:(BOOL)enabled {
110   [super stateChanged:state isEnabled:enabled];
112   if (state & (states::CHECKED | states::PRESSED | states::MIXED)) {
113     [self moxPostNotification:NSAccessibilityValueChangedNotification];
114   }
117 @end
119 @implementation mozPaneAccessible
121 - (NSArray*)moxChildren {
122   // By default, all tab panels are exposed in the a11y tree
123   // even if the tab they represent isn't the active tab. To
124   // prevent VoiceOver from navigating background tab content,
125   // only expose the tab panel that is currently on screen.
126   for (mozAccessible* child in [super moxChildren]) {
127     if (!([child state] & states::OFFSCREEN)) {
128       return [NSArray arrayWithObject:GetObjectOrRepresentedView(child)];
129     }
130   }
131   MOZ_ASSERT_UNREACHABLE("We have no on screen tab content?");
132   return @[];
135 @end
137 @implementation mozIncrementableAccessible
139 - (id)moxValue {
140   return [NSNumber numberWithDouble:mGeckoAccessible->CurValue()];
143 - (NSString*)moxValueDescription {
144   nsAutoString valueDesc;
145   mGeckoAccessible->Value(valueDesc);
146   return nsCocoaUtils::ToNSString(valueDesc);
148 - (id)moxMinValue {
149   return [NSNumber numberWithDouble:mGeckoAccessible->MinValue()];
152 - (id)moxMaxValue {
153   return [NSNumber numberWithDouble:mGeckoAccessible->MaxValue()];
156 - (void)moxSetValue:(id)value {
157   [self setValue:([value doubleValue])];
160 - (void)moxPerformIncrement {
161   [self changeValueBySteps:1];
164 - (void)moxPerformDecrement {
165   [self changeValueBySteps:-1];
168 - (NSString*)moxOrientation {
169   RefPtr<AccAttributes> attributes = mGeckoAccessible->Attributes();
170   if (attributes) {
171     nsAutoString result;
172     attributes->GetAttribute(nsGkAtoms::aria_orientation, result);
173     if (result.Equals(u"horizontal"_ns)) {
174       return NSAccessibilityHorizontalOrientationValue;
175     } else if (result.Equals(u"vertical"_ns)) {
176       return NSAccessibilityVerticalOrientationValue;
177     }
178   }
180   return NSAccessibilityUnknownOrientationValue;
183 - (void)handleAccessibleEvent:(uint32_t)eventType {
184   switch (eventType) {
185     case nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE:
186     case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
187       [self moxPostNotification:NSAccessibilityValueChangedNotification];
188       break;
189     default:
190       [super handleAccessibleEvent:eventType];
191       break;
192   }
196  * Updates the accessible's current value by factor and step.
198  * factor: A signed integer representing the number of times to
199  *    apply step to the current value. A positive value will increment,
200  *    while a negative one will decrement.
201  * step: An unsigned integer specified by the webauthor and indicating the
202  *    amount by which to increment/decrement the current value.
203  */
204 - (void)changeValueBySteps:(int)factor {
205   MOZ_ASSERT(mGeckoAccessible, "mGeckoAccessible is null");
207   double newValue =
208       mGeckoAccessible->CurValue() + (mGeckoAccessible->Step() * factor);
209   [self setValue:(newValue)];
213  * Updates the accessible's current value to the specified value
214  */
215 - (void)setValue:(double)value {
216   MOZ_ASSERT(mGeckoAccessible, "mGeckoAccessible is null");
217   mGeckoAccessible->SetCurValue(value);
220 @end
222 @implementation mozDatePickerAccessible
224 - (NSString*)moxTitle {
225   return utils::LocalizedString(u"dateField"_ns);
228 @end