diff options
Diffstat (limited to 'accessible/mac/mozActionElements.mm')
-rw-r--r-- | accessible/mac/mozActionElements.mm | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/accessible/mac/mozActionElements.mm b/accessible/mac/mozActionElements.mm new file mode 100644 index 0000000000..f39f2c8ad5 --- /dev/null +++ b/accessible/mac/mozActionElements.mm @@ -0,0 +1,228 @@ +/* clang-format off */ +/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* clang-format on */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#import "mozActionElements.h" + +#import "MacUtils.h" +#include "LocalAccessible-inl.h" +#include "DocAccessible.h" +#include "XULTabAccessible.h" +#include "HTMLFormControlAccessible.h" + +#include "nsCocoaUtils.h" +#include "mozilla/FloatingPoint.h" + +using namespace mozilla::a11y; + +@implementation mozButtonAccessible + +- (NSNumber*)moxHasPopup { + return @([self stateWithMask:states::HASPOPUP] != 0); +} + +- (NSString*)moxPopupValue { + if ([self stateWithMask:states::HASPOPUP] != 0) { + return utils::GetAccAttr(self, nsGkAtoms::aria_haspopup); + } + + return nil; +} + +@end + +@implementation mozPopupButtonAccessible + +- (NSString*)moxTitle { + // Popup buttons don't have titles. + return @""; +} + +- (BOOL)moxBlockSelector:(SEL)selector { + if (selector == @selector(moxHasPopup)) { + return YES; + } + + return [super moxBlockSelector:selector]; +} + +- (NSArray*)moxChildren { + if ([self stateWithMask:states::EXPANDED] == 0) { + // If the popup button is collapsed don't return its children. + return @[]; + } + + return [super moxChildren]; +} + +- (void)stateChanged:(uint64_t)state isEnabled:(BOOL)enabled { + [super stateChanged:state isEnabled:enabled]; + + if (state == states::EXPANDED) { + // If the EXPANDED state is updated, fire AXMenu events on the + // popups child which is the actual menu. + if (mozAccessible* popup = (mozAccessible*)[self childAt:0]) { + [popup moxPostNotification:(enabled ? @"AXMenuOpened" : @"AXMenuClosed")]; + } + } +} + +@end + +@implementation mozRadioButtonAccessible + +- (NSArray*)moxLinkedUIElements { + return [[self getRelationsByType:RelationType::MEMBER_OF] + arrayByAddingObjectsFromArray:[super moxLinkedUIElements]]; +} + +@end + +@implementation mozCheckboxAccessible + +- (int)isChecked { + // check if we're checked or in a mixed state + uint64_t state = + [self stateWithMask:(states::CHECKED | states::PRESSED | states::MIXED)]; + if (state & (states::CHECKED | states::PRESSED)) { + return kChecked; + } + + if (state & states::MIXED) { + return kMixed; + } + + return kUnchecked; +} + +- (id)moxValue { + NS_OBJC_BEGIN_TRY_BLOCK_RETURN; + + return [NSNumber numberWithInt:[self isChecked]]; + + NS_OBJC_END_TRY_BLOCK_RETURN(nil); +} + +- (void)stateChanged:(uint64_t)state isEnabled:(BOOL)enabled { + [super stateChanged:state isEnabled:enabled]; + + if (state & (states::CHECKED | states::PRESSED | states::MIXED)) { + [self moxPostNotification:NSAccessibilityValueChangedNotification]; + } +} + +@end + +@implementation mozPaneAccessible + +- (NSArray*)moxChildren { + // By default, all tab panels are exposed in the a11y tree + // even if the tab they represent isn't the active tab. To + // prevent VoiceOver from navigating background tab content, + // only expose the tab panel that is currently on screen. + for (mozAccessible* child in [super moxChildren]) { + if (!([child state] & states::OFFSCREEN)) { + return [NSArray arrayWithObject:GetObjectOrRepresentedView(child)]; + } + } + MOZ_ASSERT_UNREACHABLE("We have no on screen tab content?"); + return @[]; +} + +@end + +@implementation mozIncrementableAccessible + +- (id)moxValue { + return [NSNumber numberWithDouble:mGeckoAccessible->CurValue()]; +} + +- (NSString*)moxValueDescription { + nsAutoString valueDesc; + mGeckoAccessible->Value(valueDesc); + return nsCocoaUtils::ToNSString(valueDesc); +} +- (id)moxMinValue { + return [NSNumber numberWithDouble:mGeckoAccessible->MinValue()]; +} + +- (id)moxMaxValue { + return [NSNumber numberWithDouble:mGeckoAccessible->MaxValue()]; +} + +- (void)moxSetValue:(id)value { + [self setValue:([value doubleValue])]; +} + +- (void)moxPerformIncrement { + [self changeValueBySteps:1]; +} + +- (void)moxPerformDecrement { + [self changeValueBySteps:-1]; +} + +- (NSString*)moxOrientation { + RefPtr<AccAttributes> attributes = mGeckoAccessible->Attributes(); + if (attributes) { + nsAutoString result; + attributes->GetAttribute(nsGkAtoms::aria_orientation, result); + if (result.Equals(u"horizontal"_ns)) { + return NSAccessibilityHorizontalOrientationValue; + } else if (result.Equals(u"vertical"_ns)) { + return NSAccessibilityVerticalOrientationValue; + } + } + + return NSAccessibilityUnknownOrientationValue; +} + +- (void)handleAccessibleEvent:(uint32_t)eventType { + switch (eventType) { + case nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE: + case nsIAccessibleEvent::EVENT_VALUE_CHANGE: + [self moxPostNotification:NSAccessibilityValueChangedNotification]; + break; + default: + [super handleAccessibleEvent:eventType]; + break; + } +} + +/* + * Updates the accessible's current value by factor and step. + * + * factor: A signed integer representing the number of times to + * apply step to the current value. A positive value will increment, + * while a negative one will decrement. + * step: An unsigned integer specified by the webauthor and indicating the + * amount by which to increment/decrement the current value. + */ +- (void)changeValueBySteps:(int)factor { + MOZ_ASSERT(mGeckoAccessible, "mGeckoAccessible is null"); + + double newValue = + mGeckoAccessible->CurValue() + (mGeckoAccessible->Step() * factor); + [self setValue:(newValue)]; +} + +/* + * Updates the accessible's current value to the specified value + */ +- (void)setValue:(double)value { + MOZ_ASSERT(mGeckoAccessible, "mGeckoAccessible is null"); + mGeckoAccessible->SetCurValue(value); +} + +@end + +@implementation mozDatePickerAccessible + +- (NSString*)moxTitle { + return utils::LocalizedString(u"dateField"_ns); +} + +@end |