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.

191 lines
6.8KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 7 technical preview.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. You may use this code under the terms of the GPL v3
  6. (see www.gnu.org/licenses).
  7. For the technical preview this file cannot be licensed commercially.
  8. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  9. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  10. DISCLAIMED.
  11. ==============================================================================
  12. */
  13. namespace juce
  14. {
  15. #if JUCE_MAC
  16. //==============================================================================
  17. class MouseCursor::PlatformSpecificHandle
  18. {
  19. public:
  20. PlatformSpecificHandle (const MouseCursor::StandardCursorType type)
  21. : cursorHandle (createCursor (type)) {}
  22. PlatformSpecificHandle (const CustomMouseCursorInfo& info)
  23. : cursorHandle (createCursor (info)) {}
  24. ~PlatformSpecificHandle()
  25. {
  26. [cursorHandle release];
  27. }
  28. static void showInWindow (PlatformSpecificHandle* handle, ComponentPeer*)
  29. {
  30. auto c = [&]
  31. {
  32. if (handle == nullptr || handle->cursorHandle == nullptr)
  33. return [NSCursor arrowCursor];
  34. return handle->cursorHandle;
  35. }();
  36. [c set];
  37. }
  38. private:
  39. static NSCursor* fromNSImage (NSImage* im, NSPoint hotspot)
  40. {
  41. NSCursor* c = [[NSCursor alloc] initWithImage: im
  42. hotSpot: hotspot];
  43. [im release];
  44. return c;
  45. }
  46. static NSCursor* fromHIServices (const char* filename)
  47. {
  48. JUCE_AUTORELEASEPOOL
  49. {
  50. auto cursorPath = String ("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/"
  51. "HIServices.framework/Versions/A/Resources/cursors/")
  52. + filename;
  53. NSImage* originalImage = [[NSImage alloc] initByReferencingFile: juceStringToNS (cursorPath + "/cursor.pdf")];
  54. NSSize originalSize = [originalImage size];
  55. NSImage* resultImage = [[NSImage alloc] initWithSize: originalSize];
  56. for (int scale = 1; scale <= 4; ++scale)
  57. {
  58. NSAffineTransform* scaleTransform = [NSAffineTransform transform];
  59. [scaleTransform scaleBy: (float) scale];
  60. if (CGImageRef rasterCGImage = [originalImage CGImageForProposedRect: nil
  61. context: nil
  62. hints: [NSDictionary dictionaryWithObjectsAndKeys:
  63. NSImageHintCTM, scaleTransform, nil]])
  64. {
  65. NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithCGImage: rasterCGImage];
  66. [imageRep setSize: originalSize];
  67. [resultImage addRepresentation: imageRep];
  68. [imageRep release];
  69. }
  70. else
  71. {
  72. return nil;
  73. }
  74. }
  75. [originalImage release];
  76. NSDictionary* info = [NSDictionary dictionaryWithContentsOfFile: juceStringToNS (cursorPath + "/info.plist")];
  77. auto hotspotX = (float) [[info valueForKey: nsStringLiteral ("hotx")] doubleValue];
  78. auto hotspotY = (float) [[info valueForKey: nsStringLiteral ("hoty")] doubleValue];
  79. return fromNSImage (resultImage, NSMakePoint (hotspotX, hotspotY));
  80. }
  81. }
  82. static NSCursor* createCursor (const CustomMouseCursorInfo& info)
  83. {
  84. return fromNSImage (imageToNSImage (info.image),
  85. NSMakePoint (info.hotspot.x, info.hotspot.y));
  86. }
  87. static NSCursor* createCursor (const MouseCursor::StandardCursorType type)
  88. {
  89. JUCE_AUTORELEASEPOOL
  90. {
  91. NSCursor* c = nil;
  92. switch (type)
  93. {
  94. case NormalCursor:
  95. case ParentCursor: c = [NSCursor arrowCursor]; break;
  96. case NoCursor: return createCursor ({ ScaledImage (Image (Image::ARGB, 8, 8, true)), {} });
  97. case DraggingHandCursor: c = [NSCursor openHandCursor]; break;
  98. case WaitCursor: c = [NSCursor arrowCursor]; break; // avoid this on the mac, let the OS provide the beachball
  99. case IBeamCursor: c = [NSCursor IBeamCursor]; break;
  100. case PointingHandCursor: c = [NSCursor pointingHandCursor]; break;
  101. case LeftEdgeResizeCursor: c = [NSCursor resizeLeftCursor]; break;
  102. case RightEdgeResizeCursor: c = [NSCursor resizeRightCursor]; break;
  103. case CrosshairCursor: c = [NSCursor crosshairCursor]; break;
  104. case CopyingCursor:
  105. {
  106. c = [NSCursor dragCopyCursor];
  107. break;
  108. }
  109. case UpDownResizeCursor:
  110. case TopEdgeResizeCursor:
  111. case BottomEdgeResizeCursor:
  112. if (NSCursor* m = fromHIServices ("resizenorthsouth"))
  113. return m;
  114. c = [NSCursor resizeUpDownCursor];
  115. break;
  116. case LeftRightResizeCursor:
  117. if (NSCursor* m = fromHIServices ("resizeeastwest"))
  118. return m;
  119. c = [NSCursor resizeLeftRightCursor];
  120. break;
  121. case TopLeftCornerResizeCursor:
  122. case BottomRightCornerResizeCursor:
  123. return fromHIServices ("resizenorthwestsoutheast");
  124. case TopRightCornerResizeCursor:
  125. case BottomLeftCornerResizeCursor:
  126. return fromHIServices ("resizenortheastsouthwest");
  127. case UpDownLeftRightResizeCursor:
  128. return fromHIServices ("move");
  129. case NumStandardCursorTypes:
  130. default:
  131. jassertfalse;
  132. break;
  133. }
  134. [c retain];
  135. return c;
  136. }
  137. }
  138. NSCursor* cursorHandle;
  139. };
  140. #else
  141. class MouseCursor::PlatformSpecificHandle
  142. {
  143. public:
  144. PlatformSpecificHandle (const MouseCursor::StandardCursorType) {}
  145. PlatformSpecificHandle (const CustomMouseCursorInfo&) {}
  146. static void showInWindow (PlatformSpecificHandle*, ComponentPeer*) {}
  147. };
  148. #endif
  149. } // namespace juce