FreeRDP
Loading...
Searching...
No Matches
mac_cursor.m
1
19#import <AppKit/AppKit.h>
20
21#include <math.h>
22
23#include <winpr/assert.h>
24
25#include "mac_cursor.h"
26
27BOOL mac_cursor_get(macCursorImage *image, UINT32 maxSize)
28{
29 WINPR_ASSERT(image);
30 memset(image, 0, sizeof(*image));
31
32 @autoreleasepool
33 {
34 /* the cursor of whatever application is in front, not only ours */
35 NSCursor *cursor = [NSCursor currentSystemCursor];
36 NSImage *picture = cursor.image;
37 if (!picture)
38 return FALSE;
39
40 const NSSize size = picture.size;
41 const NSPoint hot = cursor.hotSpot;
42 const double width = ceil(size.width);
43 const double height = ceil(size.height);
44 if ((width < 1.0) || (height < 1.0) || (width > maxSize) || (height > maxSize))
45 return FALSE;
46
47 /* the representation drawn at the size in points: on a Retina display
48 * that is the 2x one, scaled down like the screen itself */
49 NSRect rect = NSMakeRect(0, 0, width, height);
50 CGImageRef cgImage = [picture CGImageForProposedRect:&rect context:nil hints:nil];
51 if (!cgImage)
52 return FALSE;
53
54 const size_t w = (size_t)width;
55 const size_t h = (size_t)height;
56 BYTE *pixels = calloc(w * h, 4);
57 if (!pixels)
58 return FALSE;
59
60 /* premultiplied ARGB in a little-endian word: B, G, R, A in memory */
61 CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
62 CGContextRef context =
63 CGBitmapContextCreate(pixels, w, h, 8, w * 4, space,
64 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
65 CGColorSpaceRelease(space);
66 if (!context)
67 {
68 free(pixels);
69 return FALSE;
70 }
71 CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage);
72 CGContextRelease(context);
73
74 image->width = (UINT32)w;
75 image->height = (UINT32)h;
76 image->xHot = (UINT32)MIN(MAX(hot.x, 0.0), width - 1.0);
77 image->yHot = (UINT32)MIN(MAX(hot.y, 0.0), height - 1.0);
78 image->pixels = pixels;
79 }
80 return TRUE;
81}
82
83void mac_cursor_image_free(macCursorImage *image)
84{
85 if (!image)
86 return;
87 free(image->pixels);
88 image->pixels = NULL;
89}