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.

163 lines
5.3KB

  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. struct CustomMouseCursorInfo
  21. {
  22. CustomMouseCursorInfo (const Image& im, Point<int> hs, float scale = 1.0f) noexcept
  23. : image (im), hotspot (hs), scaleFactor (scale)
  24. {}
  25. void* create() const;
  26. Image image;
  27. const Point<int> hotspot;
  28. const float scaleFactor;
  29. JUCE_DECLARE_NON_COPYABLE (CustomMouseCursorInfo)
  30. };
  31. class MouseCursor::SharedCursorHandle
  32. {
  33. public:
  34. explicit SharedCursorHandle (const MouseCursor::StandardCursorType type)
  35. : handle (createStandardMouseCursor (type), Deleter { true }),
  36. standardType (type)
  37. {
  38. }
  39. SharedCursorHandle (const Image& image, Point<int> hotSpot, float scaleFactor)
  40. : info (std::make_unique<CustomMouseCursorInfo> (image, hotSpot, scaleFactor)),
  41. handle (info->create(), Deleter { false }),
  42. standardType (MouseCursor::NormalCursor)
  43. {
  44. // your hotspot needs to be within the bounds of the image!
  45. jassert (image.getBounds().contains (hotSpot));
  46. }
  47. static std::shared_ptr<SharedCursorHandle> createStandard (const MouseCursor::StandardCursorType type)
  48. {
  49. if (! isPositiveAndBelow (type, MouseCursor::NumStandardCursorTypes))
  50. return nullptr;
  51. static SpinLock mutex;
  52. static std::array<std::weak_ptr<SharedCursorHandle>, MouseCursor::NumStandardCursorTypes> cursors;
  53. const SpinLock::ScopedLockType sl (mutex);
  54. auto& weak = cursors[type];
  55. if (auto strong = weak.lock())
  56. return strong;
  57. auto strong = std::make_shared<SharedCursorHandle> (type);
  58. weak = strong;
  59. return strong;
  60. }
  61. bool isStandardType (MouseCursor::StandardCursorType type) const noexcept
  62. {
  63. return type == standardType && handle.get_deleter().isStandard;
  64. }
  65. void* getHandle() const noexcept { return handle.get(); }
  66. MouseCursor::StandardCursorType getType() const noexcept { return standardType; }
  67. CustomMouseCursorInfo* getCustomInfo() const noexcept { return info.get(); }
  68. private:
  69. struct Deleter
  70. {
  71. void operator() (void* ptr) const noexcept { deleteMouseCursor (ptr, isStandard); }
  72. const bool isStandard;
  73. };
  74. std::unique_ptr<CustomMouseCursorInfo> info;
  75. std::unique_ptr<void, Deleter> handle;
  76. const MouseCursor::StandardCursorType standardType;
  77. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedCursorHandle)
  78. };
  79. //==============================================================================
  80. MouseCursor::MouseCursor() noexcept = default;
  81. MouseCursor::MouseCursor (const StandardCursorType type)
  82. : cursorHandle (type != MouseCursor::NormalCursor ? SharedCursorHandle::createStandard (type) : nullptr)
  83. {
  84. }
  85. MouseCursor::MouseCursor (const Image& image, int hotSpotX, int hotSpotY)
  86. : MouseCursor (image, hotSpotX, hotSpotY, 1.0f)
  87. {
  88. }
  89. MouseCursor::MouseCursor (const Image& image, int hotSpotX, int hotSpotY, float scaleFactor)
  90. : cursorHandle (std::make_shared<SharedCursorHandle> (image, Point<int> { hotSpotX, hotSpotY }, scaleFactor))
  91. {
  92. }
  93. MouseCursor::MouseCursor (const MouseCursor&) = default;
  94. MouseCursor::~MouseCursor() = default;
  95. MouseCursor& MouseCursor::operator= (const MouseCursor&) = default;
  96. MouseCursor::MouseCursor (MouseCursor&&) noexcept = default;
  97. MouseCursor& MouseCursor::operator= (MouseCursor&&) noexcept = default;
  98. bool MouseCursor::operator== (const MouseCursor& other) const noexcept
  99. {
  100. return getHandle() == other.getHandle();
  101. }
  102. bool MouseCursor::operator== (StandardCursorType type) const noexcept
  103. {
  104. return cursorHandle != nullptr ? cursorHandle->isStandardType (type)
  105. : (type == NormalCursor);
  106. }
  107. bool MouseCursor::operator!= (const MouseCursor& other) const noexcept { return ! operator== (other); }
  108. bool MouseCursor::operator!= (StandardCursorType type) const noexcept { return ! operator== (type); }
  109. void* MouseCursor::getHandle() const noexcept
  110. {
  111. return cursorHandle != nullptr ? cursorHandle->getHandle() : nullptr;
  112. }
  113. void MouseCursor::showWaitCursor()
  114. {
  115. Desktop::getInstance().getMainMouseSource().showMouseCursor (MouseCursor::WaitCursor);
  116. }
  117. void MouseCursor::hideWaitCursor()
  118. {
  119. Desktop::getInstance().getMainMouseSource().revealCursor();
  120. }
  121. } // namespace juce