forked from zserge/tray
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tray_darwin.m
80 lines (70 loc) · 2.44 KB
/
tray_darwin.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <Cocoa/Cocoa.h>
#include <string.h>
#include "tray.h"
@interface AppDelegate: NSObject <NSApplicationDelegate>
- (IBAction)menuCallback:(id)sender;
@end
@implementation AppDelegate{}
- (IBAction)menuCallback:(id)sender
{
struct tray_menu *m = [[sender representedObject] pointerValue];
if (m != NULL && m->cb != NULL) {
m->cb(m);
}
}
@end
static NSApplication* app;
static NSStatusBar* statusBar;
static NSStatusItem* statusItem;
static NSMenu* _tray_menu(struct tray_menu *m) {
NSMenu* menu = [[NSMenu alloc] init];
[menu setAutoenablesItems:FALSE];
for (; m != NULL && m->text != NULL; m++) {
if (strcmp(m->text, "-") == 0) {
[menu addItem:[NSMenuItem separatorItem]];
} else {
NSMenuItem* menuItem = [[NSMenuItem alloc]
initWithTitle:[NSString stringWithUTF8String:m->text]
action:@selector(menuCallback:)
keyEquivalent:@""];
[menuItem setEnabled:(m->disabled ? FALSE : TRUE)];
[menuItem setState:(m->checked ? 1 : 0)];
[menuItem setRepresentedObject:[NSValue valueWithPointer:m]];
[menu addItem:menuItem];
if (m->submenu != NULL) {
[menu setSubmenu:_tray_menu(m->submenu) forItem:menuItem];
}
}
}
return menu;
}
int tray_init(struct tray *tray) {
AppDelegate *delegate = [[AppDelegate alloc] init];
app = [NSApplication sharedApplication];
[app setDelegate:delegate];
statusBar = [NSStatusBar systemStatusBar];
statusItem = [statusBar statusItemWithLength:NSVariableStatusItemLength];
tray_update(tray);
[app activateIgnoringOtherApps:TRUE];
return 0;
}
int tray_loop(int blocking) {
NSDate* until = (blocking ? [NSDate distantFuture] : [NSDate distantPast]);
NSEvent* event = [app nextEventMatchingMask:ULONG_MAX untilDate:until
inMode:[NSString stringWithUTF8String:"kCFRunLoopDefaultMode"] dequeue:TRUE];
if (event) {
[app sendEvent:event];
}
return 0;
}
void tray_update(struct tray *tray) {
NSData* buffer = [NSData dataWithBytes:tray->icon.data length:tray->icon.length];
NSImage *image = [[NSImage alloc] initWithData:buffer];
NSSize size = NSMakeSize(16, 16);
[image setSize:NSMakeSize(16, 16)];
statusItem.button.image = image;
[statusItem setMenu:_tray_menu(tray->menu)];
}
void tray_exit() {
[app terminate:app];
}