diff --git a/Cargo.lock b/Cargo.lock index ff53e34..9273d99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,6 +83,61 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "clap" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_complete" +version = "4.5.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c757a3b7e39161a4e56f9365141ada2a6c915a8622c408ab6bb4b5d047371031" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "4.5.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "clap_lex" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" + +[[package]] +name = "color" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18ef4657441fb193b65f34dc39b3781f0dfec23d3bd94d0eeb4e88cde421edb" + [[package]] name = "colorchoice" version = "1.0.4" @@ -146,6 +201,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "indenter" version = "0.3.4" @@ -492,6 +553,12 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "1.0.109" @@ -597,6 +664,9 @@ dependencies = [ name = "wl-backdrop" version = "0.1.0" dependencies = [ + "clap", + "clap_complete", + "color", "env_logger", "eyre", "log", diff --git a/Cargo.toml b/Cargo.toml index 384b064..ccebb78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,9 @@ license = "GPLv3" readme = "README.md" [dependencies] +clap = { version = "4.5.60", features = ["cargo", "derive"] } +clap_complete = "4.5.66" +color = "0.3.2" env_logger = "0.11.9" eyre = "0.6.12" log = "0.4.29" diff --git a/src/deco.rs b/src/deco.rs index a791d16..93b2aad 100644 --- a/src/deco.rs +++ b/src/deco.rs @@ -133,6 +133,7 @@ impl Deco { subsurface.set_forward_to_client(false); subsurface.send_place_below(&host_surface); let pool = SimpleBufferPool::new(globals, 1, 1).unwrap(); + let args = crate::ARGS.get().unwrap(); let deco = Rc::new(Deco { bounds: RefCell::new(Bounds { x: 0, @@ -140,8 +141,8 @@ impl Deco { width: 10, height: 10, }), - top_size: 24, - border_size: 8, + top_size: args.thickness as i32, // TODO: title + border_size: args.thickness as i32, wl_surface: wl_surface.clone(), subsurface, toplevel: toplevel.clone(), @@ -192,13 +193,21 @@ impl Deco { fn draw(&self) -> eyre::Result> { let bounds = self.bounds.borrow(); let (width, height) = self.transform_size(bounds.width, bounds.height); - log::info!("{:?} -> {}x{}", bounds, width, height); let mut pool = self.pool.borrow_mut(); let (buf, map) = pool.buffer(width, height)?; + let (pre, pix, post) = unsafe { map.align_to_mut::() }; + assert!(pre.len() == 0 && post.len() == 0); + let bg = crate::ARGS + .get() + .unwrap() + .background + .premultiply() + .to_rgba8(); + let bg_argb = u32::from_be_bytes([bg.a, bg.r, bg.g, bg.b]); for y in 0..height { - for x in 0..width * 4 { - map[(y * (width * 4) + x) as usize] = 0xaf; + for x in 0..width { + pix[(y * width + x) as usize] = bg_argb; } } diff --git a/src/main.rs b/src/main.rs index fa61f83..8742017 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ -use std::{process::Command, rc::Rc}; +use std::{process::Command, rc::Rc, sync::OnceLock}; +use clap::{CommandFactory, Parser}; use wl_proxy::{ baseline::Baseline, object::{ConcreteObject, Object, ObjectCoreApi, ObjectRcUtils}, @@ -45,12 +46,52 @@ impl WlRegistryHandler for ClientWlRegistry { } } +/// Add window decorations to Wayland clients. +#[derive(Parser, Debug, Clone)] +struct WlBackdrop { + /// Generate shell completions instead of running the program. + #[clap(long, value_enum, value_name = "SHELL")] + generate_completion: Option, + /// The background color of the decorations. + #[clap(long, default_value = "#8ff0a4fa")] + background: color::AlphaColor, + /// The thickness of the decorations in pixels. + #[clap(long, default_value = "4")] + thickness: u8, + /// The program to run. + #[clap( + trailing_var_arg = true, + value_hint = clap::ValueHint::CommandWithArguments, + required_unless_present = "generate_completion", + )] + program: Option>, +} + +static ARGS: OnceLock = OnceLock::new(); + fn main() -> eyre::Result<()> { env_logger::builder().parse_default_env().init(); + let args = WlBackdrop::parse(); + if let Some(shell) = args.generate_completion { + let stdout = std::io::stdout(); + let mut stdout = stdout.lock(); + clap_complete::generate( + shell, + &mut WlBackdrop::command(), + "wl-backdrop", + &mut stdout, + ); + return Ok(()); + } + ARGS.set(args).unwrap(); + let server = SimpleProxy::new(Baseline::V2)?; - Command::new("gtk4-demo") - .with_wayland_display(server.display()) - .spawn_and_forward_exit_code()?; + if let Some(ref program) = ARGS.get().unwrap().program { + Command::new(&program[0]) + .args(&program[1..]) + .with_wayland_display(server.display()) + .spawn_and_forward_exit_code()?; + } Err(server.run(|| globals::ClientWlDisplay::new()).into()) }