simple-render 0.2.0

a simple immediate mode wayland ui renderer inspired by clay
Documentation
use super::runtime::State;
use super::*;

impl<R> CompositorHandler for State<R>
where
    R: Renderer,
{
    fn scale_factor_changed(
        &mut self,
        _: &Connection,
        qh: &QueueHandle<Self>,
        surface: &wl_surface::WlSurface,
        new_factor: i32,
    ) {
        let Some(id) = self.surface_id_for_wl_surface(surface) else {
            return;
        };
        let Some(surface) = self.surfaces.get_mut(&id) else {
            return;
        };
        if surface.set_scale(new_factor.max(1) as u32) {
            self.draw(qh, id, None);
        }
    }

    fn transform_changed(
        &mut self,
        _: &Connection,
        _: &QueueHandle<Self>,
        _: &wl_surface::WlSurface,
        _: wl_output::Transform,
    ) {
    }

    fn frame(
        &mut self,
        _: &Connection,
        qh: &QueueHandle<Self>,
        wl_surface: &wl_surface::WlSurface,
        time: u32,
    ) {
        let Some(id) = self.surface_id_for_wl_surface(wl_surface) else {
            return;
        };
        let Some(surface) = self.surfaces.get_mut(&id) else {
            return;
        };
        surface.frame_pending = false;
        self.draw(qh, id, Some(time));
    }

    fn surface_enter(
        &mut self,
        _: &Connection,
        _: &QueueHandle<Self>,
        _: &wl_surface::WlSurface,
        _: &wl_output::WlOutput,
    ) {
    }

    fn surface_leave(
        &mut self,
        _: &Connection,
        _: &QueueHandle<Self>,
        _: &wl_surface::WlSurface,
        _: &wl_output::WlOutput,
    ) {
    }
}

impl<R> LayerShellHandler for State<R>
where
    R: Renderer,
{
    fn closed(&mut self, _: &Connection, _: &QueueHandle<Self>, layer: &LayerSurface) {
        let Some(id) = self.surface_id_for_layer(layer) else {
            return;
        };
        self.remove_surface(id);
        self.maybe_exit_after_surface_removal();
    }

    fn configure(
        &mut self,
        _: &Connection,
        qh: &QueueHandle<Self>,
        layer: &LayerSurface,
        configure: LayerSurfaceConfigure,
        _: u32,
    ) {
        let Some(id) = self.surface_id_for_layer(layer) else {
            return;
        };
        let Some(surface) = self.surfaces.get_mut(&id) else {
            return;
        };

        if configure.new_size.0 != 0 {
            surface.width = configure.new_size.0;
        }
        if configure.new_size.1 != 0 {
            surface.height = configure.new_size.1;
        }
        surface.configured = true;
        self.renderer
            .configured_surface(id, surface.width, surface.height);
        self.draw(qh, id, None);
    }
}

impl<R: Renderer> ShmHandler for State<R> {
    fn shm_state(&mut self) -> &mut Shm {
        &mut self.shm
    }
}

impl<R: Renderer> OutputHandler for State<R> {
    fn output_state(&mut self) -> &mut OutputState {
        &mut self.output_state
    }

    fn new_output(&mut self, _: &Connection, _: &QueueHandle<Self>, output: wl_output::WlOutput) {
        if let Some(output) = self.render_output(&output) {
            self.renderer.output_added(output);
        }
    }

    fn update_output(
        &mut self,
        _: &Connection,
        _: &QueueHandle<Self>,
        output: wl_output::WlOutput,
    ) {
        if let Some(output) = self.render_output(&output) {
            self.renderer.output_updated(output);
        }
    }

    fn output_destroyed(
        &mut self,
        _: &Connection,
        _: &QueueHandle<Self>,
        output: wl_output::WlOutput,
    ) {
        if let Some(output) = self.render_output(&output) {
            self.renderer.output_removed(output);
        }
    }
}

impl<R: Renderer> SeatHandler for State<R> {
    fn seat_state(&mut self) -> &mut SeatState {
        &mut self.seat_state
    }

    fn new_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}

    fn new_capability(
        &mut self,
        _: &Connection,
        qh: &QueueHandle<Self>,
        seat: wl_seat::WlSeat,
        capability: Capability,
    ) {
        if capability == Capability::Pointer && self.pointer.is_none() {
            self.pointer = self.seat_state.get_pointer(qh, &seat).ok();
        }
    }

    fn remove_capability(
        &mut self,
        _: &Connection,
        _: &QueueHandle<Self>,
        _: wl_seat::WlSeat,
        capability: Capability,
    ) {
        if capability == Capability::Pointer {
            self.pointer.take();
        }
    }

    fn remove_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}
}

impl<R: Renderer> PointerHandler for State<R> {
    fn pointer_frame(
        &mut self,
        _: &Connection,
        qh: &QueueHandle<Self>,
        _: &wl_pointer::WlPointer,
        events: &[SctkPointerEvent],
    ) {
        for event in events {
            let Some(id) = self.surface_id_for_wl_surface(&event.surface) else {
                continue;
            };
            let event = pointer_event_from_sctk(id, event);
            let action = self.renderer.pointer_event(event);
            self.handle_input_action(qh, id, action);
        }
    }
}

impl<R: Renderer> ProvidesRegistryState for State<R> {
    fn registry(&mut self) -> &mut RegistryState {
        &mut self.registry_state
    }

    registry_handlers![OutputState, SeatState];
}

fn pointer_event_from_sctk(id: SurfaceId, event: &SctkPointerEvent) -> PointerEvent {
    let (x, y) = event.position;
    let (time, serial, kind) = match &event.kind {
        SctkPointerEventKind::Enter { serial } => (None, Some(*serial), PointerEventKind::Enter),
        SctkPointerEventKind::Leave { serial } => (None, Some(*serial), PointerEventKind::Leave),
        SctkPointerEventKind::Motion { time } => (Some(*time), None, PointerEventKind::Motion),
        SctkPointerEventKind::Press {
            time,
            button,
            serial,
        } => (
            Some(*time),
            Some(*serial),
            PointerEventKind::Button {
                button: *button,
                state: PointerButtonState::Pressed,
            },
        ),
        SctkPointerEventKind::Release {
            time,
            button,
            serial,
        } => (
            Some(*time),
            Some(*serial),
            PointerEventKind::Button {
                button: *button,
                state: PointerButtonState::Released,
            },
        ),
        SctkPointerEventKind::Axis {
            time,
            horizontal,
            vertical,
            source,
        } => (
            Some(*time),
            None,
            PointerEventKind::Axis {
                horizontal: PointerAxis {
                    absolute: horizontal.absolute,
                    discrete: horizontal.discrete,
                    stopped: horizontal.stop,
                },
                vertical: PointerAxis {
                    absolute: vertical.absolute,
                    discrete: vertical.discrete,
                    stopped: vertical.stop,
                },
                source: source.map(pointer_axis_source_from_sctk),
            },
        ),
    };

    PointerEvent {
        surface: id,
        x,
        y,
        time,
        serial,
        kind,
    }
}

fn pointer_axis_source_from_sctk(source: wl_pointer::AxisSource) -> PointerAxisSource {
    match source {
        wl_pointer::AxisSource::Wheel => PointerAxisSource::Wheel,
        wl_pointer::AxisSource::Finger => PointerAxisSource::Finger,
        wl_pointer::AxisSource::Continuous => PointerAxisSource::Continuous,
        wl_pointer::AxisSource::WheelTilt => PointerAxisSource::WheelTilt,
        _ => PointerAxisSource::Unknown,
    }
}

delegate_compositor!(@<R: Renderer> State<R>);
delegate_output!(@<R: Renderer> State<R>);
delegate_seat!(@<R: Renderer> State<R>);
delegate_pointer!(@<R: Renderer> State<R>);
delegate_shm!(@<R: Renderer> State<R>);
delegate_layer!(@<R: Renderer> State<R>);
delegate_registry!(@<R: Renderer> State<R>);