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.

435 lines
18KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #ifndef __JUCE_DESKTOP_JUCEHEADER__
  19. #define __JUCE_DESKTOP_JUCEHEADER__
  20. #include "juce_Component.h"
  21. #include "../layout/juce_ComponentAnimator.h"
  22. class MouseInputSource;
  23. class MouseInputSourceInternal;
  24. class MouseListener;
  25. //==============================================================================
  26. /**
  27. Classes can implement this interface and register themselves with the Desktop class
  28. to receive callbacks when the currently focused component changes.
  29. @see Desktop::addFocusChangeListener, Desktop::removeFocusChangeListener
  30. */
  31. class JUCE_API FocusChangeListener
  32. {
  33. public:
  34. /** Destructor. */
  35. virtual ~FocusChangeListener() {}
  36. /** Callback to indicate that the currently focused component has changed. */
  37. virtual void globalFocusChanged (Component* focusedComponent) = 0;
  38. };
  39. //==============================================================================
  40. /**
  41. Describes and controls aspects of the computer's desktop.
  42. */
  43. class JUCE_API Desktop : private DeletedAtShutdown,
  44. private Timer,
  45. private AsyncUpdater
  46. {
  47. public:
  48. //==============================================================================
  49. /** There's only one dektop object, and this method will return it.
  50. */
  51. static Desktop& JUCE_CALLTYPE getInstance();
  52. //==============================================================================
  53. /** Returns the mouse position.
  54. The co-ordinates are relative to the top-left of the main monitor.
  55. Note that this is just a shortcut for calling getMainMouseSource().getScreenPosition(), and
  56. you should only resort to grabbing the global mouse position if there's really no
  57. way to get the coordinates via a mouse event callback instead.
  58. */
  59. static Point<int> getMousePosition();
  60. /** Makes the mouse pointer jump to a given location.
  61. The co-ordinates are relative to the top-left of the main monitor.
  62. */
  63. static void setMousePosition (const Point<int>& newPosition);
  64. /** Returns the last position at which a mouse button was pressed.
  65. Note that this is just a shortcut for calling getMainMouseSource().getLastMouseDownPosition(),
  66. and in a multi-touch environment, it doesn't make much sense. ALWAYS prefer to
  67. get this information via other means, such as MouseEvent::getMouseDownScreenPosition()
  68. if possible, and only ever call this as a last resort.
  69. */
  70. static Point<int> getLastMouseDownPosition();
  71. /** Returns the number of times the mouse button has been clicked since the app started.
  72. Each mouse-down event increments this number by 1.
  73. @see getMouseWheelMoveCounter
  74. */
  75. int getMouseButtonClickCounter() const noexcept;
  76. /** Returns the number of times the mouse wheel has been moved since the app started.
  77. Each mouse-wheel event increments this number by 1.
  78. @see getMouseButtonClickCounter
  79. */
  80. int getMouseWheelMoveCounter() const noexcept;
  81. //==============================================================================
  82. /** This lets you prevent the screensaver from becoming active.
  83. Handy if you're running some sort of presentation app where having a screensaver
  84. appear would be annoying.
  85. Pass false to disable the screensaver, and true to re-enable it. (Note that this
  86. won't enable a screensaver unless the user has actually set one up).
  87. The disablement will only happen while the Juce application is the foreground
  88. process - if another task is running in front of it, then the screensaver will
  89. be unaffected.
  90. @see isScreenSaverEnabled
  91. */
  92. static void setScreenSaverEnabled (bool isEnabled);
  93. /** Returns true if the screensaver has not been turned off.
  94. This will return the last value passed into setScreenSaverEnabled(). Note that
  95. it won't tell you whether the user is actually using a screen saver, just
  96. whether this app is deliberately preventing one from running.
  97. @see setScreenSaverEnabled
  98. */
  99. static bool isScreenSaverEnabled();
  100. //==============================================================================
  101. /** Registers a MouseListener that will receive all mouse events that occur on
  102. any component.
  103. @see removeGlobalMouseListener
  104. */
  105. void addGlobalMouseListener (MouseListener* listener);
  106. /** Unregisters a MouseListener that was added with the addGlobalMouseListener()
  107. method.
  108. @see addGlobalMouseListener
  109. */
  110. void removeGlobalMouseListener (MouseListener* listener);
  111. //==============================================================================
  112. /** Registers a MouseListener that will receive a callback whenever the focused
  113. component changes.
  114. */
  115. void addFocusChangeListener (FocusChangeListener* listener);
  116. /** Unregisters a listener that was added with addFocusChangeListener(). */
  117. void removeFocusChangeListener (FocusChangeListener* listener);
  118. //==============================================================================
  119. /** Takes a component and makes it full-screen, removing the taskbar, dock, etc.
  120. The component must already be on the desktop for this method to work. It will
  121. be resized to completely fill the screen and any extraneous taskbars, menu bars,
  122. etc will be hidden.
  123. To exit kiosk mode, just call setKioskModeComponent (nullptr). When this is called,
  124. the component that's currently being used will be resized back to the size
  125. and position it was in before being put into this mode.
  126. If allowMenusAndBars is true, things like the menu and dock (on mac) are still
  127. allowed to pop up when the mouse moves onto them. If this is false, it'll try
  128. to hide as much on-screen paraphenalia as possible.
  129. */
  130. void setKioskModeComponent (Component* componentToUse,
  131. bool allowMenusAndBars = true);
  132. /** Returns the component that is currently being used in kiosk-mode.
  133. This is the component that was last set by setKioskModeComponent(). If none
  134. has been set, this returns 0.
  135. */
  136. Component* getKioskModeComponent() const noexcept { return kioskModeComponent; }
  137. //==============================================================================
  138. /** Returns the number of components that are currently active as top-level
  139. desktop windows.
  140. @see getComponent, Component::addToDesktop
  141. */
  142. int getNumComponents() const noexcept;
  143. /** Returns one of the top-level desktop window components.
  144. The index is from 0 to getNumComponents() - 1. This could return 0 if the
  145. index is out-of-range.
  146. @see getNumComponents, Component::addToDesktop
  147. */
  148. Component* getComponent (int index) const noexcept;
  149. /** Finds the component at a given screen location.
  150. This will drill down into top-level windows to find the child component at
  151. the given position.
  152. Returns 0 if the co-ordinates are inside a non-Juce window.
  153. */
  154. Component* findComponentAt (const Point<int>& screenPosition) const;
  155. /** The Desktop object has a ComponentAnimator instance which can be used for performing
  156. your animations.
  157. Having a single shared ComponentAnimator object makes it more efficient when multiple
  158. components are being moved around simultaneously. It's also more convenient than having
  159. to manage your own instance of one.
  160. @see ComponentAnimator
  161. */
  162. ComponentAnimator& getAnimator() noexcept { return animator; }
  163. //==============================================================================
  164. /** Returns the current default look-and-feel for components which don't have one
  165. explicitly set.
  166. @see setDefaultLookAndFeel
  167. */
  168. LookAndFeel& getDefaultLookAndFeel() noexcept;
  169. /** Changes the default look-and-feel.
  170. @param newDefaultLookAndFeel the new look-and-feel object to use - if this is
  171. set to nullptr, it will revert to using the system's
  172. default one. The object passed-in must be deleted by the
  173. caller when it's no longer needed.
  174. @see getDefaultLookAndFeel
  175. */
  176. void setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel);
  177. //==============================================================================
  178. /** Returns the number of MouseInputSource objects the system has at its disposal.
  179. In a traditional single-mouse system, there might be only one object. On a multi-touch
  180. system, there could be one input source per potential finger.
  181. To find out how many mouse events are currently happening, use getNumDraggingMouseSources().
  182. @see getMouseSource
  183. */
  184. int getNumMouseSources() const noexcept { return mouseSources.size(); }
  185. /** Returns one of the system's MouseInputSource objects.
  186. The index should be from 0 to getNumMouseSources() - 1. Out-of-range indexes will return
  187. a null pointer.
  188. In a traditional single-mouse system, there might be only one object. On a multi-touch
  189. system, there could be one input source per potential finger.
  190. */
  191. MouseInputSource* getMouseSource (int index) const noexcept { return mouseSources [index]; }
  192. /** Returns the main mouse input device that the system is using.
  193. @see getNumMouseSources()
  194. */
  195. MouseInputSource& getMainMouseSource() const noexcept { return *mouseSources.getUnchecked(0); }
  196. /** Returns the number of mouse-sources that are currently being dragged.
  197. In a traditional single-mouse system, this will be 0 or 1, depending on whether a
  198. juce component has the button down on it. In a multi-touch system, this could
  199. be any number from 0 to the number of simultaneous touches that can be detected.
  200. */
  201. int getNumDraggingMouseSources() const noexcept;
  202. /** Returns one of the mouse sources that's currently being dragged.
  203. The index should be between 0 and getNumDraggingMouseSources() - 1. If the index is
  204. out of range, or if no mice or fingers are down, this will return a null pointer.
  205. */
  206. MouseInputSource* getDraggingMouseSource (int index) const noexcept;
  207. /** Ensures that a non-stop stream of mouse-drag events will be sent during the
  208. current mouse-drag operation.
  209. This allows you to make sure that mouseDrag() events are sent continuously, even
  210. when the mouse isn't moving. This can be useful for things like auto-scrolling
  211. components when the mouse is near an edge.
  212. Call this method during a mouseDown() or mouseDrag() callback, specifying the
  213. minimum interval between consecutive mouse drag callbacks. The callbacks
  214. will continue until the mouse is released, and then the interval will be reset,
  215. so you need to make sure it's called every time you begin a drag event.
  216. Passing an interval of 0 or less will cancel the auto-repeat.
  217. @see mouseDrag
  218. */
  219. void beginDragAutoRepeat (int millisecondsBetweenCallbacks);
  220. //==============================================================================
  221. /** In a tablet device which can be turned around, this is used to inidicate the orientation. */
  222. enum DisplayOrientation
  223. {
  224. upright = 1, /**< Indicates that the display is the normal way up. */
  225. upsideDown = 2, /**< Indicates that the display is upside-down. */
  226. rotatedClockwise = 4, /**< Indicates that the display is turned 90 degrees clockwise from its upright position. */
  227. rotatedAntiClockwise = 8, /**< Indicates that the display is turned 90 degrees anti-clockwise from its upright position. */
  228. allOrientations = 1 + 2 + 4 + 8 /**< A combination of all the orientation values */
  229. };
  230. /** In a tablet device which can be turned around, this returns the current orientation. */
  231. DisplayOrientation getCurrentOrientation() const;
  232. /** Sets which orientations the display is allowed to auto-rotate to.
  233. For devices that support rotating desktops, this lets you specify which of the orientations your app can use.
  234. The parameter is a bitwise or-ed combination of the values in DisplayOrientation, and must contain at least one
  235. set bit.
  236. */
  237. void setOrientationsEnabled (int allowedOrientations);
  238. /** Returns whether the display is allowed to auto-rotate to the given orientation.
  239. Each orientation can be enabled using setOrientationEnabled(). By default, all orientations are allowed.
  240. */
  241. bool isOrientationEnabled (DisplayOrientation orientation) const noexcept;
  242. //==============================================================================
  243. class JUCE_API Displays
  244. {
  245. public:
  246. /** Contains details about a display device. */
  247. struct Display
  248. {
  249. /** This is the bounds of the area of this display which isn't covered by
  250. OS-dependent objects like the taskbar, menu bar, etc. */
  251. Rectangle<int> userArea;
  252. /** This is the total physical area of this display, including any taskbars, etc */
  253. Rectangle<int> totalArea;
  254. /** This is the scale-factor of this display.
  255. For higher-resolution displays, this may be a value greater than 1.0
  256. */
  257. double scale;
  258. /** This will be true if this is the user's main screen. */
  259. bool isMain;
  260. };
  261. /** Returns the display which acts as user's main screen. */
  262. const Display& getMainDisplay() const noexcept;
  263. /** Returns the display which contains a particular point.
  264. If the point lies outside all the displays, the nearest one will be returned.
  265. */
  266. const Display& getDisplayContaining (const Point<int>& position) const noexcept;
  267. /** Returns a RectangleList made up of all the displays. */
  268. RectangleList getRectangleList (bool userAreasOnly) const;
  269. /** Returns the smallest bounding box which contains all the displays. */
  270. Rectangle<int> getTotalBounds (bool userAreasOnly) const;
  271. /** The list of displays. */
  272. Array<Display> displays;
  273. #ifndef DOXYGEN
  274. /** @internal */
  275. void refresh();
  276. #endif
  277. private:
  278. friend class Desktop;
  279. Displays();
  280. ~Displays();
  281. void findDisplays();
  282. };
  283. const Displays& getDisplays() const noexcept { return displays; }
  284. //==============================================================================
  285. /** True if the OS supports semitransparent windows */
  286. static bool canUseSemiTransparentWindows() noexcept;
  287. private:
  288. //==============================================================================
  289. static Desktop* instance;
  290. friend class Component;
  291. friend class ComponentPeer;
  292. friend class MouseInputSource;
  293. friend class MouseInputSourceInternal;
  294. friend class DeletedAtShutdown;
  295. friend class TopLevelWindowManager;
  296. OwnedArray <MouseInputSource> mouseSources;
  297. void createMouseInputSources();
  298. ListenerList <MouseListener> mouseListeners;
  299. ListenerList <FocusChangeListener> focusListeners;
  300. Array <Component*> desktopComponents;
  301. Displays displays;
  302. Point<int> lastFakeMouseMove;
  303. void sendMouseMove();
  304. int mouseClickCounter, mouseWheelCounter;
  305. void incrementMouseClickCounter() noexcept;
  306. void incrementMouseWheelCounter() noexcept;
  307. ScopedPointer<Timer> dragRepeater;
  308. ScopedPointer<LookAndFeel> defaultLookAndFeel;
  309. WeakReference<LookAndFeel> currentLookAndFeel;
  310. Component* kioskModeComponent;
  311. Rectangle<int> kioskComponentOriginalBounds;
  312. int allowedOrientations;
  313. ComponentAnimator animator;
  314. void timerCallback();
  315. void resetTimer();
  316. ListenerList <MouseListener>& getMouseListeners();
  317. void addDesktopComponent (Component*);
  318. void removeDesktopComponent (Component*);
  319. void componentBroughtToFront (Component*);
  320. void setKioskComponent (Component*, bool enableOrDisable, bool allowMenusAndBars);
  321. void triggerFocusCallback();
  322. void handleAsyncUpdate();
  323. Desktop();
  324. ~Desktop();
  325. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Desktop);
  326. };
  327. #endif // __JUCE_DESKTOP_JUCEHEADER__