| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2020 - 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 6 End-User License
 -    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
 - 
 -    End User License Agreement: www.juce.com/juce-6-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.
 - 
 -   ==============================================================================
 - */
 - 
 - namespace juce
 - {
 - 
 - AccessibilityHandler* AccessibilityHandler::currentlyFocusedHandler = nullptr;
 - 
 - enum class InternalAccessibilityEvent
 - {
 -     elementCreated,
 -     elementDestroyed,
 -     focusChanged,
 -     windowOpened,
 -     windowClosed
 - };
 - 
 - void notifyAccessibilityEventInternal (const AccessibilityHandler& handler, InternalAccessibilityEvent event);
 - 
 - inline String getAccessibleApplicationOrPluginName()
 - {
 -    #if defined (JucePlugin_Name)
 -     return JucePlugin_Name;
 -    #else
 -     if (auto* app = JUCEApplicationBase::getInstance())
 -         return app->getApplicationName();
 - 
 -     return "JUCE Application";
 -    #endif
 - }
 - 
 - AccessibilityHandler::AccessibilityHandler (Component& comp,
 -                                             AccessibilityRole accessibilityRole,
 -                                             AccessibilityActions accessibilityActions,
 -                                             Interfaces interfacesIn)
 -     : component (comp),
 -       typeIndex (typeid (component)),
 -       role (accessibilityRole),
 -       actions (std::move (accessibilityActions)),
 -       interfaces (std::move (interfacesIn)),
 -       nativeImpl (createNativeImpl (*this))
 - {
 -     notifyAccessibilityEventInternal (*this, InternalAccessibilityEvent::elementCreated);
 - }
 - 
 - AccessibilityHandler::~AccessibilityHandler()
 - {
 -     giveAwayFocus();
 -     notifyAccessibilityEventInternal (*this, InternalAccessibilityEvent::elementDestroyed);
 - }
 - 
 - //==============================================================================
 - AccessibleState AccessibilityHandler::getCurrentState() const
 - {
 -     auto state = AccessibleState().withFocusable();
 - 
 -     return hasFocus (false) ? state.withFocused() : state;
 - }
 - 
 - bool AccessibilityHandler::isIgnored() const
 - {
 -     return role == AccessibilityRole::ignored
 -         || getCurrentState().isIgnored()
 -         || component.isCurrentlyBlockedByAnotherModalComponent();
 - }
 - 
 - static bool isComponentVisibleWithinWindow (const Component& comp)
 - {
 -     if (auto* peer = comp.getPeer())
 -         return ! peer->getAreaCoveredBy (comp).getIntersection (peer->getComponent().getLocalBounds()).isEmpty();
 - 
 -     return false;
 - }
 - 
 - static bool isComponentVisibleWithinParent (Component* comp)
 - {
 -     if (auto* parent = comp->getParentComponent())
 -     {
 -         if (comp->getBoundsInParent().getIntersection (parent->getLocalBounds()).isEmpty())
 -             return false;
 - 
 -         return isComponentVisibleWithinParent (parent);
 -     }
 - 
 -     return true;
 - }
 - 
 - bool AccessibilityHandler::isVisibleWithinParent() const
 - {
 -     return getCurrentState().isAccessibleOffscreen()
 -           || (isComponentVisibleWithinParent (&component) && isComponentVisibleWithinWindow (component));
 - }
 - 
 - //==============================================================================
 - const AccessibilityActions& AccessibilityHandler::getActions() const noexcept
 - {
 -     return actions;
 - }
 - 
 - AccessibilityValueInterface* AccessibilityHandler::getValueInterface() const
 - {
 -     return interfaces.value.get();
 - }
 - 
 - AccessibilityTableInterface* AccessibilityHandler::getTableInterface() const
 - {
 -     return interfaces.table.get();
 - }
 - 
 - AccessibilityCellInterface* AccessibilityHandler::getCellInterface() const
 - {
 -     return interfaces.cell.get();
 - }
 - 
 - AccessibilityTextInterface* AccessibilityHandler::getTextInterface() const
 - {
 -     return interfaces.text.get();
 - }
 - 
 - //==============================================================================
 - static AccessibilityHandler* findEnclosingHandler (Component* comp)
 - {
 -     if (comp != nullptr)
 -     {
 -         if (auto* handler = comp->getAccessibilityHandler())
 -             return handler;
 - 
 -         return findEnclosingHandler (comp->getParentComponent());
 -     }
 - 
 -     return nullptr;
 - }
 - 
 - static AccessibilityHandler* getUnignoredAncestor (AccessibilityHandler* handler)
 - {
 -     while (handler != nullptr
 -            && (handler->isIgnored() || ! handler->isVisibleWithinParent())
 -            && handler->getParent() != nullptr)
 -     {
 -         handler = handler->getParent();
 -     }
 - 
 -     return handler;
 - }
 - 
 - static AccessibilityHandler* findFirstUnignoredChild (const std::vector<AccessibilityHandler*>& handlers)
 - {
 -     if (! handlers.empty())
 -     {
 -         const auto iter = std::find_if (handlers.cbegin(), handlers.cend(),
 -                                         [] (const AccessibilityHandler* handler) { return ! handler->isIgnored() && handler->isVisibleWithinParent(); });
 - 
 -         if (iter != handlers.cend())
 -             return *iter;
 - 
 -         for (auto* handler : handlers)
 -             if (auto* unignored = findFirstUnignoredChild (handler->getChildren()))
 -                 return unignored;
 -     }
 - 
 -     return nullptr;
 - }
 - 
 - static AccessibilityHandler* getFirstUnignoredDescendant (AccessibilityHandler* handler)
 - {
 -     if (handler != nullptr && (handler->isIgnored() || ! handler->isVisibleWithinParent()))
 -         return findFirstUnignoredChild (handler->getChildren());
 - 
 -     return handler;
 - }
 - 
 - AccessibilityHandler* AccessibilityHandler::getParent() const
 - {
 -     if (auto* focusContainer = component.findFocusContainer())
 -         return getUnignoredAncestor (findEnclosingHandler (focusContainer));
 - 
 -     return nullptr;
 - }
 - 
 - std::vector<AccessibilityHandler*> AccessibilityHandler::getChildren() const
 - {
 -     if (! component.isFocusContainer() && component.getParentComponent() != nullptr)
 -         return {};
 - 
 -     std::vector<AccessibilityHandler*> children;
 - 
 -     if (auto traverser = component.createFocusTraverser())
 -     {
 -         for (auto* focusableChild : traverser->getAllComponents (&component))
 -         {
 -             if (auto* handler = findEnclosingHandler (focusableChild))
 -             {
 -                 if (! isParentOf (handler))
 -                     continue;
 - 
 -                 if (auto* unignored = getFirstUnignoredDescendant (handler))
 -                     if (std::find (children.cbegin(), children.cend(), unignored) == children.cend())
 -                         children.push_back (unignored);
 -             }
 -         }
 -     }
 - 
 -     return children;
 - }
 - 
 - bool AccessibilityHandler::isParentOf (const AccessibilityHandler* possibleChild) const noexcept
 - {
 -     while (possibleChild != nullptr)
 -     {
 -         possibleChild = possibleChild->getParent();
 - 
 -         if (possibleChild == this)
 -             return true;
 -     }
 - 
 -     return false;
 - }
 - 
 - AccessibilityHandler* AccessibilityHandler::getChildAt (Point<int> screenPoint)
 - {
 -     if (auto* comp = Desktop::getInstance().findComponentAt (screenPoint))
 -         if (isParentOf (comp->getAccessibilityHandler()))
 -             return getUnignoredAncestor (findEnclosingHandler (comp));
 - 
 -     return nullptr;
 - }
 - 
 - AccessibilityHandler* AccessibilityHandler::getChildFocus()
 - {
 -     return hasFocus (true) ? getUnignoredAncestor (currentlyFocusedHandler)
 -                            : nullptr;
 - }
 - 
 - bool AccessibilityHandler::hasFocus (bool trueIfChildFocused) const
 - {
 -     return currentlyFocusedHandler != nullptr
 -             && (currentlyFocusedHandler == this
 -                 || (trueIfChildFocused && isParentOf (currentlyFocusedHandler)));
 - }
 - 
 - void AccessibilityHandler::grabFocus()
 - {
 -     if (! hasFocus (false))
 -         grabFocusInternal (true);
 - }
 - 
 - void AccessibilityHandler::giveAwayFocus() const
 - {
 -     if (hasFocus (true))
 -         giveAwayFocusInternal();
 - }
 - 
 - void AccessibilityHandler::grabFocusInternal (bool canTryParent)
 - {
 -     if (getCurrentState().isFocusable() && ! isIgnored())
 -     {
 -         takeFocus();
 -         return;
 -     }
 - 
 -     if (isParentOf (currentlyFocusedHandler) && ! currentlyFocusedHandler->isIgnored())
 -         return;
 - 
 -     if (component.isFocusContainer() || component.getParentComponent() == nullptr)
 -     {
 -         if (auto traverser = component.createFocusTraverser())
 -         {
 -             if (auto* defaultComp = traverser->getDefaultComponent (&component))
 -             {
 -                 if (auto* handler = getUnignoredAncestor (findEnclosingHandler (defaultComp)))
 -                 {
 -                     if (isParentOf (handler))
 -                     {
 -                         handler->grabFocusInternal (false);
 -                         return;
 -                     }
 -                 }
 -             }
 -         }
 -     }
 - 
 -     if (canTryParent)
 -         if (auto* parent = getParent())
 -             parent->grabFocusInternal (true);
 - }
 - 
 - void AccessibilityHandler::giveAwayFocusInternal() const
 - {
 -     currentlyFocusedHandler = nullptr;
 - 
 -     if (auto* parent = getParent())
 -         notifyAccessibilityEventInternal (*parent, InternalAccessibilityEvent::focusChanged);
 - }
 - 
 - void AccessibilityHandler::takeFocus()
 - {
 -     currentlyFocusedHandler = this;
 -     notifyAccessibilityEventInternal (*this, InternalAccessibilityEvent::focusChanged);
 - 
 -     if ((component.isShowing() || component.isOnDesktop())
 -         && component.getWantsKeyboardFocus()
 -         && ! component.hasKeyboardFocus (true))
 -     {
 -         component.grabKeyboardFocus();
 -     }
 - }
 - 
 - //==============================================================================
 - #if ! ((JUCE_MAC && (defined (MAC_OS_X_VERSION_10_10) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10)) \
 -      || (JUCE_WINDOWS && ! JUCE_MINGW))
 - 
 - class AccessibilityHandler::AccessibilityNativeImpl { public: AccessibilityNativeImpl (AccessibilityHandler&) {} };
 - void AccessibilityHandler::notifyAccessibilityEvent (AccessibilityEvent) const {}
 - void AccessibilityHandler::postAnnouncement (const String&, AnnouncementPriority) {}
 - AccessibilityNativeHandle* AccessibilityHandler::getNativeImplementation() const { return nullptr; }
 - AccessibilityHandler::AccessibilityNativeImpl* AccessibilityHandler::createNativeImpl (AccessibilityHandler&) { return nullptr; }
 - void AccessibilityHandler::DestroyNativeImpl::operator() (AccessibilityHandler::AccessibilityNativeImpl*) const noexcept {}
 - void notifyAccessibilityEventInternal (const AccessibilityHandler&, InternalAccessibilityEvent) {}
 - 
 - #endif
 - 
 - } // namespace juce
 
 
  |