| @@ -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 | |||
| { | |||
| 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), | |||
| standardType (MouseCursor::NormalCursor), | |||
| isStandard (false) | |||
| @@ -120,7 +137,12 @@ MouseCursor::MouseCursor (const StandardCursorType type) | |||
| } | |||
| 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); | |||
| /** 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. */ | |||
| MouseCursor (const MouseCursor& other); | |||
| MouseCursor (const MouseCursor&); | |||
| /** Copies this cursor from another object. */ | |||
| MouseCursor& operator= (const MouseCursor& other); | |||
| MouseCursor& operator= (const MouseCursor&); | |||
| /** Destructor. */ | |||
| ~MouseCursor(); | |||
| #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS | |||
| MouseCursor (MouseCursor&& other) noexcept; | |||
| MouseCursor& operator= (MouseCursor&& other) noexcept; | |||
| MouseCursor (MouseCursor&&) noexcept; | |||
| MouseCursor& operator= (MouseCursor&&) noexcept; | |||
| #endif | |||
| /** Checks whether two mouse cursors are the same. | |||
| @@ -114,7 +127,7 @@ public: | |||
| recognised as the same, only MouseCursor objects that have been | |||
| 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. | |||
| @@ -122,7 +135,7 @@ public: | |||
| recognised as the same, only MouseCursor objects that have been | |||
| 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. */ | |||
| bool operator== (StandardCursorType type) const noexcept; | |||
| @@ -165,7 +178,6 @@ private: | |||
| void showInAllWindows() const; | |||
| void* getHandle() const noexcept; | |||
| static void* createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY); | |||
| static void* createStandardMouseCursor (MouseCursor::StandardCursorType type); | |||
| 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::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; | |||
| const unsigned int imageW = image.getWidth(); | |||
| const unsigned int imageH = image.getHeight(); | |||
| int hotspotX = hotspot.x; | |||
| int hotspotY = hotspot.y; | |||
| #if JUCE_USE_XCURSOR | |||
| { | |||
| @@ -2935,7 +2937,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty | |||
| { | |||
| case NormalCursor: | |||
| 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 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 }; | |||
| const int dragHandDataSize = 99; | |||
| return createMouseCursorFromImage (ImageFileFormat::loadFrom (dragHandData, dragHandDataSize), 8, 7); | |||
| return CustomMouseCursorInfo (ImageFileFormat::loadFrom (dragHandData, dragHandDataSize), 8, 7).create(); | |||
| } | |||
| 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 }; | |||
| const int copyCursorSize = 119; | |||
| return createMouseCursorFromImage (ImageFileFormat::loadFrom (copyCursorData, copyCursorSize), 1, 3); | |||
| return CustomMouseCursorInfo (ImageFileFormat::loadFrom (copyCursorData, copyCursorSize), 1, 3).create(); | |||
| } | |||
| default: | |||
| @@ -41,7 +41,7 @@ namespace MouseCursorHelpers | |||
| CGColorSpaceRelease (colourSpace); | |||
| CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; | |||
| CGContextDrawImage (cg, CGRectMake (0, 0, image.getWidth(), image.getHeight()), imageRef); | |||
| CGContextDrawImage (cg, convertToCGRect (image.getBounds()), imageRef); | |||
| CGImageRelease (imageRef); | |||
| [im unlockFocus]; | |||
| @@ -49,15 +49,6 @@ namespace MouseCursorHelpers | |||
| 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) | |||
| { | |||
| FileInputStream fileStream (String ("/System/Library/Frameworks/WebKit.framework/Frameworks/WebCore.framework/Resources/") + filename); | |||
| @@ -67,16 +58,21 @@ namespace MouseCursorHelpers | |||
| Image im (pngFormat.decodeImage (buf)); | |||
| 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; | |||
| 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) | |||
| @@ -88,7 +84,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty | |||
| { | |||
| case NormalCursor: | |||
| 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 WaitCursor: c = [NSCursor arrowCursor]; break; // avoid this on the mac, let the OS provide the beachball | |||
| case IBeamCursor: c = [NSCursor IBeamCursor]; break; | |||
| @@ -146,10 +142,10 @@ void MouseCursor::showInWindow (ComponentPeer*) const | |||
| #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 | |||
| @@ -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 maxH = GetSystemMetrics (SM_CYCURSOR); | |||
| Image im (image); | |||
| int hotspotX = hotspot.x; | |||
| int hotspotY = hotspot.y; | |||
| 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, | |||
| 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; | |||