From 63b8e1b07e725384e4c8323af7f3e63600721a82 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Sun, 24 Sep 2023 19:44:02 +0200 Subject: initial Signed-off-by: Anna (navi) Figueiredo Gomes --- .gitignore | 1 + Cargo.lock | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 10 ++++ README.md | 12 +++++ src/main.rs | 91 +++++++++++++++++++++++++++++++ 5 files changed, 289 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..3e0a48f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,175 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +dependencies = [ + "memchr", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "memchr" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "proc-macro2" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "serde" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "swayipc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab1dcff328b223d85d7ca767b2e4aadbc13dad550d36b4c6b929b9ad4d26ee9a" +dependencies = [ + "serde", + "serde_json", + "swayipc-types", +] + +[[package]] +name = "swayipc-types" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44b43b4059d825ccc04adf9726f944d0e3aa20938f4cff3b5c6b53198afcd6b3" +dependencies = [ + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "swhd" +version = "0.1.0" +dependencies = [ + "regex", + "swayipc", +] + +[[package]] +name = "syn" +version = "2.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..4d4be05 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "swhd" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +regex = "1.9.5" +swayipc = "3.0.1" diff --git a/README.md b/README.md new file mode 100644 index 0000000..92fd853 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# sway window hider daemon + +automatically hides windows, by looking into /proc. + +when a new window is spawned in sway, it looks for the pid, +and recursivelly looks for parent pids until it finds the +terminal listed, or init. in the case it finds the terminal, +it sends any windows attached to that pid to the scratchpad, +and marks the window hidden with the pid of the new process. + +once a window closes, it sees if any scratchpad windows have +that pid marked, and if so, unhides them. diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b251bab --- /dev/null +++ b/src/main.rs @@ -0,0 +1,91 @@ +use swayipc::{Connection, WindowChange, EventType}; +use std::{env,fs::File, io::Read}; +use regex::Regex; + +struct WindowHider { + term: String +} + +impl WindowHider { + fn get_parent_term_pid(&self, pid: i32) -> Option { + let mut file = String::new(); + File::open(format!("/proc/{pid}/stat")).expect("procfs stat doesn't exist").read_to_string(&mut file).unwrap(); + let re = Regex::new(r"\d+ \((.*)\) (\w) (\d+) \d+").unwrap().captures(&file).unwrap(); + let name = re.get(1).unwrap().as_str(); + let status = re.get(2).unwrap().as_str(); + let ppid = re.get(3).unwrap().as_str().parse::().unwrap(); + + println!("looking for {pid}. {name}, {status}, {ppid}"); + match name { + _ if name == self.term => { + Some(pid) + }, + _ if name == "init" => { + None + } + _ => { + self.get_parent_term_pid(ppid) + } + } + } + + fn hide(&self, conn: &mut Connection, pid: i32) -> Result<(), swayipc::Error> { + let ppid = self.get_parent_term_pid(pid); + if let Some(ppid) = ppid { + println!("found parent pid of {pid} as {ppid}"); + conn.run_command(format!("[pid={ppid}] mark --add {pid}, move scratchpad"))?; + } + Ok(()) + } + + fn show(&self, conn: &mut Connection, pid: i32) -> Result<(), swayipc::Error> { + conn.run_command(format!("[con_mark={pid}] move workspace current"))?; + conn.run_command(format!("[con_mark={pid}] floating toggle"))?; + Ok(()) + } +} + +fn main() -> Result<(), swayipc::Error> { + let mut conn = Connection::new().expect("couldn't connect to sway's socket"); + let evs = Connection::new()?.subscribe([EventType::Window])?; // one can't use the same + // connection for events and for + // running commands. :( + + let mut args: Vec = env::args().collect(); + + if args.len() < 2 { + println!("usage: swhd "); + return Ok(()); + } + + let wh = WindowHider { + term: args.remove(1) + }; + + for item in evs { + if let Ok(item) = item { + match item { + swayipc::Event::Window(win) => { + if win.change == WindowChange::New { + if let Some(pid) = win.container.pid { + match wh.hide(&mut conn, pid) { + Ok(_) => {}, + Err(_) => println!("failed to hide terminal {pid}") + }; + } + } else if win.change == WindowChange::Close { + if let Some(pid) = win.container.pid { + match wh.show(&mut conn, pid) { + Ok(_) => {}, + Err(_) => println!("failed to show terminal {pid}") + }; + } + } + } + _ => {} + } + } + } + + Ok(()) +} -- cgit v1.2.3