From 9c1b380a9e7c2b07e78700bc15bd14e21fdaf2f1 Mon Sep 17 00:00:00 2001 From: Shinyzenith Date: Mon, 20 Jun 2022 15:31:41 +0530 Subject: [PATCH] [update] add output dimension detection * Xdg_Output is now being used for dimension detection, this will soon be used to fix the dual monitor bug. Signed-off-by: Shinyzenith --- Cargo.lock | 28 +++++++-------- src/output.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++------ src/wayshot.rs | 22 ++++++------ 3 files changed, 107 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f3d33ca0..c04fa8fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,9 +63,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.1.18" +version = "3.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7" dependencies = [ "atty", "bitflags", @@ -78,9 +78,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613" dependencies = [ "os_str_bytes", ] @@ -137,9 +137,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" [[package]] name = "hermit-abi" @@ -168,9 +168,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +checksum = "6c6392766afd7964e2531940894cffe4bd8d7d17dbc3c1c4857040fd4b33bdb3" dependencies = [ "autocfg", "hashbrown", @@ -208,9 +208,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f" +checksum = "d5172b50c23043ff43dd53e51392f36519d9b35a8f3a410d30ece5d1aedd58ae" dependencies = [ "libc", ] @@ -226,9 +226,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" dependencies = [ "adler", ] @@ -408,9 +408,9 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" [[package]] name = "wayland-client" diff --git a/src/output.rs b/src/output.rs index 901cf0c5..cf50d173 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,10 +1,22 @@ use std::{cell::RefCell, process::exit, rc::Rc}; use wayland_client::{protocol::wl_output, protocol::wl_output::WlOutput, Display, GlobalManager}; +use wayland_protocols::unstable::xdg_output::v1::client::{ + zxdg_output_manager_v1::ZxdgOutputManagerV1, zxdg_output_v1, +}; #[derive(Debug, Clone)] pub struct OutputInfo { - pub wl_output: *mut WlOutput, + pub wl_output: WlOutput, pub name: String, + pub dimensions: OutputPositioning, +} + +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct OutputPositioning { + pub x: i32, + pub y: i32, + pub width: i32, + pub height: i32, } pub fn get_all_outputs(display: Display) -> Vec { @@ -12,12 +24,23 @@ pub fn get_all_outputs(display: Display) -> Vec { let mut event_queue = display.create_event_queue(); let attached_display = (*display).clone().attach(event_queue.token()); - let outputs: Rc>> = Rc::new(RefCell::new(Vec::new())); - // Instantiating the global manager. let globals = GlobalManager::new(&attached_display); event_queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap(); + let mut data: Vec = Vec::new(); + let outputs: Rc>> = Rc::new(RefCell::new(Vec::new())); + + // Bind to xdg_output global. + let zxdg_output_manager = match globals.instantiate_exact::(3) { + Ok(x) => x, + Err(e) => { + log::error!("Failed to create ZxdgOutputManagerV1 version 3. Does your compositor implement ZxdgOutputManagerV1?"); + panic!("{:#?}", e); + } + }; + + // Fetch all outputs and it's name. globals .instantiate_exact::(4) .expect("Failed to bind to wl_output global.") @@ -26,24 +49,74 @@ pub fn get_all_outputs(display: Display) -> Vec { move |output, event, _| { if let wl_output::Event::Name { name } = event { outputs.borrow_mut().push(OutputInfo { - wl_output: &mut output.detach(), + wl_output: output.detach(), name, + dimensions: OutputPositioning { + x: 0, + y: 0, + width: 0, + height: 0, + }, }); } } }); event_queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap(); - let x = outputs.borrow().to_vec(); - x + + // We loop over each output and get it's position data. + for mut output in outputs.borrow().iter().cloned() { + let output_position: Rc> = + Rc::new(RefCell::new(OutputPositioning { + x: 0, + y: 0, + width: 0, + height: 0, + })); + + // Callback to set X, Y, Width, and Height. + zxdg_output_manager + .get_xdg_output(&output.wl_output) + .quick_assign({ + let output_position = output_position.clone(); + move |_, event, _| { + match event { + zxdg_output_v1::Event::LogicalPosition { x, y } => { + output_position.borrow_mut().x = x; + output_position.borrow_mut().y = y; + log::debug!("Logical position event fired!"); + } + zxdg_output_v1::Event::LogicalSize { width, height } => { + output_position.borrow_mut().width = width; + output_position.borrow_mut().height = height; + log::debug!("Logical size event fired!"); + } + _ => {} + }; + } + }); + + // Exhaust the internal buffer queue until we get our required data. + event_queue + .sync_roundtrip(&mut (), |_, _, _| unreachable!()) + .unwrap(); + + // Set the output dimensions + output.dimensions = output_position.take(); + data.push(output); + } + if data.is_empty() { + log::error!("Compositor did not advertise any wl_output devices!"); + exit(1); + } + log::debug!("Outputs detected: {:#?}", data); + data } /// Get a wl_output object from the output name. -pub fn get_wloutput(name: String, outputs: Vec) -> &'static WlOutput { +pub fn get_wloutput(name: String, outputs: Vec) -> WlOutput { for output in outputs { if output.name == name { - unsafe { - return &*output.wl_output; - } + return output.wl_output; } } log::error!("Error: No output of name \"{}\" was found", name); diff --git a/src/wayshot.rs b/src/wayshot.rs index 389cc422..d33f7f91 100644 --- a/src/wayshot.rs +++ b/src/wayshot.rs @@ -30,7 +30,6 @@ fn main() -> Result<(), Box> { let display = Display::connect_to_env()?; let mut extension = backend::EncodingFormat::Png; - let output: &WlOutput; let mut cursor_overlay: i32 = 0; if args.is_present("cursor") { @@ -45,19 +44,18 @@ fn main() -> Result<(), Box> { exit(1); } - if args.is_present("output") { - output = &*output::get_wloutput( + let output: WlOutput = if args.is_present("output") { + output::get_wloutput( args.value_of("output").unwrap().trim().to_string(), output::get_all_outputs(display.clone()), ) } else { - unsafe { - output = &*output::get_all_outputs(display.clone()) - .first() - .unwrap() - .wl_output; - } - } + output::get_all_outputs(display.clone()) + .first() + .unwrap() + .wl_output + .clone() + }; let frame_copy: backend::FrameCopy = if args.is_present("slurp") { if args.value_of("slurp").unwrap() == "" { @@ -74,7 +72,7 @@ fn main() -> Result<(), Box> { backend::capture_output_frame( display, cursor_overlay, - output.clone(), + output, Some(backend::CaptureRegion { x_coordinate, y_coordinate, @@ -83,7 +81,7 @@ fn main() -> Result<(), Box> { }), )? } else { - backend::capture_output_frame(display, cursor_overlay, output.clone(), None)? + backend::capture_output_frame(display, cursor_overlay, output, None)? }; if args.is_present("stdout") {