diff --git a/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.cpp b/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.cpp index 74932355d8..4329e26850 100644 --- a/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.cpp +++ b/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.cpp @@ -79,6 +79,13 @@ AccessibleState AccessibilityHandler::getCurrentState() const 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()) @@ -100,16 +107,10 @@ static bool isComponentVisibleWithinParent (Component* comp) return true; } -bool AccessibilityHandler::isIgnored() const +bool AccessibilityHandler::isVisibleWithinParent() const { - const auto state = getCurrentState(); - - return role == AccessibilityRole::ignored - || state.isIgnored() - || ! component.isShowing() - || (! state.isAccessibleOffscreen() - && (! isComponentVisibleWithinParent (&component) - || ! isComponentVisibleWithinWindow (component))); + return getCurrentState().isAccessibleOffscreen() + || (isComponentVisibleWithinParent (&component) && isComponentVisibleWithinWindow (component)); } //============================================================================== @@ -155,7 +156,7 @@ static AccessibilityHandler* findEnclosingHandler (Component* comp) static AccessibilityHandler* getUnignoredAncestor (AccessibilityHandler* handler) { while (handler != nullptr - && handler->isIgnored() + && (handler->isIgnored() || ! handler->isVisibleWithinParent()) && handler->getParent() != nullptr) { handler = handler->getParent(); @@ -169,7 +170,7 @@ static AccessibilityHandler* findFirstUnignoredChild (const std::vectorisIgnored(); }); + [] (const AccessibilityHandler* handler) { return ! handler->isIgnored() && handler->isVisibleWithinParent(); }); if (iter != handlers.cend()) return *iter; @@ -184,7 +185,7 @@ static AccessibilityHandler* findFirstUnignoredChild (const std::vectorisIgnored()) + if (handler != nullptr && (handler->isIgnored() || ! handler->isVisibleWithinParent())) return findFirstUnignoredChild (handler->getChildren()); return handler; @@ -308,28 +309,18 @@ void AccessibilityHandler::grabFocusInternal (bool canTryParent) void AccessibilityHandler::giveAwayFocusInternal() const { currentlyFocusedHandler = nullptr; - notifyAccessibilityEventInternal (*this, InternalAccessibilityEvent::focusChanged); - if (auto* focusedComponent = Component::getCurrentlyFocusedComponent()) - if (auto* handler = focusedComponent->getAccessibilityHandler()) - handler->grabFocus(); + if (auto* parent = getParent()) + notifyAccessibilityEventInternal (*parent, InternalAccessibilityEvent::focusChanged); } void AccessibilityHandler::takeFocus() { currentlyFocusedHandler = this; - - WeakReference weakComponent (&component); - actions.invoke (AccessibilityActionType::focus); - - if (weakComponent != nullptr - && component.getWantsKeyboardFocus() - && ! component.hasKeyboardFocus (true)) - { - component.grabKeyboardFocus(); - } - notifyAccessibilityEventInternal (*this, InternalAccessibilityEvent::focusChanged); + + if (component.getWantsKeyboardFocus() && ! component.hasKeyboardFocus (true)) + component.grabKeyboardFocus(); } //============================================================================== diff --git a/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.h b/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.h index 111c7f87b3..8150c1ff68 100644 --- a/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.h +++ b/modules/juce_gui_basics/accessibility/juce_AccessibilityHandler.h @@ -161,6 +161,13 @@ public: /** Returns true if this UI element should be ignored by accessibility clients. */ bool isIgnored() const; + /** Returns true if this UI element is visible within its parent. + + This will always return true for UI elements with the AccessibleState::accessibleOffscreen + flag set. + */ + bool isVisibleWithinParent() const; + //============================================================================== /** Returns the set of actions that the UI element supports and the associated callbacks. @@ -232,10 +239,9 @@ public: /** Tries to give focus to this UI element. - If the UI element is focusable, as indicated by AccessibleState::isFocusable(), - this will perform its AccessibilityActionType::focus action, try to give keyboard - focus to the Component it represents, and notify any listening accessibility - clients that the current focus has changed. + If the UI element is focusable and not ignored this will update the currently focused + element, try to give keyboard focus to the Component it represents, and notify any + listening accessibility clients that the current focus has changed. @see hasFocus, giveAwayFocus */