feat: add tray layout controls

This commit is contained in:
Steve Cliff
2026-08-20 09:31:15 +01:00
parent 45ee82692d
commit cb00340c55
10 changed files with 523 additions and 31 deletions
+49
View File
@@ -76,7 +76,9 @@ var (
procSetProcessDPIAwareV2 = user32.NewProc("SetProcessDpiAwarenessContext")
procEnumDisplayMonitors = user32.NewProc("EnumDisplayMonitors")
procCreateMutex = kernel32.NewProc("CreateMutexW")
procFreeConsole = kernel32.NewProc("FreeConsole")
procDwmGetWindowAttribute = dwmapi.NewProc("DwmGetWindowAttribute")
procMessageBox = user32.NewProc("MessageBoxW")
)
type point struct{ X, Y int32 }
@@ -121,10 +123,20 @@ type engine struct {
debug bool
overlay *overlayManager
overlayFailed bool
tray *trayIcon
}
var activeEngine *engine
func PrepareBackground() { procFreeConsole.Call() }
func ShowError(title, message string) {
t, _ := windows.UTF16PtrFromString(title)
m, _ := windows.UTF16PtrFromString(message)
const mbOKIconErrorSetForeground = 0x00000000 | 0x00000010 | 0x00010000
procMessageBox.Call(0, uintptr(unsafe.Pointer(m)), uintptr(unsafe.Pointer(t)), mbOKIconErrorSetForeground)
}
func Run(configPath string, cfg config.Config, debug bool) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@@ -142,6 +154,12 @@ func Run(configPath string, cfg config.Config, debug bool) error {
e := &engine{configPath: configPath, cfg: cfg, hotkeys: make(map[int]hotkeyBinding), debug: debug, overlay: &overlayManager{}}
defer e.overlay.hide()
tray, err := newTrayIcon(cfg.ActiveLayout, cfg.LayoutNames())
if err != nil {
return err
}
e.tray = tray
defer e.tray.close()
e.rememberConfigTime()
activeEngine = e
defer func() { activeEngine = nil }()
@@ -690,5 +708,36 @@ func (e *engine) reloadIfChanged() {
_ = e.registerHotkeys()
return
}
e.tray.setLayouts(cfg.ActiveLayout, cfg.LayoutNames())
log.Printf("configuration reloaded: active layout=%q", cfg.ActiveLayout)
}
func (e *engine) selectLayout(name string) {
e.mu.RLock()
cfg := e.cfg
e.mu.RUnlock()
found := false
for _, candidate := range cfg.LayoutNames() {
if strings.EqualFold(candidate, name) {
name = candidate
found = true
break
}
}
if !found || strings.EqualFold(cfg.ActiveLayout, name) {
return
}
if err := config.SetActiveLayout(e.configPath, name); err != nil {
log.Printf("cannot select layout %q: %v", name, err)
ShowError("FancyWin", fmt.Sprintf("Could not select layout %q:\n\n%v", name, err))
return
}
cfg.ActiveLayout = name
e.mu.Lock()
e.cfg = cfg
e.mu.Unlock()
e.rememberConfigTime()
e.overlay.hide()
e.tray.setLayouts(name, cfg.LayoutNames())
log.Printf("active layout changed from tray: %q", name)
}