You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
8.0 KiB
241 lines
8.0 KiB
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"flag"
|
|
"math"
|
|
"strings"
|
|
"strconv"
|
|
"os/user"
|
|
"io/ioutil"
|
|
. "codeberg.org/snaums/swayrandr/lib"
|
|
)
|
|
|
|
var Version string = "";
|
|
var BuildDate string = "";
|
|
var BuildWith string = "";
|
|
|
|
func main () {
|
|
var output string;
|
|
var leftOf string;
|
|
var rightOf string;
|
|
var above string;
|
|
var below string;
|
|
var sameAs string;
|
|
var position string;
|
|
var mode string;
|
|
var primary bool;
|
|
var active bool;
|
|
var inactive bool;
|
|
var dryrun bool;
|
|
var help bool;
|
|
var disable bool;
|
|
var enable bool;
|
|
var off bool;
|
|
var scale float64;
|
|
var refresh float64;
|
|
var ver bool;
|
|
var listMonitors bool;
|
|
var listActiveMonitors bool;
|
|
|
|
var configFile string;
|
|
|
|
flag.StringVar ( &output, "output", "", "The output to manipulate" );
|
|
|
|
flag.StringVar ( &leftOf, "left-of", "", "Place <output> left of the provided monitor" );
|
|
flag.StringVar ( &rightOf, "right-of", "", "Place <output> right of the provided monitor");
|
|
flag.StringVar ( &above, "above", "", "Place <output> above the provided monitor" );
|
|
flag.StringVar ( &below, "below", "", "Place <output> below the provided monitor" );
|
|
flag.StringVar ( &sameAs, "same-as", "", "Place <output> on top of the provided monitor and use the same resolution if available" );
|
|
flag.StringVar ( &mode, "mode", "", "Set the provided mode: <Width>x<Height>@<RefreshRate>" );
|
|
flag.StringVar ( &position, "position", "", "Set the top-left corner of <ouput> to the coordinates <X>x<Y> (or <X>+<Y>)" );
|
|
flag.Float64Var ( &refresh, "refresh", math.Inf(-1), "Set the refresh rate (in KHz; float)" );
|
|
|
|
flag.Float64Var ( &scale, "scale", math.Inf(-1), "Set the scaling-factor of <output>; floats > 0");
|
|
|
|
flag.BoolVar ( &primary, "primary", false, "Set <output> as the primary one (focused)" );
|
|
flag.BoolVar ( &active, "active", false, "Set <output> active (contrasts inactive and disabled)" );
|
|
flag.BoolVar ( &inactive, "inactive", false, "Disable <output>" );
|
|
flag.BoolVar ( &enable, "enable", false, "Enable <output>" );
|
|
flag.BoolVar ( &disable, "disable", false, "Disable <output>" );
|
|
flag.BoolVar ( &off, "off", false, "Disable <output>" );
|
|
|
|
flag.BoolVar ( &dryrun, "dryrun", false, "Don't write any configuration files, just dry-run and throw any occurring errors" );
|
|
flag.StringVar ( &configFile, "config-file", "~/.config/sway/monitor.swayconfig", "Configuration file to write to" );
|
|
flag.BoolVar ( &listMonitors, "listmonitors", false, "List all connected monitors" );
|
|
flag.BoolVar ( &listActiveMonitors, "listactivemonitors", false, "List all active monitors" );
|
|
|
|
flag.BoolVar ( &help, "help", false, "Print this help text" );
|
|
flag.BoolVar ( &ver, "version", false, "Print version Information" );
|
|
|
|
flag.Parse();
|
|
|
|
if configFile[0] == '~' {
|
|
usr, err := user.Current();
|
|
if err != nil {
|
|
fmt.Println ("Cannot find the current users home-dir");
|
|
return
|
|
}
|
|
configFile = usr.HomeDir + configFile[1:]
|
|
}
|
|
|
|
// print version information
|
|
if ver == true {
|
|
fmt.Println ("SwayRandr version:\t", Version );
|
|
fmt.Println (" Build on: \t", BuildDate );
|
|
fmt.Println (" Build with: \t", BuildWith );
|
|
fmt.Println ("Sway version: \t", SwayVersion() );
|
|
return;
|
|
}
|
|
|
|
// print help text and parameter-descriptions
|
|
if help == true {
|
|
fmt.Println ("** SwayRandr **");
|
|
flag.PrintDefaults();
|
|
return
|
|
}
|
|
|
|
// read all the screen information from swaymsg
|
|
screens, err := ReadScreen ()
|
|
if err != nil {
|
|
fmt.Println ("Errors when reading screen information: ", err.Error() );
|
|
return
|
|
}
|
|
|
|
// print available screen-modes similar to xrandr
|
|
if flag.NFlag() == 0 {
|
|
PrintModes ( screens );
|
|
return
|
|
}
|
|
|
|
// list Monitors or active monitors like xrandr --listmonitors (or xrandr --listactivemonitors)
|
|
if listMonitors == true || listActiveMonitors == true {
|
|
var screenList []Screen = screens;
|
|
if listActiveMonitors == true {
|
|
screenList = []Screen{};
|
|
for _, sc := range screens {
|
|
if sc.Active == true {
|
|
screenList = append(screenList, sc);
|
|
}
|
|
}
|
|
}
|
|
fmt.Printf ( "Monitors: %d\n", len(screenList) )
|
|
|
|
for k, v := range screenList {
|
|
minHeight := 99999; minWidth := 99999
|
|
maxHeight := 0; maxWidth := 0
|
|
for _, c := range v.Modes {
|
|
if c.Width > maxWidth {
|
|
maxWidth = c.Width
|
|
}
|
|
if c.Width < minWidth {
|
|
minWidth = c.Width
|
|
}
|
|
if c.Height > maxHeight {
|
|
maxHeight = c.Height
|
|
}
|
|
if c.Height < minHeight {
|
|
minHeight = c.Height
|
|
}
|
|
}
|
|
|
|
fmt.Printf (" %d: +%s %d/%dx%d/%d+%d+%d %s %s\n", k, v.Name , maxWidth, minWidth, maxHeight, minHeight, v.Rect.X, v.Rect.Y, v.Make, v.Model );
|
|
}
|
|
return;
|
|
}
|
|
|
|
// find the --output monitor
|
|
outputScreen := FindScreen ( screens, output );
|
|
if output == "" || outputScreen == nil {
|
|
fmt.Println ("Cannot find output-screen: ", output);
|
|
return;
|
|
}
|
|
|
|
// process same-as; set the output monitors settings to the ones
|
|
// of the referenced same-as monitor
|
|
if sameAs != "" {
|
|
sas := FindScreen ( screens, sameAs );
|
|
if sas == nil {
|
|
fmt.Println ("Cannot find same-as monitor: ", sameAs );
|
|
return
|
|
}
|
|
|
|
outputScreen.CurrentMode = sas.CurrentMode;
|
|
outputScreen.Rect = sas.Rect;
|
|
outputScreen.Active = sas.Active;
|
|
outputScreen.Transform = sas.Transform;
|
|
outputScreen.Scale = sas.Scale;
|
|
}
|
|
|
|
// disable the --output screen and abort everything else
|
|
if disable == true || inactive == true || off == true {
|
|
outputScreen.Active = false;
|
|
} else {
|
|
if enable == true || active == true || outputScreen.Active == true {
|
|
outputScreen.Active = true;
|
|
|
|
// primary parameters influences the Focused-attribute
|
|
if primary == true {
|
|
for i := 0; i < len(screens); i++ {
|
|
screens[i].Focused = false;
|
|
}
|
|
outputScreen.Focused = true;
|
|
}
|
|
|
|
// set scaling
|
|
if scale > 0.0 {
|
|
outputScreen.Scale = scale;
|
|
}
|
|
|
|
// set the mode (returns if no mode is selected)
|
|
err = ProcessMode ( outputScreen, mode, refresh );
|
|
if err != nil {
|
|
fmt.Println ( err );
|
|
return;
|
|
}
|
|
|
|
// set the positioning (returns if no mode is selected)
|
|
err = ProcessPosition ( outputScreen, leftOf, rightOf, above, below, screens );
|
|
if err != nil {
|
|
fmt.Println ( err );
|
|
return;
|
|
}
|
|
|
|
if position != "" {
|
|
var xy []string
|
|
if strings.Index ( position, "+" ) != -1 {
|
|
xy = strings.Split (position, "+");
|
|
} else {
|
|
xy = strings.Split (position, "x" );
|
|
}
|
|
|
|
x, err := strconv.Atoi ( xy[0] );
|
|
if err != nil {
|
|
fmt.Println ( err );
|
|
}
|
|
y, err := strconv.Atoi ( xy[1] );
|
|
if err != nil {
|
|
fmt.Println ( err );
|
|
}
|
|
|
|
outputScreen.Rect.X = x;
|
|
outputScreen.Rect.Y = y;
|
|
}
|
|
}
|
|
}
|
|
|
|
// create config; write it to file and reload sway OR print it to stdout (dryrun)
|
|
cfg := CreateConfig ( screens );
|
|
buf := PrintConfig ( cfg );
|
|
if dryrun == true {
|
|
fmt.Println ( buf );
|
|
} else {
|
|
err = ioutil.WriteFile ( configFile, []byte( buf ), 0644 );
|
|
if err != nil {
|
|
fmt.Println ( err );
|
|
}
|
|
|
|
ReloadSway ();
|
|
}
|
|
}
|