waycrate / wayshot

Mirrored at https://git.sr.ht/~shinyzenith/wayshot | screenshot tool for wlroots based compositors implementing zwlr_screencopy_v1
https://crates.io/crates/wayshot
BSD 2-Clause "Simplified" License
115 stars 20 forks source link

Support instantly taking screenshot before choosing portion with slurp #62

Open AndreasBackx opened 1 year ago

AndreasBackx commented 1 year ago

I often want to take a screenshot from a popup window, whether it be in the browser or elsewhere. Unfortunately these popups close when focus is lost. MacOS takes a screenshot when the screenshot button is pressed and the selection tool then allows you to select a portion of the screen thus allowing you to take screenshot of popups.

Having this functionality in Wayshot would not be trivial as it would require creating an overlay on which slurp can then be used. Currently slurp is also run before Wayshot so we cannot take a screenshot and show it as a moment capture before running slurp so that needs to be changed as well. We could make --slurp accept any command and run it from inside of the CLI so we can take a screenshot first and show it to the user after which we can run slurp to select what thay want and then we'd only need to do a crop. What do you think?

Shinyzenith commented 1 year ago

Currently slurp is also run before Wayshot so we cannot take a screenshot and show it as a moment capture before running slurp so that needs to be changed as well.

I don't quite understand what this sentence means.

We could make --slurp accept any command and run it from inside of the CLI so we can take a screenshot first and show it to the user after which we can run slurp to select what thay want and then we'd only need to do a crop. What do you think?

Please correct me if I understood you incorrectly:

Proposed solution:

Here's a solution that I had thought of since day 1 of writing wayshot which might be more feasible. We take a full-monitor screenshot of the active monitor and then just pipe the contents into a second program ( a swappy clone which is fast and not laggy.. ), here we can do: cropping/blurring/coloring etc etc

I never got the time to execute this idea but if someone wants to pick up on it, let me know.

AndreasBackx commented 1 year ago

I don't quite understand what this sentence means.

When we pass --slurp, it uses the output from slurp that has already been executed. Though ideally when you select the region you want to save, you want to see exactly what is about to be saved. In this case that means we want to immediately see the screenshot of when we call wayshot. Because slurp runs before this, there is no way we can do that.

So currently it's "slurp -> region screenshot". We would need "screenshot everything -> slurp -> crop".

In this approach we would have to take the screenshot of all monitors, composite them into one, encode them and then clip/crop it again? Feels inefficient and might lead to loss of detail if I'm not mistaken.

We don't necessarily need to encode them in the middle. We can keep the buffer in memory and drop/destroy it when we no longer need it. This also will not lead to any loss in quality, we are however holding onto more memory and for slightly longer. Though I don't think this is an issue.

Leaving the above point aside, what if we only want to select a portion of one monitor? Well now we are still capturing all outputs because we can expect any form of slurp transforms with any number of available monitors being panned across.

I'm not sure if you're asking me anything here. Though we will indeed take an entire screenshot each time.

There's also the elephant in the room that I haven't addressed. This would require a major rewrite including zwlr_layer_shell and other generic wayland boilerplate that feels out of scope for the project.

Yes, zwlr_layer_shell will be required. I currently have an implementation that is leveraging zwlr_layer_shell to take a screenshot and reuse the same buffer the screenshot was taken to as a top layer and then slurp is called to select a region. There are no unneeded copies of data. I have to work a bit with the coordinates and use imageops::crop to crop the final image, though so far it seems very possible.

Would you be down to chat on Discord and we can possibly talk further there? I'll post something.

AndreasBackx commented 1 year ago

Future reference: we discussed further via Discord. Will share a PoC when ready.