Fix detection of initial rotation state

This ensures that if rot8 starts while the window server output is
rotated, but the physical device is in a "normal" position, rot8 will
detect the initial misalignment and rotate the window server's output to
reflect the device's physical state.

This scenario occurs if you frequently toggle rot8 on and off as form of
rotation lock, and you:

1. Use rot8 to rotate the output sideways
2. Turn rot8 off
3. Move the physical device back into a "normal" position
4. Turn rot8 back on
This commit is contained in:
mnussbaum 2019-09-05 07:08:19 -07:00
parent 1e0cc3ed57
commit 5ca46c50f8
3 changed files with 217 additions and 14 deletions

129
Cargo.lock generated
View File

@ -1,5 +1,13 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "ansi_term" name = "ansi_term"
version = "0.11.0" version = "0.11.0"
@ -42,16 +50,47 @@ name = "glob"
version = "0.3.0" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itoa"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.55" version = "0.2.55"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "numtoa" name = "numtoa"
version = "0.1.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.1.54" version = "0.1.54"
@ -65,12 +104,64 @@ dependencies = [
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "regex"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "rot8" name = "rot8"
version = "0.1.1" version = "0.1.1"
dependencies = [ dependencies = [
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ryu"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -78,6 +169,16 @@ name = "strsim"
version = "0.8.0" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "termion" name = "termion"
version = "1.5.2" version = "1.5.2"
@ -97,11 +198,24 @@ dependencies = [
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "thread_local"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.5" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "vec_map" name = "vec_map"
version = "0.8.1" version = "0.8.1"
@ -127,19 +241,34 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata] [metadata]
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" "checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880" "checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd"
"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425"
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" "checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"

View File

@ -11,5 +11,8 @@ keywords = ["sway", "x11", "display", "rotation"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
glob = "0.3"
clap = "2.33" clap = "2.33"
glob = "0.3"
regex = "1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

View File

@ -1,37 +1,107 @@
extern crate clap; extern crate clap;
extern crate glob; extern crate glob;
extern crate regex;
use clap::{App, Arg}; use clap::{App, Arg};
use glob::glob; use glob::glob;
use serde::Deserialize;
use std::fs; use std::fs;
use std::process::Command; use std::process::Command;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
enum BackendMode { enum Backend {
Sway, Sway,
Xorg, Xorg,
} }
#[derive(Deserialize)]
struct SwayOutput {
name: String,
transform: String,
}
fn get_window_server_rotation_state(display: &str, backend: &Backend) -> Result<String, String> {
match backend {
Backend::Sway => {
let raw_rotation_state = String::from_utf8(
Command::new("swaymsg")
.arg("-t")
.arg("get_outputs")
.arg("--raw")
.output()
.expect("Swaymsg get outputs command failed to start")
.stdout,
)
.unwrap();
let deserialized: Vec<SwayOutput> = serde_json::from_str(&raw_rotation_state)
.expect("Unable to deserialize swaymsg JSON output");
for output in deserialized {
if output.name == display {
return Ok(output.transform);
}
}
return Err(format!(
"Unable to determine rotation state: display {} not found in 'swaymsg -t get_outputs'",
display
)
.to_owned());
}
Backend::Xorg => {
let raw_rotation_state = String::from_utf8(
Command::new("xrandr")
.output()
.expect("Xrandr get outputs command failed to start")
.stdout,
)
.unwrap();
let xrandr_output_pattern = regex::Regex::new(format!(
r"^{} connected .+? .+? (normal |inverted |left |right )?\(normal left inverted right x axis y axis\) .+$",
regex::escape(display),
).as_str()).unwrap();
for xrandr_output_line in raw_rotation_state.split("\n") {
if !xrandr_output_pattern.is_match(xrandr_output_line) {
continue;
}
let xrandr_output_captures =
xrandr_output_pattern.captures(xrandr_output_line).unwrap();
if let Some(transform) = xrandr_output_captures.get(1) {
return Ok(transform.as_str().to_owned());
} else {
return Ok("normal".to_owned());
}
}
return Err(format!(
"Unable to determine rotation state: display {} not found in xrandr output",
display
)
.to_owned());
}
}
}
fn main() -> Result<(), String> { fn main() -> Result<(), String> {
let mut old_state = "normal";
let mut new_state: &str; let mut new_state: &str;
let mut path_x: String = "".to_string(); let mut path_x: String = "".to_string();
let mut path_y: String = "".to_string(); let mut path_y: String = "".to_string();
let mut matrix: [&str; 9]; let mut matrix: [&str; 9];
let mut x_state: &str; let mut x_state: &str;
let mode = if String::from_utf8(Command::new("pidof").arg("sway").output().unwrap().stdout) let backend = if String::from_utf8(Command::new("pidof").arg("sway").output().unwrap().stdout)
.unwrap() .unwrap()
.len() .len()
>= 1 >= 1
{ {
BackendMode::Sway Backend::Sway
} else if String::from_utf8(Command::new("pidof").arg("Xorg").output().unwrap().stdout) } else if String::from_utf8(Command::new("pidof").arg("Xorg").output().unwrap().stdout)
.unwrap() .unwrap()
.len() .len()
>= 1 >= 1
{ {
BackendMode::Xorg Backend::Xorg
} else { } else {
return Err("Unable to find Sway or Xorg procceses".to_owned()); return Err("Unable to find Sway or Xorg procceses".to_owned());
}; };
@ -66,6 +136,8 @@ fn main() -> Result<(), String> {
let sleep = matches.value_of("sleep").unwrap_or("default.conf"); let sleep = matches.value_of("sleep").unwrap_or("default.conf");
let display = matches.value_of("display").unwrap_or("default.conf"); let display = matches.value_of("display").unwrap_or("default.conf");
let touchscreen = matches.value_of("touchscreen").unwrap_or("default.conf"); let touchscreen = matches.value_of("touchscreen").unwrap_or("default.conf");
let old_state_owned = get_window_server_rotation_state(display, &backend)?;
let mut old_state = old_state_owned.as_str();
for entry in glob("/sys/bus/iio/devices/iio:device*/in_accel_*_raw").unwrap() { for entry in glob("/sys/bus/iio/devices/iio:device*/in_accel_*_raw").unwrap() {
match entry { match entry {
@ -77,8 +149,7 @@ fn main() -> Result<(), String> {
} else if path.to_str().unwrap().contains("z_raw") { } else if path.to_str().unwrap().contains("z_raw") {
continue; continue;
} else { } else {
println!("{:?}", path); panic!("Unknown accelerometer device path {:?}", path);
panic!();
} }
} }
Err(e) => println!("{:?}", e), Err(e) => println!("{:?}", e),
@ -124,22 +195,22 @@ fn main() -> Result<(), String> {
} }
if new_state != old_state { if new_state != old_state {
match mode { match backend {
BackendMode::Sway => { Backend::Sway => {
Command::new("swaymsg") Command::new("swaymsg")
.arg("output") .arg("output")
.arg(display) .arg(display)
.arg("transform") .arg("transform")
.arg(new_state) .arg(new_state)
.spawn() .spawn()
.expect("rotate command failed to start"); .expect("Swaymsg rotate command failed to start");
} }
BackendMode::Xorg => { Backend::Xorg => {
Command::new("xrandr") Command::new("xrandr")
.arg("-o") .arg("-o")
.arg(x_state) .arg(x_state)
.spawn() .spawn()
.expect("rotate command failed to start"); .expect("Xrandr rotate command failed to start");
Command::new("xinput") Command::new("xinput")
.arg("set-prop") .arg("set-prop")
@ -149,7 +220,7 @@ fn main() -> Result<(), String> {
.arg("Matrix") .arg("Matrix")
.args(&matrix) .args(&matrix)
.spawn() .spawn()
.expect("rotate command failed to start"); .expect("Xinput rotate command failed to start");
} }
} }
old_state = new_state; old_state = new_state;