From 2d4a8cbe8e04f3d7d08827d9aaeec4402bbaf89d Mon Sep 17 00:00:00 2001 From: Shinyzenith Date: Tue, 15 Feb 2022 22:27:12 +0530 Subject: [PATCH 1/2] [testing] Per output capture. --- Cargo.toml | 2 +- README.md | 7 +++- src/main.rs | 109 +++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 106 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6f3cfb96..251cb2f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -authors = ["Shinyzenith ", "Cmeissl "] +authors = ["Shinyzenith ", "Cmeissl ", "Victor Berger "] edition = "2021" name = "wayshot" version = "0.1.0" diff --git a/README.md b/README.md index 5d342fa7..8fbe5d61 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ Pick a color, using ImageMagick: wayshot -s "$(slurp -p -f '%x %y %w %h')" | convert - -format '%[pixel:p{0,0}]' txt:- ``` # Installation + ## AUR: `wayshot-git` has been packaged. `wayshot-bin` & `wayshot-musl-bin` will be released soon. @@ -64,11 +65,13 @@ wayshot -s "$(slurp -p -f '%x %y %w %h')" | convert - -format '%[pixel:p{0,0}]' https://discord.gg/KKZRDYrRYW +# Smithay Developers: + +Massive thanks to smithay developer Cmeissl and Victor Berger. Without them this project won't be possible as my wayland knowledge is very very limited. + # Contributors: -# Cmeissl: -Massive thanks to smithay contributor Cmeissl. Without them this project won't be possible as my wayland knowledge is very very limited. diff --git a/src/main.rs b/src/main.rs index b4f56080..fac7866b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,8 +23,9 @@ use nix::{ use tracing::debug; use smithay_client_toolkit::{ - default_environment, new_default_environment, - output::with_output_info, + environment, + environment::Environment, + output::{with_output_info, OutputHandler, OutputInfo, XdgOutputHandler}, reexports::{ client::{ protocol::{ @@ -37,14 +38,29 @@ use smithay_client_toolkit::{ }, Display, GlobalManager, Main, }, - protocols::wlr::unstable::screencopy::v1::client::{ - zwlr_screencopy_frame_v1, zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1, - zwlr_screencopy_manager_v1::ZwlrScreencopyManagerV1, + protocols::{ + unstable::xdg_output::v1::client::zxdg_output_manager_v1::ZxdgOutputManagerV1, + wlr::unstable::screencopy::v1::client::{ + zwlr_screencopy_frame_v1, zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1, + zwlr_screencopy_manager_v1::ZwlrScreencopyManagerV1, + }, }, }, }; -default_environment!(Env); +struct ValidOutputs { + outputs: OutputHandler, + xdg_output: XdgOutputHandler, +} + +environment! {ValidOutputs, + singles = [ + ZxdgOutputManagerV1 => xdg_output, + ], + multis = [ + WlOutput => outputs, + ] +} #[derive(Debug, Copy, Clone)] struct FrameFormat { @@ -108,6 +124,7 @@ fn main() -> Result<()> { Some(output) => output, None => bail!("compositor did not advertise a output"), }; + let mut output = output.detach(); let frame_formats: Rc>> = Rc::new(RefCell::new(Vec::new())); let frame_state: Rc>> = Rc::new(RefCell::new(None)); @@ -121,6 +138,30 @@ fn main() -> Result<()> { cursor_overlay = 1; } + if args.is_present("listoutputs") { + print_valid_outputs(); + std::process::exit(1); + } + + if args.is_present("output") { + let mut is_present = false; + let valid_outputs = get_valid_outputs(); + + for device in valid_outputs { + let (output_device, info) = device; + if info.name == args.value_of("output").unwrap().trim() { + is_present = true; + output = output_device.clone(); + } + } + if !is_present { + bail!( + "\"{}\" is not a valid output.", + args.value_of("output").unwrap().trim() + ); + } + } + if args.is_present("slurp") { if args.value_of("slurp").unwrap() == "" { bail!("Failed to recieve geometry."); @@ -129,14 +170,14 @@ fn main() -> Result<()> { let slurp: Vec = slurp.iter().map(|i| i.parse::().unwrap()).collect(); frame = screencopy_manager.capture_output_region( cursor_overlay, - &output.detach(), + &output, slurp[0], slurp[1], slurp[2], slurp[3], ); } else { - frame = screencopy_manager.capture_output(cursor_overlay, &output.detach()); + frame = screencopy_manager.capture_output(cursor_overlay, &output); } frame.quick_assign({ @@ -258,7 +299,6 @@ fn main() -> Result<()> { } } }; - result } @@ -337,6 +377,19 @@ fn set_flags() -> App<'static> { .takes_value(true) .help("Choose a portion of your display to screenshot using slurp."), ) + .arg( + arg!(-l - -listoutputs) + .required(false) + .takes_value(false) + .help("List all valid outputs."), + ) + .arg( + arg!(-o --output ) + .required(false) + .takes_value(true) + .conflicts_with("slurp") + .help("Choose a particular display to screenshot."), + ) .arg( arg!(-c - -cursor) .required(false) @@ -345,3 +398,41 @@ fn set_flags() -> App<'static> { ); app } + +fn get_valid_outputs() -> Vec<(WlOutput, OutputInfo)> { + let display = Display::connect_to_env().unwrap(); + let mut queue = display.create_event_queue(); + let attached_display = display.attach(queue.token()); + + let (outputs, xdg_output) = XdgOutputHandler::new_output_handlers(); + let mut valid_outputs: Vec<(WlOutput, OutputInfo)> = Vec::new(); + + let env = Environment::new( + &attached_display, + &mut &mut queue, + ValidOutputs { + outputs, + xdg_output, + }, + ) + .unwrap(); + + queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap(); + + for output in env.get_all_outputs() { + with_output_info(&output, |info| { + if info.obsolete == false { + valid_outputs.push((output.clone(), info.clone())); + } + }); + } + valid_outputs +} + +fn print_valid_outputs() { + let valid_outputs = get_valid_outputs(); + for output in valid_outputs { + let (_, info) = output; + println!("{:#?}", info.name); + } +} From 263b9d2a1f03f640cab3c144eee1cdf1d1ec1fb0 Mon Sep 17 00:00:00 2001 From: Shinyzenith Date: Tue, 15 Feb 2022 22:55:42 +0530 Subject: [PATCH 2/2] [bug fix] wl_output invalid object. --- src/main.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/main.rs b/src/main.rs index fac7866b..da16061c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -139,13 +139,17 @@ fn main() -> Result<()> { } if args.is_present("listoutputs") { - print_valid_outputs(); + let valid_outputs = get_valid_outputs(display); + for output in valid_outputs { + let (_, info) = output; + println!("{:#?}", info.name); + } std::process::exit(1); } if args.is_present("output") { let mut is_present = false; - let valid_outputs = get_valid_outputs(); + let valid_outputs = get_valid_outputs(display); for device in valid_outputs { let (output_device, info) = device; @@ -399,8 +403,7 @@ fn set_flags() -> App<'static> { app } -fn get_valid_outputs() -> Vec<(WlOutput, OutputInfo)> { - let display = Display::connect_to_env().unwrap(); +fn get_valid_outputs(display: Display) -> Vec<(WlOutput, OutputInfo)> { let mut queue = display.create_event_queue(); let attached_display = display.attach(queue.token()); @@ -427,12 +430,4 @@ fn get_valid_outputs() -> Vec<(WlOutput, OutputInfo)> { }); } valid_outputs -} - -fn print_valid_outputs() { - let valid_outputs = get_valid_outputs(); - for output in valid_outputs { - let (_, info) = output; - println!("{:#?}", info.name); - } -} +} \ No newline at end of file