Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for watching NSStatusItem appearance changes #2

Merged
merged 2 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions systray.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import (
)

var (
systrayReady func()
systrayExit func()
systrayExitCalled bool
menuItems = make(map[uint32]*MenuItem)
menuItemsLock sync.RWMutex
systrayReady func()
systrayExit func()
systrayOnAppearanceChanged func(bool)
systrayExitCalled bool
menuItems = make(map[uint32]*MenuItem)
menuItemsLock sync.RWMutex

currentID = uint32(0)
quitOnce sync.Once
Expand Down Expand Up @@ -78,17 +79,17 @@ func newMenuItem(title string, tooltip string, parent *MenuItem) *MenuItem {

// Run initializes GUI and starts the event loop, then invokes the onReady
// callback. It blocks until systray.Quit() is called.
func Run(onReady, onExit func()) {
func Run(onReady, onExit func(), onAppearanceChanged func(bool)) {
setInternalLoop(true)
Register(onReady, onExit)
Register(onReady, onExit, onAppearanceChanged)

nativeLoop()
}

// RunWithExternalLoop allows the systemtray module to operate with other tookits.
// The returned start and end functions should be called by the toolkit when the application has started and will end.
func RunWithExternalLoop(onReady, onExit func()) (start, end func()) {
Register(onReady, onExit)
func RunWithExternalLoop(onReady, onExit func(), onAppearanceChanged func(bool)) (start, end func()) {
Register(onReady, onExit, onAppearanceChanged)

return nativeStart, func() {
nativeEnd()
Expand All @@ -101,7 +102,7 @@ func RunWithExternalLoop(onReady, onExit func()) (start, end func()) {
// needs to show other UI elements, for example, webview.
// To overcome some OS weirdness, On macOS versions before Catalina, calling
// this does exactly the same as Run().
func Register(onReady func(), onExit func()) {
func Register(onReady func(), onExit func(), onAppearanceChanged func(bool)) {
if onReady == nil {
systrayReady = func() {}
} else {
Expand Down Expand Up @@ -266,3 +267,9 @@ func systrayMenuItemSelected(id uint32) {
default:
}
}

func systrayAppearanceChanged(dark bool) {
if systrayOnAppearanceChanged != nil {
systrayOnAppearanceChanged(dark)
}
}
1 change: 1 addition & 0 deletions systray.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
extern void systray_ready();
extern void systray_on_exit();
extern void systray_menu_item_selected(int menu_id);
extern void systray_appearance_changed(bool dark);
void registerSystray(void);
void nativeEnd(void);
int nativeLoop(void);
Expand Down
5 changes: 5 additions & 0 deletions systray_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,8 @@ func systray_on_exit() {
func systray_menu_item_selected(cID C.int) {
systrayMenuItemSelected(uint32(cID))
}

//export systray_appearance_changed
func systray_appearance_changed(dark C.bool) {
systrayAppearanceChanged(bool(dark))
}
15 changes: 15 additions & 0 deletions systray_darwin.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,24 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
self->menu = [[NSMenu alloc] init];
[self->menu setAutoenablesItems: FALSE];
[self->statusItem setMenu:self->menu];
[self->statusItem addObserver:self forKeyPath:@"button.effectiveAppearance" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial context:nil];
systray_ready();
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"button.effectiveAppearance"]) {
NSStatusItem *item = object;
NSAppearance *appearance = item.button.effectiveAppearance;
NSString *appearanceName = (NSString*)(appearance.name);
if ([[appearanceName lowercaseString] containsString:@"dark"]) {
systray_appearance_changed(true);
} else {
systray_appearance_changed(false);
}
}
}

- (void)applicationWillTerminate:(NSNotification *)aNotification
{
systray_on_exit();
Expand Down