smithay_client_toolkit/shm/
mod.rs

1pub mod multi;
2pub mod raw;
3pub mod slot;
4
5use std::io;
6
7use wayland_client::{
8    globals::{BindError, GlobalList},
9    protocol::wl_shm,
10    Connection, Dispatch, QueueHandle, WEnum,
11};
12
13use crate::{
14    error::GlobalError,
15    globals::{GlobalData, ProvidesBoundGlobal},
16};
17
18pub trait ShmHandler {
19    fn shm_state(&mut self) -> &mut Shm;
20}
21
22#[derive(Debug)]
23pub struct Shm {
24    wl_shm: wl_shm::WlShm,
25    formats: Vec<wl_shm::Format>,
26}
27
28impl From<wl_shm::WlShm> for Shm {
29    fn from(wl_shm: wl_shm::WlShm) -> Self {
30        Self { wl_shm, formats: Vec::new() }
31    }
32}
33
34impl Shm {
35    pub fn bind<State>(globals: &GlobalList, qh: &QueueHandle<State>) -> Result<Shm, BindError>
36    where
37        State: Dispatch<wl_shm::WlShm, GlobalData, State> + ShmHandler + 'static,
38    {
39        let wl_shm = globals.bind(qh, 1..=1, GlobalData)?;
40        // Compositors must advertise Argb8888 and Xrgb8888, so let's reserve space for those formats.
41        Ok(Shm { wl_shm, formats: Vec::with_capacity(2) })
42    }
43
44    pub fn wl_shm(&self) -> &wl_shm::WlShm {
45        &self.wl_shm
46    }
47
48    /// Returns the formats supported in memory pools.
49    pub fn formats(&self) -> &[wl_shm::Format] {
50        &self.formats[..]
51    }
52}
53
54impl ProvidesBoundGlobal<wl_shm::WlShm, 1> for Shm {
55    fn bound_global(&self) -> Result<wl_shm::WlShm, GlobalError> {
56        Ok(self.wl_shm.clone())
57    }
58}
59
60/// An error that may occur when creating a pool.
61#[derive(Debug, thiserror::Error)]
62pub enum CreatePoolError {
63    /// The wl_shm global is not bound.
64    #[error(transparent)]
65    Global(#[from] GlobalError),
66
67    /// Error while allocating the shared memory.
68    #[error(transparent)]
69    Create(#[from] io::Error),
70}
71
72/// Delegates the handling of [`wl_shm`] to some [`Shm`].
73///
74/// This macro requires two things, the type that will delegate to [`Shm`] and a closure specifying how
75/// to obtain the state object.
76///
77/// ```
78/// use smithay_client_toolkit::shm::{ShmHandler, Shm};
79/// use smithay_client_toolkit::delegate_shm;
80///
81/// struct ExampleApp {
82///     /// The state object that will be our delegate.
83///     shm: Shm,
84/// }
85///
86/// // Use the macro to delegate wl_shm to Shm.
87/// delegate_shm!(ExampleApp);
88///
89/// // You must implement the ShmHandler trait to provide a way to access the Shm from your data type.
90/// impl ShmHandler for ExampleApp {
91///     fn shm_state(&mut self) -> &mut Shm {
92///         &mut self.shm
93///     }
94/// }
95#[macro_export]
96macro_rules! delegate_shm {
97    ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
98        $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty:
99            [
100                $crate::reexports::client::protocol::wl_shm::WlShm: $crate::globals::GlobalData
101            ] => $crate::shm::Shm
102        );
103    };
104}
105
106impl<D> Dispatch<wl_shm::WlShm, GlobalData, D> for Shm
107where
108    D: Dispatch<wl_shm::WlShm, GlobalData> + ShmHandler,
109{
110    fn event(
111        state: &mut D,
112        _proxy: &wl_shm::WlShm,
113        event: wl_shm::Event,
114        _: &GlobalData,
115        _: &Connection,
116        _: &QueueHandle<D>,
117    ) {
118        match event {
119            wl_shm::Event::Format { format } => {
120                match format {
121                    WEnum::Value(format) => {
122                        state.shm_state().formats.push(format);
123                        log::debug!(target: "sctk", "supported wl_shm format {:?}", format);
124                    }
125
126                    // Ignore formats we don't know about.
127                    WEnum::Unknown(raw) => {
128                        log::debug!(target: "sctk", "Unknown supported wl_shm format {:x}", raw);
129                    }
130                };
131            }
132
133            _ => unreachable!(),
134        }
135    }
136}