docs and renames
This commit is contained in:
59
src/main.rs
59
src/main.rs
@@ -5,30 +5,42 @@ use std::env;
|
|||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::{fs, str};
|
use std::{fs, str};
|
||||||
|
|
||||||
// parse the config to this
|
/// Configuration for swayout.
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct Rules {
|
struct Config {
|
||||||
|
/// Monitor name is independent of output name. It can be anything.
|
||||||
monitors: HashMap<String, Monitor>,
|
monitors: HashMap<String, Monitor>,
|
||||||
// Map of layout name to : map of monitor name to output config
|
/// Definition of layouts: a map of the layout name to the outputs.
|
||||||
|
/// The outputs is a map of the monitor name (in `monitors`) to the configuration
|
||||||
|
/// of that monitor for this layout.
|
||||||
|
/// Available outputs that do not match a monitor in the map are disabled.
|
||||||
layouts: HashMap<String, HashMap<String, OutputConfig>>,
|
layouts: HashMap<String, HashMap<String, OutputConfig>>,
|
||||||
}
|
}
|
||||||
|
/// Defines a monitor by make, model, and serial.
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct Monitor {
|
struct Monitor {
|
||||||
make: String,
|
make: String,
|
||||||
model: String,
|
model: String,
|
||||||
serial: String,
|
serial: String,
|
||||||
}
|
}
|
||||||
|
/// Configuration for an enabled output.
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct OutputConfig {
|
struct OutputConfig {
|
||||||
|
/// mode. See man 5 sway-output
|
||||||
mode: String,
|
mode: String,
|
||||||
|
/// scale. See man 5 sway-output
|
||||||
scale: String,
|
scale: String,
|
||||||
|
/// x value for position. See man 5 sway-output
|
||||||
x: u16,
|
x: u16,
|
||||||
|
/// y value for position. See man 5 sway-output
|
||||||
y: u16,
|
y: u16,
|
||||||
|
/// transform. See man 5 sway-output
|
||||||
transform: String,
|
transform: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse output of swaymsg -t get_outputs to this
|
/// An output, as returned by `swaymsg -t get_outputs`.
|
||||||
struct Output {
|
struct Output {
|
||||||
|
/// output name, according to sway
|
||||||
name: String,
|
name: String,
|
||||||
make: String,
|
make: String,
|
||||||
model: String,
|
model: String,
|
||||||
@@ -48,9 +60,8 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get all outputs currently available
|
/// Get all outputs currently available, according to `swaymsg -t get_outputs`.
|
||||||
fn get_outputs() -> Vec<Output> {
|
fn get_outputs() -> Vec<Output> {
|
||||||
// call `swaymsg -t get_outputs` to get outputs
|
|
||||||
let output = Command::new("swaymsg")
|
let output = Command::new("swaymsg")
|
||||||
.arg("-t")
|
.arg("-t")
|
||||||
.arg("get_outputs")
|
.arg("get_outputs")
|
||||||
@@ -82,7 +93,7 @@ fn get_outputs() -> Vec<Output> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the mode from the output JSON into a string suitable for the mode param for sway-output.
|
/// Parse the mode from the output JSON into a string suitable for the mode param for sway-output.
|
||||||
/// This will go into OutputConfig.mode
|
/// This will go into `OutputConfig.mode`.
|
||||||
fn get_mode(output: &Value) -> String {
|
fn get_mode(output: &Value) -> String {
|
||||||
if let Value::Array(modes) = &output["modes"] {
|
if let Value::Array(modes) = &output["modes"] {
|
||||||
if let Some(mode) = modes.first() {
|
if let Some(mode) = modes.first() {
|
||||||
@@ -101,15 +112,16 @@ fn get_mode(output: &Value) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the rules from ~/.config/swayout/config.toml
|
/// Get a `Config` from ~/.config/swayout/config.toml.
|
||||||
fn get_rules() -> Rules {
|
/// (It really uses XDG config dirs.)
|
||||||
|
fn get_config() -> Config {
|
||||||
let xdg_dirs = xdg::BaseDirectories::with_prefix("swayout").unwrap();
|
let xdg_dirs = xdg::BaseDirectories::with_prefix("swayout").unwrap();
|
||||||
if let Some(path) = xdg_dirs.find_config_file("config.toml") {
|
if let Some(path) = xdg_dirs.find_config_file("config.toml") {
|
||||||
let toml = fs::read_to_string(path).expect("error reading file");
|
let toml = fs::read_to_string(path).expect("error reading file");
|
||||||
toml::from_str(&toml).expect("toml parse error")
|
toml::from_str(&toml).expect("toml parse error")
|
||||||
} else {
|
} else {
|
||||||
// no config files, use an empty rules
|
// no config files, use an empty rules
|
||||||
Rules {
|
Config {
|
||||||
monitors: HashMap::new(),
|
monitors: HashMap::new(),
|
||||||
layouts: HashMap::new(),
|
layouts: HashMap::new(),
|
||||||
}
|
}
|
||||||
@@ -118,17 +130,16 @@ fn get_rules() -> Rules {
|
|||||||
|
|
||||||
/// Determine the available layout names.
|
/// Determine the available layout names.
|
||||||
/// Return one layout for each layout defined in the configuration file
|
/// Return one layout for each layout defined in the configuration file
|
||||||
/// (for which all outputs are available),
|
/// for which all outputs are available,
|
||||||
/// one for each monitor defined in the configuration file
|
/// one for each monitor defined in the configuration file (for using just that monitor),
|
||||||
/// (for using just that monitor),
|
|
||||||
/// and one for each available output that is not a configured monitor (for using just that output).
|
/// and one for each available output that is not a configured monitor (for using just that output).
|
||||||
fn get_layouts() -> Vec<String> {
|
fn get_layouts() -> Vec<String> {
|
||||||
let available_outputs = get_outputs();
|
let available_outputs = get_outputs();
|
||||||
let rules = get_rules();
|
let rules = get_config();
|
||||||
|
|
||||||
let mut layout_names: Vec<String> = Vec::new();
|
let mut layout_names: Vec<String> = Vec::new();
|
||||||
|
|
||||||
// Get the names of monitors that are available (that match a current output)
|
// Get the names of monitors that are available (that match an available output)
|
||||||
let available_monitor_names:Vec<&String> = rules.monitors.iter()
|
let available_monitor_names:Vec<&String> = rules.monitors.iter()
|
||||||
.filter(|(_monitor_name,monitor)|
|
.filter(|(_monitor_name,monitor)|
|
||||||
available_outputs.iter().any(|output|
|
available_outputs.iter().any(|output|
|
||||||
@@ -175,9 +186,10 @@ fn print_layout_names() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Apply the specified layout.
|
/// Apply the specified layout.
|
||||||
/// layout_name may be the name of a layout rule, the name of a monitor, or the name of an output.
|
/// layout_name may be the name of a layout in the config, the name of a monitor,
|
||||||
|
/// or the name of an output.
|
||||||
fn apply_layout(layout_name: &String) {
|
fn apply_layout(layout_name: &String) {
|
||||||
let rules = get_rules();
|
let rules = get_config();
|
||||||
let outputs = get_outputs();
|
let outputs = get_outputs();
|
||||||
|
|
||||||
// Map of output name to config for all outputs to enable.
|
// Map of output name to config for all outputs to enable.
|
||||||
@@ -192,7 +204,6 @@ fn apply_layout(layout_name: &String) {
|
|||||||
let monitor = &rules.monitors[monitor_name];
|
let monitor = &rules.monitors[monitor_name];
|
||||||
|
|
||||||
// find the output for the monitor to get the output name.
|
// find the output for the monitor to get the output name.
|
||||||
// (You can allegedly use "<make> <model> <serial>" instead of output name.)
|
|
||||||
let output_opt = outputs.iter().find(|output| {
|
let output_opt = outputs.iter().find(|output| {
|
||||||
output.make == monitor.make
|
output.make == monitor.make
|
||||||
&& output.model == monitor.model
|
&& output.model == monitor.model
|
||||||
@@ -210,8 +221,7 @@ fn apply_layout(layout_name: &String) {
|
|||||||
if let Some(monitor) = rules.monitors.get(layout_name) {
|
if let Some(monitor) = rules.monitors.get(layout_name) {
|
||||||
// It is a monitor name. Find the matching output...
|
// It is a monitor name. Find the matching output...
|
||||||
if let Some(output) = outputs.iter().find(|output| {
|
if let Some(output) = outputs.iter().find(|output| {
|
||||||
output.make == monitor.make
|
output.make == monitor.make && output.model == monitor.model
|
||||||
&& output.model == monitor.model
|
|
||||||
&& output.serial == monitor.serial
|
&& output.serial == monitor.serial
|
||||||
}) {
|
}) {
|
||||||
output_config_map.insert(&output.name, &output.output_config);
|
output_config_map.insert(&output.name, &output.output_config);
|
||||||
@@ -234,12 +244,13 @@ fn apply_layout(layout_name: &String) {
|
|||||||
|
|
||||||
/// Apply the specified outputs. Enable all outputs in [outputs], disable others.
|
/// Apply the specified outputs. Enable all outputs in [outputs], disable others.
|
||||||
fn apply_outputs(all_outputs: &Vec<Output>, outputs: &HashMap<&String, &OutputConfig>) {
|
fn apply_outputs(all_outputs: &Vec<Output>, outputs: &HashMap<&String, &OutputConfig>) {
|
||||||
let mut cmd = Command::new("swaymsg");
|
|
||||||
|
|
||||||
// enabled first, then disabled.
|
// set enabled outputs first, then set disabled outputs.
|
||||||
// That way if some work before an error, you at least have one output enabled.
|
// That way if some work before an error, you have at least one output enabled.
|
||||||
|
|
||||||
|
// for outputs to be enabled: map of output name to config
|
||||||
let mut enabled: HashMap<&String,&OutputConfig> = HashMap::new();
|
let mut enabled: HashMap<&String,&OutputConfig> = HashMap::new();
|
||||||
|
// for outputs to be disabled: output names
|
||||||
let mut disabled: Vec<&String> = Vec::new();
|
let mut disabled: Vec<&String> = Vec::new();
|
||||||
|
|
||||||
all_outputs.iter().for_each(|output| {
|
all_outputs.iter().for_each(|output| {
|
||||||
@@ -250,6 +261,7 @@ fn apply_outputs(all_outputs: &Vec<Output>, outputs: &HashMap<&String, &OutputCo
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let mut cmd = Command::new("swaymsg");
|
||||||
enabled.iter().for_each(|(output_name,output_config)| {
|
enabled.iter().for_each(|(output_name,output_config)| {
|
||||||
cmd.arg("output");
|
cmd.arg("output");
|
||||||
cmd.arg(&output_name);
|
cmd.arg(&output_name);
|
||||||
@@ -273,6 +285,7 @@ fn apply_outputs(all_outputs: &Vec<Output>, outputs: &HashMap<&String, &OutputCo
|
|||||||
cmd.arg(",");
|
cmd.arg(",");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// print what we are about to do.
|
||||||
cmd.get_args()
|
cmd.get_args()
|
||||||
.for_each(|arg| print!("{} ", arg.to_str().unwrap()));
|
.for_each(|arg| print!("{} ", arg.to_str().unwrap()));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user