diff --git a/Cargo.lock b/Cargo.lock index 9695db0..9e0c55c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -597,6 +597,26 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[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" @@ -742,6 +762,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", + "swayipc", "x11", "zbus", ] diff --git a/Cargo.toml b/Cargo.toml index 03ce876..aedaffc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,8 +2,6 @@ name = "xremap" version = "0.1.0" edition = "2021" -description = "Dynamic key remapp for X and Wayland" -license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -11,6 +9,7 @@ license = "MIT" env_logger = "0.9.0" evdev = "0.11.3" getopts = "0.2" +swayipc = { git = "https://github.com/k0kubun/swayipc-rs" } lazy_static = "1.4.0" log = "0.4.14" nix = "0.23.1" @@ -23,4 +22,5 @@ zbus = "1.9.2" [features] gnome = [] +sway = [] x11 = [] diff --git a/src/client/mod.rs b/src/client/mod.rs index 5a28467..053c41b 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -48,6 +48,13 @@ pub fn build_client() -> WMClient { WMClient::new("GNOME", Box::new(gnome_client::GnomeClient::new())) } +#[cfg(feature = "sway")] +mod sway_client; +#[cfg(feature = "sway")] +pub fn build_client() -> WMClient { + WMClient::new("Sway", Box::new(sway_client::SwayClient::new())) +} + #[cfg(feature = "x11")] mod x11_client; #[cfg(feature = "x11")] @@ -55,9 +62,9 @@ pub fn build_client() -> WMClient { WMClient::new("X11", Box::new(x11_client::X11Client::new())) } -#[cfg(not(any(feature = "gnome", feature = "x11")))] +#[cfg(not(any(feature = "gnome", feature = "sway", feature = "x11")))] mod null_client; -#[cfg(not(any(feature = "gnome", feature = "x11")))] +#[cfg(not(any(feature = "gnome", feature = "sway", feature = "x11")))] pub fn build_client() -> WMClient { WMClient::new("none", Box::new(null_client::NullClient)) } diff --git a/src/client/sway_client.rs b/src/client/sway_client.rs new file mode 100644 index 0000000..72a250c --- /dev/null +++ b/src/client/sway_client.rs @@ -0,0 +1,65 @@ +use crate::client::Client; +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, +} + +impl SwayClient { + pub fn new() -> SwayClient { + SwayClient { connection: None } + } + + fn connect(&mut self) { + if let None = self.connection { + if let Some(socket) = find_socket() { + if let Ok(unix_stream) = UnixStream::connect(socket) { + self.connection = Some(Connection(unix_stream)); + } + } + } + } +} + +impl Client for SwayClient { + fn supported(&mut self) -> bool { + self.connect(); + self.connection.is_some() + } + + fn current_application(&mut self) -> Option { + self.connect(); + 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. TODO: Make it configurable + 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 +}