Initial project import

This commit is contained in:
Agila Forge Importer committed 2026-07-13 15:20:32 +00:00
commit 23f2d29e32
11957 files changed
+1754577

No files matched your search

Whitespace-only changes.
Binary file not shown.

After

Width:  |  Height:  |  Size: 690 B

+131
View File
@@ -0,0 +1,131 @@
// #include <Cocoa/Cocoa.h> // Uncomment for C/C++ intellisense
// See this tutorial to learn about NSApplicationDelegate:
// https://bumbershootsoft.wordpress.com/2018/11/22/unfiltered-cocoa-completing-the-application/
static NSString *nsstring(string s) {
return [[NSString alloc] initWithBytesNoCopy:s.str
length:s.len
encoding:NSUTF8StringEncoding
freeWhenDone:NO];
}
// Manages the app lifecycle.
@interface AppDelegate : NSObject <NSApplicationDelegate> {
NSAutoreleasePool *pool;
NSApplication *app;
NSStatusItem *statusItem; // our button
main__TrayParams trayParams; // TrayParams is defined in tray.v
}
@end
@implementation AppDelegate
- (AppDelegate *)initWithParams:(main__TrayParams)params {
if (self = [super init]) {
trayParams = params;
}
return self;
}
// Called when NSMenuItem is clicked.
- (void)onAction:(id)sender {
struct main__TrayMenuItem *item =
(struct main__TrayMenuItem *)[[sender representedObject] pointerValue];
if (item) {
trayParams.on_click(*item);
}
}
- (NSMenu *)buildMenu {
NSMenu *menu = [NSMenu new];
[menu autorelease];
[menu setAutoenablesItems:NO];
main__TrayMenuItem *params_items = trayParams.items.data;
for (int i = 0; i < trayParams.items.len; i++) {
NSString *title = nsstring(params_items[i].text);
NSMenuItem *item = [menu addItemWithTitle:title
action:@selector(onAction:)
keyEquivalent:@""];
NSValue *representedObject = [NSValue valueWithPointer:(params_items + i)];
[item setRepresentedObject:representedObject];
[item setTarget:self];
[item autorelease];
[item setEnabled:YES];
}
return menu;
}
- (void)initTrayMenuItem {
NSStatusBar *statusBar = [NSStatusBar systemStatusBar];
statusItem = [statusBar statusItemWithLength:NSSquareStatusItemLength];
[statusItem retain];
[statusItem setVisible:YES];
NSStatusBarButton *statusBarButton = [statusItem button];
// Height must be 22px.
NSImage *img = [NSImage imageNamed:@"icon.png"];
[statusBarButton setImage:img];
NSMenu *menu = [self buildMenu];
[statusItem setMenu:menu];
}
- (void)applicationWillFinishLaunching:(NSNotification *)notification {
NSLog(@"applicationWillFinishLaunching called");
}
- (void)applicationWillTerminate:(NSNotification *)notif;
{ NSLog(@"applicationWillTerminate called"); }
- (NSApplicationTerminateReply)applicationShouldTerminate:
(NSApplication *)sender {
NSLog(@"applicationShouldTerminate called");
return NSTerminateNow;
}
@end
// Initializes NSApplication and NSStatusItem, aka system tray menu item.
main__TrayInfo *tray_app_init(main__TrayParams params) {
NSApplication *app = [NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] initWithParams:params];
// Hide icon from the doc.
[app setActivationPolicy:NSApplicationActivationPolicyProhibited];
[app setDelegate:appDelegate];
[appDelegate initTrayMenuItem];
main__TrayInfo *tray_info = malloc(sizeof(main__TrayInfo));
tray_info->app = app;
tray_info->app_delegate = appDelegate;
return tray_info;
}
// Blocks and runs the application.
void tray_app_run(main__TrayInfo *tray_info) {
NSApplication *app = (NSApplication *)(tray_info->app);
[app run];
}
// Processes a single NSEvent while blocking the thread
// until there is an event.
void tray_app_loop(main__TrayInfo *tray_info) {
NSDate *until = [NSDate distantFuture];
NSApplication *app = (NSApplication *)(tray_info->app);
NSEvent *event = [app nextEventMatchingMask:ULONG_MAX
untilDate:until
inMode:@"kCFRunLoopDefaultMode"
dequeue:YES];
if (event) {
[app sendEvent:event];
}
}
// Terminates the app.
void tray_app_exit(main__TrayInfo *tray_info) {
NSApplication *app = (NSApplication *)(tray_info->app);
[app terminate:app];
}
+71
View File
@@ -0,0 +1,71 @@
// vtest build: macos
// Simple windows-less application that shows a icon button on Mac OS tray.
// Tested on Mac OS Monterey (12.3).
module main
#include <Cocoa/Cocoa.h>
#flag -framework Cocoa
#include "@VMODROOT/tray.m"
fn C.tray_app_init(TrayParams) &TrayInfo
fn C.tray_app_loop(&TrayInfo)
fn C.tray_app_run(&TrayInfo)
fn C.tray_app_exit(&TrayInfo)
struct TrayMenuItem {
id string @[required] // Unique ID.
text string @[required] // Text to display.
}
// Parameters to configure the tray button.
struct TrayParams {
items []TrayMenuItem @[required]
on_click fn (item TrayMenuItem) @[required]
}
// Internal Cocoa application state.
struct TrayInfo {
app voidptr // pointer to NSApplication
app_delegate voidptr // pointer to AppDelegate
}
@[heap]
struct MyApp {
mut:
tray_info &TrayInfo = unsafe { nil }
}
fn (app &MyApp) on_menu_item_click(item TrayMenuItem) {
println('click ${item.id}')
if item.id == 'quit' {
C.tray_app_exit(app.tray_info)
}
}
fn main() {
mut my_app := &MyApp{
tray_info: unsafe { nil }
}
my_app.tray_info = C.tray_app_init(TrayParams{
items: [TrayMenuItem{
id: 'hello'
text: 'Hello'
}, TrayMenuItem{
id: 'quit'
text: 'Quit!'
}]
on_click: my_app.on_menu_item_click
})
//// Use this:
// for {
// C.tray_app_loop(my_app.tray_info)
// // println("loop")
// }
//// Or this:
C.tray_app_run(my_app.tray_info)
}
View File
Whitespace-only changes.