v2 / vlib / gg / gg_darwin.m
208 lines · 190 sloc · 6.16 KB · cc5c71e1cb91979944a23001c75f04d6bf2669d2
Raw
1#include <Cocoa/Cocoa.h>
2
3NSColor* nscolor(gg__Color c) {
4 float red = (float)c.r / 255.0f;
5 float green = (float)c.g / 255.0f;
6 float blue = (float)c.b / 255.0f;
7 return [NSColor colorWithDeviceRed:red green:green blue:blue alpha:1.0f];
8}
9
10NSString* nsstring(string s) {
11 return [[NSString alloc] initWithBytesNoCopy:s.str
12 length:s.len
13 encoding:NSUTF8StringEncoding
14 freeWhenDone:false];
15}
16
17gg__Size gg_get_screen_size() {
18 NSScreen *currentScreen = nil;
19 NSWindow *mainWindow = [NSApp mainWindow];
20 // 1. Try screen containing the main window
21 if (mainWindow) {
22 currentScreen = [mainWindow screen];
23 }
24 // 2. If no main window, try the key window (might be different, e.g., a panel)
25 if (!currentScreen) {
26 NSWindow *keyWindow = [NSApp keyWindow];
27 if (keyWindow) {
28 currentScreen = [keyWindow screen];
29 }
30 }
31 // 3. If no relevant window, find the screen containing the mouse cursor
32 if (!currentScreen) {
33 // Get mouse location in global screen coordinates (bottom-left origin)
34 NSPoint mouseLocation = [NSEvent mouseLocation];
35 NSArray<NSScreen *> *screens = [NSScreen screens];
36 for (NSScreen *screen in screens) {
37 // Check if the mouse location is within the screen's frame
38 // Note: Both mouseLocation and screen.frame use bottom-left origin coordinates
39 if (NSMouseInRect(mouseLocation, [screen frame], NO)) {
40 currentScreen = screen;
41 break; // Found the screen with the mouse
42 }
43 }
44 }
45 // 4. As a last resort, fall back to the main screen
46 if (!currentScreen) {
47 NSLog(@"Warning: Could not determine current screen based on window or mouse. Falling back to mainScreen.");
48 currentScreen = [NSScreen mainScreen];
49 }
50 // Now get the size of the determined screen
51 NSDictionary *description = [currentScreen deviceDescription];
52 // Use NSDeviceSize to get pixel dimensions
53 NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue];
54 // Create the V gg.Size object
55 gg__Size res;
56 res.width = displayPixelSize.width;
57 res.height = displayPixelSize.height;
58 return res;
59}
60
61void gg_macos_resize_window(void *window_ptr, int width, int height) {
62 if (window_ptr == nil || width <= 0 || height <= 0) {
63 return;
64 }
65 NSWindow *window = (__bridge NSWindow *)window_ptr;
66 [window setContentSize:NSMakeSize((CGFloat)width, (CGFloat)height)];
67}
68
69void gg_macos_set_window_resizable(void *window_ptr, bool resizable) {
70 if (window_ptr == nil) {
71 return;
72 }
73 NSWindow *window = (__bridge NSWindow *)window_ptr;
74 NSWindowStyleMask style = [window styleMask];
75 if (resizable) {
76 style |= NSWindowStyleMaskResizable;
77 } else {
78 style &= ~NSWindowStyleMaskResizable;
79 }
80 [window setStyleMask:style];
81}
82
83void darwin_draw_string(int x, int y, string s, gg__TextCfg cfg) {
84 NSFont* font = [NSFont userFontOfSize:cfg.size];
85 // # NSFont* font = [NSFont fontWithName:@"Roboto Mono" size:cfg.size];
86 if (cfg.mono) {
87 // # font = [NSFont fontWithName:@"Roboto Mono" size:cfg.size];
88 font = [NSFont fontWithName:@"Menlo" size:cfg.size - 5];
89 }
90 if (cfg.bold) {
91 font = [[NSFontManager sharedFontManager] convertFont:font toHaveTrait:NSBoldFontMask];
92 }
93
94 NSDictionary* attr = @{
95 NSForegroundColorAttributeName : nscolor(cfg.color),
96 // NSParagraphStyleAttributeName: paragraphStyle,
97 NSFontAttributeName : font,
98 };
99 [nsstring(s) drawAtPoint:NSMakePoint(x, y - 15) withAttributes:attr];
100}
101
102int darwin_text_width(string s) {
103 // println('text_width "${s}" len=${s.len}')
104 NSString* n = @"";
105 if (s.len == 1) {
106 // println('len=1')
107 n = [NSString stringWithFormat:@"%c", s.str[0]];
108 } else {
109 n = nsstring(s);
110 }
111 /*
112 # if (!defaultFont){
113 # defaultFont = [NSFont userFontOfSize: ui__DEFAULT_FONT_SIZE];
114 # }
115 # NSDictionary *attrs = @{
116 # NSFontAttributeName: defaultFont,
117 # };
118 */
119 NSSize size = [n sizeWithAttributes:nil];
120 // # printf("!!!%f\n", ceil(size.width));
121 return (int)(ceil(size.width));
122}
123
124void darwin_draw_rect(float x, float y, float width, float height, gg__Color c) {
125 NSColor* color = nscolor(c);
126 NSRect rect = NSMakeRect(x, y, width, height);
127 [color setFill];
128 NSRectFill(rect);
129}
130
131static void mark_view_tree_needs_display(NSView *view) {
132 if (view == nil) {
133 return;
134 }
135 [view setNeedsDisplay:YES];
136 for (NSView *subview in [view subviews]) {
137 mark_view_tree_needs_display(subview);
138 }
139}
140
141void darwin_window_refresh() {
142 dispatch_async(dispatch_get_main_queue(), ^{
143 NSWindow *window = [NSApp mainWindow];
144 if (window == nil) {
145 window = [NSApp keyWindow];
146 }
147 if (window == nil) {
148 return;
149 }
150 NSView *contentView = [window contentView];
151 if (contentView == nil) {
152 return;
153 }
154 mark_view_tree_needs_display(contentView);
155 [window displayIfNeeded];
156 });
157
158 // puts("refresh");
159 //[[NSApp mainWindow].contentView drawRect:NSMakeRect(0,0,2000,2000)];
160 //[[NSGraphicsContext currentContext] flushGraphics];
161}
162
163gg__Image darwin_create_image(string path_) {
164 // file = file.trim_space()
165 NSString* path = nsstring(path_);
166 NSImage* img = [[NSImage alloc] initWithContentsOfFile:path];
167 if (img == 0) {
168 }
169 NSSize size = [img size];
170 gg__Image res;
171 res.width = size.width;
172 res.height = size.height;
173 res.path = path_;
174 res.ok = true;
175 // printf("inited img width=%d\n", res.width) ;
176 // need __bridge_retained so that the pointer is not freed by ARC
177 res.data = (__bridge_retained voidptr)(img);
178 return res;
179}
180
181void darwin_draw_image(float x, float y, float w, float h, gg__Image* img) {
182 NSImage* i = (__bridge NSImage*)(img->data);
183 [i drawInRect:NSMakeRect(x, y, w, h)];
184}
185
186void darwin_draw_circle(float x, float y, float d, gg__Color color) {
187 NSColor* c = nscolor(color);
188 NSRect rect = NSMakeRect(x, y, d * 2, d * 2);
189 NSBezierPath* circlePath = [NSBezierPath bezierPath];
190 [circlePath appendBezierPathWithOvalInRect:rect];
191 [c setFill];
192 // [circlePath stroke];
193 [circlePath fill];
194 // NSRectFill(rect);
195}
196
197void darwin_draw_circle_empty(float x, float y, float d, gg__Color color) {
198 NSColor* outlineColor = nscolor(color);
199 CGFloat outlineWidth = 1.0; //2.0;
200
201 NSRect rect = NSMakeRect(x, y, d * 2, d * 2);
202 NSBezierPath* circlePath = [NSBezierPath bezierPath];
203 [circlePath appendBezierPathWithOvalInRect:rect];
204
205 [outlineColor setStroke];
206 [circlePath setLineWidth:outlineWidth];
207 [circlePath stroke];
208}
209