| 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 | |