commit 8b50666489eb91a1b0603a81072129cf272b8c2d Author: Milarin Date: Tue Apr 9 19:19:33 2024 +0200 initial commit diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..579fac5 --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module git.milar.in/milarin/hypr-fixspecialworkspaces + +go 1.22.1 + +require ( + git.milar.in/hyprland-tools/hypr v0.1.7 + git.milar.in/milarin/slices v0.0.8 +) + +require git.milar.in/milarin/gmath v0.0.3 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e2ad460 --- /dev/null +++ b/go.sum @@ -0,0 +1,6 @@ +git.milar.in/hyprland-tools/hypr v0.1.7 h1:x5t09YBHDkuSxxuvl3/aCiS8Yj+4ob23NT9NdHOu6sE= +git.milar.in/hyprland-tools/hypr v0.1.7/go.mod h1:suJt+N7Nb8T7kaOUsRbFDPV4E/EddVTqpAbpjaJ1xN4= +git.milar.in/milarin/gmath v0.0.3 h1:ii6rKNItS55O/wtIFhD1cTN2BMwDZjTBmiOocKURvxM= +git.milar.in/milarin/gmath v0.0.3/go.mod h1:HDLftG5RLpiNGKiIWh+O2G1PYkNzyLDADO8Cd/1abiE= +git.milar.in/milarin/slices v0.0.8 h1:qN9TE3tkArdTixMKSnwvNPcApwAjxpLVwA5a9k1rm2s= +git.milar.in/milarin/slices v0.0.8/go.mod h1:qMhdtMnfWswc1rHpwgNw33lB84aNEkdBn5BDiYA+G3k= diff --git a/main.go b/main.go new file mode 100644 index 0000000..ac4a74b --- /dev/null +++ b/main.go @@ -0,0 +1,89 @@ +package main + +import ( + "context" + "fmt" + "log" + "strings" + + "git.milar.in/hyprland-tools/hypr" + "git.milar.in/milarin/slices" +) + +func main() { + client, err := hypr.GetDefaultClient() + if err != nil { + panic(err) + } + + events, err := client.Subscribe(context.Background(), hypr.EventTypeMonitorAdded) + if err != nil { + panic(err) + } + + for event := range events { + monitorName := event.Data[0] + log.Printf("monitor %s added", monitorName) + + activeWorkspace, err := client.GetActiveWorkspace() + if err != nil { + log.Println(fmt.Errorf("active workspace: %w", err)) + } + + if err := client.DispatchExpectOK(fmt.Sprintf("focusmonitor %s", monitorName)); err != nil { + log.Println(fmt.Errorf("focus monitor '%s': %w", monitorName, err)) + } + + if err := FixAllSpecialWorkspacesOnMonitor(client, monitorName); err != nil { + log.Println(err) + continue + } + + if err := client.DispatchExpectOK(fmt.Sprintf("focusmonitor %s", activeWorkspace.Monitor)); err != nil { + log.Println(fmt.Errorf("focus monitor '%s': %w", monitorName, err)) + } + } +} + +func FixAllSpecialWorkspacesOnMonitor(client *hypr.Client, monitorName string) error { + workspaces, err := client.GetWorkspaces() + if err != nil { + return fmt.Errorf("retrieve workspaces from Hyprland: %w", err) + } + + workspacesOnMonitor := slices.Filter(workspaces, WorkspaceIsOnMonitor(monitorName)) + specialWorkspacesOnMonitor := slices.Filter(workspacesOnMonitor, WorkspaceIsSpecial) + + for _, workspace := range specialWorkspacesOnMonitor { + if err := ToggleSpecialWorkspace(client, workspace.Name); err != nil { + return fmt.Errorf("toggle special workspace '%s': %w", workspace.Name, err) + } + + if err := ToggleSpecialWorkspace(client, workspace.Name); err != nil { + return fmt.Errorf("toggle special workspace '%s': %w", workspace.Name, err) + } + + log.Printf("special workspace '%s' fixed", workspace.Name) + } + + return nil +} + +func WorkspaceIsSpecial(w *hypr.Workspace) bool { + return w.ID < 0 +} + +func WorkspaceIsOnMonitor(monitorName string) func(w *hypr.Workspace) bool { + return func(w *hypr.Workspace) bool { + return w.Monitor == monitorName + } +} + +func ToggleSpecialWorkspace(client *hypr.Client, workspaceName string) error { + if workspaceName == "special" { + return client.DispatchExpectOK("togglespecialworkspace") + } + + specialWorkspaceName := strings.TrimPrefix(workspaceName, "special:") + return client.DispatchExpectOK(fmt.Sprintf("togglespecialworkspace %s", specialWorkspaceName)) +}