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.

175 lines
6.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 6 technical preview.
  4. Copyright (c) 2020 - 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 this technical preview, this file is not subject to commercial licensing.
  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. namespace MouseCursorHelpers
  18. {
  19. static NSCursor* fromNSImage (NSImage* im, NSPoint hotspot)
  20. {
  21. NSCursor* c = [[NSCursor alloc] initWithImage: im
  22. hotSpot: hotspot];
  23. [im release];
  24. return c;
  25. }
  26. static void* fromHIServices (const char* filename)
  27. {
  28. JUCE_AUTORELEASEPOOL
  29. {
  30. auto cursorPath = String ("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/"
  31. "HIServices.framework/Versions/A/Resources/cursors/")
  32. + filename;
  33. NSImage* originalImage = [[NSImage alloc] initByReferencingFile: juceStringToNS (cursorPath + "/cursor.pdf")];
  34. NSSize originalSize = [originalImage size];
  35. NSImage* resultImage = [[NSImage alloc] initWithSize: originalSize];
  36. for (int scale = 1; scale <= 4; ++scale)
  37. {
  38. NSAffineTransform* scaleTransform = [NSAffineTransform transform];
  39. [scaleTransform scaleBy: (float) scale];
  40. if (CGImageRef rasterCGImage = [originalImage CGImageForProposedRect: nil
  41. context: nil
  42. hints: [NSDictionary dictionaryWithObjectsAndKeys:
  43. NSImageHintCTM, scaleTransform, nil]])
  44. {
  45. NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithCGImage: rasterCGImage];
  46. [imageRep setSize: originalSize];
  47. [resultImage addRepresentation: imageRep];
  48. [imageRep release];
  49. }
  50. else
  51. {
  52. return nil;
  53. }
  54. }
  55. [originalImage release];
  56. NSDictionary* info = [NSDictionary dictionaryWithContentsOfFile: juceStringToNS (cursorPath + "/info.plist")];
  57. auto hotspotX = (float) [[info valueForKey: nsStringLiteral ("hotx")] doubleValue];
  58. auto hotspotY = (float) [[info valueForKey: nsStringLiteral ("hoty")] doubleValue];
  59. return fromNSImage (resultImage, NSMakePoint (hotspotX, hotspotY));
  60. }
  61. }
  62. }
  63. void* CustomMouseCursorInfo::create() const
  64. {
  65. return MouseCursorHelpers::fromNSImage (imageToNSImage (image, scaleFactor),
  66. NSMakePoint (hotspot.x, hotspot.y));
  67. }
  68. void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType type)
  69. {
  70. JUCE_AUTORELEASEPOOL
  71. {
  72. NSCursor* c = nil;
  73. switch (type)
  74. {
  75. case NormalCursor:
  76. case ParentCursor: c = [NSCursor arrowCursor]; break;
  77. case NoCursor: return CustomMouseCursorInfo (Image (Image::ARGB, 8, 8, true), {}).create();
  78. case DraggingHandCursor: c = [NSCursor openHandCursor]; break;
  79. case WaitCursor: c = [NSCursor arrowCursor]; break; // avoid this on the mac, let the OS provide the beachball
  80. case IBeamCursor: c = [NSCursor IBeamCursor]; break;
  81. case PointingHandCursor: c = [NSCursor pointingHandCursor]; break;
  82. case LeftEdgeResizeCursor: c = [NSCursor resizeLeftCursor]; break;
  83. case RightEdgeResizeCursor: c = [NSCursor resizeRightCursor]; break;
  84. case CrosshairCursor: c = [NSCursor crosshairCursor]; break;
  85. case CopyingCursor:
  86. {
  87. c = [NSCursor dragCopyCursor];
  88. break;
  89. }
  90. case UpDownResizeCursor:
  91. case TopEdgeResizeCursor:
  92. case BottomEdgeResizeCursor:
  93. if (void* m = MouseCursorHelpers::fromHIServices ("resizenorthsouth"))
  94. return m;
  95. c = [NSCursor resizeUpDownCursor];
  96. break;
  97. case LeftRightResizeCursor:
  98. if (void* m = MouseCursorHelpers::fromHIServices ("resizeeastwest"))
  99. return m;
  100. c = [NSCursor resizeLeftRightCursor];
  101. break;
  102. case TopLeftCornerResizeCursor:
  103. case BottomRightCornerResizeCursor:
  104. return MouseCursorHelpers::fromHIServices ("resizenorthwestsoutheast");
  105. case TopRightCornerResizeCursor:
  106. case BottomLeftCornerResizeCursor:
  107. return MouseCursorHelpers::fromHIServices ("resizenortheastsouthwest");
  108. case UpDownLeftRightResizeCursor:
  109. return MouseCursorHelpers::fromHIServices ("move");
  110. case NumStandardCursorTypes:
  111. default:
  112. jassertfalse;
  113. break;
  114. }
  115. [c retain];
  116. return c;
  117. }
  118. }
  119. void MouseCursor::deleteMouseCursor (void* const cursorHandle, const bool /*isStandard*/)
  120. {
  121. [((NSCursor*) cursorHandle) release];
  122. }
  123. void MouseCursor::showInWindow (ComponentPeer*) const
  124. {
  125. auto c = (NSCursor*) getHandle();
  126. if (c == nil)
  127. c = [NSCursor arrowCursor];
  128. [c set];
  129. }
  130. #else
  131. void* CustomMouseCursorInfo::create() const { return nullptr; }
  132. void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType) { return nullptr; }
  133. void MouseCursor::deleteMouseCursor (void*, bool) {}
  134. void MouseCursor::showInWindow (ComponentPeer*) const {}
  135. #endif
  136. } // namespace juce