Files
mamamiyear ceecbb6af4 feat(app): implement basic function
General
- 配置界面支持配置对象存储桶
- 快捷键进入截图
- 一键上传截图 & 复制截图链接

MacOS
- 状态栏指示器和应用图标
2026-06-01 21:17:29 +08:00

63 lines
1.6 KiB
Go

//go:build darwin
package tray
/*
#cgo darwin LDFLAGS: -framework Foundation
#include <dispatch/dispatch.h>
// runOnMainQueue submits the Go-side callback (identified by handle) to the
// main dispatch queue. We use dispatch_async so the caller — typically a
// Wails OnStartup goroutine — does not block the cocoa runloop while waiting
// for the main thread to drain.
extern void trayDispatchMainCallback(unsigned long handle);
static void runOnMainQueue(unsigned long handle) {
dispatch_async(dispatch_get_main_queue(), ^{
trayDispatchMainCallback(handle);
});
}
*/
import "C"
import (
"sync"
"sync/atomic"
)
// dispatchRegistry stores Go closures keyed by an integer handle so that the
// C side can call back into Go without leaking unsafe.Pointer-cast function
// pointers (which CGo disallows).
var (
dispatchMu sync.Mutex
dispatchTable = map[uint64]func(){}
dispatchNextID uint64
)
// dispatchOnMain schedules fn to run on the macOS main thread. This is the
// Cocoa contract for any API that touches NSWindow / NSStatusBar — calling
// them from a goroutine triggers the "should only be instantiated on the
// main thread" assertion.
func dispatchOnMain(fn func()) {
if fn == nil {
return
}
id := atomic.AddUint64(&dispatchNextID, 1)
dispatchMu.Lock()
dispatchTable[id] = fn
dispatchMu.Unlock()
C.runOnMainQueue(C.ulong(id))
}
//export trayDispatchMainCallback
func trayDispatchMainCallback(handle C.ulong) {
id := uint64(handle)
dispatchMu.Lock()
fn := dispatchTable[id]
delete(dispatchTable, id)
dispatchMu.Unlock()
if fn != nil {
fn()
}
}