diff --git a/lcl/interfaces/cocoa/cocoagdiobjects.pas b/lcl/interfaces/cocoa/cocoagdiobjects.pas index 9b63dbfc60..17ddf3cef2 100644 --- a/lcl/interfaces/cocoa/cocoagdiobjects.pas +++ b/lcl/interfaces/cocoa/cocoagdiobjects.pas @@ -301,6 +301,7 @@ type public constructor CreateStandard(const ACursor: NSCursor); constructor CreateFromBitmap(const ABitmap: TCocoaBitmap; const hotSpot: NSPoint); + constructor CreateFromCustomCursor(const ACursor: NSCursor); destructor Destroy; override; function Install: TCocoaCursor; procedure SetCursor; @@ -1185,6 +1186,12 @@ begin FStandard := False; end; +constructor TCocoaCursor.CreateFromCustomCursor(const ACursor: NSCursor); +begin + FCursor := ACursor; + FStandard := False; +end; + destructor TCocoaCursor.Destroy; begin FreeAndNil(FBitmap); diff --git a/lcl/interfaces/cocoa/cocoalclintf.inc b/lcl/interfaces/cocoa/cocoalclintf.inc index d77ba8a0cb..75e655152f 100644 --- a/lcl/interfaces/cocoa/cocoalclintf.inc +++ b/lcl/interfaces/cocoa/cocoalclintf.inc @@ -36,16 +36,16 @@ begin crIBeam : Result := HCursor(TCocoaCursor.CreateStandard(NSCursor.IBeamCursor)); crSizeNS, crVSplit : Result := HCursor(TCocoaCursor.CreateStandard(NSCursor.resizeUpDownCursor)); - crSizeNESW, - crSizeNWSE, + crSizeNESW : Result := HCursor(TCocoaCursor.CreateFromCustomCursor( AllocCursorFromCursorByDegrees(NSCursor.resizeLeftRightCursor, -45) )); + crSizeNWSE : Result := HCursor(TCocoaCursor.CreateFromCustomCursor( AllocCursorFromCursorByDegrees(NSCursor.resizeLeftRightCursor, 45) )); crSizeWE, crHSplit : Result := HCursor(TCocoaCursor.CreateStandard(NSCursor.resizeLeftRightCursor)); crSizeN : Result := HCursor(TCocoaCursor.CreateStandard(NSCursor.resizeUpCursor)); - crSizeNW, - crSizeSW, + crSizeNW : Result := HCursor(TCocoaCursor.CreateFromCustomCursor( AllocCursorFromCursorByDegrees(NSCursor.resizeLeftCursor, -45) )); + crSizeSW : Result := HCursor(TCocoaCursor.CreateFromCustomCursor( AllocCursorFromCursorByDegrees(NSCursor.resizeLeftCursor, 45) )); crSizeW : Result := HCursor(TCocoaCursor.CreateStandard(NSCursor.resizeLeftCursor)); - crSizeNE, - crSizeSE, + crSizeNE : Result := HCursor(TCocoaCursor.CreateFromCustomCursor( AllocCursorFromCursorByDegrees(NSCursor.resizeRightCursor, 45) )); + crSizeSE : Result := HCursor(TCocoaCursor.CreateFromCustomCursor( AllocCursorFromCursorByDegrees(NSCursor.resizeRightCursor, -45) )); crSizeE : Result := HCursor(TCocoaCursor.CreateStandard(NSCursor.resizeRightCursor)); crSizeS : Result := HCursor(TCocoaCursor.CreateStandard(NSCursor.resizeDownCursor)); crNo, diff --git a/lcl/interfaces/cocoa/cocoautils.pas b/lcl/interfaces/cocoa/cocoautils.pas index ef4057170c..a2286c487a 100644 --- a/lcl/interfaces/cocoa/cocoautils.pas +++ b/lcl/interfaces/cocoa/cocoautils.pas @@ -117,6 +117,9 @@ const function NSEventRawKeyChar(ev: NSEvent): System.WideChar; +function AllocImageRotatedByDegrees(src: NSImage; degrees: double): NSImage; +function AllocCursorFromCursorByDegrees(src: NSCursor; degrees: double): NSCursor; + implementation procedure ApplicationWillShowModal; @@ -938,5 +941,64 @@ begin Result := System.WideChar(m.characterAtIndex(0)); end; +function AllocImageRotatedByDegrees(src: NSImage; degrees: double): NSImage; +var + imageBounds : NSRect; + pathBounds : NSBezierPath; + transform : NSAffineTransform; + rotatedBounds : NSRect; + rotatedImage : NSImage; +begin + if not Assigned(src) then + begin + Result := nil; + Exit; + end; + + // src: https://stackoverflow.com/questions/31699235/rotate-nsimage-in-swift-cocoa-mac-osx + + imageBounds.size := src.size; + pathBounds := NSBezierPath.bezierPathWithRect(imageBounds); + transform := NSAffineTransform.alloc.init; + transform.rotatebyDegrees(degrees); + pathBounds.transformUsingAffineTransform(transform); + rotatedBounds := NSMakeRect(NSZeroPoint.x, NSZeroPoint.y, src.size.width, src.size.height ); + rotatedImage := NSImage(NSImage.alloc).initWithSize(rotatedBounds.size); + + //Center the image within the rotated bounds + imageBounds.origin.x := NSMidX(rotatedBounds) - (NSWidth(imageBounds) / 2); + imageBounds.origin.y := NSMidY(rotatedBounds) - (NSHeight(imageBounds) / 2); + transform.release; + + // Start a new transform + transform := NSAffineTransform.alloc.init; + // Move coordinate system to the center (since we want to rotate around the center) + transform.translateXBy_yBy(rotatedBounds.size.width / 2, rotatedBounds.size.width / 2); + transform.rotateByDegrees(degrees); + // Move the coordinate system bak to normal + transform.translateXBy_yBy(-rotatedBounds.size.width / 2, -rotatedBounds.size.height / 2); + // Draw the original image, rotated, into the new image + rotatedImage.lockFocus; + transform.concat(); + src.drawInRect_fromRect_operation_fraction(imageBounds, NSZeroRect, NSCompositeCopy, 1.0); + rotatedImage.unlockFocus(); + Result := rotatedImage; + + transform.release; +end; + +function AllocCursorFromCursorByDegrees(src: NSCursor; degrees: double): NSCursor; +var + img : NSImage; +begin + img := AllocImageRotatedByDegrees(src.image, degrees); + //todo: a better hotspot detection + Result := NSCursor.alloc.initWithImage_hotSpot( + img, + NSMakePoint(img.size.height / 2, img.size.width / 2) + ); + img.release; +end; + end.