diff --git a/Cargo.lock b/Cargo.lock index 93a76afe..473e8674 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -446,8 +446,7 @@ checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "smithay-client-toolkit" version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a28f16a97fa0e8ce563b2774d1e732dd5d4025d2772c5dba0a41a0f90a29da3" +source = "git+https://github.com/shinyzenith/client-toolkit?branch=patch-1#c4718c71776a61a053eb99a4a652d31b035a685f" dependencies = [ "bitflags", "calloop", @@ -578,7 +577,7 @@ dependencies = [ [[package]] name = "wayshot" -version = "1.1.5" +version = "1.1.7" dependencies = [ "clap", "env_logger", diff --git a/Cargo.toml b/Cargo.toml index c9f4c090..f9e3dfbd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["screenshot", "wayland", "wlroots"] license = "BSD-2-Clause" name = "wayshot" repository = "https://git.sr.ht/~shinyzenith/wayshot" -version = "1.1.5" +version = "1.1.7" exclude = [ "CODE_OF_CONDUCT.md", "CONTRIBUTING.md", diff --git a/Makefile b/Makefile index fb7359d5..47b25a49 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ uninstall: check: @cargo fmt @cargo check + @cargo clippy clean: @cargo clean diff --git a/src/backend.rs b/src/backend.rs index 01cb187b..5bd1498b 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -116,22 +116,19 @@ pub fn capture_output_frame( } }; - // Instantiating the image frame. - let frame: Main; - // Capture output. - if let Some(region) = capture_region { - frame = screencopy_manager.capture_output_region( + let frame: Main = if let Some(region) = capture_region { + screencopy_manager.capture_output_region( cursor_overlay, &output, region.x_coordinate, region.y_coordinate, region.width, region.height, - ); + ) } else { - frame = screencopy_manager.capture_output(cursor_overlay, &output); - } + screencopy_manager.capture_output(cursor_overlay, &output) + }; // Assign callback to frame. frame.quick_assign({ @@ -197,13 +194,12 @@ pub fn capture_output_frame( let frame_format = frame_formats .borrow() .iter() - .filter(|frame| { + .find(|frame| { matches!( frame.format, wl_shm::Format::Argb8888 | wl_shm::Format::Xrgb8888 | wl_shm::Format::Xbgr8888 ) }) - .nth(0) .copied(); log::debug!("Selected frame buffer format: {:#?}", frame_format); @@ -257,9 +253,7 @@ pub fn capture_output_frame( wl_shm::Format::Argb8888 | wl_shm::Format::Xrgb8888 => { // Swap out b with r as these formats are in little endian notation. for chunk in data.chunks_exact_mut(4) { - let alpha = chunk[0]; - chunk[0] = chunk[2]; - chunk[2] = alpha; + chunk.swap(0, 2); } Rgba8 } diff --git a/src/output.rs b/src/output.rs index 5973cad3..b69ce503 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,54 +1,53 @@ -use smithay_client_toolkit::{ - environment, - environment::Environment, - output::{with_output_info, OutputHandler, OutputInfo, XdgOutputHandler}, - reexports::{ - client::{protocol::wl_output::WlOutput, Display}, - protocols::unstable::xdg_output::v1::client::zxdg_output_manager_v1::ZxdgOutputManagerV1, - }, +use smithay_client_toolkit::reexports::client::{ + protocol::wl_output, protocol::wl_output::WlOutput, Display, GlobalManager, }; +use std::{cell::RefCell, process::exit, rc::Rc}; -struct App { - outputs: OutputHandler, - xdg_output: XdgOutputHandler, +#[derive(Debug, Clone)] +pub struct OutputInfo { + pub wl_output: *mut WlOutput, + pub name: String, } -environment! {App, - singles = [ - ZxdgOutputManagerV1 => xdg_output, - ], - multis = [ - WlOutput => outputs, - ] -} - -pub fn get_valid_outputs(display: Display) -> Vec<(WlOutput, OutputInfo)> { - 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(); +pub fn get_all_outputs(display: Display) -> Vec { + // Connecting to wayland environment. + let mut event_queue = display.create_event_queue(); + let attached_display = (*display).clone().attach(event_queue.token()); - let env = Environment::new( - &attached_display, - &mut &mut queue, - App { - outputs, - xdg_output, - }, - ) - .unwrap(); + let outputs: Rc>> = Rc::new(RefCell::new(Vec::new())); - queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap(); + // Instantiating the global manager. + let globals = GlobalManager::new(&attached_display); + event_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())); - } else { - output.release(); + globals + .instantiate_exact::(4) + .expect("Failed to bind to wl_output global.") + .quick_assign({ + let outputs = outputs.clone(); + move |output, event, _| { + if let wl_output::Event::Name { name } = event { + outputs.borrow_mut().push(OutputInfo { + wl_output: &mut output.detach(), + name, + }); + } } }); + event_queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap(); + let x = outputs.borrow().to_vec(); + x +} + +/// Get a wl_output object from the output name. +pub fn get_wloutput(name: String, outputs: Vec) -> &'static WlOutput { + for output in outputs { + if output.name == name { + unsafe { + return &*output.wl_output; + } + } } - valid_outputs + log::error!("Error: No output of name \"{}\" was found", name); + exit(1); } diff --git a/src/wayshot.rs b/src/wayshot.rs index 2f959369..d2a923c6 100644 --- a/src/wayshot.rs +++ b/src/wayshot.rs @@ -7,10 +7,7 @@ use std::{ time::{SystemTime, UNIX_EPOCH}, }; -use smithay_client_toolkit::{ - output::OutputInfo, - reexports::client::{protocol::wl_output::WlOutput, Display}, -}; +use smithay_client_toolkit::reexports::client::{protocol::wl_output::WlOutput, Display}; mod backend; mod clap; @@ -35,8 +32,7 @@ fn main() -> Result<(), Box> { let display = Display::connect_to_env()?; let mut extension = backend::EncodingFormat::Png; - let frame_copy: backend::FrameCopy; - let output: WlOutput; + let output: &WlOutput; let mut cursor_overlay: i32 = 0; if args.is_present("cursor") { @@ -44,56 +40,53 @@ fn main() -> Result<(), Box> { } if args.is_present("listoutputs") { - let valid_outputs = output::get_valid_outputs(display); + let valid_outputs = output::get_all_outputs(display); for output in valid_outputs { - let (_, info) = output; - log::info!("{:#?}", info.name); + log::info!("{:#?}", output.name); } exit(1); } if args.is_present("output") { - output = get_wloutput( + output = &*output::get_wloutput( args.value_of("output").unwrap().trim().to_string(), - output::get_valid_outputs(display.clone()), + output::get_all_outputs(display.clone()), ) } else { - (output, _) = output::get_valid_outputs(display.clone()) - .first() - .unwrap() - .clone(); + unsafe { + output = &*output::get_all_outputs(display.clone()) + .first() + .unwrap() + .wl_output; + } } - if args.is_present("slurp") { + let frame_copy: backend::FrameCopy = if args.is_present("slurp") { if args.value_of("slurp").unwrap() == "" { log::error!("Failed to recieve geometry."); exit(1); } - let slurp: Vec<_> = args.value_of("slurp").unwrap().trim().split(" ").collect(); + let slurp: Vec<_> = args.value_of("slurp").unwrap().trim().split(' ').collect(); let slurp: Vec = slurp.iter().map(|i| i.parse::().unwrap()).collect(); let x_coordinate = slurp[0]; let y_coordinate = slurp[1]; let width = slurp[2]; let height = slurp[3]; - //let out = output::get_valid_outputs(display.clone()); - //println!("{:#?}", out); - //exit(1); - - frame_copy = backend::capture_output_frame( - display.clone(), + backend::capture_output_frame( + display, cursor_overlay, - output, + output.clone(), Some(backend::CaptureRegion { x_coordinate, y_coordinate, width, height, }), - )?; + )? } else { - frame_copy = backend::capture_output_frame(display.clone(), cursor_overlay, output, None)?; - } + backend::capture_output_frame(display, cursor_overlay, output.clone(), None)? + }; if args.is_present("stdout") { let stdout = stdout(); @@ -126,28 +119,14 @@ fn main() -> Result<(), Box> { } } } - path = (time + path = time + match extension { backend::EncodingFormat::Png => "-wayshot.png", backend::EncodingFormat::Jpg => "-wayshot.jpg", - }) - .to_string(); + }; } backend::write_to_file(File::create(path)?, extension, frame_copy)?; } Ok(()) } - -//TODO: This should be a part of output.rs which inturn should be merged into backend.rs -/// Get a wl_output object from the output name. -fn get_wloutput(name: String, valid_outputs: Vec<(WlOutput, OutputInfo)>) -> WlOutput { - for device in valid_outputs.clone() { - let (output_device, info) = device; - if info.name == name { - return output_device; - } - } - println!("Error: No output of name \"{}\" was found", name); - exit(1); -}