JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_AccessibilityHandler.cpp
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
29AccessibilityHandler* AccessibilityHandler::currentlyFocusedHandler = nullptr;
30
32{
33public:
34 static NativeChildHandler& getInstance()
35 {
36 static NativeChildHandler instance;
37 return instance;
38 }
39
40 void* getNativeChild (Component& component) const
41 {
42 if (auto it = nativeChildForComponent.find (&component);
43 it != nativeChildForComponent.end())
44 {
45 return it->second;
46 }
47
48 return nullptr;
49 }
50
51 Component* getComponent (void* nativeChild) const
52 {
53 if (auto it = componentForNativeChild.find (nativeChild);
54 it != componentForNativeChild.end())
55 {
56 return it->second;
57 }
58
59 return nullptr;
60 }
61
62 void setNativeChild (Component& component, void* nativeChild)
63 {
64 clearComponent (component);
65
66 if (nativeChild != nullptr)
67 {
68 nativeChildForComponent[&component] = nativeChild;
69 componentForNativeChild[nativeChild] = &component;
70 }
71 }
72
73private:
74 NativeChildHandler() = default;
75
76 void clearComponent (Component& component)
77 {
78 if (auto* nativeChild = getNativeChild (component))
79 componentForNativeChild.erase (nativeChild);
80
81 nativeChildForComponent.erase (&component);
82 }
83
84 std::map<void*, Component*> componentForNativeChild;
85 std::map<Component*, void*> nativeChildForComponent;
86};
87
92 : component (comp),
93 typeIndex (typeid (component)),
94 role (accessibilityRole),
95 actions (std::move (accessibilityActions)),
96 interfaces (std::move (interfacesIn)),
97 nativeImpl (createNativeImpl (*this))
98{
99}
100
102{
104 detail::AccessibilityHelpers::notifyAccessibilityEvent (*this, detail::AccessibilityHelpers::Event::elementDestroyed);
105}
106
107//==============================================================================
109{
112 return {};
113
114 auto state = AccessibleState().withFocusable();
115
116 return hasFocus (false) ? state.withFocused() : state;
117}
118
120{
121 return role == AccessibilityRole::ignored || getCurrentState().isIgnored();
122}
123
124static bool isComponentVisibleWithinWindow (const Component& comp)
125{
126 if (auto* peer = comp.getPeer())
127 return ! peer->getAreaCoveredBy (comp).getIntersection (peer->getComponent().getLocalBounds()).isEmpty();
128
129 return false;
130}
131
132static bool isComponentVisibleWithinParent (Component* comp)
133{
134 if (auto* parent = comp->getParentComponent())
135 {
136 if (comp->getBoundsInParent().getIntersection (parent->getLocalBounds()).isEmpty())
137 return false;
138
139 return isComponentVisibleWithinParent (parent);
140 }
141
142 return true;
143}
144
146{
148 || (isComponentVisibleWithinParent (&component) && isComponentVisibleWithinWindow (component));
149}
150
151//==============================================================================
153{
154 return actions;
155}
156
158{
159 return interfaces.value.get();
160}
161
163{
164 return interfaces.table.get();
165}
166
168{
169 return interfaces.cell.get();
170}
171
173{
174 return interfaces.text.get();
175}
176
177//==============================================================================
178static AccessibilityHandler* findEnclosingHandler (Component* comp)
179{
180 if (comp != nullptr)
181 {
182 if (auto* handler = comp->getAccessibilityHandler())
183 return handler;
184
185 return findEnclosingHandler (comp->getParentComponent());
186 }
187
188 return nullptr;
189}
190
191static AccessibilityHandler* getUnignoredAncestor (AccessibilityHandler* handler)
192{
193 while (handler != nullptr
194 && (handler->isIgnored() || ! handler->isVisibleWithinParent())
195 && handler->getParent() != nullptr)
196 {
197 handler = handler->getParent();
198 }
199
200 return handler;
201}
202
203static AccessibilityHandler* findFirstUnignoredChild (const std::vector<AccessibilityHandler*>& handlers)
204{
205 if (! handlers.empty())
206 {
207 const auto iter = std::find_if (handlers.cbegin(), handlers.cend(),
208 [] (const AccessibilityHandler* handler) { return ! handler->isIgnored() && handler->isVisibleWithinParent(); });
209
210 if (iter != handlers.cend())
211 return *iter;
212
213 for (auto* handler : handlers)
214 if (auto* unignored = findFirstUnignoredChild (handler->getChildren()))
216 }
217
218 return nullptr;
219}
220
221static AccessibilityHandler* getFirstUnignoredDescendant (AccessibilityHandler* handler)
222{
223 if (handler != nullptr && (handler->isIgnored() || ! handler->isVisibleWithinParent()))
224 return findFirstUnignoredChild (handler->getChildren());
225
226 return handler;
227}
228
230{
231 if (auto* focusContainer = component.findFocusContainer())
232 return getUnignoredAncestor (findEnclosingHandler (focusContainer));
233
234 return nullptr;
235}
236
238{
239 if (! component.isFocusContainer() && component.getParentComponent() != nullptr)
240 return {};
241
244 {
245 if (focusableComponent == nullptr)
246 return;
247
248 if (auto* handler = findEnclosingHandler (focusableComponent))
249 {
250 if (! handler->getCurrentState().isFocusable() || ! isParentOf (handler))
251 return;
252
253 if (auto* unignored = getFirstUnignoredDescendant (handler))
254 if (std::find (childHandlers.cbegin(), childHandlers.cend(), unignored) == childHandlers.cend())
256 }
257 };
258
260
261 if (auto traverser = component.createFocusTraverser())
262 {
263 addChildComponentHandler (traverser->getDefaultComponent (&component), children);
264
265 for (auto* focusableChild : traverser->getAllComponents (&component))
267 }
268
269 return children;
270}
271
273{
274 while (possibleChild != nullptr)
275 {
276 possibleChild = possibleChild->getParent();
277
278 if (possibleChild == this)
279 return true;
280 }
281
282 return false;
283}
284
286{
287 if (auto* comp = Desktop::getInstance().findComponentAt (screenPoint))
288 {
289 if (auto* handler = getUnignoredAncestor (findEnclosingHandler (comp)))
290 if (isParentOf (handler))
291 return handler;
292 }
293
294 return nullptr;
295}
296
298{
299 return hasFocus (true) ? getUnignoredAncestor (currentlyFocusedHandler)
300 : nullptr;
301}
302
304{
305 return currentlyFocusedHandler != nullptr
306 && (currentlyFocusedHandler == this
307 || (trueIfChildFocused && isParentOf (currentlyFocusedHandler)));
308}
309
311{
312 if (! hasFocus (false))
313 grabFocusInternal (true);
314}
315
317{
318 if (hasFocus (true))
319 giveAwayFocusInternal();
320}
321
322void AccessibilityHandler::grabFocusInternal (bool canTryParent)
323{
324 if (getCurrentState().isFocusable() && ! isIgnored())
325 {
326 takeFocus();
327 return;
328 }
329
330 if (isParentOf (currentlyFocusedHandler))
331 return;
332
333 if (auto traverser = component.createFocusTraverser())
334 {
335 if (auto* defaultComp = traverser->getDefaultComponent (&component))
336 {
337 if (auto* handler = getUnignoredAncestor (findEnclosingHandler (defaultComp)))
338 {
339 if (isParentOf (handler))
340 {
341 handler->grabFocusInternal (false);
342 return;
343 }
344 }
345 }
346 }
347
348 if (canTryParent)
349 if (auto* parent = getParent())
350 parent->grabFocusInternal (true);
351}
352
353void AccessibilityHandler::giveAwayFocusInternal() const
354{
355 currentlyFocusedHandler = nullptr;
356 detail::AccessibilityHelpers::notifyAccessibilityEvent (*this, detail::AccessibilityHelpers::Event::focusChanged);
357}
358
359void AccessibilityHandler::takeFocus()
360{
361 currentlyFocusedHandler = this;
362 detail::AccessibilityHelpers::notifyAccessibilityEvent (*this, detail::AccessibilityHelpers::Event::focusChanged);
363
364 if ((component.isShowing() || component.isOnDesktop())
365 && component.getWantsKeyboardFocus()
366 && ! component.hasKeyboardFocus (true))
367 {
368 component.grabKeyboardFocus();
369 }
370}
371
372std::unique_ptr<AccessibilityHandler::AccessibilityNativeImpl> AccessibilityHandler::createNativeImpl (AccessibilityHandler& handler)
373{
374 #if JUCE_NATIVE_ACCESSIBILITY_INCLUDED
375 return std::make_unique<AccessibilityNativeImpl> (handler);
376 #else
377 ignoreUnused (handler);
378 return nullptr;
379 #endif
380}
381
382void* AccessibilityHandler::getNativeChildForComponent (Component& component)
383{
384 return NativeChildHandler::getInstance().getNativeChild (component);
385}
386
387Component* AccessibilityHandler::getComponentForNativeChild (void* nativeChild)
388{
389 return NativeChildHandler::getInstance().getComponent (nativeChild);
390}
391
392void AccessibilityHandler::setNativeChildForComponent (Component& component, void* nativeChild)
393{
394 NativeChildHandler::getInstance().setNativeChild (component, nativeChild);
395}
396
397#if ! JUCE_NATIVE_ACCESSIBILITY_INCLUDED
400 AccessibilityNativeHandle* AccessibilityHandler::getNativeImplementation() const { return nullptr; }
401#endif
402
403} // namespace juce
A simple wrapper for building a collection of supported accessibility actions and corresponding callb...
An abstract interface which represents a UI element that supports a cell interface.
Base class for accessible Components.
virtual AccessibleState getCurrentState() const
Returns the current state of the UI element.
std::vector< AccessibilityHandler * > getChildren() const
Returns the unignored children of this UI element in the accessibility hierarchy.
void grabFocus()
Tries to give focus to this UI element.
const AccessibilityActions & getActions() const noexcept
Returns the set of actions that the UI element supports and the associated callbacks.
AccessibilityCellInterface * getCellInterface() const
Returns the cell interface for this UI element, or nullptr if it is not supported.
AccessibilityHandler * getChildAt(Point< int > screenPoint)
Returns the deepest child of this UI element in the accessibility hierarchy that contains the given s...
bool isIgnored() const
Returns true if this UI element should be ignored by accessibility clients.
AccessibilityHandler * getChildFocus()
Returns the deepest UI element which currently has focus.
bool hasFocus(bool trueIfChildFocused) const
Returns true if this UI element has the focus.
void giveAwayFocus() const
If this UI element or any of its children in the accessibility hierarchy currently have focus,...
void notifyAccessibilityEvent(AccessibilityEvent event) const
Used to send a notification to any observing accessibility clients that something has changed in the ...
AccessibilityTableInterface * getTableInterface() const
Returns the table interface for this UI element, or nullptr if it is not supported.
AccessibilityHandler * getParent() const
Returns the first unignored parent of this UI element in the accessibility hierarchy,...
AccessibilityValueInterface * getValueInterface() const
Returns the value interface for this UI element, or nullptr if it is not supported.
AnnouncementPriority
A priority level that can help an accessibility client determine how to handle an announcement reques...
bool isVisibleWithinParent() const
Returns true if this UI element is visible within its parent.
AccessibilityTextInterface * getTextInterface() const
Returns the text interface for this UI element, or nullptr if it is not supported.
static void postAnnouncement(const String &announcementString, AnnouncementPriority priority)
Posts an announcement to be made to the user.
AccessibilityHandler(Component &componentToWrap, AccessibilityRole accessibilityRole, AccessibilityActions actions={}, Interfaces interfaces={})
Constructor.
bool isParentOf(const AccessibilityHandler *possibleChild) const noexcept
Checks whether a given UI element is a child of this one in the accessibility hierarchy.
An abstract interface which represents a UI element that supports a table interface.
An abstract interface which represents a UI element that supports a text interface.
An abstract interface representing the value of an accessibility element.
Represents the state of an accessible UI element.
bool isAccessibleOffscreen() const noexcept
Returns true if the UI element is accessible offscreen.
AccessibleState withFocusable() const noexcept
Sets the focusable flag and returns the new state.
bool isIgnored() const noexcept
Returns true if the UI element is ignored.
The base class for all JUCE user-interface objects.
static Component *JUCE_CALLTYPE getCurrentlyModalComponent(int index=0) noexcept
Returns one of the components that are currently modal.
bool isVisible() const noexcept
Tests whether the component is visible or not.
Component * getParentComponent() const noexcept
Returns the component which this component is inside.
void grabKeyboardFocus()
Tries to give keyboard focus to this component.
Component * findFocusContainer() const
Returns the focus container for this component.
bool isShowing() const
Tests whether this component and all its parents are visible.
bool hasKeyboardFocus(bool trueIfChildIsFocused) const
Returns true if this component currently has the keyboard focus.
bool isCurrentlyBlockedByAnotherModalComponent() const
Checks whether there's a modal component somewhere that's stopping this one from receiving messages.
AccessibilityHandler * getAccessibilityHandler()
Returns the accessibility handler for this component, or nullptr if this component is not accessible.
bool isOnDesktop() const noexcept
Returns true if this component is currently showing on the desktop.
bool isFocusContainer() const noexcept
Returns true if this component has been marked as a focus container.
virtual std::unique_ptr< ComponentTraverser > createFocusTraverser()
Creates a ComponentTraverser object to determine the logic by which focus should be passed from this ...
bool getWantsKeyboardFocus() const noexcept
Returns true if the component is interested in getting keyboard focus.
ComponentPeer * getPeer() const
Returns the heavyweight window that contains this component.
static Desktop &JUCE_CALLTYPE getInstance()
There's only one desktop object, and this method will return it.
A pair of (x, y) coordinates.
Definition juce_Point.h:42
The JUCE String class!
Definition juce_String.h:53
T find_if(T... args)
JUCE Namespace.
AccessibilityEvent
A list of events that can be notified to any subscribed accessibility clients.
void ignoreUnused(Types &&...) noexcept
Handy function for avoiding unused variables warning.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
AccessibilityRole
The list of available roles for an AccessibilityHandler object.
T push_back(T... args)
Utility struct which holds one or more accessibility interfaces.