xrandr/arrangement.go
2023-12-18 23:08:42 +01:00

103 lines
2.3 KiB
Go

package xrandr
import (
"encoding/json"
"errors"
"fmt"
"os/exec"
"strings"
)
type Arrangement map[string]*DisplayArrangement
type DisplayArrangement struct {
Off bool `json:"off,omitempty"`
Primary bool `json:"primary,omitempty"`
Position *Position `json:"position,omitempty"`
Resolution *Resolution `json:"resolution,omitempty"`
Rate float64 `json:"rate,omitempty"`
Rotation Rotation `json:"rotation,omitempty"`
Reflection Reflection `json:"reflection,omitempty"`
}
func (a *DisplayArrangement) Equivalent(b *DisplayArrangement) bool {
return a.Off == b.Off &&
a.Primary == b.Primary &&
a.Position.Equivalent(b.Position) &&
a.Resolution.Equivalent(b.Resolution) &&
a.Rate == b.Rate &&
a.Rotation == b.Rotation &&
a.Reflection == b.Reflection
}
func (a *Arrangement) xrandr() string {
b := new(strings.Builder)
b.WriteString("xrandr")
for port, display := range *a {
b.WriteString(fmt.Sprintf(" --output %s", port))
if display.Off {
b.WriteString(" --off")
continue
}
if display.Primary {
b.WriteString(" --primary")
}
b.WriteString(" --preferred")
if display.Position != nil {
b.WriteString(fmt.Sprintf(" --pos %dx%d", display.Position.X, display.Position.Y))
}
if display.Resolution != nil {
b.WriteString(fmt.Sprintf(" --mode %dx%d", display.Resolution.Width, display.Resolution.Height))
}
if display.Rate > 0 {
b.WriteString(fmt.Sprintf(" --rate %g", display.Rate))
}
b.WriteString(fmt.Sprintf(" --rotate %s", display.Rotation))
b.WriteString(fmt.Sprintf(" --reflect %s", display.Reflection.xrandr()))
}
return b.String()
}
func (a *Arrangement) Apply() error {
cmd := strings.Split(a.xrandr(), " ")
xrandr := exec.Command(cmd[0], cmd[1:]...)
if err := xrandr.Start(); err != nil {
return err
}
if err := xrandr.Wait(); err != nil {
return err
}
if !xrandr.ProcessState.Success() {
return errors.New("xrandr could not apply display arrangement")
}
return nil
}
func (a *Arrangement) Display(port string) *DisplayArrangement {
return (*a)[port]
}
func (a *Arrangement) String() string {
data, _ := json.MarshalIndent(a, "", "\t")
return string(data)
}
func (a *DisplayArrangement) String() string {
data, _ := json.MarshalIndent(a, "", "\t")
return string(data)
}