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.

801 lines
29KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - 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 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-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. //==============================================================================
  21. static int numAlwaysOnTopPeers = 0;
  22. bool juce_areThereAnyAlwaysOnTopWindows() { return numAlwaysOnTopPeers > 0; }
  23. //==============================================================================
  24. class LinuxComponentPeer : public ComponentPeer
  25. {
  26. public:
  27. LinuxComponentPeer (Component& comp, int windowStyleFlags, ::Window parentToAddTo)
  28. : ComponentPeer (comp, windowStyleFlags),
  29. isAlwaysOnTop (comp.isAlwaysOnTop())
  30. {
  31. // it's dangerous to create a window on a thread other than the message thread.
  32. JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
  33. if (! XWindowSystem::getInstance()->isX11Available())
  34. return;
  35. if (isAlwaysOnTop)
  36. ++numAlwaysOnTopPeers;
  37. repainter = std::make_unique<LinuxRepaintManager> (*this);
  38. windowH = XWindowSystem::getInstance()->createWindow (parentToAddTo, this);
  39. parentWindow = parentToAddTo;
  40. setTitle (component.getName());
  41. getNativeRealtimeModifiers = []() -> ModifierKeys { return XWindowSystem::getInstance()->getNativeRealtimeModifiers(); };
  42. }
  43. ~LinuxComponentPeer() override
  44. {
  45. // it's dangerous to delete a window on a thread other than the message thread.
  46. JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
  47. repainter = nullptr;
  48. XWindowSystem::getInstance()->destroyWindow (windowH);
  49. if (isAlwaysOnTop)
  50. --numAlwaysOnTopPeers;
  51. }
  52. ::Window getWindowHandle() const noexcept
  53. {
  54. return windowH;
  55. }
  56. //==============================================================================
  57. void* getNativeHandle() const override
  58. {
  59. return reinterpret_cast<void*> (getWindowHandle());
  60. }
  61. //==============================================================================
  62. void setBounds (const Rectangle<int>& newBounds, bool isNowFullScreen) override
  63. {
  64. const auto correctedNewBounds = newBounds.withSize (jmax (1, newBounds.getWidth()),
  65. jmax (1, newBounds.getHeight()));
  66. if (bounds == correctedNewBounds && fullScreen == isNowFullScreen)
  67. return;
  68. bounds = correctedNewBounds;
  69. updateScaleFactorFromNewBounds (bounds, false);
  70. auto physicalBounds = parentWindow == 0 ? Desktop::getInstance().getDisplays().logicalToPhysical (bounds)
  71. : bounds * currentScaleFactor;
  72. WeakReference<Component> deletionChecker (&component);
  73. XWindowSystem::getInstance()->setBounds (windowH, physicalBounds, isNowFullScreen);
  74. fullScreen = isNowFullScreen;
  75. if (deletionChecker != nullptr)
  76. {
  77. updateBorderSize();
  78. handleMovedOrResized();
  79. }
  80. }
  81. Point<int> getScreenPosition (bool physical) const
  82. {
  83. auto physicalParentPosition = XWindowSystem::getInstance()->getPhysicalParentScreenPosition();
  84. auto parentPosition = parentWindow == 0 ? Desktop::getInstance().getDisplays().physicalToLogical (physicalParentPosition)
  85. : physicalParentPosition / currentScaleFactor;
  86. auto screenBounds = parentWindow == 0 ? bounds
  87. : bounds.translated (parentPosition.x, parentPosition.y);
  88. if (physical)
  89. return parentWindow == 0 ? Desktop::getInstance().getDisplays().logicalToPhysical (screenBounds.getTopLeft())
  90. : screenBounds.getTopLeft() * currentScaleFactor;
  91. return screenBounds.getTopLeft();
  92. }
  93. Rectangle<int> getBounds() const override
  94. {
  95. return bounds;
  96. }
  97. BorderSize<int> getFrameSize() const override
  98. {
  99. return windowBorder;
  100. }
  101. Point<float> localToGlobal (Point<float> relativePosition) override
  102. {
  103. return relativePosition + getScreenPosition (false).toFloat();
  104. }
  105. Point<float> globalToLocal (Point<float> screenPosition) override
  106. {
  107. return screenPosition - getScreenPosition (false).toFloat();
  108. }
  109. using ComponentPeer::localToGlobal;
  110. using ComponentPeer::globalToLocal;
  111. //==============================================================================
  112. StringArray getAvailableRenderingEngines() override
  113. {
  114. return { "Software Renderer" };
  115. }
  116. void setVisible (bool shouldBeVisible) override
  117. {
  118. XWindowSystem::getInstance()->setVisible (windowH, shouldBeVisible);
  119. }
  120. void setTitle (const String& title) override
  121. {
  122. XWindowSystem::getInstance()->setTitle (windowH, title);
  123. }
  124. void setMinimised (bool shouldBeMinimised) override
  125. {
  126. if (shouldBeMinimised)
  127. XWindowSystem::getInstance()->setMinimised (windowH, shouldBeMinimised);
  128. else
  129. setVisible (true);
  130. }
  131. bool isMinimised() const override
  132. {
  133. return XWindowSystem::getInstance()->isMinimised (windowH);
  134. }
  135. void setFullScreen (bool shouldBeFullScreen) override
  136. {
  137. auto r = lastNonFullscreenBounds; // (get a copy of this before de-minimising)
  138. setMinimised (false);
  139. if (fullScreen != shouldBeFullScreen)
  140. {
  141. const auto usingNativeTitleBar = ((styleFlags & windowHasTitleBar) != 0);
  142. if (usingNativeTitleBar)
  143. XWindowSystem::getInstance()->setMaximised (windowH, shouldBeFullScreen);
  144. if (shouldBeFullScreen)
  145. r = usingNativeTitleBar ? XWindowSystem::getInstance()->getWindowBounds (windowH, parentWindow)
  146. : Desktop::getInstance().getDisplays().getDisplayForRect (bounds)->userArea;
  147. if (! r.isEmpty())
  148. setBounds (ScalingHelpers::scaledScreenPosToUnscaled (component, r), shouldBeFullScreen);
  149. component.repaint();
  150. }
  151. }
  152. bool isFullScreen() const override
  153. {
  154. return fullScreen;
  155. }
  156. bool contains (Point<int> localPos, bool trueIfInAChildWindow) const override
  157. {
  158. if (! bounds.withZeroOrigin().contains (localPos))
  159. return false;
  160. for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;)
  161. {
  162. auto* c = Desktop::getInstance().getComponent (i);
  163. if (c == &component)
  164. break;
  165. if (! c->isVisible())
  166. continue;
  167. if (auto* peer = c->getPeer())
  168. if (peer->contains (localPos + bounds.getPosition() - peer->getBounds().getPosition(), true))
  169. return false;
  170. }
  171. if (trueIfInAChildWindow)
  172. return true;
  173. return XWindowSystem::getInstance()->contains (windowH, localPos * currentScaleFactor);
  174. }
  175. void toFront (bool makeActive) override
  176. {
  177. if (makeActive)
  178. {
  179. setVisible (true);
  180. grabFocus();
  181. }
  182. XWindowSystem::getInstance()->toFront (windowH, makeActive);
  183. handleBroughtToFront();
  184. }
  185. void toBehind (ComponentPeer* other) override
  186. {
  187. if (auto* otherPeer = dynamic_cast<LinuxComponentPeer*> (other))
  188. {
  189. if (otherPeer->styleFlags & windowIsTemporary)
  190. return;
  191. setMinimised (false);
  192. XWindowSystem::getInstance()->toBehind (windowH, otherPeer->windowH);
  193. }
  194. else
  195. {
  196. jassertfalse; // wrong type of window?
  197. }
  198. }
  199. bool isFocused() const override
  200. {
  201. return XWindowSystem::getInstance()->isFocused (windowH);
  202. }
  203. void grabFocus() override
  204. {
  205. if (XWindowSystem::getInstance()->grabFocus (windowH))
  206. isActiveApplication = true;
  207. }
  208. //==============================================================================
  209. void repaint (const Rectangle<int>& area) override
  210. {
  211. if (repainter != nullptr)
  212. repainter->repaint (area.getIntersection (bounds.withZeroOrigin()));
  213. }
  214. void performAnyPendingRepaintsNow() override
  215. {
  216. if (repainter != nullptr)
  217. repainter->performAnyPendingRepaintsNow();
  218. }
  219. void setIcon (const Image& newIcon) override
  220. {
  221. XWindowSystem::getInstance()->setIcon (windowH, newIcon);
  222. }
  223. double getPlatformScaleFactor() const noexcept override
  224. {
  225. return currentScaleFactor;
  226. }
  227. void setAlpha (float) override {}
  228. bool setAlwaysOnTop (bool) override { return false; }
  229. void textInputRequired (Point<int>, TextInputTarget&) override {}
  230. //==============================================================================
  231. void addOpenGLRepaintListener (Component* dummy)
  232. {
  233. if (dummy != nullptr)
  234. glRepaintListeners.addIfNotAlreadyThere (dummy);
  235. }
  236. void removeOpenGLRepaintListener (Component* dummy)
  237. {
  238. if (dummy != nullptr)
  239. glRepaintListeners.removeAllInstancesOf (dummy);
  240. }
  241. void repaintOpenGLContexts()
  242. {
  243. for (auto* c : glRepaintListeners)
  244. c->handleCommandMessage (0);
  245. }
  246. //==============================================================================
  247. ::Window getParentWindow() { return parentWindow; }
  248. void setParentWindow (::Window newParent) { parentWindow = newParent; }
  249. //==============================================================================
  250. void updateWindowBounds()
  251. {
  252. jassert (windowH != 0);
  253. if (windowH != 0)
  254. {
  255. auto physicalBounds = XWindowSystem::getInstance()->getWindowBounds (windowH, parentWindow);
  256. updateScaleFactorFromNewBounds (physicalBounds, true);
  257. bounds = parentWindow == 0 ? Desktop::getInstance().getDisplays().physicalToLogical (physicalBounds)
  258. : physicalBounds / currentScaleFactor;
  259. }
  260. }
  261. void updateBorderSize()
  262. {
  263. if ((styleFlags & windowHasTitleBar) == 0)
  264. windowBorder = {};
  265. else if (windowBorder.getTopAndBottom() == 0 && windowBorder.getLeftAndRight() == 0)
  266. windowBorder = XWindowSystem::getInstance()->getBorderSize (windowH);
  267. }
  268. //==============================================================================
  269. static bool isActiveApplication;
  270. bool focused = false;
  271. private:
  272. //==============================================================================
  273. class LinuxRepaintManager : public Timer
  274. {
  275. public:
  276. LinuxRepaintManager (LinuxComponentPeer& p)
  277. : peer (p),
  278. isSemiTransparentWindow ((peer.getStyleFlags() & ComponentPeer::windowIsSemiTransparent) != 0)
  279. {
  280. }
  281. void timerCallback() override
  282. {
  283. XWindowSystem::getInstance()->processPendingPaintsForWindow (peer.windowH);
  284. if (XWindowSystem::getInstance()->getNumPaintsPendingForWindow (peer.windowH) > 0)
  285. return;
  286. if (! regionsNeedingRepaint.isEmpty())
  287. {
  288. stopTimer();
  289. performAnyPendingRepaintsNow();
  290. }
  291. else if (Time::getApproximateMillisecondCounter() > lastTimeImageUsed + 3000)
  292. {
  293. stopTimer();
  294. image = Image();
  295. }
  296. }
  297. void repaint (Rectangle<int> area)
  298. {
  299. if (! isTimerRunning())
  300. startTimer (repaintTimerPeriod);
  301. regionsNeedingRepaint.add (area * peer.currentScaleFactor);
  302. }
  303. void performAnyPendingRepaintsNow()
  304. {
  305. if (XWindowSystem::getInstance()->getNumPaintsPendingForWindow (peer.windowH) > 0)
  306. {
  307. startTimer (repaintTimerPeriod);
  308. return;
  309. }
  310. auto originalRepaintRegion = regionsNeedingRepaint;
  311. regionsNeedingRepaint.clear();
  312. auto totalArea = originalRepaintRegion.getBounds();
  313. if (! totalArea.isEmpty())
  314. {
  315. if (image.isNull() || image.getWidth() < totalArea.getWidth()
  316. || image.getHeight() < totalArea.getHeight())
  317. {
  318. image = XWindowSystem::getInstance()->createImage (isSemiTransparentWindow,
  319. totalArea.getWidth(), totalArea.getHeight(),
  320. useARGBImagesForRendering);
  321. }
  322. startTimer (repaintTimerPeriod);
  323. RectangleList<int> adjustedList (originalRepaintRegion);
  324. adjustedList.offsetAll (-totalArea.getX(), -totalArea.getY());
  325. if (XWindowSystem::getInstance()->canUseARGBImages())
  326. for (auto& i : originalRepaintRegion)
  327. image.clear (i - totalArea.getPosition());
  328. {
  329. auto context = peer.getComponent().getLookAndFeel()
  330. .createGraphicsContext (image, -totalArea.getPosition(), adjustedList);
  331. context->addTransform (AffineTransform::scale ((float) peer.currentScaleFactor));
  332. peer.handlePaint (*context);
  333. }
  334. for (auto& i : originalRepaintRegion)
  335. XWindowSystem::getInstance()->blitToWindow (peer.windowH, image, i, totalArea);
  336. }
  337. lastTimeImageUsed = Time::getApproximateMillisecondCounter();
  338. startTimer (repaintTimerPeriod);
  339. }
  340. private:
  341. enum { repaintTimerPeriod = 1000 / 100 };
  342. LinuxComponentPeer& peer;
  343. const bool isSemiTransparentWindow;
  344. Image image;
  345. uint32 lastTimeImageUsed = 0;
  346. RectangleList<int> regionsNeedingRepaint;
  347. bool useARGBImagesForRendering = XWindowSystem::getInstance()->canUseARGBImages();
  348. JUCE_DECLARE_NON_COPYABLE (LinuxRepaintManager)
  349. };
  350. //==============================================================================
  351. void updateScaleFactorFromNewBounds (const Rectangle<int>& newBounds, bool isPhysical)
  352. {
  353. Point<int> translation = (parentWindow != 0 ? getScreenPosition (isPhysical) : Point<int>());
  354. const auto& desktop = Desktop::getInstance();
  355. if (auto* display = desktop.getDisplays().getDisplayForRect (newBounds.translated (translation.x, translation.y),
  356. isPhysical))
  357. {
  358. auto newScaleFactor = display->scale / desktop.getGlobalScaleFactor();
  359. if (! approximatelyEqual (newScaleFactor, currentScaleFactor))
  360. {
  361. currentScaleFactor = newScaleFactor;
  362. scaleFactorListeners.call ([&] (ScaleFactorListener& l) { l.nativeScaleFactorChanged (currentScaleFactor); });
  363. }
  364. }
  365. }
  366. //==============================================================================
  367. std::unique_ptr<LinuxRepaintManager> repainter;
  368. ::Window windowH = {}, parentWindow = {};
  369. Rectangle<int> bounds;
  370. BorderSize<int> windowBorder;
  371. bool fullScreen = false, isAlwaysOnTop = false;
  372. double currentScaleFactor = 1.0;
  373. Array<Component*> glRepaintListeners;
  374. //==============================================================================
  375. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LinuxComponentPeer)
  376. };
  377. bool LinuxComponentPeer::isActiveApplication = false;
  378. //==============================================================================
  379. ComponentPeer* Component::createNewPeer (int styleFlags, void* nativeWindowToAttachTo)
  380. {
  381. return new LinuxComponentPeer (*this, styleFlags, (::Window) nativeWindowToAttachTo);
  382. }
  383. //==============================================================================
  384. JUCE_API bool JUCE_CALLTYPE Process::isForegroundProcess() { return LinuxComponentPeer::isActiveApplication; }
  385. JUCE_API void JUCE_CALLTYPE Process::makeForegroundProcess() {}
  386. JUCE_API void JUCE_CALLTYPE Process::hide() {}
  387. //==============================================================================
  388. void Desktop::setKioskComponent (Component* comp, bool enableOrDisable, bool)
  389. {
  390. if (enableOrDisable)
  391. comp->setBounds (getDisplays().getDisplayForRect (comp->getScreenBounds())->totalArea);
  392. }
  393. void Displays::findDisplays (float masterScale)
  394. {
  395. if (XWindowSystem::getInstance()->getDisplay() != nullptr)
  396. {
  397. displays = XWindowSystem::getInstance()->findDisplays (masterScale);
  398. if (! displays.isEmpty())
  399. updateToLogical();
  400. }
  401. }
  402. bool Desktop::canUseSemiTransparentWindows() noexcept
  403. {
  404. return XWindowSystem::getInstance()->canUseSemiTransparentWindows();
  405. }
  406. static bool screenSaverAllowed = true;
  407. void Desktop::setScreenSaverEnabled (bool isEnabled)
  408. {
  409. if (screenSaverAllowed != isEnabled)
  410. {
  411. screenSaverAllowed = isEnabled;
  412. XWindowSystem::getInstance()->setScreenSaverEnabled (screenSaverAllowed);
  413. }
  414. }
  415. bool Desktop::isScreenSaverEnabled()
  416. {
  417. return screenSaverAllowed;
  418. }
  419. double Desktop::getDefaultMasterScale() { return 1.0; }
  420. Desktop::DisplayOrientation Desktop::getCurrentOrientation() const { return upright; }
  421. void Desktop::allowedOrientationsChanged() {}
  422. //==============================================================================
  423. bool MouseInputSource::SourceList::addSource()
  424. {
  425. if (sources.isEmpty())
  426. {
  427. addSource (0, MouseInputSource::InputSourceType::mouse);
  428. return true;
  429. }
  430. return false;
  431. }
  432. bool MouseInputSource::SourceList::canUseTouch()
  433. {
  434. return false;
  435. }
  436. Point<float> MouseInputSource::getCurrentRawMousePosition()
  437. {
  438. return Desktop::getInstance().getDisplays().physicalToLogical (XWindowSystem::getInstance()->getCurrentMousePosition());
  439. }
  440. void MouseInputSource::setRawMousePosition (Point<float> newPosition)
  441. {
  442. XWindowSystem::getInstance()->setMousePosition (Desktop::getInstance().getDisplays().logicalToPhysical (newPosition));
  443. }
  444. //==============================================================================
  445. void* CustomMouseCursorInfo::create() const
  446. {
  447. return XWindowSystem::getInstance()->createCustomMouseCursorInfo (image, hotspot);
  448. }
  449. void MouseCursor::deleteMouseCursor (void* cursorHandle, bool)
  450. {
  451. if (cursorHandle != nullptr)
  452. XWindowSystem::getInstance()->deleteMouseCursor (cursorHandle);
  453. }
  454. void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType type)
  455. {
  456. return XWindowSystem::getInstance()->createStandardMouseCursor (type);
  457. }
  458. void MouseCursor::showInWindow (ComponentPeer* peer) const
  459. {
  460. if (peer != nullptr)
  461. XWindowSystem::getInstance()->showCursor ((::Window) peer->getNativeHandle(), getHandle());
  462. }
  463. //==============================================================================
  464. static LinuxComponentPeer* getPeerForDragEvent (Component* sourceComp)
  465. {
  466. if (sourceComp == nullptr)
  467. if (auto* draggingSource = Desktop::getInstance().getDraggingMouseSource (0))
  468. sourceComp = draggingSource->getComponentUnderMouse();
  469. if (sourceComp != nullptr)
  470. if (auto* lp = dynamic_cast<LinuxComponentPeer*> (sourceComp->getPeer()))
  471. return lp;
  472. jassertfalse; // This method must be called in response to a component's mouseDown or mouseDrag event!
  473. return nullptr;
  474. }
  475. bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, bool canMoveFiles,
  476. Component* sourceComp, std::function<void()> callback)
  477. {
  478. if (files.isEmpty())
  479. return false;
  480. if (auto* peer = getPeerForDragEvent (sourceComp))
  481. return XWindowSystem::getInstance()->externalDragFileInit (peer, files, canMoveFiles, std::move (callback));
  482. // This method must be called in response to a component's mouseDown or mouseDrag event!
  483. jassertfalse;
  484. return false;
  485. }
  486. bool DragAndDropContainer::performExternalDragDropOfText (const String& text, Component* sourceComp,
  487. std::function<void()> callback)
  488. {
  489. if (text.isEmpty())
  490. return false;
  491. if (auto* peer = getPeerForDragEvent (sourceComp))
  492. return XWindowSystem::getInstance()->externalDragTextInit (peer, text, std::move (callback));
  493. // This method must be called in response to a component's mouseDown or mouseDrag event!
  494. jassertfalse;
  495. return false;
  496. }
  497. //==============================================================================
  498. void SystemClipboard::copyTextToClipboard (const String& clipText)
  499. {
  500. XWindowSystem::getInstance()->copyTextToClipboard (clipText);
  501. }
  502. String SystemClipboard::getTextFromClipboard()
  503. {
  504. return XWindowSystem::getInstance()->getTextFromClipboard();
  505. }
  506. //==============================================================================
  507. bool KeyPress::isKeyCurrentlyDown (int keyCode)
  508. {
  509. return XWindowSystem::getInstance()->isKeyCurrentlyDown (keyCode);
  510. }
  511. void LookAndFeel::playAlertSound()
  512. {
  513. std::cout << "\a" << std::flush;
  514. }
  515. //==============================================================================
  516. static int showDialog (const MessageBoxOptions& options,
  517. ModalComponentManager::Callback* callback,
  518. Async async)
  519. {
  520. const auto dummyCallback = [] (int) {};
  521. switch (options.getNumButtons())
  522. {
  523. case 2:
  524. {
  525. if (async == Async::yes && callback == nullptr)
  526. callback = ModalCallbackFunction::create (dummyCallback);
  527. return AlertWindow::showOkCancelBox (options.getIconType(),
  528. options.getTitle(),
  529. options.getMessage(),
  530. options.getButtonText (0),
  531. options.getButtonText (1),
  532. options.getAssociatedComponent(),
  533. callback) ? 1 : 0;
  534. }
  535. case 3:
  536. {
  537. if (async == Async::yes && callback == nullptr)
  538. callback = ModalCallbackFunction::create (dummyCallback);
  539. return AlertWindow::showYesNoCancelBox (options.getIconType(),
  540. options.getTitle(),
  541. options.getMessage(),
  542. options.getButtonText (0),
  543. options.getButtonText (1),
  544. options.getButtonText (2),
  545. options.getAssociatedComponent(),
  546. callback);
  547. }
  548. case 1:
  549. default:
  550. break;
  551. }
  552. #if JUCE_MODAL_LOOPS_PERMITTED
  553. if (async == Async::no)
  554. {
  555. AlertWindow::showMessageBox (options.getIconType(),
  556. options.getTitle(),
  557. options.getMessage(),
  558. options.getButtonText (0),
  559. options.getAssociatedComponent());
  560. }
  561. else
  562. #endif
  563. {
  564. AlertWindow::showMessageBoxAsync (options.getIconType(),
  565. options.getTitle(),
  566. options.getMessage(),
  567. options.getButtonText (0),
  568. options.getAssociatedComponent(),
  569. callback);
  570. }
  571. return 0;
  572. }
  573. #if JUCE_MODAL_LOOPS_PERMITTED
  574. void JUCE_CALLTYPE NativeMessageBox::showMessageBox (MessageBoxIconType iconType,
  575. const String& title, const String& message,
  576. Component* /*associatedComponent*/)
  577. {
  578. AlertWindow::showMessageBox (iconType, title, message);
  579. }
  580. int JUCE_CALLTYPE NativeMessageBox::show (const MessageBoxOptions& options)
  581. {
  582. return showDialog (options, nullptr, Async::no);
  583. }
  584. #endif
  585. void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (MessageBoxIconType iconType,
  586. const String& title, const String& message,
  587. Component* associatedComponent,
  588. ModalComponentManager::Callback* callback)
  589. {
  590. AlertWindow::showMessageBoxAsync (iconType, title, message, {}, associatedComponent, callback);
  591. }
  592. bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (MessageBoxIconType iconType,
  593. const String& title, const String& message,
  594. Component* associatedComponent,
  595. ModalComponentManager::Callback* callback)
  596. {
  597. return AlertWindow::showOkCancelBox (iconType, title, message, {}, {}, associatedComponent, callback);
  598. }
  599. int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (MessageBoxIconType iconType,
  600. const String& title, const String& message,
  601. Component* associatedComponent,
  602. ModalComponentManager::Callback* callback)
  603. {
  604. return AlertWindow::showYesNoCancelBox (iconType, title, message, {}, {}, {},
  605. associatedComponent, callback);
  606. }
  607. int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (MessageBoxIconType iconType,
  608. const String& title, const String& message,
  609. Component* associatedComponent,
  610. ModalComponentManager::Callback* callback)
  611. {
  612. return AlertWindow::showOkCancelBox (iconType, title, message, TRANS("Yes"), TRANS("No"),
  613. associatedComponent, callback);
  614. }
  615. void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options,
  616. ModalComponentManager::Callback* callback)
  617. {
  618. showDialog (options, callback, Async::yes);
  619. }
  620. void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options,
  621. std::function<void (int)> callback)
  622. {
  623. showAsync (options, ModalCallbackFunction::create (callback));
  624. }
  625. //==============================================================================
  626. Image juce_createIconForFile (const File&)
  627. {
  628. return {};
  629. }
  630. void juce_LinuxAddRepaintListener (ComponentPeer* peer, Component* dummy)
  631. {
  632. if (auto* linuxPeer = dynamic_cast<LinuxComponentPeer*> (peer))
  633. linuxPeer->addOpenGLRepaintListener (dummy);
  634. }
  635. void juce_LinuxRemoveRepaintListener (ComponentPeer* peer, Component* dummy)
  636. {
  637. if (auto* linuxPeer = dynamic_cast<LinuxComponentPeer*> (peer))
  638. linuxPeer->removeOpenGLRepaintListener (dummy);
  639. }
  640. } // namespace juce