diff --git a/Cargo.lock b/Cargo.lock index 18cd97c..3b9e5a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,6 +80,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "lazy_static" version = "1.4.0" @@ -176,6 +182,17 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_yaml" version = "0.8.23" @@ -188,6 +205,26 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "swayipc" +version = "3.0.0-alpha.3" +source = "git+https://github.com/k0kubun/swayipc-rs#580b5b6e02b911547c4741bfe240ea8d81d1147c" +dependencies = [ + "serde", + "serde_json", + "swayipc-types", +] + +[[package]] +name = "swayipc-types" +version = "1.0.0-alpha.3" +source = "git+https://github.com/k0kubun/swayipc-rs#580b5b6e02b911547c4741bfe240ea8d81d1147c" +dependencies = [ + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "syn" version = "1.0.82" @@ -205,6 +242,26 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-width" version = "0.1.9" @@ -246,6 +303,7 @@ dependencies = [ "nix", "serde", "serde_yaml", + "swayipc", "x11", ] diff --git a/Cargo.toml b/Cargo.toml index a0c6d4f..b9b0cb0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] evdev = "0.11.3" getopts = "0.2" +swayipc = { git = "https://github.com/k0kubun/swayipc-rs" } lazy_static = "1.4.0" nix = "0.23.1" serde = { version = "1.0", features = ["derive"] } diff --git a/example/config.yml b/example/config.yml index ac781ed..da3a509 100644 --- a/example/config.yml +++ b/example/config.yml @@ -109,6 +109,9 @@ keymap: '3': C-M-3 '0': C-M-0 + # workaround + C-c: Esc + - name: Chrome, Slack (modified from Default) wm_class: only: [Google-chrome, Slack] diff --git a/src/client/mod.rs b/src/client/mod.rs index afc7592..2a4bc73 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1 +1,2 @@ pub mod x11_client; +pub mod sway_client; diff --git a/src/client/sway_client.rs b/src/client/sway_client.rs new file mode 100644 index 0000000..2124775 --- /dev/null +++ b/src/client/sway_client.rs @@ -0,0 +1,70 @@ +use std::fs::read_dir; +use std::os::unix::ffi::OsStrExt; +use std::os::unix::net::UnixStream; +use swayipc::Connection; + +pub struct SwayClient { + connection: Option, + supported: Option, +} + +impl SwayClient { + pub fn new() -> SwayClient { + SwayClient { + connection: None, + supported: None, + } + } + + pub fn supported(&mut self) -> bool { + match self.supported { + Some(supported) => supported, + None => { + self.supported = Some(false); + if let Some(socket) = find_socket() { + if let Ok(unix_stream) = UnixStream::connect(socket) { + self.connection = Some(Connection(unix_stream)); + self.supported = Some(true); + } + } + self.supported.unwrap() + } + } + } + + pub fn current_wm_class(&mut self) -> Option { + if !self.supported() { + return None; + } + + let connection = match &mut self.connection { + Some(connection) => connection, + None => return None, + }; + + if let Ok(node) = connection.get_tree() { + if let Some(node) = node.find_focused(|n| n.focused) { + return node.app_id + } + } + None + } +} + +// e.g. "/run/user/1000/sway-ipc.1000.2575.sock" +fn find_socket() -> Option { + let uid = 1000; // Assume a first nornal Linux user + if let Some(run_user) = read_dir(format!("/run/user/{}", uid)).as_mut().ok() { + while let Some(entry) = run_user.next() { + let path = entry.ok()?.path(); + if let Some(fname) = path.file_name() { + if fname.as_bytes().starts_with(b"sway-ipc.") { + if let Ok(path) = path.into_os_string().into_string() { + return Some(path) + } + } + } + } + } + None +} diff --git a/src/main.rs b/src/main.rs index 689ef64..641194d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use crate::input::{event_loop, select_device}; use getopts::Options; use std::env; use std::process::exit; +use crate::client::sway_client::SwayClient; extern crate getopts; @@ -23,6 +24,10 @@ fn abort(message: &str) -> ! { } fn main() { + let mut client = SwayClient::new(); + println!("supported: {}", client.supported()); + println!("active: {:?}", client.current_wm_class()); + let argv: Vec = env::args().collect(); let program = argv[0].clone();