// Monitor enumeration for the settings UI. // // The screen-capture backend itself selects a monitor by index; this file // provides a way to list the available monitors so the GUI can present a // friendly picker instead of a raw index. // // Hyprland exposes monitor info via the `hyprctl monitors` command. Other // Wayland compositors would need a portal-based enumeration; for now we only // implement the Hyprland path (the primary dev environment) and return a // clear error elsewhere. package capture import ( "encoding/json" "errors" "os/exec" ) // Monitor describes one capturable output. type Monitor struct { Index int // capture StreamIndex to pass to OpenPipeWire Name string // compositor name, e.g. "eDP-1" Width int Height int Primary bool } // ErrNoMonitors is returned when monitor enumeration is unsupported or fails. var ErrNoMonitors = errors.New("capture: monitor enumeration unavailable on this compositor") // ListMonitors returns the available monitors for the GUI picker. func ListMonitors() ([]Monitor, error) { if hyprctlAvailable() { return hyprctlMonitors() } return nil, ErrNoMonitors } // hyprctlAvailable reports whether the Hyprland monitor command exists. func hyprctlAvailable() bool { _, err := exec.LookPath("hyprctl") return err == nil } // hyprctlMonitor is the JSON shape emitted by `hyprctl monitors -j`. type hyprctlMonitor struct { ID int `json:"id"` Name string `json:"name"` Width int `json:"width"` Height int `json:"height"` Description string `json:"description"` Focused bool `json:"focused"` } // hyprctlMonitors lists monitors via the Hyprland IPC command. func hyprctlMonitors() ([]Monitor, error) { out, err := exec.Command("hyprctl", "monitors", "-j").Output() if err != nil { return nil, ErrNoMonitors } var raw []hyprctlMonitor if err := json.Unmarshal(out, &raw); err != nil { return nil, ErrNoMonitors } monitors := make([]Monitor, 0, len(raw)) for _, m := range raw { monitors = append(monitors, Monitor{ Index: m.ID, Name: m.Name, Width: m.Width, Height: m.Height, Primary: m.Focused, }) } return monitors, nil }