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.

308 lines
13KB

  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. Represents a linear source of mouse events from a mouse device or individual finger
  23. in a multi-touch environment.
  24. Each MouseEvent object contains a reference to the MouseInputSource that generated
  25. it. In an environment with a single mouse for input, all events will come from the
  26. same source, but in a multi-touch system, there may be multiple MouseInputSource
  27. objects active, each representing a stream of events coming from a particular finger.
  28. Events coming from a single MouseInputSource are always sent in a fixed and predictable
  29. order: a mouseMove will never be called without a mouseEnter having been sent beforehand,
  30. the only events that can happen between a mouseDown and its corresponding mouseUp are
  31. mouseDrags, etc.
  32. When there are multiple touches arriving from multiple MouseInputSources, their
  33. event streams may arrive in an interleaved order, so you should use the getIndex()
  34. method to find out which finger each event came from.
  35. @see MouseEvent
  36. @tags{GUI}
  37. */
  38. class JUCE_API MouseInputSource final
  39. {
  40. public:
  41. /** Possible mouse input sources. */
  42. enum InputSourceType
  43. {
  44. mouse,
  45. touch,
  46. pen
  47. };
  48. //==============================================================================
  49. MouseInputSource (const MouseInputSource&) noexcept;
  50. MouseInputSource& operator= (const MouseInputSource&) noexcept;
  51. ~MouseInputSource() noexcept;
  52. //==============================================================================
  53. bool operator== (const MouseInputSource& other) const noexcept { return pimpl == other.pimpl; }
  54. bool operator!= (const MouseInputSource& other) const noexcept { return pimpl != other.pimpl; }
  55. //==============================================================================
  56. /** Returns the type of input source that this object represents. */
  57. MouseInputSource::InputSourceType getType() const noexcept;
  58. /** Returns true if this object represents a normal desk-based mouse device. */
  59. bool isMouse() const noexcept;
  60. /** Returns true if this object represents a source of touch events. */
  61. bool isTouch() const noexcept;
  62. /** Returns true if this object represents a pen device. */
  63. bool isPen() const noexcept;
  64. /** Returns true if this source has an on-screen pointer that can hover over
  65. items without clicking them.
  66. */
  67. bool canHover() const noexcept;
  68. /** Returns true if this source may have a scroll wheel. */
  69. bool hasMouseWheel() const noexcept;
  70. /** Returns this source's index in the global list of possible sources.
  71. If the system only has a single mouse, there will only be a single MouseInputSource
  72. with an index of 0.
  73. If the system supports multi-touch input, then the index will represent a finger
  74. number, starting from 0. When the first touch event begins, it will have finger
  75. number 0, and then if a second touch happens while the first is still down, it
  76. will have index 1, etc.
  77. */
  78. int getIndex() const noexcept;
  79. /** Returns true if this device is currently being pressed. */
  80. bool isDragging() const noexcept;
  81. /** Returns the last-known screen position of this source. */
  82. Point<float> getScreenPosition() const noexcept;
  83. /** Returns the last-known screen position of this source without any scaling applied. */
  84. Point<float> getRawScreenPosition() const noexcept;
  85. /** Returns a set of modifiers that indicate which buttons are currently
  86. held down on this device.
  87. */
  88. ModifierKeys getCurrentModifiers() const noexcept;
  89. /** Returns the device's current touch or pen pressure.
  90. The range is 0 (soft) to 1 (hard).
  91. If the input device doesn't provide any pressure data, it may return a negative
  92. value here, or 0.0 or 1.0, depending on the platform.
  93. */
  94. float getCurrentPressure() const noexcept;
  95. /** Returns the device's current orientation in radians. 0 indicates a touch pointer
  96. aligned with the x-axis and pointing from left to right; increasing values indicate
  97. rotation in the clockwise direction. Only reported by a touch pointer.
  98. */
  99. float getCurrentOrientation() const noexcept;
  100. /** Returns the device's current rotation. Indicates the clockwise rotation, or twist, of the pointer
  101. in radians. The default is 0. Only reported by a pen pointer.
  102. */
  103. float getCurrentRotation() const noexcept;
  104. /** Returns the angle of tilt of the pointer in a range of -1.0 to 1.0 either in the x- or y-axis. The default is 0.
  105. If x-axis, a positive value indicates a tilt to the right and if y-axis, a positive value indicates a tilt toward the user.
  106. Only reported by a pen pointer.
  107. */
  108. float getCurrentTilt (bool tiltX) const noexcept;
  109. /** Returns true if the current pressure value is meaningful. */
  110. bool isPressureValid() const noexcept;
  111. /** Returns true if the current orientation value is meaningful. */
  112. bool isOrientationValid() const noexcept;
  113. /** Returns true if the current rotation value is meaningful. */
  114. bool isRotationValid() const noexcept;
  115. /** Returns true if the current tilt value (either x- or y-axis) is meaningful. */
  116. bool isTiltValid (bool tiltX) const noexcept;
  117. /** Returns the component that was last known to be under this pointer. */
  118. Component* getComponentUnderMouse() const;
  119. /** Tells the device to dispatch a mouse-move or mouse-drag event.
  120. This is asynchronous - the event will occur on the message thread.
  121. */
  122. void triggerFakeMove() const;
  123. /** Returns the number of clicks that should be counted as belonging to the
  124. current mouse event.
  125. So the mouse is currently down and it's the second click of a double-click, this
  126. will return 2.
  127. */
  128. int getNumberOfMultipleClicks() const noexcept;
  129. /** Returns the time at which the last mouse-down occurred. */
  130. Time getLastMouseDownTime() const noexcept;
  131. /** Returns the screen position at which the last mouse-down occurred. */
  132. Point<float> getLastMouseDownPosition() const noexcept;
  133. /** Returns true if this input source represents a long-press or drag interaction i.e. it has been held down for a significant
  134. amount of time or it has been dragged more than a couple of pixels from the place it was pressed. */
  135. bool isLongPressOrDrag() const noexcept;
  136. /** Returns true if this input source has been dragged more than a couple of pixels from the place it was pressed. */
  137. bool hasMovedSignificantlySincePressed() const noexcept;
  138. /** Returns true if this input source uses a visible mouse cursor. */
  139. bool hasMouseCursor() const noexcept;
  140. /** Changes the mouse cursor, (if there is one). */
  141. void showMouseCursor (const MouseCursor& cursor);
  142. /** Hides the mouse cursor (if there is one). */
  143. void hideCursor();
  144. /** Un-hides the mouse cursor if it was hidden by hideCursor(). */
  145. void revealCursor();
  146. /** Forces an update of the mouse cursor for whatever component it's currently over. */
  147. void forceMouseCursorUpdate();
  148. /** Returns true if this mouse can be moved indefinitely in any direction without running out of space. */
  149. bool canDoUnboundedMovement() const noexcept;
  150. /** Allows the mouse to move beyond the edges of the screen.
  151. Calling this method when the mouse button is currently pressed will remove the cursor
  152. from the screen and allow the mouse to (seem to) move beyond the edges of the screen.
  153. This means that the coordinates returned to mouseDrag() will be unbounded, and this
  154. can be used for things like custom slider controls or dragging objects around, where
  155. movement would be otherwise be limited by the mouse hitting the edges of the screen.
  156. The unbounded mode is automatically turned off when the mouse button is released, or
  157. it can be turned off explicitly by calling this method again.
  158. @param isEnabled whether to turn this mode on or off
  159. @param keepCursorVisibleUntilOffscreen if set to false, the cursor will immediately be
  160. hidden; if true, it will only be hidden when it
  161. is moved beyond the edge of the screen
  162. */
  163. void enableUnboundedMouseMovement (bool isEnabled, bool keepCursorVisibleUntilOffscreen = false) const;
  164. /** Returns true if this source is currently in "unbounded" mode. */
  165. bool isUnboundedMouseMovementEnabled() const;
  166. /** Attempts to set this mouse pointer's screen position. */
  167. void setScreenPosition (Point<float> newPosition);
  168. /** A default value for pressure, which is used when a device doesn't support it, or for
  169. mouse-moves, mouse-ups, etc.
  170. */
  171. static constexpr float defaultPressure = 0.0f;
  172. /** A default value for orientation, which is used when a device doesn't support it */
  173. static constexpr float defaultOrientation = 0.0f;
  174. /** A default value for rotation, which is used when a device doesn't support it */
  175. static constexpr float defaultRotation = 0.0f;
  176. /** Default values for tilt, which are used when a device doesn't support it */
  177. static constexpr float defaultTiltX = 0.0f;
  178. static constexpr float defaultTiltY = 0.0f;
  179. /** A default value for pressure, which is used when a device doesn't support it.
  180. This is a valid value, returning true when calling isPressureValid() hence the
  181. deprecation. Use defaultPressure instead.
  182. */
  183. [[deprecated ("Use defaultPressure instead.")]]
  184. static const float invalidPressure;
  185. /** A default value for orientation, which is used when a device doesn't support it.
  186. This is a valid value, returning true when calling isOrientationValid() hence the
  187. deprecation. Use defaultOrientation instead.
  188. */
  189. [[deprecated ("Use defaultOrientation instead.")]]
  190. static const float invalidOrientation;
  191. /** A default value for rotation, which is used when a device doesn't support it.
  192. This is a valid value, returning true when calling isRotationValid() hence the
  193. deprecation. Use defaultRotation instead.
  194. */
  195. [[deprecated ("Use defaultRotation instead.")]]
  196. static const float invalidRotation;
  197. /** Default values for tilt, which are used when a device doesn't support it
  198. These are valid values, returning true when calling isTiltValid() hence the
  199. deprecation. Use defaultTiltX and defaultTiltY instead.
  200. */
  201. [[deprecated ("Use defaultTiltX instead.")]]
  202. static const float invalidTiltX;
  203. [[deprecated ("Use defaultTiltY instead.")]]
  204. static const float invalidTiltY;
  205. /** An offscreen mouse position used when triggering mouse exits where we don't want to move
  206. the cursor over an existing component.
  207. */
  208. static const Point<float> offscreenMousePos;
  209. //==============================================================================
  210. #ifndef DOXYGEN
  211. [[deprecated ("This method has been replaced with the isLongPressOrDrag and hasMovedSignificantlySincePressed "
  212. "methods. If you want the same behaviour you should use isLongPressOrDrag which accounts for the "
  213. "amount of time that the input source has been held down for, but if you only want to know whether "
  214. "it has been moved use hasMovedSignificantlySincePressed instead.")]]
  215. bool hasMouseMovedSignificantlySincePressed() const noexcept;
  216. #endif
  217. private:
  218. //==============================================================================
  219. friend class ComponentPeer;
  220. friend class Desktop;
  221. friend class MouseInputSourceInternal;
  222. MouseInputSourceInternal* pimpl;
  223. struct SourceList;
  224. explicit MouseInputSource (MouseInputSourceInternal*) noexcept;
  225. void handleEvent (ComponentPeer&, Point<float>, int64 time, ModifierKeys, float, float, const PenDetails&);
  226. void handleWheel (ComponentPeer&, Point<float>, int64 time, const MouseWheelDetails&);
  227. void handleMagnifyGesture (ComponentPeer&, Point<float>, int64 time, float scaleFactor);
  228. static Point<float> getCurrentRawMousePosition();
  229. static void setRawMousePosition (Point<float>);
  230. JUCE_LEAK_DETECTOR (MouseInputSource)
  231. };
  232. } // namespace juce