diff options
Diffstat (limited to 'src/macos.m')
-rw-r--r-- | src/macos.m | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/src/macos.m b/src/macos.m new file mode 100644 index 00000000..edbb6df0 --- /dev/null +++ b/src/macos.m | |||
@@ -0,0 +1,502 @@ | |||
1 | /* Copyright 2020 Jaakko Keränen <jaakko.keranen@iki.fi> | ||
2 | |||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions are met: | ||
5 | |||
6 | 1. Redistributions of source code must retain the above copyright notice, this | ||
7 | list of conditions and the following disclaimer. | ||
8 | 2. Redistributions in binary form must reproduce the above copyright notice, | ||
9 | this list of conditions and the following disclaimer in the documentation | ||
10 | and/or other materials provided with the distribution. | ||
11 | |||
12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
14 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
15 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||
16 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
18 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | ||
22 | |||
23 | #include "macos.h" | ||
24 | #include "app.h" | ||
25 | #include "ui/command.h" | ||
26 | #include "ui/widget.h" | ||
27 | #include "ui/color.h" | ||
28 | |||
29 | #import <AppKit/AppKit.h> | ||
30 | |||
31 | #if 0 | ||
32 | static NSTouchBarItemIdentifier play_TouchId_ = @"fi.skyjake.BitwiseHarmony.play"; | ||
33 | static NSTouchBarItemIdentifier restart_TouchId_ = @"fi.skyjake.BitwiseHarmony.restart"; | ||
34 | |||
35 | static NSTouchBarItemIdentifier seqMoveUp_TouchId_ = @"fi.skyjake.BitwiseHarmony.sequence.move.up"; | ||
36 | static NSTouchBarItemIdentifier seqMoveDown_TouchId_ = @"fi.skyjake.BitwiseHarmony.sequence.move.down"; | ||
37 | |||
38 | static NSTouchBarItemIdentifier goto_TouchId_ = @"fi.skyjake.BitwiseHarmony.goto"; | ||
39 | static NSTouchBarItemIdentifier mute_TouchId_ = @"fi.skyjake.BitwiseHarmony.mute"; | ||
40 | static NSTouchBarItemIdentifier solo_TouchId_ = @"fi.skyjake.BitwiseHarmony.solo"; | ||
41 | static NSTouchBarItemIdentifier color_TouchId_ = @"fi.skyjake.BitwiseHarmony.color"; | ||
42 | static NSTouchBarItemIdentifier event_TouchId_ = @"fi.skyjake.BitwiseHarmony.event"; | ||
43 | |||
44 | static NSTouchBarItemIdentifier eventList_TouchId_ = @"fi.skyjake.BitwiseHarmony.eventlist"; | ||
45 | static NSTouchBarItemIdentifier masterGainEvent_TouchId_ = @"fi.skyjake.BitwiseHarmony.event.mastergain"; | ||
46 | static NSTouchBarItemIdentifier resetEvent_TouchId_ = @"fi.skyjake.BitwiseHarmony.event.reset"; | ||
47 | static NSTouchBarItemIdentifier voiceEvent_TouchId_ = @"fi.skyjake.BitwiseHarmony.event.voice"; | ||
48 | static NSTouchBarItemIdentifier panEvent_TouchId_ = @"fi.skyjake.BitwiseHarmony.event.pan"; | ||
49 | static NSTouchBarItemIdentifier gainEvent_TouchId_ = @"fi.skyjake.BitwiseHarmony.event.gain"; | ||
50 | static NSTouchBarItemIdentifier fadeEvent_TouchId_ = @"fi.skyjake.BitwiseHarmony.event.fade"; | ||
51 | static NSTouchBarItemIdentifier pitchSpeedEvent_TouchId_ = @"fi.skyjake.BitwiseHarmony.event.pitchspeed"; | ||
52 | static NSTouchBarItemIdentifier pitchBendUpEvent_TouchId_ = @"fi.skyjake.BitwiseHarmony.event.pitchbendup"; | ||
53 | static NSTouchBarItemIdentifier pitchBendDownEvent_TouchId_ = @"fi.skyjake.BitwiseHarmony.event.pitchbenddown"; | ||
54 | static NSTouchBarItemIdentifier tremoloEvent_TouchId_ = @"fi.skyjake.BitwiseHarmony.event.tremolo"; | ||
55 | #endif | ||
56 | |||
57 | enum iTouchBarVariant { | ||
58 | default_TouchBarVariant, | ||
59 | }; | ||
60 | |||
61 | @interface CommandButton : NSButtonTouchBarItem { | ||
62 | NSString *command; | ||
63 | iWidget *widget; | ||
64 | } | ||
65 | - (id)initWithIdentifier:(NSTouchBarItemIdentifier)identifier | ||
66 | title:(NSString *)title | ||
67 | command:(NSString *)cmd; | ||
68 | - (id)initWithIdentifier:(NSTouchBarItemIdentifier)identifier | ||
69 | title:(NSString *)title | ||
70 | widget:(iWidget *)widget | ||
71 | command:(NSString *)cmd; | ||
72 | - (void)dealloc; | ||
73 | @end | ||
74 | |||
75 | @implementation CommandButton | ||
76 | |||
77 | - (id)initWithIdentifier:(NSTouchBarItemIdentifier)identifier | ||
78 | title:(NSString *)title | ||
79 | command:(NSString *)cmd { | ||
80 | [super initWithIdentifier:identifier]; | ||
81 | self.title = title; | ||
82 | self.target = self; | ||
83 | self.action = @selector(buttonPressed); | ||
84 | command = cmd; | ||
85 | return self; | ||
86 | } | ||
87 | |||
88 | - (id)initWithIdentifier:(NSTouchBarItemIdentifier)identifier | ||
89 | title:(NSString *)title | ||
90 | widget:(iWidget *)aWidget | ||
91 | command:(NSString *)cmd { | ||
92 | [self initWithIdentifier:identifier title:title command:[cmd retain]]; | ||
93 | widget = aWidget; | ||
94 | return self; | ||
95 | } | ||
96 | |||
97 | - (void)dealloc { | ||
98 | [command release]; | ||
99 | [super dealloc]; | ||
100 | } | ||
101 | |||
102 | - (void)buttonPressed { | ||
103 | const char *cmd = [command cStringUsingEncoding:NSUTF8StringEncoding]; | ||
104 | if (widget) { | ||
105 | postCommand_Widget(widget, "%s", cmd); | ||
106 | } | ||
107 | else { | ||
108 | postCommand_App(cmd); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | @end | ||
113 | |||
114 | @interface MyDelegate : NSResponder<NSApplicationDelegate, NSTouchBarDelegate> { | ||
115 | enum iTouchBarVariant touchBarVariant; | ||
116 | NSString *currentAppearanceName; | ||
117 | NSObject<NSApplicationDelegate> *sdlDelegate; | ||
118 | NSMutableDictionary<NSString *, NSString*> *menuCommands; | ||
119 | } | ||
120 | - (id)initWithSDLDelegate:(NSObject<NSApplicationDelegate> *)sdl; | ||
121 | //- (NSTouchBar *)makeTouchBar; | ||
122 | /* SDL needs to do its own thing. */ | ||
123 | - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename; | ||
124 | - (void)applicationDidFinishLaunching:(NSNotification *)notifications; | ||
125 | @end | ||
126 | |||
127 | @implementation MyDelegate | ||
128 | |||
129 | - (id)initWithSDLDelegate:(NSObject<NSApplicationDelegate> *)sdl { | ||
130 | [super init]; | ||
131 | currentAppearanceName = nil; | ||
132 | menuCommands = [[NSMutableDictionary<NSString *, NSString *> alloc] init]; | ||
133 | touchBarVariant = default_TouchBarVariant; | ||
134 | sdlDelegate = sdl; | ||
135 | return self; | ||
136 | } | ||
137 | |||
138 | - (void)dealloc { | ||
139 | [menuCommands release]; | ||
140 | [currentAppearanceName release]; | ||
141 | [super dealloc]; | ||
142 | } | ||
143 | |||
144 | - (void)setTouchBarVariant:(enum iTouchBarVariant)variant { | ||
145 | touchBarVariant = variant; | ||
146 | self.touchBar = nil; | ||
147 | } | ||
148 | |||
149 | static void appearanceChanged_MacOS_(NSString *name) { | ||
150 | const iBool isDark = [name containsString:@"Dark"]; | ||
151 | const iBool isHighContrast = [name containsString:@"HighContrast"]; | ||
152 | postCommandf_App("os.theme.changed dark:%d contrast:%d", isDark ? 1 : 0, isHighContrast ? 1 : 0); | ||
153 | // printf("Effective appearance changed: %s\n", [name cStringUsingEncoding:NSUTF8StringEncoding]); | ||
154 | // fflush(stdout); | ||
155 | } | ||
156 | |||
157 | - (void)setAppearance:(NSString *)name { | ||
158 | if (!currentAppearanceName || ![name isEqualToString:currentAppearanceName]) { | ||
159 | if (currentAppearanceName) { | ||
160 | [currentAppearanceName release]; | ||
161 | } | ||
162 | currentAppearanceName = [name retain]; | ||
163 | appearanceChanged_MacOS_(currentAppearanceName); | ||
164 | } | ||
165 | } | ||
166 | |||
167 | - (void)setCommand:(NSString *)command forMenuItem:(NSMenuItem *)menuItem { | ||
168 | [menuCommands setObject:command forKey:[menuItem title]]; | ||
169 | } | ||
170 | |||
171 | - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { | ||
172 | return [sdlDelegate application:theApplication openFile:filename]; | ||
173 | } | ||
174 | |||
175 | - (void)applicationDidFinishLaunching:(NSNotification *)notification { | ||
176 | [sdlDelegate applicationDidFinishLaunching:notification]; | ||
177 | } | ||
178 | |||
179 | - (void)observeValueForKeyPath:(NSString *)keyPath | ||
180 | ofObject:(id)object | ||
181 | change:(NSDictionary *)change | ||
182 | context:(void *)context { | ||
183 | iUnused(object, change); | ||
184 | if ([keyPath isEqualToString:@"effectiveAppearance"] && context == self) { | ||
185 | [self setAppearance:[[NSApp effectiveAppearance] name]]; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | #if 0 | ||
190 | - (NSTouchBar *)makeTouchBar { | ||
191 | NSTouchBar *bar = [[NSTouchBar alloc] init]; | ||
192 | bar.delegate = self; | ||
193 | switch (touchBarVariant) { | ||
194 | case default_TouchBarVariant: | ||
195 | bar.defaultItemIdentifiers = @[ play_TouchId_, restart_TouchId_, | ||
196 | NSTouchBarItemIdentifierFixedSpaceSmall, | ||
197 | NSTouchBarItemIdentifierOtherItemsProxy ]; | ||
198 | break; | ||
199 | case sequence_TouchBarVariant: | ||
200 | bar.defaultItemIdentifiers = @[ play_TouchId_, restart_TouchId_, | ||
201 | NSTouchBarItemIdentifierFlexibleSpace, | ||
202 | seqMoveUp_TouchId_, seqMoveDown_TouchId_, | ||
203 | NSTouchBarItemIdentifierFlexibleSpace, | ||
204 | NSTouchBarItemIdentifierOtherItemsProxy]; | ||
205 | break; | ||
206 | case tracker_TouchBarVariant: | ||
207 | bar.defaultItemIdentifiers = @[ play_TouchId_, restart_TouchId_, | ||
208 | NSTouchBarItemIdentifierFlexibleSpace, | ||
209 | goto_TouchId_, | ||
210 | event_TouchId_, | ||
211 | NSTouchBarItemIdentifierFlexibleSpace, | ||
212 | solo_TouchId_, mute_TouchId_, color_TouchId_, | ||
213 | NSTouchBarItemIdentifierFlexibleSpace, | ||
214 | NSTouchBarItemIdentifierOtherItemsProxy ]; | ||
215 | break; | ||
216 | case wide_TouchBarVariant: | ||
217 | bar.defaultItemIdentifiers = @[ play_TouchId_, restart_TouchId_, | ||
218 | NSTouchBarItemIdentifierFlexibleSpace, | ||
219 | event_TouchId_, | ||
220 | NSTouchBarItemIdentifierFlexibleSpace, | ||
221 | solo_TouchId_, mute_TouchId_, color_TouchId_, | ||
222 | NSTouchBarItemIdentifierFlexibleSpace, | ||
223 | seqMoveUp_TouchId_, seqMoveDown_TouchId_, | ||
224 | NSTouchBarItemIdentifierFlexibleSpace, | ||
225 | NSTouchBarItemIdentifierOtherItemsProxy ]; | ||
226 | break; | ||
227 | } | ||
228 | return bar; | ||
229 | } | ||
230 | #endif | ||
231 | |||
232 | - (void)showPreferences { | ||
233 | postCommand_App("preferences"); | ||
234 | } | ||
235 | |||
236 | - (void)closeTab { | ||
237 | postCommand_App("tabs.close"); | ||
238 | } | ||
239 | |||
240 | - (void)postMenuItemCommand:(id)sender { | ||
241 | NSString *command = [menuCommands objectForKey:[(NSMenuItem *)sender title]]; | ||
242 | if (command) { | ||
243 | postCommand_App([command cStringUsingEncoding:NSUTF8StringEncoding]); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | - (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar | ||
248 | makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier { | ||
249 | iUnused(touchBar); | ||
250 | #if 0 | ||
251 | if ([identifier isEqualToString:play_TouchId_]) { | ||
252 | return [NSButtonTouchBarItem | ||
253 | buttonTouchBarItemWithIdentifier:identifier | ||
254 | image:[NSImage imageNamed:NSImageNameTouchBarPlayPauseTemplate] | ||
255 | target:self | ||
256 | action:@selector(playPressed)]; | ||
257 | } | ||
258 | else if ([identifier isEqualToString:restart_TouchId_]) { | ||
259 | return [NSButtonTouchBarItem | ||
260 | buttonTouchBarItemWithIdentifier:identifier | ||
261 | image:[NSImage imageNamed:NSImageNameTouchBarSkipToStartTemplate] | ||
262 | target:self | ||
263 | action:@selector(restartPressed)]; | ||
264 | } | ||
265 | else if ([identifier isEqualToString:seqMoveUp_TouchId_]) { | ||
266 | return [[CommandButton alloc] initWithIdentifier:identifier | ||
267 | title:@"Seq\u2b06" | ||
268 | widget:findWidget_App("sequence") | ||
269 | command:@"sequence.swap arg:-1"]; | ||
270 | } | ||
271 | else if ([identifier isEqualToString:seqMoveDown_TouchId_]) { | ||
272 | return [[CommandButton alloc] initWithIdentifier:identifier | ||
273 | title:@"Seq\u2b07" | ||
274 | widget:findWidget_App("sequence") | ||
275 | command:@"sequence.swap arg:1"]; | ||
276 | } | ||
277 | else if ([identifier isEqualToString:goto_TouchId_]) { | ||
278 | return [[CommandButton alloc] initWithIdentifier:identifier | ||
279 | title:@"Go to…" | ||
280 | command:@"pattern.goto arg:-1"]; | ||
281 | } | ||
282 | else if ([identifier isEqualToString:event_TouchId_]) { | ||
283 | NSTouchBar *events = [[NSTouchBar alloc] init]; | ||
284 | events.delegate = self; | ||
285 | events.defaultItemIdentifiers = @[ eventList_TouchId_ ]; | ||
286 | NSPopoverTouchBarItem *pop = [[NSPopoverTouchBarItem alloc] initWithIdentifier:identifier]; | ||
287 | pop.collapsedRepresentationLabel = @"Event"; | ||
288 | pop.popoverTouchBar = events; | ||
289 | [events release]; | ||
290 | return pop; | ||
291 | } | ||
292 | else if ([identifier isEqualToString:eventList_TouchId_]) { | ||
293 | const struct { | ||
294 | NSTouchBarItemIdentifier id; | ||
295 | const char *title; | ||
296 | const char *command; | ||
297 | } buttonDefs_[] = { | ||
298 | { voiceEvent_TouchId_, "Voice", "tracker.setevent type:2" }, | ||
299 | { panEvent_TouchId_, "Pan", "tracker.setevent type:3 arg:128" }, | ||
300 | { gainEvent_TouchId_, "Gain", "tracker.setevent type:4 arg:128" }, | ||
301 | { fadeEvent_TouchId_, "Fade", "tracker.setevent type:5" }, | ||
302 | { tremoloEvent_TouchId_, "Trem", "tracker.setevent type:9" }, | ||
303 | { pitchSpeedEvent_TouchId_, "P.Spd", "tracker.setevent type:6" }, | ||
304 | { pitchBendUpEvent_TouchId_, "BnUp", "tracker.setevent type:7" }, | ||
305 | { pitchBendDownEvent_TouchId_, "BnDn", "tracker.setevent type:8" }, | ||
306 | { masterGainEvent_TouchId_, "M.Gain", "tracker.setevent type:10 arg:64" }, | ||
307 | { resetEvent_TouchId_, "Reset", "tracker.setevent type:1" }, | ||
308 | }; | ||
309 | NSMutableArray *items = [[NSMutableArray alloc] init]; | ||
310 | iForIndices(i, buttonDefs_) { | ||
311 | CommandButton *button = [[CommandButton alloc] | ||
312 | initWithIdentifier:buttonDefs_[i].id | ||
313 | title:[NSString stringWithUTF8String:buttonDefs_[i].title] | ||
314 | widget:findWidget_App("tracker") | ||
315 | command:[NSString stringWithUTF8String:buttonDefs_[i].command] | ||
316 | ]; | ||
317 | [items addObject:button]; | ||
318 | } | ||
319 | NSGroupTouchBarItem *group = [NSGroupTouchBarItem groupItemWithIdentifier:identifier | ||
320 | items:items]; | ||
321 | [items release]; | ||
322 | return group; | ||
323 | } | ||
324 | else if ([identifier isEqualToString:mute_TouchId_]) { | ||
325 | return [[CommandButton alloc] initWithIdentifier:identifier | ||
326 | title:@"Mute" | ||
327 | widget:findWidget_App("tracker") | ||
328 | command:@"tracker.mute"]; | ||
329 | } | ||
330 | else if ([identifier isEqualToString:solo_TouchId_]) { | ||
331 | return [[CommandButton alloc] initWithIdentifier:identifier | ||
332 | title:@"Solo" | ||
333 | widget:findWidget_App("tracker") | ||
334 | command:@"tracker.solo"]; | ||
335 | } | ||
336 | else if ([identifier isEqualToString:color_TouchId_]) { | ||
337 | NSTouchBar *colors = [[NSTouchBar alloc] init]; | ||
338 | colors.delegate = self; | ||
339 | colors.defaultItemIdentifiers = @[ NSTouchBarItemIdentifierFlexibleSpace, | ||
340 | whiteColor_TouchId_, | ||
341 | yellowColor_TouchId_, | ||
342 | orangeColor_TouchId_, | ||
343 | redColor_TouchId_, | ||
344 | magentaColor_TouchId_, | ||
345 | blueColor_TouchId_, | ||
346 | cyanColor_TouchId_, | ||
347 | greenColor_TouchId_, | ||
348 | NSTouchBarItemIdentifierFlexibleSpace ]; | ||
349 | NSPopoverTouchBarItem *pop = [[NSPopoverTouchBarItem alloc] initWithIdentifier:identifier]; | ||
350 | pop.collapsedRepresentationImage = [NSImage imageNamed:NSImageNameTouchBarColorPickerFill]; | ||
351 | pop.popoverTouchBar = colors; | ||
352 | [colors release]; | ||
353 | return pop; | ||
354 | } | ||
355 | else if ([identifier isEqualToString:whiteColor_TouchId_]) { | ||
356 | return [[ColorButton alloc] initWithIdentifier:identifier | ||
357 | trackColor:white_TrackColor]; | ||
358 | } | ||
359 | else if ([identifier isEqualToString:yellowColor_TouchId_]) { | ||
360 | return [[ColorButton alloc] initWithIdentifier:identifier | ||
361 | trackColor:yellow_TrackColor]; | ||
362 | } | ||
363 | else if ([identifier isEqualToString:orangeColor_TouchId_]) { | ||
364 | return [[ColorButton alloc] initWithIdentifier:identifier | ||
365 | trackColor:orange_TrackColor]; | ||
366 | } | ||
367 | else if ([identifier isEqualToString:redColor_TouchId_]) { | ||
368 | return [[ColorButton alloc] initWithIdentifier:identifier | ||
369 | trackColor:red_TrackColor]; | ||
370 | } | ||
371 | else if ([identifier isEqualToString:magentaColor_TouchId_]) { | ||
372 | return [[ColorButton alloc] initWithIdentifier:identifier | ||
373 | trackColor:magenta_TrackColor]; | ||
374 | } | ||
375 | else if ([identifier isEqualToString:blueColor_TouchId_]) { | ||
376 | return [[ColorButton alloc] initWithIdentifier:identifier | ||
377 | trackColor:blue_TrackColor]; | ||
378 | } | ||
379 | else if ([identifier isEqualToString:cyanColor_TouchId_]) { | ||
380 | return [[ColorButton alloc] initWithIdentifier:identifier | ||
381 | trackColor:cyan_TrackColor]; | ||
382 | } | ||
383 | else if ([identifier isEqualToString:greenColor_TouchId_]) { | ||
384 | return [[ColorButton alloc] initWithIdentifier:identifier | ||
385 | trackColor:green_TrackColor]; | ||
386 | } | ||
387 | #endif | ||
388 | return nil; | ||
389 | } | ||
390 | |||
391 | @end | ||
392 | |||
393 | void enableMomentumScroll_MacOS(void) { | ||
394 | [[NSUserDefaults standardUserDefaults] setBool: YES | ||
395 | forKey: @"AppleMomentumScrollSupported"]; | ||
396 | } | ||
397 | |||
398 | void setupApplication_MacOS(void) { | ||
399 | NSApplication *app = [NSApplication sharedApplication]; | ||
400 | //appearanceChanged_MacOS_([[app effectiveAppearance] name]); | ||
401 | /* Our delegate will override SDL's delegate. */ | ||
402 | MyDelegate *myDel = [[MyDelegate alloc] initWithSDLDelegate:app.delegate]; | ||
403 | [myDel setAppearance:[[app effectiveAppearance] name]]; | ||
404 | app.delegate = myDel; | ||
405 | NSMenu *appMenu = [[[NSApp mainMenu] itemAtIndex:0] submenu]; | ||
406 | NSMenuItem *prefsItem = [appMenu itemWithTitle:@"Preferences…"]; | ||
407 | prefsItem.target = myDel; | ||
408 | prefsItem.action = @selector(showPreferences); | ||
409 | /* Get rid of the default window close item */ | ||
410 | NSMenu *windowMenu = [[[NSApp mainMenu] itemWithTitle:@"Window"] submenu]; | ||
411 | NSMenuItem *windowCloseItem = [windowMenu itemWithTitle:@"Close"]; | ||
412 | windowCloseItem.target = myDel; | ||
413 | windowCloseItem.action = @selector(closeTab); | ||
414 | } | ||
415 | |||
416 | void insertMenuItems_MacOS(const char *menuLabel, int atIndex, const iMenuItem *items, size_t count) { | ||
417 | NSApplication *app = [NSApplication sharedApplication]; | ||
418 | MyDelegate *myDel = (MyDelegate *) app.delegate; | ||
419 | [app addObserver:myDel | ||
420 | forKeyPath:@"effectiveAppearance" | ||
421 | options:0 | ||
422 | context:myDel]; | ||
423 | NSMenu *appMenu = [app mainMenu]; | ||
424 | NSMenuItem *mainItem = [appMenu insertItemWithTitle:[NSString stringWithUTF8String:menuLabel] | ||
425 | action:nil | ||
426 | keyEquivalent:@"" | ||
427 | atIndex:atIndex]; | ||
428 | NSMenu *menu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:menuLabel]]; | ||
429 | for (size_t i = 0; i < count; ++i) { | ||
430 | const char *label = items[i].label; | ||
431 | if (label[0] == '\r') { | ||
432 | /* Skip the formatting escape. */ | ||
433 | label += 2; | ||
434 | } | ||
435 | if (equal_CStr(label, "---")) { | ||
436 | [menu addItem:[NSMenuItem separatorItem]]; | ||
437 | } | ||
438 | else { | ||
439 | const iBool hasCommand = (items[i].command && items[i].command[0]); | ||
440 | iString key; | ||
441 | init_String(&key); | ||
442 | if (items[i].key == SDLK_LEFT) { | ||
443 | appendChar_String(&key, 0x2190); | ||
444 | } | ||
445 | else if (items[i].key == SDLK_RIGHT) { | ||
446 | appendChar_String(&key, 0x2192); | ||
447 | } | ||
448 | else if (items[i].key) { | ||
449 | appendChar_String(&key, items[i].key); | ||
450 | } | ||
451 | NSMenuItem *item = [menu addItemWithTitle:[NSString stringWithUTF8String:label] | ||
452 | action:(hasCommand ? @selector(postMenuItemCommand:) : nil) | ||
453 | keyEquivalent:[NSString stringWithUTF8String:cstr_String(&key)]]; | ||
454 | NSEventModifierFlags modMask = 0; | ||
455 | if (items[i].kmods & KMOD_GUI) { | ||
456 | modMask |= NSEventModifierFlagCommand; | ||
457 | } | ||
458 | if (items[i].kmods & KMOD_ALT) { | ||
459 | modMask |= NSEventModifierFlagOption; | ||
460 | } | ||
461 | if (items[i].kmods & KMOD_CTRL) { | ||
462 | modMask |= NSEventModifierFlagControl; | ||
463 | } | ||
464 | if (items[i].kmods & KMOD_SHIFT) { | ||
465 | modMask |= NSEventModifierFlagShift; | ||
466 | } | ||
467 | [item setKeyEquivalentModifierMask:modMask]; | ||
468 | if (hasCommand) { | ||
469 | [myDel setCommand:[NSString stringWithUTF8String:items[i].command] forMenuItem:item]; | ||
470 | } | ||
471 | deinit_String(&key); | ||
472 | } | ||
473 | } | ||
474 | [mainItem setSubmenu:menu]; | ||
475 | [menu release]; | ||
476 | } | ||
477 | |||
478 | void handleCommand_MacOS(const char *cmd) { | ||
479 | if (equal_Command(cmd, "prefs.ostheme.changed")) { | ||
480 | if (arg_Command(cmd)) { | ||
481 | appearanceChanged_MacOS_([[NSApp effectiveAppearance] name]); | ||
482 | } | ||
483 | } | ||
484 | #if 0 | ||
485 | if (equal_Command(cmd, "tabs.changed")) { | ||
486 | MyDelegate *myDel = (MyDelegate *) [[NSApplication sharedApplication] delegate]; | ||
487 | const char *tabId = suffixPtr_Command(cmd, "id"); | ||
488 | if (equal_CStr(tabId, "tracker")) { | ||
489 | [myDel setTouchBarVariant:tracker_TouchBarVariant]; | ||
490 | } | ||
491 | else if (equal_CStr(tabId, "sequence")) { | ||
492 | [myDel setTouchBarVariant:sequence_TouchBarVariant]; | ||
493 | } | ||
494 | else if (equal_CStr(tabId, "trackertab")) { | ||
495 | [myDel setTouchBarVariant:wide_TouchBarVariant]; | ||
496 | } | ||
497 | else { | ||
498 | [myDel setTouchBarVariant:default_TouchBarVariant]; | ||
499 | } | ||
500 | } | ||
501 | #endif | ||
502 | } | ||