package hyprman import ( "encoding/json" "fmt" "log" "net" "os" "os/exec" "path/filepath" yaml "github.com/goccy/go-yaml" ) func DefaultConfigPath() string { configPath, exists := os.LookupEnv("XDG_CONFIG_HOME") if !exists { home, exists := os.LookupEnv("HOME") if !exists { log.Fatalln("failed to set default icons.json path is $HOME or $XDG_CONFIG_HOME set?") } configPath = filepath.Join(home, ".config") } return filepath.Join(configPath, "hyprman", "config.yml") } func hyprSocketBase() string { runtimeDir, exists := os.LookupEnv("XDG_RUNTIME_DIR") if !exists { log.Fatalln("XDG_RUNTIME_DIR not set") } instanceSig, exists := os.LookupEnv("HYPRLAND_INSTANCE_SIGNATURE") if !exists { log.Fatalln("HYPRLAND_INSTANCE_SIGNATURE not set") } return filepath.Join(runtimeDir, "hypr", instanceSig) } func hyprSocket() string { return filepath.Join(hyprSocketBase(), ".socket.sock") } func hyprSocket2() string { return filepath.Join(hyprSocketBase(), ".socket2.sock") } type Workspace struct { Name string Id int } type Client struct { Class string Workspace Workspace } type Icons map[string]string type Hyprman struct { Config Config } type Config struct { Classes Icons NoClientIcon string `yaml:"no-client"` DefaultIcon string `yaml:"default-icon"` } func (hm *Hyprman) LoadConfig(path string) { var config Config data, err := os.ReadFile(path) if err != nil { log.Fatal(fmt.Errorf("failed to read config at %s:\n%w", path, err)) } if err := yaml.Unmarshal([]byte(data), &config); err != nil { log.Fatal(fmt.Errorf("failed to read config at %s:\n%w", path, err)) } hm.Config = config } func hyprctl(cmd string) []byte { socketPath := hyprSocket() conn, err := net.Dial("unix", socketPath) if err != nil { log.Fatalln("Error connecting to hyprland IPC:", err) } defer conn.Close() _, err = conn.Write([]byte(cmd)) if err != nil { log.Fatal(err) } buf := make([]byte, 1024*8) // Bigger? n, err := conn.Read(buf) if err != nil { log.Fatal(err) } return buf[0:n] } type ActiveWorkspace struct { Name string Id int } type Monitor struct { ActiveWorkspace ActiveWorkspace Id int } // generic or interface? func getMonitors() []Monitor { data := hyprctl("[-j]/monitors") var monitors []Monitor err := json.Unmarshal(data, &monitors) if err != nil { log.Fatalln(err) } return monitors } func getClients() []Client { data := hyprctl("[-j]/clients") var clients []Client err := json.Unmarshal(data, &clients) if err != nil { log.Fatalln(err) } return clients } func openWorkspaces(monitors []Monitor) []int { open := make([]int, len(monitors)) for i, m := range monitors { open[i] = m.ActiveWorkspace.Id } return open } func notify(message string) { cmd := exec.Command( "notify-send", "--app-name=hyprman", "--transient", message, ) cmd.Run() }