1 | pub mod multi; |
2 | pub mod raw; |
3 | pub mod slot; |
4 | |
5 | use std::io; |
6 | |
7 | use wayland_client::{ |
8 | globals::{BindError, GlobalList}, |
9 | protocol::wl_shm, |
10 | Connection, Dispatch, QueueHandle, WEnum, |
11 | }; |
12 | |
13 | use crate::{ |
14 | error::GlobalError, |
15 | globals::{GlobalData, ProvidesBoundGlobal}, |
16 | }; |
17 | |
18 | pub trait ShmHandler { |
19 | fn shm_state(&mut self) -> &mut Shm; |
20 | } |
21 | |
22 | #[derive (Debug)] |
23 | pub struct Shm { |
24 | wl_shm: wl_shm::WlShm, |
25 | formats: Vec<wl_shm::Format>, |
26 | } |
27 | |
28 | impl 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 | |
34 | impl 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, version:1..=1, udata: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 | |
54 | impl 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)] |
62 | pub 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 ] |
96 | macro_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 | |
106 | impl<D> Dispatch<wl_shm::WlShm, GlobalData, D> for Shm |
107 | where |
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 | } |
137 | |