Set-up monitors for sway tiling window manager
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.
 
 
 

240 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 ();
}
}