Skip to main content

spell_framework/wayland_adapter/
fractional_scaling.rs

1// Courtesy DrepDays
2// Implementaion is taken and modified from here.
3// https://github.com/DerpDays/draw/blob/main/platform%2Fwayland%2Fsrc%2Ffractional_scale.rs
4use smithay_client_toolkit::globals::GlobalData;
5use smithay_client_toolkit::reexports::{
6    client::{
7        Connection, Dispatch, Proxy, QueueHandle,
8        globals::{BindError, GlobalList},
9        protocol::wl_surface::WlSurface,
10    },
11    protocols::wp::fractional_scale::v1::client::{
12        wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1,
13        wp_fractional_scale_v1::{Event::PreferredScale, WpFractionalScaleV1},
14    },
15};
16
17#[derive(Debug)]
18#[allow(unused)]
19pub struct FractionalScaleState {
20    manager: WpFractionalScaleManagerV1,
21}
22
23/// An owned instance of WpFractionalScaleV1, when this is dropped, the underlying interface is
24/// destroyed, and hence events for the corresponding surface are no longer emitted.
25#[derive(Debug)]
26pub struct FractionalScale {
27    fractional_scale: WpFractionalScaleV1,
28}
29
30impl FractionalScaleState {
31    pub(crate) fn bind<State>(
32        globals: &GlobalList,
33        queue_handle: &QueueHandle<State>,
34    ) -> Result<Self, BindError>
35    where
36        State: Dispatch<WpFractionalScaleManagerV1, GlobalData, State>
37            + FractionalScaleHandler
38            + 'static,
39    {
40        let manager = globals.bind(queue_handle, 1..=1, GlobalData)?;
41        Ok(FractionalScaleState { manager })
42    }
43
44    pub(crate) fn get_scale<State>(
45        &self,
46        surface: &WlSurface,
47        queue_handle: &QueueHandle<State>,
48    ) -> FractionalScale
49    where
50        State: Dispatch<WpFractionalScaleV1, WlSurface> + 'static,
51    {
52        FractionalScale {
53            fractional_scale: self.manager.get_fractional_scale(
54                surface,
55                queue_handle,
56                surface.clone(),
57            ),
58        }
59    }
60}
61
62impl Drop for FractionalScale {
63    fn drop(&mut self) {
64        self.fractional_scale.destroy();
65    }
66}
67
68impl<D> Dispatch<WpFractionalScaleManagerV1, GlobalData, D> for FractionalScaleState
69where
70    D: Dispatch<WpFractionalScaleManagerV1, GlobalData> + FractionalScaleHandler + 'static,
71{
72    fn event(
73        _: &mut D,
74        _: &WpFractionalScaleManagerV1,
75        _: <WpFractionalScaleManagerV1 as Proxy>::Event,
76        _: &GlobalData,
77        _: &Connection,
78        _: &QueueHandle<D>,
79    ) {
80        unreachable!("WpFractionalScaleManagerV1 has no events")
81    }
82}
83
84impl<D> Dispatch<WpFractionalScaleV1, WlSurface, D> for FractionalScaleState
85where
86    D: Dispatch<WpFractionalScaleV1, WlSurface> + FractionalScaleHandler + 'static,
87{
88    fn event(
89        state: &mut D,
90        _: &WpFractionalScaleV1,
91        event: <WpFractionalScaleV1 as Proxy>::Event,
92        surface: &WlSurface,
93        conn: &Connection,
94        qh: &QueueHandle<D>,
95    ) {
96        match event {
97            PreferredScale { scale } => {
98                state.preferred_scale(conn, qh, surface, scale);
99            }
100            _ => unreachable!("WpFractionalScaleV1 should only have a preferred_scale event"),
101        }
102    }
103}
104
105pub trait FractionalScaleHandler: Sized {
106    /// When this function is called, the compositor is indicating the preferred fractional scale
107    /// for the given surface.
108    ///
109    /// The scale received in this event has a denominator of 120, so the true fractional scale
110    /// would be (scale.to_f64().unwrap() / 120.)
111    fn preferred_scale(
112        &mut self,
113        conn: &Connection,
114        qh: &QueueHandle<Self>,
115        surface: &WlSurface,
116        scale: u32,
117    );
118}
119
120#[macro_export]
121macro_rules! delegate_fractional_scale {
122    ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
123            smithay_client_toolkit::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
124            smithay_client_toolkit::reexports::protocols::wp::fractional_scale::v1::client::wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1: smithay_client_toolkit::globals::GlobalData
125        ] => $crate::wayland_adapter::fractional_scaling::FractionalScaleState);
126        smithay_client_toolkit::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
127            smithay_client_toolkit::reexports::protocols::wp::fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1: smithay_client_toolkit::reexports::client::protocol::wl_surface::WlSurface
128        ] => $crate::wayland_adapter::fractional_scaling::FractionalScaleState);
129    };
130}