|
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2022 - Raw Material Software Limited
-
- JUCE is an open source library subject to commercial or open-source
- licensing.
-
- By using JUCE, you agree to the terms of both the JUCE 7 End-User License
- Agreement and JUCE Privacy Policy.
-
- End User License Agreement: www.juce.com/juce-7-licence
- Privacy Policy: www.juce.com/juce-privacy-policy
-
- Or: You may also use this code under the terms of the GPL v3 (see
- www.gnu.org/licenses).
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- static void juceFreeAccessibilityPlatformSpecificData (UIAccessibilityElement* element)
- {
- if (auto* container = juce::getIvar<UIAccessibilityElement*> (element, "container"))
- {
- object_setInstanceVariable (element, "container", nullptr);
- object_setInstanceVariable (container, "handler", nullptr);
-
- [container release];
- }
- }
-
- namespace juce
- {
-
- #define JUCE_NATIVE_ACCESSIBILITY_INCLUDED 1
-
- template <typename> struct Signature;
-
- template <typename Result, typename... Args>
- struct Signature<Result (Args...)> {};
-
- // @selector isn't constexpr, so the 'sel' members are functions rather than static constexpr data members
- struct SignatureHasText : Signature<BOOL()> { static auto sel() { return @selector (hasText); } };
- struct SignatureSetSelectedTextRange : Signature<void (UITextRange*)> { static auto sel() { return @selector (setSelectedTextRange:); } };
- struct SignatureSelectedTextRange : Signature<UITextRange*()> { static auto sel() { return @selector (selectedTextRange); } };
- struct SignatureMarkedTextRange : Signature<UITextRange*()> { static auto sel() { return @selector (markedTextRange); } };
- struct SignatureSetMarkedTextSelectedRange : Signature<void (NSString*, NSRange)> { static auto sel() { return @selector (setMarkedText:selectedRange:); } };
- struct SignatureUnmarkText : Signature<void()> { static auto sel() { return @selector (unmarkText); } };
- struct SignatureMarkedTextStyle : Signature<NSDictionary<NSAttributedStringKey, id>*()> { static auto sel() { return @selector (markedTextStyle); } };
- struct SignatureSetMarkedTextStyle : Signature<void (NSDictionary<NSAttributedStringKey, id>*)> { static auto sel() { return @selector (setMarkedTextStyle:); } };
- struct SignatureBeginningOfDocument : Signature<UITextPosition*()> { static auto sel() { return @selector (beginningOfDocument); } };
- struct SignatureEndOfDocument : Signature<UITextPosition*()> { static auto sel() { return @selector (endOfDocument); } };
- struct SignatureTokenizer : Signature<id<UITextInputTokenizer>()> { static auto sel() { return @selector (tokenizer); } };
- struct SignatureBaseWritingDirection : Signature<NSWritingDirection (UITextPosition*, UITextStorageDirection)> { static auto sel() { return @selector (baseWritingDirectionForPosition:inDirection:); } };
- struct SignatureCaretRectForPosition : Signature<CGRect (UITextPosition*)> { static auto sel() { return @selector (caretRectForPosition:); } };
- struct SignatureCharacterRangeByExtending : Signature<UITextRange* (UITextPosition*, UITextLayoutDirection)> { static auto sel() { return @selector (characterRangeByExtendingPosition:inDirection:); } };
- struct SignatureCharacterRangeAtPoint : Signature<UITextRange* (CGPoint)> { static auto sel() { return @selector (characterRangeAtPoint:); } };
- struct SignatureClosestPositionToPoint : Signature<UITextPosition* (CGPoint)> { static auto sel() { return @selector (closestPositionToPoint:); } };
- struct SignatureClosestPositionToPointInRange : Signature<UITextPosition* (CGPoint, UITextRange*)> { static auto sel() { return @selector (closestPositionToPoint:withinRange:); } };
- struct SignatureComparePositionToPosition : Signature<NSComparisonResult (UITextPosition*, UITextPosition*)> { static auto sel() { return @selector (comparePosition:toPosition:); } };
- struct SignatureOffsetFromPositionToPosition : Signature<NSInteger (UITextPosition*, UITextPosition*)> { static auto sel() { return @selector (offsetFromPosition:toPosition:); } };
- struct SignaturePositionFromPositionInDirection : Signature<UITextPosition* (UITextPosition*, UITextLayoutDirection, NSInteger)> { static auto sel() { return @selector (positionFromPosition:inDirection:offset:); } };
- struct SignaturePositionFromPositionOffset : Signature<UITextPosition* (UITextPosition*, NSInteger)> { static auto sel() { return @selector (positionFromPosition:offset:); } };
- struct SignatureFirstRectForRange : Signature<CGRect (UITextRange*)> { static auto sel() { return @selector (firstRectForRange:); } };
- struct SignatureSelectionRectsForRange : Signature<NSArray<UITextSelectionRect*>* (UITextRange*)> { static auto sel() { return @selector (selectionRectsForRange:); } };
- struct SignaturePositionWithinRange : Signature<UITextPosition* (UITextRange*, UITextLayoutDirection)> { static auto sel() { return @selector (positionWithinRange:farthestInDirection:); } };
- struct SignatureReplaceRangeWithText : Signature<void (UITextRange*, NSString*)> { static auto sel() { return @selector (replaceRange:withText:); } };
- struct SignatureSetBaseWritingDirection : Signature<void (NSWritingDirection, UITextRange*)> { static auto sel() { return @selector (setBaseWritingDirection:forRange:); } };
- struct SignatureTextInRange : Signature<NSString* (UITextRange*)> { static auto sel() { return @selector (textInRange:); } };
- struct SignatureTextRangeFromPosition : Signature<UITextRange* (UITextPosition*, UITextPosition*)> { static auto sel() { return @selector (textRangeFromPosition:toPosition:); } };
- struct SignatureSetInputDelegate : Signature<void (id)> { static auto sel() { return @selector (setInputDelegate:); } };
- struct SignatureInputDelegate : Signature<id()> { static auto sel() { return @selector (inputDelegate); } };
- struct SignatureKeyboardType : Signature<UIKeyboardType()> { static auto sel() { return @selector (keyboardType); } };
- struct SignatureAutocapitalizationType : Signature<UITextAutocapitalizationType()> { static auto sel() { return @selector (autocapitalizationType); } };
- struct SignatureAutocorrectionType : Signature<UITextAutocorrectionType()> { static auto sel() { return @selector (autocorrectionType); } };
-
- //==============================================================================
- class AccessibilityHandler::AccessibilityNativeImpl
- {
- public:
- explicit AccessibilityNativeImpl (AccessibilityHandler& handler)
- : accessibilityElement (AccessibilityElement::create (handler))
- {
- }
-
- UIAccessibilityElement* getAccessibilityElement() const noexcept
- {
- return accessibilityElement.get();
- }
-
- private:
- //==============================================================================
- class AccessibilityContainer : public AccessibleObjCClass<NSObject>
- {
- public:
- AccessibilityContainer()
- : AccessibleObjCClass ("JUCEUIAccessibilityContainer_")
- {
- addMethod (@selector (isAccessibilityElement), [] (id, SEL) { return false; });
-
- addMethod (@selector (accessibilityFrame), [] (id self, SEL)
- {
- if (auto* handler = getHandler (self))
- return convertToCGRect (handler->getComponent().getScreenBounds());
-
- return CGRectZero;
- });
-
- addMethod (@selector (accessibilityElements), [] (id self, SEL) -> NSArray*
- {
- if (auto* handler = getHandler (self))
- return getContainerAccessibilityElements (*handler);
-
- return nil;
- });
-
- if (@available (iOS 11.0, *))
- {
- addMethod (@selector (accessibilityDataTableCellElementForRow:column:), [] (id self, SEL, NSUInteger row, NSUInteger column) -> id
- {
- if (auto* tableHandler = getEnclosingHandlerWithInterface (getHandler (self), &AccessibilityHandler::getTableInterface))
- if (auto* tableInterface = tableHandler->getTableInterface())
- if (auto* cellHandler = tableInterface->getCellHandler ((int) row, (int) column))
- if (auto* parent = getAccessibleParent (cellHandler))
- return static_cast<id> (parent->getNativeImplementation());
-
- return nil;
- });
-
- addMethod (@selector (accessibilityRowCount), getAccessibilityRowCount);
- addMethod (@selector (accessibilityColumnCount), getAccessibilityColumnCount);
-
- addMethod (@selector (accessibilityHeaderElementsForColumn:), [] (id self, SEL, NSUInteger column) -> NSArray*
- {
- if (auto* tableHandler = getEnclosingHandlerWithInterface (getHandler (self), &AccessibilityHandler::getTableInterface))
- {
- if (auto* tableInterface = tableHandler->getTableInterface())
- {
- if (auto* header = tableInterface->getHeaderHandler())
- {
- if (isPositiveAndBelow (column, header->getChildren().size()))
- {
- auto* result = [NSMutableArray new];
- [result addObject: static_cast<id> (header->getChildren()[(size_t) column]->getNativeImplementation())];
- return result;
- }
- }
- }
- }
-
- return nullptr;
- });
-
- addProtocol (@protocol (UIAccessibilityContainerDataTable));
-
- addMethod (@selector (accessibilityContainerType), [] (id self, SEL) -> NSInteger
- {
- if (auto* handler = getHandler (self))
- {
- if (handler->getTableInterface() != nullptr)
- {
- if (@available (iOS 11.0, *))
- return UIAccessibilityContainerTypeDataTable;
-
- return 1; // UIAccessibilityContainerTypeDataTable
- }
-
- const auto handlerRole = handler->getRole();
-
- if (handlerRole == AccessibilityRole::popupMenu
- || handlerRole == AccessibilityRole::list
- || handlerRole == AccessibilityRole::tree)
- {
- if (@available (iOS 11.0, *))
- return UIAccessibilityContainerTypeList;
-
- return 2; // UIAccessibilityContainerTypeList
- }
- }
-
- if (@available (iOS 11.0, *))
- return UIAccessibilityContainerTypeNone;
-
- return 0; // UIAccessibilityContainerTypeNone
- });
- }
-
- registerClass();
- }
-
- private:
- static const AccessibilityHandler* getAccessibleParent (const AccessibilityHandler* h)
- {
- if (h == nullptr)
- return nullptr;
-
- if ([static_cast<id> (h->getNativeImplementation()) isAccessibilityElement])
- return h;
-
- return getAccessibleParent (h->getParent());
- }
-
- static AccessibilityHandler* getHandler (id self)
- {
- return getIvar<AccessibilityHandler*> (self, "handler");
- }
- };
-
- //==============================================================================
- class AccessibilityElement : public AccessibleObjCClass<UIAccessibilityElement>
- {
- template <typename Func, typename... Items>
- static constexpr void forEach (Func&& func, Items&&... items)
- {
- (func (std::forward<Items> (items)), ...);
- }
-
- public:
- enum class Type { defaultElement, textElement };
-
- static Holder create (AccessibilityHandler& handler)
- {
- static AccessibilityElement cls { Type::defaultElement };
- static AccessibilityElement textCls { Type::textElement };
-
- id instance = (hasEditableText (handler) ? textCls : cls).createInstance();
-
- Holder element ([instance initWithAccessibilityContainer: static_cast<id> (handler.getComponent().getWindowHandle())]);
- object_setInstanceVariable (element.get(), "handler", &handler);
- return element;
- }
-
- AccessibilityElement (Type elementType)
- {
- addMethod (@selector (isAccessibilityElement), [] (id self, SEL)
- {
- auto* handler = getHandler (self);
-
- const auto hasAccessiblePropertiesOrIsTableCell = [] (auto& handlerRef)
- {
- const auto isTableCell = [&]
- {
- if (auto* tableHandler = getEnclosingHandlerWithInterface (&handlerRef, &AccessibilityHandler::getTableInterface))
- {
- if (auto* tableInterface = tableHandler->getTableInterface())
- {
- return tableInterface->getRowSpan (handlerRef).hasValue()
- && tableInterface->getColumnSpan (handlerRef).hasValue();
- }
- }
-
- return false;
- };
-
- return handlerRef.getTitle().isNotEmpty()
- || handlerRef.getHelp().isNotEmpty()
- || handlerRef.getTextInterface() != nullptr
- || handlerRef.getValueInterface() != nullptr
- || isTableCell();
- };
-
- return handler != nullptr
- && ! handler->isIgnored()
- && handler->getRole() != AccessibilityRole::window
- && hasAccessiblePropertiesOrIsTableCell (*handler);
- });
-
- addMethod (@selector (accessibilityContainer), [] (id self, SEL) -> id
- {
- if (auto* handler = getHandler (self))
- {
- if (handler->getComponent().isOnDesktop())
- return static_cast<id> (handler->getComponent().getWindowHandle());
-
- if (! handler->getChildren().empty())
- {
- if (UIAccessibilityElement* container = getContainer (self))
- return container;
-
- static AccessibilityContainer cls;
-
- id container = cls.createInstance();
-
- object_setInstanceVariable (container, "handler", handler);
- object_setInstanceVariable (self, "container", container);
-
- return container;
- }
-
- if (auto* parent = handler->getParent())
- return [static_cast<id> (parent->getNativeImplementation()) accessibilityContainer];
- }
-
- return nil;
- });
-
- addMethod (@selector (accessibilityFrame), [] (id self, SEL)
- {
- if (auto* handler = getHandler (self))
- return convertToCGRect (handler->getComponent().getScreenBounds());
-
- return CGRectZero;
- });
-
- addMethod (@selector (accessibilityTraits), [] (id self, SEL)
- {
- auto traits = UIAccessibilityTraits{};
-
- if (auto* handler = getHandler (self))
- {
- traits |= [&handler]
- {
- switch (handler->getRole())
- {
- case AccessibilityRole::button:
- case AccessibilityRole::toggleButton:
- case AccessibilityRole::radioButton:
- case AccessibilityRole::comboBox: return UIAccessibilityTraitButton;
-
- case AccessibilityRole::label:
- case AccessibilityRole::staticText: return UIAccessibilityTraitStaticText;
-
- case AccessibilityRole::image: return UIAccessibilityTraitImage;
- case AccessibilityRole::tableHeader: return UIAccessibilityTraitHeader;
- case AccessibilityRole::hyperlink: return UIAccessibilityTraitLink;
- case AccessibilityRole::ignored: return UIAccessibilityTraitNotEnabled;
-
- case AccessibilityRole::editableText: return UIAccessibilityTraitKeyboardKey;
-
- case AccessibilityRole::slider:
- case AccessibilityRole::menuItem:
- case AccessibilityRole::menuBar:
- case AccessibilityRole::popupMenu:
- case AccessibilityRole::table:
- case AccessibilityRole::column:
- case AccessibilityRole::row:
- case AccessibilityRole::cell:
- case AccessibilityRole::list:
- case AccessibilityRole::listItem:
- case AccessibilityRole::tree:
- case AccessibilityRole::treeItem:
- case AccessibilityRole::progressBar:
- case AccessibilityRole::group:
- case AccessibilityRole::dialogWindow:
- case AccessibilityRole::window:
- case AccessibilityRole::scrollBar:
- case AccessibilityRole::tooltip:
- case AccessibilityRole::splashScreen:
- case AccessibilityRole::unspecified: break;
- }
-
- return UIAccessibilityTraitNone;
- }();
-
- const auto state = handler->getCurrentState();
-
- if (state.isSelected() || state.isChecked())
- traits |= UIAccessibilityTraitSelected;
-
- if (auto* valueInterface = getValueInterface (self))
- if (! valueInterface->isReadOnly() && valueInterface->getRange().isValid())
- traits |= UIAccessibilityTraitAdjustable;
- }
-
- return traits | sendSuperclassMessage<UIAccessibilityTraits> (self, @selector (accessibilityTraits));
- });
-
- addMethod (@selector (accessibilityLabel), getAccessibilityTitle);
- addMethod (@selector (accessibilityHint), getAccessibilityHelp);
-
- addMethod (@selector (accessibilityValue), [] (id self, SEL) -> NSString*
- {
- if (auto* handler = getHandler (self))
- {
- if (handler->getCurrentState().isCheckable())
- return handler->getCurrentState().isChecked() ? @"1" : @"0";
-
- return (NSString*) getAccessibilityValueFromInterfaces (*handler);
- }
-
- return nil;
- });
-
- addMethod (@selector (setAccessibilityValue:), setAccessibilityValue);
-
- addMethod (@selector (accessibilityElementDidBecomeFocused), [] (id self, SEL)
- {
- if (auto* handler = getHandler (self))
- {
- const WeakReference<Component> safeComponent (&handler->getComponent());
-
- performActionIfSupported (self, AccessibilityActionType::focus);
-
- if (safeComponent != nullptr)
- handler->grabFocus();
- }
- });
-
- addMethod (@selector (accessibilityElementDidLoseFocus), [] (id self, SEL)
- {
- if (auto* handler = getHandler (self))
- handler->giveAwayFocus();
- });
-
- addMethod (@selector (accessibilityElementIsFocused), [] (id self, SEL) -> BOOL
- {
- if (auto* handler = getHandler (self))
- return handler->hasFocus (false);
-
- return NO;
- });
-
- addMethod (@selector (accessibilityViewIsModal), getIsAccessibilityModal);
-
- addMethod (@selector (accessibilityActivate), [] (id self, SEL)
- {
- if (auto* handler = getHandler (self))
- {
- // Occasionally VoiceOver sends accessibilityActivate to the wrong element, so we first query
- // which element it thinks has focus and forward the event on to that element if it differs
- id focusedElement = UIAccessibilityFocusedElement (UIAccessibilityNotificationVoiceOverIdentifier);
-
- if (focusedElement != nullptr && ! [static_cast<id> (handler->getNativeImplementation()) isEqual: focusedElement])
- return [focusedElement accessibilityActivate];
-
- if (handler->hasFocus (false))
- return accessibilityPerformPress (self, {});
- }
-
- return NO;
- });
-
- addMethod (@selector (accessibilityIncrement), accessibilityPerformIncrement);
- addMethod (@selector (accessibilityDecrement), accessibilityPerformDecrement);
-
- addMethod (@selector (accessibilityPerformEscape), [] (id self, SEL)
- {
- if (auto* handler = getHandler (self))
- {
- if (auto* modal = Component::getCurrentlyModalComponent())
- {
- if (auto* modalHandler = modal->getAccessibilityHandler())
- {
- if (modalHandler == handler || modalHandler->isParentOf (handler))
- {
- modal->exitModalState (0);
- return YES;
- }
- }
- }
- }
-
- return NO;
- });
-
- if (elementType == Type::textElement)
- {
- addMethod (@selector (deleteBackward), [] (id, SEL) {});
- addMethod (@selector (insertText:), [] (id, SEL, NSString*) {});
-
- forEach ([this] (auto signature) { addPassthroughMethodWithSignature (signature); },
- SignatureHasText{},
- SignatureSetSelectedTextRange{},
- SignatureSelectedTextRange{},
- SignatureMarkedTextRange{},
- SignatureSetMarkedTextSelectedRange{},
- SignatureUnmarkText{},
- SignatureMarkedTextStyle{},
- SignatureSetMarkedTextStyle{},
- SignatureBeginningOfDocument{},
- SignatureEndOfDocument{},
- SignatureTokenizer{},
- SignatureBaseWritingDirection{},
- SignatureCaretRectForPosition{},
- SignatureCharacterRangeByExtending{},
- SignatureCharacterRangeAtPoint{},
- SignatureClosestPositionToPoint{},
- SignatureClosestPositionToPointInRange{},
- SignatureComparePositionToPosition{},
- SignatureOffsetFromPositionToPosition{},
- SignaturePositionFromPositionInDirection{},
- SignaturePositionFromPositionOffset{},
- SignatureFirstRectForRange{},
- SignatureSelectionRectsForRange{},
- SignaturePositionWithinRange{},
- SignatureReplaceRangeWithText{},
- SignatureSetBaseWritingDirection{},
- SignatureTextInRange{},
- SignatureTextRangeFromPosition{},
- SignatureSetInputDelegate{},
- SignatureInputDelegate{},
- SignatureKeyboardType{},
- SignatureAutocapitalizationType{},
- SignatureAutocorrectionType{});
-
- addProtocol (@protocol (UITextInput));
- }
-
- if (@available (iOS 11.0, *))
- {
- addMethod (@selector (accessibilityRowRange), getAccessibilityRowIndexRange);
- addMethod (@selector (accessibilityColumnRange), getAccessibilityColumnIndexRange);
- addProtocol (@protocol (UIAccessibilityContainerDataTableCell));
- }
-
- addIvar<UIAccessibilityElement*> ("container");
-
- registerClass();
- }
-
- private:
- template <typename Result>
- static auto getResult (NSInvocation* invocation, detail::Tag<Result>)
- {
- Result result{};
- [invocation getReturnValue: &result];
- return result;
- }
-
- static void getResult (NSInvocation*, detail::Tag<void>) {}
-
- template <typename HasSelector, typename Result, typename... Args>
- auto makePassthroughCallback (HasSelector, Signature<Result (Args...)>)
- {
- return [] (id self, SEL, Args... args) -> Result
- {
- if (auto* input = getPeerTextInput (self))
- {
- const auto s = detail::makeCompileTimeStr (@encode (Result), @encode (id), @encode (SEL), @encode (Args)...);
- const auto signature = [NSMethodSignature signatureWithObjCTypes: s.data()];
- const auto invocation = [NSInvocation invocationWithMethodSignature: signature];
- invocation.selector = HasSelector::sel();
-
- // Indices 0 and 1 are 'id self' and 'SEL _cmd' respectively
- auto counter = 2;
- forEach ([&] (auto& arg) { [invocation setArgument: &arg atIndex: counter++]; }, args...);
-
- [invocation invokeWithTarget: input];
-
- return getResult (invocation, detail::Tag<Result>{});
- }
-
- jassertfalse;
- return {};
- };
- }
-
- template <typename Signature>
- void addPassthroughMethodWithSignature (Signature signature)
- {
- addMethod (Signature::sel(), makePassthroughCallback (signature, signature));
- }
-
- static UIAccessibilityElement* getContainer (id self)
- {
- return getIvar<UIAccessibilityElement*> (self, "container");
- }
-
- static UIViewComponentPeer* getPeer (id self)
- {
- if (auto* handler = getHandler (self))
- return static_cast<UIViewComponentPeer*> (handler->getComponent().getPeer());
-
- return nil;
- }
-
- static JuceTextView* getPeerTextInput (id self)
- {
- if (auto* peer = getPeer (self))
- return peer->hiddenTextInput.get();
-
- return nil;
- }
-
- //==============================================================================
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AccessibilityElement)
- };
-
- //==============================================================================
- AccessibilityElement::Holder accessibilityElement;
-
- //==============================================================================
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AccessibilityNativeImpl)
- };
-
- //==============================================================================
- AccessibilityNativeHandle* AccessibilityHandler::getNativeImplementation() const
- {
- return (AccessibilityNativeHandle*) nativeImpl->getAccessibilityElement();
- }
-
- static bool areAnyAccessibilityClientsActive()
- {
- return UIAccessibilityIsVoiceOverRunning();
- }
-
- static void sendAccessibilityEvent (UIAccessibilityNotifications notification, id argument)
- {
- if (! areAnyAccessibilityClientsActive())
- return;
-
- jassert (notification != UIAccessibilityNotifications{});
-
- UIAccessibilityPostNotification (notification, argument);
- }
-
- void notifyAccessibilityEventInternal (const AccessibilityHandler& handler, InternalAccessibilityEvent eventType)
- {
- auto notification = [eventType]
- {
- switch (eventType)
- {
- case InternalAccessibilityEvent::elementCreated:
- case InternalAccessibilityEvent::elementDestroyed:
- case InternalAccessibilityEvent::elementMovedOrResized:
- case InternalAccessibilityEvent::focusChanged: return UIAccessibilityLayoutChangedNotification;
-
- case InternalAccessibilityEvent::windowOpened:
- case InternalAccessibilityEvent::windowClosed: return UIAccessibilityScreenChangedNotification;
- }
-
- return UIAccessibilityNotifications{};
- }();
-
- if (notification != UIAccessibilityNotifications{})
- {
- const bool moveToHandler = (eventType == InternalAccessibilityEvent::focusChanged && handler.hasFocus (false));
-
- sendAccessibilityEvent (notification,
- moveToHandler ? static_cast<id> (handler.getNativeImplementation()) : nil);
- }
- }
-
- void AccessibilityHandler::notifyAccessibilityEvent (AccessibilityEvent eventType) const
- {
- auto notification = [eventType]
- {
- switch (eventType)
- {
- case AccessibilityEvent::textSelectionChanged:
- case AccessibilityEvent::rowSelectionChanged:
- case AccessibilityEvent::textChanged:
- case AccessibilityEvent::valueChanged:
- case AccessibilityEvent::titleChanged: break;
-
- case AccessibilityEvent::structureChanged: return UIAccessibilityLayoutChangedNotification;
- }
-
- return UIAccessibilityNotifications{};
- }();
-
- if (notification != UIAccessibilityNotifications{})
- sendAccessibilityEvent (notification, static_cast<id> (getNativeImplementation()));
- }
-
- void AccessibilityHandler::postAnnouncement (const String& announcementString, AnnouncementPriority)
- {
- sendAccessibilityEvent (UIAccessibilityAnnouncementNotification, juceStringToNS (announcementString));
- }
-
- } // namespace juce
|