The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

659 lines
25KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wlanguage-extension-token")
  21. int AccessibilityNativeHandle::idCounter = 0;
  22. //==============================================================================
  23. class UIAScrollProvider : public UIAProviderBase,
  24. public ComBaseClassHelper<ComTypes::IScrollProvider>
  25. {
  26. public:
  27. using UIAProviderBase::UIAProviderBase;
  28. JUCE_COMCALL Scroll (ComTypes::ScrollAmount, ComTypes::ScrollAmount) override { return E_FAIL; }
  29. JUCE_COMCALL SetScrollPercent (double, double) override { return E_FAIL; }
  30. JUCE_COMCALL get_HorizontalScrollPercent (double*) override { return E_FAIL; }
  31. JUCE_COMCALL get_VerticalScrollPercent (double*) override { return E_FAIL; }
  32. JUCE_COMCALL get_HorizontalViewSize (double*) override { return E_FAIL; }
  33. JUCE_COMCALL get_VerticalViewSize (double*) override { return E_FAIL; }
  34. JUCE_COMCALL get_HorizontallyScrollable (BOOL*) override { return E_FAIL; }
  35. JUCE_COMCALL get_VerticallyScrollable (BOOL*) override { return E_FAIL; }
  36. private:
  37. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIAScrollProvider)
  38. };
  39. class UIAScrollItemProvider : public UIAProviderBase,
  40. public ComBaseClassHelper<ComTypes::IScrollItemProvider>
  41. {
  42. public:
  43. using UIAProviderBase::UIAProviderBase;
  44. JUCE_COMCALL ScrollIntoView() override
  45. {
  46. if (auto* handler = detail::AccessibilityHelpers::getEnclosingHandlerWithInterface (&getHandler(), &AccessibilityHandler::getTableInterface))
  47. {
  48. if (auto* tableInterface = handler->getTableInterface())
  49. {
  50. tableInterface->showCell (getHandler());
  51. return S_OK;
  52. }
  53. }
  54. return (HRESULT) UIA_E_NOTSUPPORTED;
  55. }
  56. private:
  57. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIAScrollItemProvider)
  58. };
  59. //==============================================================================
  60. static String getAutomationId (const AccessibilityHandler& handler)
  61. {
  62. auto result = handler.getTitle();
  63. auto* parentComponent = handler.getComponent().getParentComponent();
  64. while (parentComponent != nullptr)
  65. {
  66. if (auto* parentHandler = parentComponent->getAccessibilityHandler())
  67. {
  68. auto parentTitle = parentHandler->getTitle();
  69. result << "." << (parentTitle.isNotEmpty() ? parentTitle : "<empty>");
  70. }
  71. parentComponent = parentComponent->getParentComponent();
  72. }
  73. return result;
  74. }
  75. static auto roleToControlTypeId (AccessibilityRole roleType)
  76. {
  77. using namespace ComTypes::Constants;
  78. switch (roleType)
  79. {
  80. case AccessibilityRole::popupMenu:
  81. case AccessibilityRole::dialogWindow:
  82. case AccessibilityRole::splashScreen:
  83. case AccessibilityRole::window: return UIA_WindowControlTypeId;
  84. case AccessibilityRole::label:
  85. case AccessibilityRole::staticText: return UIA_TextControlTypeId;
  86. case AccessibilityRole::column:
  87. case AccessibilityRole::row: return UIA_ListItemControlTypeId;
  88. case AccessibilityRole::button: return UIA_ButtonControlTypeId;
  89. case AccessibilityRole::toggleButton: return UIA_CheckBoxControlTypeId;
  90. case AccessibilityRole::radioButton: return UIA_RadioButtonControlTypeId;
  91. case AccessibilityRole::comboBox: return UIA_ComboBoxControlTypeId;
  92. case AccessibilityRole::image: return UIA_ImageControlTypeId;
  93. case AccessibilityRole::slider: return UIA_SliderControlTypeId;
  94. case AccessibilityRole::editableText: return UIA_EditControlTypeId;
  95. case AccessibilityRole::menuItem: return UIA_MenuItemControlTypeId;
  96. case AccessibilityRole::menuBar: return UIA_MenuBarControlTypeId;
  97. case AccessibilityRole::table: return UIA_TableControlTypeId;
  98. case AccessibilityRole::tableHeader: return UIA_HeaderControlTypeId;
  99. case AccessibilityRole::cell: return UIA_DataItemControlTypeId;
  100. case AccessibilityRole::hyperlink: return UIA_HyperlinkControlTypeId;
  101. case AccessibilityRole::list: return UIA_ListControlTypeId;
  102. case AccessibilityRole::listItem: return UIA_ListItemControlTypeId;
  103. case AccessibilityRole::tree: return UIA_TreeControlTypeId;
  104. case AccessibilityRole::treeItem: return UIA_TreeItemControlTypeId;
  105. case AccessibilityRole::progressBar: return UIA_ProgressBarControlTypeId;
  106. case AccessibilityRole::group: return UIA_GroupControlTypeId;
  107. case AccessibilityRole::scrollBar: return UIA_ScrollBarControlTypeId;
  108. case AccessibilityRole::tooltip: return UIA_ToolTipControlTypeId;
  109. case AccessibilityRole::ignored:
  110. case AccessibilityRole::unspecified: break;
  111. };
  112. return UIA_CustomControlTypeId;
  113. }
  114. //==============================================================================
  115. AccessibilityNativeHandle::AccessibilityNativeHandle (AccessibilityHandler& handler)
  116. : ComBaseClassHelper (0),
  117. accessibilityHandler (handler)
  118. {
  119. }
  120. //==============================================================================
  121. JUCE_COMRESULT AccessibilityNativeHandle::QueryInterface (REFIID refId, void** result)
  122. {
  123. *result = nullptr;
  124. if (! isElementValid())
  125. return (HRESULT) UIA_E_ELEMENTNOTAVAILABLE;
  126. if ((refId == __uuidof (ComTypes::IRawElementProviderFragmentRoot) && ! isFragmentRoot()))
  127. return E_NOINTERFACE;
  128. return ComBaseClassHelper::QueryInterface (refId, result);
  129. }
  130. //==============================================================================
  131. JUCE_COMRESULT AccessibilityNativeHandle::get_HostRawElementProvider (IRawElementProviderSimple** pRetVal)
  132. {
  133. return withCheckedComArgs (pRetVal, *this, [&]
  134. {
  135. if (auto* wrapper = WindowsUIAWrapper::getInstanceWithoutCreating())
  136. {
  137. if (isFragmentRoot())
  138. return wrapper->hostProviderFromHwnd ((HWND) accessibilityHandler.getComponent().getWindowHandle(), pRetVal);
  139. if (auto* embeddedWindow = static_cast<HWND> (AccessibilityHandler::getNativeChildForComponent (accessibilityHandler.getComponent())))
  140. return wrapper->hostProviderFromHwnd (embeddedWindow, pRetVal);
  141. }
  142. return S_OK;
  143. });
  144. }
  145. JUCE_COMRESULT AccessibilityNativeHandle::get_ProviderOptions (ProviderOptions* options)
  146. {
  147. if (options == nullptr)
  148. return E_INVALIDARG;
  149. *options = (ProviderOptions) (ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading);
  150. if (AccessibilityHandler::getNativeChildForComponent (accessibilityHandler.getComponent()) != nullptr)
  151. *options = (ProviderOptions) (*options | ProviderOptions_OverrideProvider);
  152. return S_OK;
  153. }
  154. JUCE_COMRESULT AccessibilityNativeHandle::GetPatternProvider (PATTERNID pId, IUnknown** pRetVal)
  155. {
  156. return withCheckedComArgs (pRetVal, *this, [&]
  157. {
  158. *pRetVal = [&]() -> IUnknown*
  159. {
  160. const auto role = accessibilityHandler.getRole();
  161. const auto fragmentRoot = isFragmentRoot();
  162. const auto isListOrTableCell = [] (auto& handler)
  163. {
  164. if (auto* tableHandler = detail::AccessibilityHelpers::getEnclosingHandlerWithInterface (&handler, &AccessibilityHandler::getTableInterface))
  165. {
  166. if (auto* tableInterface = tableHandler->getTableInterface())
  167. {
  168. const auto row = tableInterface->getRowSpan (handler);
  169. const auto column = tableInterface->getColumnSpan (handler);
  170. return row.hasValue() && column.hasValue();
  171. }
  172. }
  173. return false;
  174. };
  175. using namespace ComTypes::Constants;
  176. switch (pId)
  177. {
  178. case UIA_WindowPatternId:
  179. {
  180. if (fragmentRoot)
  181. return new UIAWindowProvider (this);
  182. break;
  183. }
  184. case UIA_TransformPatternId:
  185. {
  186. if (fragmentRoot)
  187. return new UIATransformProvider (this);
  188. break;
  189. }
  190. case UIA_TextPatternId:
  191. case UIA_TextPattern2Id:
  192. {
  193. if (accessibilityHandler.getTextInterface() != nullptr)
  194. return new UIATextProvider (this);
  195. break;
  196. }
  197. case UIA_ValuePatternId:
  198. {
  199. if (accessibilityHandler.getValueInterface() != nullptr)
  200. return new UIAValueProvider (this);
  201. break;
  202. }
  203. case UIA_RangeValuePatternId:
  204. {
  205. if (accessibilityHandler.getValueInterface() != nullptr
  206. && accessibilityHandler.getValueInterface()->getRange().isValid())
  207. {
  208. return new UIARangeValueProvider (this);
  209. }
  210. break;
  211. }
  212. case UIA_TogglePatternId:
  213. {
  214. if (accessibilityHandler.getCurrentState().isCheckable()
  215. && (accessibilityHandler.getActions().contains (AccessibilityActionType::toggle)
  216. || accessibilityHandler.getActions().contains (AccessibilityActionType::press)))
  217. {
  218. return new UIAToggleProvider (this);
  219. }
  220. break;
  221. }
  222. case UIA_SelectionPatternId:
  223. {
  224. if (role == AccessibilityRole::list
  225. || role == AccessibilityRole::popupMenu
  226. || role == AccessibilityRole::tree)
  227. {
  228. return new UIASelectionProvider (this);
  229. }
  230. break;
  231. }
  232. case UIA_SelectionItemPatternId:
  233. {
  234. auto state = accessibilityHandler.getCurrentState();
  235. if (state.isSelectable() || state.isMultiSelectable() || role == AccessibilityRole::radioButton)
  236. {
  237. return new UIASelectionItemProvider (this);
  238. }
  239. break;
  240. }
  241. case UIA_TablePatternId:
  242. case UIA_GridPatternId:
  243. {
  244. if (accessibilityHandler.getTableInterface() != nullptr
  245. && (pId == UIA_GridPatternId || accessibilityHandler.getRole() == AccessibilityRole::table))
  246. return static_cast<ComTypes::IGridProvider*> (new UIAGridProvider (this));
  247. break;
  248. }
  249. case UIA_TableItemPatternId:
  250. case UIA_GridItemPatternId:
  251. {
  252. if (isListOrTableCell (accessibilityHandler))
  253. return static_cast<ComTypes::IGridItemProvider*> (new UIAGridItemProvider (this));
  254. break;
  255. }
  256. case UIA_InvokePatternId:
  257. {
  258. if (accessibilityHandler.getActions().contains (AccessibilityActionType::press))
  259. return new UIAInvokeProvider (this);
  260. break;
  261. }
  262. case UIA_ExpandCollapsePatternId:
  263. {
  264. if (accessibilityHandler.getActions().contains (AccessibilityActionType::showMenu)
  265. && accessibilityHandler.getCurrentState().isExpandable())
  266. return new UIAExpandCollapseProvider (this);
  267. break;
  268. }
  269. case UIA_ScrollPatternId:
  270. {
  271. if (accessibilityHandler.getTableInterface() != nullptr)
  272. return new UIAScrollProvider (this);
  273. break;
  274. }
  275. case UIA_ScrollItemPatternId:
  276. {
  277. if (isListOrTableCell (accessibilityHandler))
  278. return new UIAScrollItemProvider (this);
  279. break;
  280. }
  281. }
  282. return nullptr;
  283. }();
  284. return S_OK;
  285. });
  286. }
  287. JUCE_COMRESULT AccessibilityNativeHandle::GetPropertyValue (PROPERTYID propertyId, VARIANT* pRetVal)
  288. {
  289. return withCheckedComArgs (pRetVal, *this, [&]
  290. {
  291. VariantHelpers::clear (pRetVal);
  292. const auto role = accessibilityHandler.getRole();
  293. const auto state = accessibilityHandler.getCurrentState();
  294. const auto ignored = accessibilityHandler.isIgnored();
  295. using namespace ComTypes::Constants;
  296. switch (propertyId)
  297. {
  298. case UIA_AutomationIdPropertyId:
  299. VariantHelpers::setString (getAutomationId (accessibilityHandler), pRetVal);
  300. break;
  301. case UIA_ControlTypePropertyId:
  302. VariantHelpers::setInt (roleToControlTypeId (role), pRetVal);
  303. break;
  304. case UIA_FrameworkIdPropertyId:
  305. VariantHelpers::setString ("JUCE", pRetVal);
  306. break;
  307. case UIA_FullDescriptionPropertyId:
  308. VariantHelpers::setString (accessibilityHandler.getDescription(), pRetVal);
  309. break;
  310. case UIA_HelpTextPropertyId:
  311. VariantHelpers::setString (accessibilityHandler.getHelp(), pRetVal);
  312. break;
  313. case UIA_IsContentElementPropertyId:
  314. VariantHelpers::setBool (! ignored && accessibilityHandler.isVisibleWithinParent(),
  315. pRetVal);
  316. break;
  317. case UIA_IsControlElementPropertyId:
  318. VariantHelpers::setBool (true, pRetVal);
  319. break;
  320. case UIA_IsDialogPropertyId:
  321. VariantHelpers::setBool (role == AccessibilityRole::dialogWindow, pRetVal);
  322. break;
  323. case UIA_IsEnabledPropertyId:
  324. VariantHelpers::setBool (accessibilityHandler.getComponent().isEnabled(), pRetVal);
  325. break;
  326. case UIA_IsKeyboardFocusablePropertyId:
  327. VariantHelpers::setBool (state.isFocusable(), pRetVal);
  328. break;
  329. case UIA_HasKeyboardFocusPropertyId:
  330. VariantHelpers::setBool (accessibilityHandler.hasFocus (true), pRetVal);
  331. break;
  332. case UIA_IsOffscreenPropertyId:
  333. VariantHelpers::setBool (! accessibilityHandler.isVisibleWithinParent(), pRetVal);
  334. break;
  335. case UIA_IsPasswordPropertyId:
  336. if (auto* textInterface = accessibilityHandler.getTextInterface())
  337. VariantHelpers::setBool (textInterface->isDisplayingProtectedText(), pRetVal);
  338. break;
  339. case UIA_IsPeripheralPropertyId:
  340. VariantHelpers::setBool (role == AccessibilityRole::tooltip
  341. || role == AccessibilityRole::popupMenu
  342. || role == AccessibilityRole::splashScreen,
  343. pRetVal);
  344. break;
  345. case UIA_NamePropertyId:
  346. if (! ignored)
  347. VariantHelpers::setString (getElementName(), pRetVal);
  348. break;
  349. case UIA_ProcessIdPropertyId:
  350. VariantHelpers::setInt ((int) GetCurrentProcessId(), pRetVal);
  351. break;
  352. case UIA_NativeWindowHandlePropertyId:
  353. if (isFragmentRoot())
  354. VariantHelpers::setInt ((int) (pointer_sized_int) accessibilityHandler.getComponent().getWindowHandle(), pRetVal);
  355. break;
  356. }
  357. return S_OK;
  358. });
  359. }
  360. //==============================================================================
  361. JUCE_COMRESULT AccessibilityNativeHandle::Navigate (ComTypes::NavigateDirection direction, ComTypes::IRawElementProviderFragment** pRetVal)
  362. {
  363. return withCheckedComArgs (pRetVal, *this, [&]
  364. {
  365. auto* handler = [&]() -> AccessibilityHandler*
  366. {
  367. if (direction == ComTypes::NavigateDirection_Parent)
  368. return accessibilityHandler.getParent();
  369. if (direction == ComTypes::NavigateDirection_FirstChild
  370. || direction == ComTypes::NavigateDirection_LastChild)
  371. {
  372. auto children = accessibilityHandler.getChildren();
  373. return children.empty() ? nullptr
  374. : (direction == ComTypes::NavigateDirection_FirstChild ? children.front()
  375. : children.back());
  376. }
  377. if (direction == ComTypes::NavigateDirection_NextSibling
  378. || direction == ComTypes::NavigateDirection_PreviousSibling)
  379. {
  380. if (auto* parent = accessibilityHandler.getParent())
  381. {
  382. const auto siblings = parent->getChildren();
  383. const auto iter = std::find (siblings.cbegin(), siblings.cend(), &accessibilityHandler);
  384. if (iter == siblings.end())
  385. return nullptr;
  386. if (direction == ComTypes::NavigateDirection_NextSibling && iter != std::prev (siblings.cend()))
  387. return *std::next (iter);
  388. if (direction == ComTypes::NavigateDirection_PreviousSibling && iter != siblings.cbegin())
  389. return *std::prev (iter);
  390. }
  391. }
  392. return nullptr;
  393. }();
  394. if (handler != nullptr)
  395. if (auto* provider = handler->getNativeImplementation())
  396. if (provider->isElementValid())
  397. provider->QueryInterface (IID_PPV_ARGS (pRetVal));
  398. return S_OK;
  399. });
  400. }
  401. JUCE_COMRESULT AccessibilityNativeHandle::GetRuntimeId (SAFEARRAY** pRetVal)
  402. {
  403. return withCheckedComArgs (pRetVal, *this, [&]
  404. {
  405. if (! isFragmentRoot())
  406. {
  407. *pRetVal = SafeArrayCreateVector (VT_I4, 0, 2);
  408. if (*pRetVal == nullptr)
  409. return E_OUTOFMEMORY;
  410. for (LONG i = 0; i < 2; ++i)
  411. {
  412. auto hr = SafeArrayPutElement (*pRetVal, &i, &rtid[(size_t) i]);
  413. if (FAILED (hr))
  414. return E_FAIL;
  415. }
  416. }
  417. return S_OK;
  418. });
  419. }
  420. JUCE_COMRESULT AccessibilityNativeHandle::get_BoundingRectangle (ComTypes::UiaRect* pRetVal)
  421. {
  422. return withCheckedComArgs (pRetVal, *this, [&]
  423. {
  424. auto bounds = Desktop::getInstance().getDisplays()
  425. .logicalToPhysical (accessibilityHandler.getComponent().getScreenBounds());
  426. pRetVal->left = bounds.getX();
  427. pRetVal->top = bounds.getY();
  428. pRetVal->width = bounds.getWidth();
  429. pRetVal->height = bounds.getHeight();
  430. return S_OK;
  431. });
  432. }
  433. JUCE_COMRESULT AccessibilityNativeHandle::GetEmbeddedFragmentRoots (SAFEARRAY** pRetVal)
  434. {
  435. return withCheckedComArgs (pRetVal, *this, []
  436. {
  437. return S_OK;
  438. });
  439. }
  440. JUCE_COMRESULT AccessibilityNativeHandle::SetFocus()
  441. {
  442. if (! isElementValid())
  443. return (HRESULT) UIA_E_ELEMENTNOTAVAILABLE;
  444. const WeakReference<Component> safeComponent (&accessibilityHandler.getComponent());
  445. accessibilityHandler.getActions().invoke (AccessibilityActionType::focus);
  446. if (safeComponent != nullptr)
  447. accessibilityHandler.grabFocus();
  448. return S_OK;
  449. }
  450. JUCE_COMRESULT AccessibilityNativeHandle::get_FragmentRoot (ComTypes::IRawElementProviderFragmentRoot** pRetVal)
  451. {
  452. return withCheckedComArgs (pRetVal, *this, [&]() -> HRESULT
  453. {
  454. auto* handler = [&]() -> AccessibilityHandler*
  455. {
  456. if (isFragmentRoot())
  457. return &accessibilityHandler;
  458. if (auto* peer = accessibilityHandler.getComponent().getPeer())
  459. return peer->getComponent().getAccessibilityHandler();
  460. return nullptr;
  461. }();
  462. if (handler != nullptr)
  463. {
  464. handler->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  465. return S_OK;
  466. }
  467. return (HRESULT) UIA_E_ELEMENTNOTAVAILABLE;
  468. });
  469. }
  470. //==============================================================================
  471. JUCE_COMRESULT AccessibilityNativeHandle::ElementProviderFromPoint (double x, double y, ComTypes::IRawElementProviderFragment** pRetVal)
  472. {
  473. return withCheckedComArgs (pRetVal, *this, [&]
  474. {
  475. auto* handler = [&]
  476. {
  477. auto logicalScreenPoint = Desktop::getInstance().getDisplays()
  478. .physicalToLogical (Point<int> (roundToInt (x),
  479. roundToInt (y)));
  480. if (auto* child = accessibilityHandler.getChildAt (logicalScreenPoint))
  481. return child;
  482. return &accessibilityHandler;
  483. }();
  484. handler->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  485. return S_OK;
  486. });
  487. }
  488. JUCE_COMRESULT AccessibilityNativeHandle::GetFocus (ComTypes::IRawElementProviderFragment** pRetVal)
  489. {
  490. return withCheckedComArgs (pRetVal, *this, [&]
  491. {
  492. const auto getFocusHandler = [this]() -> AccessibilityHandler*
  493. {
  494. if (auto* modal = Component::getCurrentlyModalComponent())
  495. {
  496. const auto& component = accessibilityHandler.getComponent();
  497. if (! component.isParentOf (modal)
  498. && component.isCurrentlyBlockedByAnotherModalComponent())
  499. {
  500. if (auto* modalHandler = modal->getAccessibilityHandler())
  501. {
  502. if (auto* focusChild = modalHandler->getChildFocus())
  503. return focusChild;
  504. return modalHandler;
  505. }
  506. }
  507. }
  508. if (auto* focusChild = accessibilityHandler.getChildFocus())
  509. return focusChild;
  510. return nullptr;
  511. };
  512. if (auto* focusHandler = getFocusHandler())
  513. focusHandler->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  514. return S_OK;
  515. });
  516. }
  517. JUCE_COMRESULT AccessibilityNativeHandle::GetOverrideProviderForHwnd (HWND hwnd, IRawElementProviderSimple** pRetVal)
  518. {
  519. return withCheckedComArgs (pRetVal, *this, [&]
  520. {
  521. if (auto* component = AccessibilityHandler::getComponentForNativeChild (hwnd))
  522. if (auto* handler = component->getAccessibilityHandler())
  523. handler->getNativeImplementation()->QueryInterface (IID_PPV_ARGS (pRetVal));
  524. return S_OK;
  525. });
  526. }
  527. //==============================================================================
  528. String AccessibilityNativeHandle::getElementName() const
  529. {
  530. if (accessibilityHandler.getRole() == AccessibilityRole::tooltip)
  531. return accessibilityHandler.getDescription();
  532. auto name = accessibilityHandler.getTitle();
  533. if (name.isEmpty() && isFragmentRoot())
  534. return detail::AccessibilityHelpers::getApplicationOrPluginName();
  535. return name;
  536. }
  537. JUCE_END_IGNORE_WARNINGS_GCC_LIKE
  538. } // namespace juce