package main import ( "fmt" "io" "log" "os" "slices" "strconv" "syscall" // _ "embed" "fyne.io/systray" hook "github.com/robotn/gohook" ) var ( us32 = syscall.MustLoadDLL("user32.dll") SetForegroundWindow = us32.MustFindProc("SetForegroundWindow") GetForegroundWindow = us32.MustFindProc("GetForegroundWindow") ) // //go:embed duck2.jpg // var icon []byte var Error *log.Logger var Warning *log.Logger func init() { log.SetFlags(log.Lmicroseconds | log.Lshortfile) logFile, err := os.Create("main.log") if err != nil { log.Printf("Error creating log file: %v", err) os.Exit(1) } logger := io.MultiWriter(os.Stdout, logFile) log.SetOutput(logger) Error = log.New(io.MultiWriter(logFile, os.Stderr, os.Stdout), fmt.Sprintf("%sERROR:%s ", "\033[0;101m", "\033[0m"), log.Lmicroseconds|log.Lshortfile) Warning = log.New(io.MultiWriter(logFile, os.Stdout), fmt.Sprintf("%sWarning:%s ", "\033[0;93m", "\033[0m"), log.Lmicroseconds|log.Lshortfile) } var windows = make([]uintptr, 10, 10) func main() { go systray.Run(onReady, nil) hook.Register(hook.KeyDown, []string{"alt", "-"}, func(e hook.Event) { hwnd, _, _ := GetForegroundWindow.Call() TrackWindow(hwnd) }) for i := 1; i <= 9; i++ { tabIndex := i - 1 log.Printf("Registering tab %d", tabIndex) hook.Register(hook.KeyDown, []string{"alt", strconv.Itoa(i)}, func(e hook.Event) { TabTo(tabIndex) }) hook.Register(hook.KeyDown, []string{"alt", "shift", strconv.Itoa(i)}, func(e hook.Event) { Swap(tabIndex) }) } s := hook.Start() <-hook.Process(s) } func TabTo(idx int) { log.Printf("TabTo: %d", idx) log.Printf("%+v", windows) if idx > cap(windows)-1 { Warning.Printf("idx %d is greater than length of windows %d", idx, cap(windows)) return } hwnd := windows[idx] if hwnd == 0 { Warning.Printf("hwnd for idx %d is 0", idx) return } SetForegroundWindow.Call(hwnd) } func Swap(idx int) { log.Printf("Swap: %d", idx) if idx > cap(windows)-1 { Warning.Printf("idx %d is greater than length of windows %d", idx, cap(windows)) return } hwnd, _, _ := GetForegroundWindow.Call() if !IsTracked(hwnd) { TrackWindow(hwnd) } log.Printf("Swapping %d to %d", hwnd, idx) for i := 0; i < cap(windows); i++ { if windows[i] == hwnd { windows[i] = windows[idx] windows[idx] = hwnd log.Printf("Swapped %d to %d at index %d", hwnd, idx, i) break } } log.Printf("windows swapped: %+v", windows) } func TrackWindow(hwnd uintptr) { if IsTracked(hwnd) { log.Printf("Untracking window: %d", hwnd) windows = slices.DeleteFunc(windows, func(i uintptr) bool { return i == hwnd }) } else { log.Printf("Tracking window: %d", hwnd) for i := 0; i < cap(windows); i++ { if windows[i] == 0 { windows[i] = hwnd log.Printf("Tracked window: %d at index %d", hwnd, i) return } } } } func IsTracked(hwnd uintptr) bool { return slices.Contains(windows, hwnd) } func onReady() { // Icons no workey... idk why... // systray error: unable to set icon: The operation completed successfully. //systray.SetIcon(icon) systray.SetTitle("Awesome App") systray.SetTooltip("Pretty awesome超级棒") mQuit := systray.AddMenuItem("Quit", "Quit the whole app") go func() { <-mQuit.ClickedCh fmt.Println("Requesting quit") systray.Quit() os.Exit(0) // TODO: Quit properly, not this exit bullshit fmt.Println("Finished quitting") }() // Sets the icon of a menu item. Only available on Mac and Windows. //mQuit.SetIcon(icon) }