WIP
This commit is contained in:
parent
5e90576c49
commit
72100921e6
66
Cargo.lock
generated
66
Cargo.lock
generated
@ -1,5 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.14"
|
||||
@ -15,6 +17,12 @@ version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "fixscreen"
|
||||
version = "0.1.0"
|
||||
@ -22,6 +30,23 @@ dependencies = [
|
||||
"anyhow",
|
||||
"regex",
|
||||
"thiserror",
|
||||
"xrandr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -30,12 +55,24 @@ version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
@ -85,18 +122,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.21"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42"
|
||||
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.21"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab"
|
||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -117,3 +154,24 @@ name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
||||
[[package]]
|
||||
name = "x11"
|
||||
version = "2.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xrandr"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9faecbb5f354fe09959775758b6f7b6524ee80103a6c5c66a57112a2f707862"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"thiserror",
|
||||
"x11",
|
||||
]
|
||||
|
||||
@ -10,3 +10,4 @@ edition = "2018"
|
||||
thiserror = "1.0.21"
|
||||
anyhow = "1.0.33"
|
||||
regex = "1.4.2"
|
||||
xrandr = "0.1.1"
|
||||
|
||||
70
src/lib.rs
70
src/lib.rs
@ -9,6 +9,59 @@ use std::{
|
||||
|
||||
use regex::Regex;
|
||||
use thiserror::Error;
|
||||
use xrandr::{XHandle, XrandrError};
|
||||
|
||||
pub fn swap_workspaces(cfg: &Config) -> Result<Vec<Result<Output, CommandError>>, CommandError> {
|
||||
let monitors = XHandle::open()?.monitors()?;
|
||||
|
||||
// TODO(wathiede): if I ever get two monitors with the same resolution, use EDID to find a
|
||||
// better key.
|
||||
let map: HashMap<_, _> = monitors
|
||||
.iter()
|
||||
.map(|m| ((m.width_px as usize, m.height_px as usize), m.name.clone()))
|
||||
.collect();
|
||||
// TODO(wathiede):
|
||||
// i3-msg commands to move them.
|
||||
// Example:
|
||||
// i3-msg '[workspace="trustee"]' move workspace to output DP-0
|
||||
Ok(cfg
|
||||
.screens
|
||||
.iter()
|
||||
.map(|s| {
|
||||
let key = match s.orientation {
|
||||
Orientation::None | Orientation::Invert => {
|
||||
(s.resolution.width, s.resolution.height)
|
||||
}
|
||||
Orientation::Left | Orientation::Right => (s.resolution.height, s.resolution.width),
|
||||
};
|
||||
if let Some(m) = map.get(&key) {
|
||||
println!("Moving {:?} to {}", s.workspaces, m);
|
||||
run_move_workspace_cmd(&s.workspaces, m)
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.collect())
|
||||
}
|
||||
fn run_move_workspace_cmd(
|
||||
workspaces: &[String],
|
||||
monitor: &str,
|
||||
) -> Vec<Result<Output, CommandError>> {
|
||||
workspaces
|
||||
.iter()
|
||||
.map(|workspace| {
|
||||
let s = format!(r#"'[workspace="{monitor}"]'"#);
|
||||
let args = vec!["i3-msg", &s, "move", "workspace", "to", workspace];
|
||||
if cfg!(debug_assertions) {
|
||||
Command::new("echo").args(args).output()
|
||||
} else {
|
||||
Command::new(&args[0]).args(&args[1..]).output()
|
||||
}
|
||||
})
|
||||
.map(|r| r.map_err(CommandError::from))
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ParseError {
|
||||
@ -16,6 +69,8 @@ pub enum ParseError {
|
||||
Io(#[from] io::Error),
|
||||
#[error("invalid data: {0}")]
|
||||
Parse(String),
|
||||
#[error("xrandr: {0}")]
|
||||
XrandrError(#[from] XrandrError),
|
||||
}
|
||||
|
||||
// Map monitor name to DFP connection.
|
||||
@ -43,20 +98,23 @@ pub enum CommandError {
|
||||
MissingMonitor(String),
|
||||
#[error("error executing command")]
|
||||
Io(#[from] io::Error),
|
||||
#[error("xrandr error: {0}")]
|
||||
XrandrError(#[from] XrandrError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Resolution {
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Offset {
|
||||
pub x: isize,
|
||||
pub y: isize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Orientation {
|
||||
None,
|
||||
Right,
|
||||
@ -80,12 +138,14 @@ impl fmt::Debug for Orientation {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Screen {
|
||||
pub name: String,
|
||||
pub resolution: Resolution,
|
||||
pub offset: Offset,
|
||||
pub orientation: Orientation,
|
||||
pub primary: bool,
|
||||
pub workspaces: Vec<String>,
|
||||
}
|
||||
|
||||
impl Screen {
|
||||
@ -137,7 +197,7 @@ pub struct Config {
|
||||
pub screens: Vec<Screen>,
|
||||
}
|
||||
|
||||
pub fn run_cmd(screen_mapping: &ScreenMapping, cfg: Config) -> Result<Output, CommandError> {
|
||||
pub fn run_cmd(screen_mapping: &ScreenMapping, cfg: &Config) -> Result<Output, CommandError> {
|
||||
let args = build_cmd_args(screen_mapping, cfg)?;
|
||||
if cfg!(debug_assertions) {
|
||||
Ok(Command::new("echo").args(args).output()?)
|
||||
@ -148,7 +208,7 @@ pub fn run_cmd(screen_mapping: &ScreenMapping, cfg: Config) -> Result<Output, Co
|
||||
|
||||
fn build_cmd_args(
|
||||
screen_mapping: &ScreenMapping,
|
||||
cfg: Config,
|
||||
cfg: &Config,
|
||||
) -> Result<Vec<String>, CommandError> {
|
||||
let metamode = cfg
|
||||
.screens
|
||||
|
||||
15
src/main.rs
15
src/main.rs
@ -13,6 +13,7 @@ fn main() -> Result<()> {
|
||||
y: 1440 * 2 - 1920,
|
||||
},
|
||||
orientation: Orientation::Left,
|
||||
workspaces: vec!["distortion".to_string()],
|
||||
..Default::default()
|
||||
};
|
||||
let lg = Screen {
|
||||
@ -29,6 +30,7 @@ fn main() -> Result<()> {
|
||||
x: 1 + dell.resolution.height as isize,
|
||||
y: 0,
|
||||
},
|
||||
workspaces: vec!["virtue".to_string()],
|
||||
..Default::default()
|
||||
};
|
||||
let lenovo = Screen {
|
||||
@ -41,15 +43,24 @@ fn main() -> Result<()> {
|
||||
x: (dell.resolution.height + (lg.resolution.width - 2560) / 2) as isize,
|
||||
y: (lg.resolution.height) as isize,
|
||||
},
|
||||
primary: true,
|
||||
workspaces: vec!["fraud".to_string(), "twilight".to_string()],
|
||||
..Default::default()
|
||||
};
|
||||
let screens = vec![dell, lg, lenovo];
|
||||
let cfg = Config {
|
||||
screens: vec![dell, lg, lenovo],
|
||||
screens: screens.clone(),
|
||||
};
|
||||
|
||||
let map = screen_mapping_from_xorg_log("/var/log/X.0.log")?;
|
||||
let cmd = run_cmd(&map, cfg)?;
|
||||
let cmd = run_cmd(&map, &cfg)?;
|
||||
println!("cmd {:#?}", cmd);
|
||||
// TODO(wathiede): run xrandr --output $DPY --primary
|
||||
// TODO(wathiede): i3-msg to move workspaces to proper places.
|
||||
let res = swap_workspaces(&cfg)?;
|
||||
for r in res {
|
||||
println!("r = {:?}", r);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user