| @@ -23,6 +23,23 @@ | |||||
| ============================================================================== | ============================================================================== | ||||
| */ | */ | ||||
| struct CustomMouseCursorInfo | |||||
| { | |||||
| CustomMouseCursorInfo (const Image& im, int hsX, int hsY) noexcept | |||||
| : image (im), hotspot (hsX, hsY), scaleFactor (1.0f) | |||||
| {} | |||||
| CustomMouseCursorInfo (const Image& im, const Point<int>& hs, float scale) noexcept | |||||
| : image (im), hotspot (hs), scaleFactor (scale) | |||||
| {} | |||||
| void* create() const; | |||||
| Image image; | |||||
| const Point<int> hotspot; | |||||
| float scaleFactor; | |||||
| }; | |||||
| class MouseCursor::SharedCursorHandle | class MouseCursor::SharedCursorHandle | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -34,8 +51,8 @@ public: | |||||
| { | { | ||||
| } | } | ||||
| SharedCursorHandle (const Image& image, const int hotSpotX, const int hotSpotY) | |||||
| : handle (createMouseCursorFromImage (image, hotSpotX, hotSpotY)), | |||||
| SharedCursorHandle (const Image& image, const Point<int>& hotSpot, const float scaleFactor) | |||||
| : handle (CustomMouseCursorInfo (image, hotSpot, scaleFactor).create()), | |||||
| refCount (1), | refCount (1), | ||||
| standardType (MouseCursor::NormalCursor), | standardType (MouseCursor::NormalCursor), | ||||
| isStandard (false) | isStandard (false) | ||||
| @@ -120,7 +137,12 @@ MouseCursor::MouseCursor (const StandardCursorType type) | |||||
| } | } | ||||
| MouseCursor::MouseCursor (const Image& image, const int hotSpotX, const int hotSpotY) | MouseCursor::MouseCursor (const Image& image, const int hotSpotX, const int hotSpotY) | ||||
| : cursorHandle (new SharedCursorHandle (image, hotSpotX, hotSpotY)) | |||||
| : cursorHandle (new SharedCursorHandle (image, Point<int> (hotSpotX, hotSpotY), 1.0f)) | |||||
| { | |||||
| } | |||||
| MouseCursor::MouseCursor (const Image& image, const int hotSpotX, const int hotSpotY, float scaleFactor) | |||||
| : cursorHandle (new SharedCursorHandle (image, Point<int> (hotSpotX, hotSpotY), scaleFactor)) | |||||
| { | { | ||||
| } | } | ||||
| @@ -93,19 +93,32 @@ public: | |||||
| */ | */ | ||||
| MouseCursor (const Image& image, int hotSpotX, int hotSpotY); | MouseCursor (const Image& image, int hotSpotX, int hotSpotY); | ||||
| /** Creates a custom cursor from an image. | |||||
| @param image the image to use for the cursor - if this is bigger than the | |||||
| system can manage, it might get scaled down first, and might | |||||
| also have to be turned to black-and-white if it can't do colour | |||||
| cursors. | |||||
| @param hotSpotX the x position of the cursor's hotspot within the image | |||||
| @param hotSpotY the y position of the cursor's hotspot within the image | |||||
| @param dpiFactor the factor by which this image is larger than the target | |||||
| screen size of the cursor. | |||||
| */ | |||||
| MouseCursor (const Image& image, int hotSpotX, int hotSpotY, float scaleFactor); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Creates a copy of another cursor object. */ | /** Creates a copy of another cursor object. */ | ||||
| MouseCursor (const MouseCursor& other); | |||||
| MouseCursor (const MouseCursor&); | |||||
| /** Copies this cursor from another object. */ | /** Copies this cursor from another object. */ | ||||
| MouseCursor& operator= (const MouseCursor& other); | |||||
| MouseCursor& operator= (const MouseCursor&); | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| ~MouseCursor(); | ~MouseCursor(); | ||||
| #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS | #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS | ||||
| MouseCursor (MouseCursor&& other) noexcept; | |||||
| MouseCursor& operator= (MouseCursor&& other) noexcept; | |||||
| MouseCursor (MouseCursor&&) noexcept; | |||||
| MouseCursor& operator= (MouseCursor&&) noexcept; | |||||
| #endif | #endif | ||||
| /** Checks whether two mouse cursors are the same. | /** Checks whether two mouse cursors are the same. | ||||
| @@ -114,7 +127,7 @@ public: | |||||
| recognised as the same, only MouseCursor objects that have been | recognised as the same, only MouseCursor objects that have been | ||||
| copied from the same object. | copied from the same object. | ||||
| */ | */ | ||||
| bool operator== (const MouseCursor& other) const noexcept; | |||||
| bool operator== (const MouseCursor&) const noexcept; | |||||
| /** Checks whether two mouse cursors are the same. | /** Checks whether two mouse cursors are the same. | ||||
| @@ -122,7 +135,7 @@ public: | |||||
| recognised as the same, only MouseCursor objects that have been | recognised as the same, only MouseCursor objects that have been | ||||
| copied from the same object. | copied from the same object. | ||||
| */ | */ | ||||
| bool operator!= (const MouseCursor& other) const noexcept; | |||||
| bool operator!= (const MouseCursor&) const noexcept; | |||||
| /** Checks whether this cursor is of the standard type mentioned. */ | /** Checks whether this cursor is of the standard type mentioned. */ | ||||
| bool operator== (StandardCursorType type) const noexcept; | bool operator== (StandardCursorType type) const noexcept; | ||||
| @@ -165,7 +178,6 @@ private: | |||||
| void showInAllWindows() const; | void showInAllWindows() const; | ||||
| void* getHandle() const noexcept; | void* getHandle() const noexcept; | ||||
| static void* createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY); | |||||
| static void* createStandardMouseCursor (MouseCursor::StandardCursorType type); | static void* createStandardMouseCursor (MouseCursor::StandardCursorType type); | ||||
| static void deleteMouseCursor (void* cursorHandle, bool isStandard); | static void deleteMouseCursor (void* cursorHandle, bool isStandard); | ||||
| @@ -715,7 +715,7 @@ Image juce_createIconForFile (const File& file) | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void* MouseCursor::createMouseCursorFromImage (const Image&, int, int) { return nullptr; } | |||||
| void* CustomMouseCursorInfo::create() const { return nullptr; } | |||||
| void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorType) { return nullptr; } | void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorType) { return nullptr; } | ||||
| void MouseCursor::deleteMouseCursor (void* const /*cursorHandle*/, const bool /*isStandard*/) {} | void MouseCursor::deleteMouseCursor (void* const /*cursorHandle*/, const bool /*isStandard*/) {} | ||||
| @@ -2800,11 +2800,13 @@ bool Desktop::isScreenSaverEnabled() | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void* MouseCursor::createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) | |||||
| void* CustomMouseCursorInfo::create() const | |||||
| { | { | ||||
| ScopedXLock xlock; | ScopedXLock xlock; | ||||
| const unsigned int imageW = image.getWidth(); | const unsigned int imageW = image.getWidth(); | ||||
| const unsigned int imageH = image.getHeight(); | const unsigned int imageH = image.getHeight(); | ||||
| int hotspotX = hotspot.x; | |||||
| int hotspotY = hotspot.y; | |||||
| #if JUCE_USE_XCURSOR | #if JUCE_USE_XCURSOR | ||||
| { | { | ||||
| @@ -2935,7 +2937,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty | |||||
| { | { | ||||
| case NormalCursor: | case NormalCursor: | ||||
| case ParentCursor: return None; // Use parent cursor | case ParentCursor: return None; // Use parent cursor | ||||
| case NoCursor: return createMouseCursorFromImage (Image (Image::ARGB, 16, 16, true), 0, 0); | |||||
| case NoCursor: return CustomMouseCursorInfo (Image (Image::ARGB, 16, 16, true), 0, 0).create(); | |||||
| case WaitCursor: shape = XC_watch; break; | case WaitCursor: shape = XC_watch; break; | ||||
| case IBeamCursor: shape = XC_xterm; break; | case IBeamCursor: shape = XC_xterm; break; | ||||
| @@ -2960,7 +2962,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty | |||||
| 132,117,151,116,132,146,248,60,209,138,98,22,203,114,34,236,37,52,77,217, 247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 }; | 132,117,151,116,132,146,248,60,209,138,98,22,203,114,34,236,37,52,77,217, 247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 }; | ||||
| const int dragHandDataSize = 99; | const int dragHandDataSize = 99; | ||||
| return createMouseCursorFromImage (ImageFileFormat::loadFrom (dragHandData, dragHandDataSize), 8, 7); | |||||
| return CustomMouseCursorInfo (ImageFileFormat::loadFrom (dragHandData, dragHandDataSize), 8, 7).create(); | |||||
| } | } | ||||
| case CopyingCursor: | case CopyingCursor: | ||||
| @@ -2971,7 +2973,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty | |||||
| 252,114,147,74,83,5,50,68,147,208,217,16,71,149,252,124,5,0,59,0,0 }; | 252,114,147,74,83,5,50,68,147,208,217,16,71,149,252,124,5,0,59,0,0 }; | ||||
| const int copyCursorSize = 119; | const int copyCursorSize = 119; | ||||
| return createMouseCursorFromImage (ImageFileFormat::loadFrom (copyCursorData, copyCursorSize), 1, 3); | |||||
| return CustomMouseCursorInfo (ImageFileFormat::loadFrom (copyCursorData, copyCursorSize), 1, 3).create(); | |||||
| } | } | ||||
| default: | default: | ||||
| @@ -41,7 +41,7 @@ namespace MouseCursorHelpers | |||||
| CGColorSpaceRelease (colourSpace); | CGColorSpaceRelease (colourSpace); | ||||
| CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; | CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; | ||||
| CGContextDrawImage (cg, CGRectMake (0, 0, image.getWidth(), image.getHeight()), imageRef); | |||||
| CGContextDrawImage (cg, convertToCGRect (image.getBounds()), imageRef); | |||||
| CGImageRelease (imageRef); | CGImageRelease (imageRef); | ||||
| [im unlockFocus]; | [im unlockFocus]; | ||||
| @@ -49,15 +49,6 @@ namespace MouseCursorHelpers | |||||
| return im; | return im; | ||||
| } | } | ||||
| static void* createFromImage (const Image& image, float hotspotX, float hotspotY) | |||||
| { | |||||
| NSImage* im = createNSImage (image); | |||||
| NSCursor* c = [[NSCursor alloc] initWithImage: im | |||||
| hotSpot: NSMakePoint (hotspotX, hotspotY)]; | |||||
| [im release]; | |||||
| return c; | |||||
| } | |||||
| static void* fromWebKitFile (const char* filename, float hx, float hy) | static void* fromWebKitFile (const char* filename, float hx, float hy) | ||||
| { | { | ||||
| FileInputStream fileStream (String ("/System/Library/Frameworks/WebKit.framework/Frameworks/WebCore.framework/Resources/") + filename); | FileInputStream fileStream (String ("/System/Library/Frameworks/WebKit.framework/Frameworks/WebCore.framework/Resources/") + filename); | ||||
| @@ -67,16 +58,21 @@ namespace MouseCursorHelpers | |||||
| Image im (pngFormat.decodeImage (buf)); | Image im (pngFormat.decodeImage (buf)); | ||||
| if (im.isValid()) | if (im.isValid()) | ||||
| return createFromImage (im, hx * im.getWidth(), hy * im.getHeight()); | |||||
| return CustomMouseCursorInfo (im, (int) (hx * im.getWidth()), | |||||
| (int) (hy * im.getHeight())).create(); | |||||
| jassertfalse; | jassertfalse; | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| } | } | ||||
| void* MouseCursor::createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) | |||||
| void* CustomMouseCursorInfo::create() const | |||||
| { | { | ||||
| return MouseCursorHelpers::createFromImage (image, (float) hotspotX, (float) hotspotY); | |||||
| NSImage* im = MouseCursorHelpers::createNSImage (image); | |||||
| NSCursor* c = [[NSCursor alloc] initWithImage: im | |||||
| hotSpot: NSMakePoint (hotspot.x, hotspot.y)]; | |||||
| [im release]; | |||||
| return c; | |||||
| } | } | ||||
| void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType type) | void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType type) | ||||
| @@ -88,7 +84,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty | |||||
| { | { | ||||
| case NormalCursor: | case NormalCursor: | ||||
| case ParentCursor: c = [NSCursor arrowCursor]; break; | case ParentCursor: c = [NSCursor arrowCursor]; break; | ||||
| case NoCursor: return createMouseCursorFromImage (Image (Image::ARGB, 8, 8, true), 0, 0); | |||||
| case NoCursor: return CustomMouseCursorInfo (Image (Image::ARGB, 8, 8, true), 0, 0).create(); | |||||
| case DraggingHandCursor: c = [NSCursor openHandCursor]; break; | case DraggingHandCursor: c = [NSCursor openHandCursor]; break; | ||||
| case WaitCursor: c = [NSCursor arrowCursor]; break; // avoid this on the mac, let the OS provide the beachball | case WaitCursor: c = [NSCursor arrowCursor]; break; // avoid this on the mac, let the OS provide the beachball | ||||
| case IBeamCursor: c = [NSCursor IBeamCursor]; break; | case IBeamCursor: c = [NSCursor IBeamCursor]; break; | ||||
| @@ -146,10 +142,10 @@ void MouseCursor::showInWindow (ComponentPeer*) const | |||||
| #else | #else | ||||
| void* MouseCursor::createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) { return nullptr; } | |||||
| void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType type) { return nullptr; } | |||||
| void MouseCursor::deleteMouseCursor (void* const cursorHandle, const bool isStandard) {} | |||||
| void MouseCursor::showInAllWindows() const {} | |||||
| void MouseCursor::showInWindow (ComponentPeer*) const {} | |||||
| void* CustomMouseCursorInfo::create() const { return nullptr; } | |||||
| void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType type) { return nullptr; } | |||||
| void MouseCursor::deleteMouseCursor (void* const cursorHandle, const bool isStandard) {} | |||||
| void MouseCursor::showInAllWindows() const {} | |||||
| void MouseCursor::showInWindow (ComponentPeer*) const {} | |||||
| #endif | #endif | ||||
| @@ -3129,12 +3129,14 @@ Image juce_createIconForFile (const File& file) | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void* MouseCursor::createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) | |||||
| void* CustomMouseCursorInfo::create() const | |||||
| { | { | ||||
| const int maxW = GetSystemMetrics (SM_CXCURSOR); | const int maxW = GetSystemMetrics (SM_CXCURSOR); | ||||
| const int maxH = GetSystemMetrics (SM_CYCURSOR); | const int maxH = GetSystemMetrics (SM_CYCURSOR); | ||||
| Image im (image); | Image im (image); | ||||
| int hotspotX = hotspot.x; | |||||
| int hotspotY = hotspot.y; | |||||
| if (im.getWidth() > maxW || im.getHeight() > maxH) | if (im.getWidth() > maxW || im.getHeight() > maxH) | ||||
| { | { | ||||
| @@ -3200,7 +3202,7 @@ void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorT | |||||
| 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39,132,117,151,116,132,146,248,60,209,138, | 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39,132,117,151,116,132,146,248,60,209,138, | ||||
| 98,22,203,114,34,236,37,52,77,217,247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 }; | 98,22,203,114,34,236,37,52,77,217,247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 }; | ||||
| dragHandCursor = createMouseCursorFromImage (ImageFileFormat::loadFrom (dragHandData, sizeof (dragHandData)), 8, 7); | |||||
| dragHandCursor = CustomMouseCursorInfo (ImageFileFormat::loadFrom (dragHandData, sizeof (dragHandData)), 8, 7).create(); | |||||
| } | } | ||||
| return dragHandCursor; | return dragHandCursor; | ||||