Skip to content

Commit

Permalink
[update] replace xdg-output-handler with wl_output
Browse files Browse the repository at this point in the history
* Update some dependencies.

* Rewrite output.rs to use wl_output version 4 instead of
  xdg-output-handler

* Sent patch to smithay to update wl_output least supported version Smithay/client-toolkit#259.
  • Loading branch information
Shinyzenith committed May 29, 2022
1 parent fc90d64 commit 0469431
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 103 deletions.
5 changes: 2 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ uninstall:
check:
@cargo fmt
@cargo check
@cargo clippy

clean:
@cargo clean
Expand Down
20 changes: 7 additions & 13 deletions src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,19 @@ pub fn capture_output_frame(
}
};

// Instantiating the image frame.
let frame: Main<ZwlrScreencopyFrameV1>;

// Capture output.
if let Some(region) = capture_region {
frame = screencopy_manager.capture_output_region(
let frame: Main<ZwlrScreencopyFrameV1> = 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({
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
}
Expand Down
85 changes: 42 additions & 43 deletions src/output.rs
Original file line number Diff line number Diff line change
@@ -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<OutputInfo> {
// 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<RefCell<Vec<OutputInfo>>> = 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::<WlOutput>(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<OutputInfo>) -> &'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);
}
65 changes: 22 additions & 43 deletions src/wayshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -35,65 +32,61 @@ fn main() -> Result<(), Box<dyn Error>> {

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") {
cursor_overlay = 1;
}

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<i32> = slurp.iter().map(|i| i.parse::<i32>().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();
Expand Down Expand Up @@ -126,28 +119,14 @@ fn main() -> Result<(), Box<dyn Error>> {
}
}
}
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);
}

0 comments on commit 0469431

Please sign in to comment.