Audio plugin host https://kx.studio/carla
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.

485 lines
20KB

  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. //==============================================================================
  21. /**
  22. Classes can implement this interface and register themselves with the Desktop class
  23. to receive callbacks when the currently focused component changes.
  24. @see Desktop::addFocusChangeListener, Desktop::removeFocusChangeListener
  25. @tags{GUI}
  26. */
  27. class JUCE_API FocusChangeListener
  28. {
  29. public:
  30. /** Destructor. */
  31. virtual ~FocusChangeListener() = default;
  32. /** Callback to indicate that the currently focused component has changed. */
  33. virtual void globalFocusChanged (Component* focusedComponent) = 0;
  34. };
  35. //==============================================================================
  36. /**
  37. Classes can implement this interface and register themselves with the Desktop class
  38. to receive callbacks when the operating system dark mode setting changes. The
  39. Desktop::isDarkModeActive() method can then be used to query the current setting.
  40. @see Desktop::addDarkModeSettingListener, Desktop::removeDarkModeSettingListener,
  41. Desktop::isDarkModeActive
  42. @tags{GUI}
  43. */
  44. class JUCE_API DarkModeSettingListener
  45. {
  46. public:
  47. /** Destructor. */
  48. virtual ~DarkModeSettingListener() = default;
  49. /** Callback to indicate that the dark mode setting has changed. */
  50. virtual void darkModeSettingChanged() = 0;
  51. };
  52. //==============================================================================
  53. /**
  54. Describes and controls aspects of the computer's desktop.
  55. @tags{GUI}
  56. */
  57. class JUCE_API Desktop : private DeletedAtShutdown,
  58. private Timer,
  59. private AsyncUpdater
  60. {
  61. public:
  62. //==============================================================================
  63. /** There's only one desktop object, and this method will return it. */
  64. static Desktop& JUCE_CALLTYPE getInstance();
  65. //==============================================================================
  66. /** Returns the mouse position.
  67. The coordinates are relative to the top-left of the main monitor.
  68. Note that this is just a shortcut for calling getMainMouseSource().getScreenPosition(), and
  69. you should only resort to grabbing the global mouse position if there's really no
  70. way to get the coordinates via a mouse event callback instead.
  71. */
  72. static Point<int> getMousePosition();
  73. /** Makes the mouse pointer jump to a given location.
  74. The coordinates are relative to the top-left of the main monitor.
  75. Note that this is a pretty old method, kept around mainly for backwards-compatibility,
  76. and you should use the MouseInputSource class directly in new code.
  77. */
  78. static void setMousePosition (Point<int> newPosition);
  79. /** Returns the last position at which a mouse button was pressed.
  80. Note that this is just a shortcut for calling getMainMouseSource().getLastMouseDownPosition(),
  81. and in a multi-touch environment, it doesn't make much sense. ALWAYS prefer to
  82. get this information via other means, such as MouseEvent::getMouseDownScreenPosition()
  83. if possible, and only ever call this as a last resort.
  84. */
  85. static Point<int> getLastMouseDownPosition();
  86. /** Returns the number of times the mouse button has been clicked since the app started.
  87. Each mouse-down event increments this number by 1.
  88. @see getMouseWheelMoveCounter
  89. */
  90. int getMouseButtonClickCounter() const noexcept;
  91. /** Returns the number of times the mouse wheel has been moved since the app started.
  92. Each mouse-wheel event increments this number by 1.
  93. @see getMouseButtonClickCounter
  94. */
  95. int getMouseWheelMoveCounter() const noexcept;
  96. //==============================================================================
  97. /** This lets you prevent the screensaver from becoming active.
  98. Handy if you're running some sort of presentation app where having a screensaver
  99. appear would be annoying.
  100. Pass false to disable the screensaver, and true to re-enable it. (Note that this
  101. won't enable a screensaver unless the user has actually set one up).
  102. The disablement will only happen while the JUCE application is the foreground
  103. process - if another task is running in front of it, then the screensaver will
  104. be unaffected.
  105. @see isScreenSaverEnabled
  106. */
  107. static void setScreenSaverEnabled (bool isEnabled);
  108. /** Returns true if the screensaver has not been turned off.
  109. This will return the last value passed into setScreenSaverEnabled(). Note that
  110. it won't tell you whether the user is actually using a screen saver, just
  111. whether this app is deliberately preventing one from running.
  112. @see setScreenSaverEnabled
  113. */
  114. static bool isScreenSaverEnabled();
  115. //==============================================================================
  116. /** Registers a MouseListener that will receive all mouse events that occur on
  117. any component.
  118. @see removeGlobalMouseListener
  119. */
  120. void addGlobalMouseListener (MouseListener* listener);
  121. /** Unregisters a MouseListener that was added with addGlobalMouseListener().
  122. @see addGlobalMouseListener
  123. */
  124. void removeGlobalMouseListener (MouseListener* listener);
  125. //==============================================================================
  126. /** Registers a FocusChangeListener that will receive a callback whenever the focused
  127. component changes.
  128. @see removeFocusChangeListener
  129. */
  130. void addFocusChangeListener (FocusChangeListener* listener);
  131. /** Unregisters a FocusChangeListener that was added with addFocusChangeListener().
  132. @see addFocusChangeListener
  133. */
  134. void removeFocusChangeListener (FocusChangeListener* listener);
  135. //==============================================================================
  136. /** Registers a DarkModeSettingListener that will receive a callback when the
  137. operating system dark mode setting changes. To query whether dark mode is on
  138. use the isDarkModeActive() method.
  139. @see isDarkModeActive, removeDarkModeSettingListener
  140. */
  141. void addDarkModeSettingListener (DarkModeSettingListener* listener);
  142. /** Unregisters a DarkModeSettingListener that was added with addDarkModeSettingListener().
  143. @see addDarkModeSettingListener
  144. */
  145. void removeDarkModeSettingListener (DarkModeSettingListener* listener);
  146. /** True if the operating system "dark mode" is active.
  147. To receive a callback when this setting changes implement the DarkModeSettingListener
  148. interface and use the addDarkModeSettingListener() to register a listener.
  149. @see addDarkModeSettingListener, removeDarkModeSettingListener
  150. */
  151. bool isDarkModeActive() const;
  152. //==============================================================================
  153. /** Takes a component and makes it full-screen, removing the taskbar, dock, etc.
  154. The component must already be on the desktop for this method to work. It will
  155. be resized to completely fill the screen and any extraneous taskbars, menu bars,
  156. etc will be hidden.
  157. To exit kiosk mode, just call setKioskModeComponent (nullptr). When this is called,
  158. the component that's currently being used will be resized back to the size
  159. and position it was in before being put into this mode.
  160. If allowMenusAndBars is true, things like the menu and dock (on mac) are still
  161. allowed to pop up when the mouse moves onto them. If this is false, it'll try
  162. to hide as much on-screen paraphernalia as possible.
  163. */
  164. void setKioskModeComponent (Component* componentToUse,
  165. bool allowMenusAndBars = true);
  166. /** Returns the component that is currently being used in kiosk-mode.
  167. This is the component that was last set by setKioskModeComponent(). If none
  168. has been set, this returns nullptr.
  169. */
  170. Component* getKioskModeComponent() const noexcept { return kioskModeComponent; }
  171. //==============================================================================
  172. /** Returns the number of components that are currently active as top-level
  173. desktop windows.
  174. @see getComponent, Component::addToDesktop
  175. */
  176. int getNumComponents() const noexcept;
  177. /** Returns one of the top-level desktop window components.
  178. The index is from 0 to getNumComponents() - 1. This could return 0 if the
  179. index is out-of-range.
  180. @see getNumComponents, Component::addToDesktop
  181. */
  182. Component* getComponent (int index) const noexcept;
  183. /** Finds the component at a given screen location.
  184. This will drill down into top-level windows to find the child component at
  185. the given position.
  186. Returns nullptr if the coordinates are inside a non-JUCE window.
  187. */
  188. Component* findComponentAt (Point<int> screenPosition) const;
  189. /** The Desktop object has a ComponentAnimator instance which can be used for performing
  190. your animations.
  191. Having a single shared ComponentAnimator object makes it more efficient when multiple
  192. components are being moved around simultaneously. It's also more convenient than having
  193. to manage your own instance of one.
  194. @see ComponentAnimator
  195. */
  196. ComponentAnimator& getAnimator() noexcept { return animator; }
  197. //==============================================================================
  198. /** Returns the current default look-and-feel for components which don't have one
  199. explicitly set.
  200. @see setDefaultLookAndFeel
  201. */
  202. LookAndFeel& getDefaultLookAndFeel() noexcept;
  203. /** Changes the default look-and-feel.
  204. @param newDefaultLookAndFeel the new look-and-feel object to use - if this is
  205. set to nullptr, it will revert to using the system's
  206. default one. The object passed-in must be deleted by the
  207. caller when it's no longer needed.
  208. @see getDefaultLookAndFeel
  209. */
  210. void setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel);
  211. //==============================================================================
  212. /** Provides access to the array of mouse sources, for iteration.
  213. In a traditional single-mouse system, there might be only one MouseInputSource. On a
  214. multi-touch system, there could be one input source per potential finger. The number
  215. of mouse sources returned here may increase dynamically as the program runs.
  216. To find out how many mouse events are currently happening, use getNumDraggingMouseSources().
  217. */
  218. const Array<MouseInputSource>& getMouseSources() const noexcept;
  219. /** Returns the number of MouseInputSource objects the system has at its disposal.
  220. In a traditional single-mouse system, there might be only one MouseInputSource. On a
  221. multi-touch system, there could be one input source per potential finger. The number
  222. of mouse sources returned here may increase dynamically as the program runs.
  223. To find out how many mouse events are currently happening, use getNumDraggingMouseSources().
  224. @see getMouseSource
  225. */
  226. int getNumMouseSources() const noexcept;
  227. /** Returns one of the system's MouseInputSource objects.
  228. The index should be from 0 to getNumMouseSources() - 1. Out-of-range indexes will return
  229. a null pointer.
  230. In a traditional single-mouse system, there might be only one object. On a multi-touch
  231. system, there could be one input source per potential finger.
  232. */
  233. MouseInputSource* getMouseSource (int index) const noexcept;
  234. /** Returns the main mouse input device that the system is using.
  235. @see getNumMouseSources()
  236. */
  237. MouseInputSource getMainMouseSource() const noexcept;
  238. /** Returns the number of mouse-sources that are currently being dragged.
  239. In a traditional single-mouse system, this will be 0 or 1, depending on whether a
  240. JUCE component has the button down on it. In a multi-touch system, this could
  241. be any number from 0 to the number of simultaneous touches that can be detected.
  242. */
  243. int getNumDraggingMouseSources() const noexcept;
  244. /** Returns one of the mouse sources that's currently being dragged.
  245. The index should be between 0 and getNumDraggingMouseSources() - 1. If the index is
  246. out of range, or if no mice or fingers are down, this will return a null pointer.
  247. */
  248. MouseInputSource* getDraggingMouseSource (int index) const noexcept;
  249. /** Ensures that a non-stop stream of mouse-drag events will be sent during the
  250. current mouse-drag operation.
  251. This allows you to make sure that mouseDrag() events are sent continuously, even
  252. when the mouse isn't moving. This can be useful for things like auto-scrolling
  253. components when the mouse is near an edge.
  254. Call this method during a mouseDown() or mouseDrag() callback, specifying the
  255. minimum interval between consecutive mouse drag callbacks. The callbacks
  256. will continue until the mouse is released, and then the interval will be reset,
  257. so you need to make sure it's called every time you begin a drag event.
  258. Passing an interval of 0 or less will cancel the auto-repeat.
  259. @see mouseDrag
  260. */
  261. void beginDragAutoRepeat (int millisecondsBetweenCallbacks);
  262. //==============================================================================
  263. /** In a tablet/mobile device which can be turned around, this is used to indicate the orientation. */
  264. enum DisplayOrientation
  265. {
  266. upright = 1, /**< Indicates that the device is the normal way up. */
  267. upsideDown = 2, /**< Indicates that the device is upside-down. */
  268. rotatedClockwise = 4, /**< Indicates that the device is turned 90 degrees clockwise from its upright position. */
  269. rotatedAntiClockwise = 8, /**< Indicates that the device is turned 90 degrees anti-clockwise from its upright position. */
  270. allOrientations = 1 + 2 + 4 + 8 /**< A combination of all the orientation values */
  271. };
  272. /** In a tablet device which can be turned around, this returns the current orientation. */
  273. DisplayOrientation getCurrentOrientation() const;
  274. /** Sets which orientations the display is allowed to auto-rotate to.
  275. For devices that support rotating desktops, this lets you specify which of the orientations your app can use.
  276. The parameter is a bitwise or-ed combination of the values in DisplayOrientation, and must contain at least one
  277. set bit.
  278. */
  279. void setOrientationsEnabled (int allowedOrientations);
  280. /** Returns the set of orientations the display is allowed to rotate to.
  281. @see setOrientationsEnabled
  282. */
  283. int getOrientationsEnabled() const noexcept;
  284. /** Returns whether the display is allowed to auto-rotate to the given orientation.
  285. Each orientation can be enabled using setOrientationEnabled(). By default, all orientations are allowed.
  286. */
  287. bool isOrientationEnabled (DisplayOrientation orientation) const noexcept;
  288. //==============================================================================
  289. /** Returns the Displays object representing the connected displays.
  290. @see Displays
  291. */
  292. const Displays& getDisplays() const noexcept { return *displays; }
  293. //==============================================================================
  294. /** Sets a global scale factor to be used for all desktop windows.
  295. Setting this will also scale the monitor sizes that are returned by getDisplays().
  296. */
  297. void setGlobalScaleFactor (float newScaleFactor) noexcept;
  298. /** Returns the current global scale factor, as set by setGlobalScaleFactor().
  299. @see setGlobalScaleFactor
  300. */
  301. float getGlobalScaleFactor() const noexcept { return masterScaleFactor; }
  302. //==============================================================================
  303. /** True if the OS supports semitransparent windows */
  304. static bool canUseSemiTransparentWindows() noexcept;
  305. #if JUCE_MAC && ! defined (DOXYGEN)
  306. [[deprecated ("This macOS-specific method has been deprecated in favour of the cross-platform "
  307. " isDarkModeActive() method.")]]
  308. static bool isOSXDarkModeActive() { return Desktop::getInstance().isDarkModeActive(); }
  309. #endif
  310. //==============================================================================
  311. /** Returns true on a headless system where there are no connected displays. */
  312. bool isHeadless() const noexcept;
  313. private:
  314. //==============================================================================
  315. static Desktop* instance;
  316. friend class Component;
  317. friend class ComponentPeer;
  318. friend class MouseInputSourceInternal;
  319. friend class DeletedAtShutdown;
  320. friend class TopLevelWindowManager;
  321. friend class Displays;
  322. std::unique_ptr<MouseInputSource::SourceList> mouseSources;
  323. ListenerList<MouseListener> mouseListeners;
  324. ListenerList<FocusChangeListener> focusListeners;
  325. ListenerList<DarkModeSettingListener> darkModeSettingListeners;
  326. Array<Component*> desktopComponents;
  327. Array<ComponentPeer*> peers;
  328. std::unique_ptr<Displays> displays;
  329. Point<float> lastFakeMouseMove;
  330. void sendMouseMove();
  331. int mouseClickCounter = 0, mouseWheelCounter = 0;
  332. void incrementMouseClickCounter() noexcept;
  333. void incrementMouseWheelCounter() noexcept;
  334. std::unique_ptr<LookAndFeel> defaultLookAndFeel;
  335. WeakReference<LookAndFeel> currentLookAndFeel;
  336. std::unique_ptr<FocusOutline> focusOutline;
  337. Component* kioskModeComponent = nullptr;
  338. Rectangle<int> kioskComponentOriginalBounds;
  339. bool kioskModeReentrant = false;
  340. int allowedOrientations = allOrientations;
  341. void allowedOrientationsChanged();
  342. float masterScaleFactor;
  343. ComponentAnimator animator;
  344. void timerCallback() override;
  345. void resetTimer();
  346. ListenerList<MouseListener>& getMouseListeners();
  347. void addDesktopComponent (Component*);
  348. void removeDesktopComponent (Component*);
  349. void componentBroughtToFront (Component*);
  350. void setKioskComponent (Component*, bool shouldBeEnabled, bool allowMenusAndBars);
  351. void triggerFocusCallback();
  352. void updateFocusOutline();
  353. void handleAsyncUpdate() override;
  354. static Point<float> getMousePositionFloat();
  355. static double getDefaultMasterScale();
  356. Desktop();
  357. ~Desktop() override;
  358. //==============================================================================
  359. class NativeDarkModeChangeDetectorImpl;
  360. std::unique_ptr<NativeDarkModeChangeDetectorImpl> nativeDarkModeChangeDetectorImpl;
  361. static std::unique_ptr<NativeDarkModeChangeDetectorImpl> createNativeDarkModeChangeDetectorImpl();
  362. void darkModeChanged();
  363. //==============================================================================
  364. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Desktop)
  365. };
  366. } // namespace juce