103 lines
2.3 KiB
Go
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)
|
||
|
}
|