~whynothugo/shotman

cfce6199330944cbdb4824e47b90686f4f0e3d5c — Hugo Osvaldo Barrera 1 year, 9 months ago 19d5e3d scale
WIP: Implement scaling support

This renders okay, but:

- Viewport coordinates are unscale but work fine? Is this intentional??
- When switching anchor, the resulting location is wrong (sway bug?)
1 files changed, 43 insertions(+), 6 deletions(-)

M src/main.rs
M src/main.rs => src/main.rs +43 -6
@@ 10,7 10,7 @@ use std::thread;
use anyhow::Context;
use chrono::Local;
use clap::{Parser, ValueEnum};
use log::{debug, error, info, warn};
use log::{debug, error, info, trace, warn};
use rustix::fs::{fcntl_getfl, fcntl_setfl, OFlags};
use smithay_client_toolkit::output::{OutputHandler, OutputState};
use smithay_client_toolkit::registry::{ProvidesRegistryState, RegistryHandler, RegistryState};


@@ 173,6 173,7 @@ struct State {
    wl_data_device_manager: Option<wl_data_device_manager::WlDataDeviceManager>,
    // `configure` and `set_size` use u32, so stick to this.
    window_size: Option<(u32, u32)>,
    window_scale: i32,
    ctrl: bool,
    delete_file_on_paste: bool,
    /// The currently taken selection (if we own it).


@@ 182,6 183,12 @@ struct State {
    window_anchor: Anchor,
}

// pub struct WindowProps {
//     width: i32,
//     height: i32,
//     scale: ScaleFactor,
// }

#[derive(Clone, Debug)]
pub struct ScreenshotBufferInfo {
    format: Format,


@@ 278,6 285,7 @@ impl State {
            wl_seat: None,
            wl_data_device_manager: None,
            window_size: None,
            window_scale: 1,
            ctrl: false,
            delete_file_on_paste: false,
            current_selection: None,


@@ 334,13 342,29 @@ impl State {
            .as_ref()
            .context("screenshot buffer info is undefined")?;

        // debug!("Using scale factor of {}.", self.window_scale);
        // window_surface.set_buffer_scale(self.window_scale);

        // TODO: this doesn't account for scaling, so dividing by 5 yields bogus results.
        // TODO: very small screenshots should have a minimum window size.
        // TODO: all BORDER_WIDTH references need to account for scaling.
        let scale = self.window_scale as u32;
        let border = BORDER_WIDTH * scale;

        let (thumb_width, thumb_height) = ((shot_info.width / 5), (shot_info.height / 5));
        let (window_width, window_height) = (
            thumb_width + (BORDER_WIDTH as u32 * 2),
            thumb_height + (BORDER_WIDTH as u32 * 2),
            thumb_width * scale + (border * 2),
            thumb_height * scale + (border * 2),
        );
        trace!(
            "Rendering thumbnail with size {}x{}.",
            thumb_width,
            thumb_height
        );
        trace!(
            "Rendering window with size {}x{}.",
            window_width,
            window_height
        );

        // TODO: Don't re-create buffers on each resize. Re-use when possible, especially if size


@@ 393,6 417,7 @@ impl State {
            .set_keyboard_interactivity(zwlr_layer_surface_v1::KeyboardInteractivity::Exclusive);

        shot_subsurface.set_position(BORDER_WIDTH as i32, BORDER_WIDTH as i32);
        // shot_surface.set_buffer_scale(self.window_scale);

        // FIXME: should re-use the same viewporter as long as the surface does not change.
        // Looks like sway allows this, even though the spec this should ERROR. Good for me.


@@ 672,14 697,22 @@ dispatch_noop!(State: [wl_data_offer::WlDataOffer]);
impl Dispatch<wl_surface::WlSurface, ()> for State {
    fn event(
        state: &mut Self,
        _: &wl_surface::WlSurface,
        surface: &wl_surface::WlSurface,
        event: wl_surface::Event,
        _: &(),
        _: &Connection,
        qh: &QueueHandle<Self>,
    ) {
        if let wl_surface::Event::Enter { output } = event {
            // TODO: save scale from output.
            let output_info = state.output_state.info(&output).unwrap();
            surface.set_buffer_scale(output_info.scale_factor);
            state.window_scale = output_info.scale_factor;

            state
                .wlr_layer_surface
                .as_ref()
                .unwrap()
                .set_margin(64, 32, 64, 64);

            // The surface which we enter is the "currently active" one (or whatever the
            // compositor's preference may be), so we use that same one for the screenshot if the


@@ 692,6 725,10 @@ impl Dispatch<wl_surface::WlSurface, ()> for State {
                    .capture_output(1, &output, qh, ())
                    .expect("can request screencopy")
                    .into();
            } else {
                // XXX: do we really want this? I think only if the output has changed.
                println!("11111: {:?}", &output);
                state.render(qh, None).unwrap();
            }
        };
    }


@@ 761,7 798,7 @@ impl Dispatch<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, ()> for State {
                    // File descriptor is dropped immediately here. The compositor has a copy, and
                    // memory will be released when the compositor is done with that.
                    let (_pool, buffer, _) =
                        buffers::init_buffer(wl_shm, 1, 1, Format::Xrgb8888, qh, 127.into())
                        buffers::init_buffer(wl_shm, 12, 12, Format::Xrgb8888, qh, 127.into())
                            .unwrap();
                    let window_surface = state.window_surface.as_ref().unwrap();
                    window_surface.attach(Some(&buffer), 0, 0);