| 1 | use crate::error::GlobalError; |
| 2 | use wayland_client::Proxy; |
| 3 | |
| 4 | /// A trait implemented by types that provide access to capability globals. |
| 5 | /// |
| 6 | /// The returned global must be fully compatible with the provided `API_COMPAT_VERSION` generic |
| 7 | /// argument. For example: |
| 8 | /// |
| 9 | /// - A global that binds to `wl_compositor` with maximum version 4 could implement |
| 10 | /// `ProvidesBoundGlobal<WlCompositor, 4>`, `ProvidesBoundGlobal<WlCompositor, 3>`, |
| 11 | /// `ProvidesBoundGlobal<WlCompositor, 2>`, and `ProvidesBoundGlobal<WlCompositor, 1>` because |
| 12 | /// versions 2-4 only add additional requests to the `wl_surface` API. |
| 13 | /// - A global that binds to `wl_compositor` with maximum version 5 may only implement |
| 14 | /// `ProvidesBoundGlobal<WlCompositor, 5>` because version 5 makes using `wl_surface::attach` with |
| 15 | /// a nonzero offset a protocol error. A caller who is only aware of the version 4 API risks |
| 16 | /// causing these protocol errors if it uses surfaces created by such a global. |
| 17 | /// |
| 18 | /// Changes that cause compatibility breaks include: |
| 19 | /// |
| 20 | /// - Adding a new event to the global or to any object created by the global. |
| 21 | /// - Adding a new requirement to an existing request. |
| 22 | /// |
| 23 | /// The resulting global may have a version lower than `API_COMPAT_VERSION` if, at runtime, the |
| 24 | /// compositor does not support the new version. Clients should either be prepared to handle |
| 25 | /// earlier versions of the protocol or use [`ProvidesBoundGlobal::with_min_version`] to produce an |
| 26 | /// error in this case. |
| 27 | /// |
| 28 | /// It is permitted to implement `ProvidesBoundGlobal` for versions that are higher than the |
| 29 | /// maximum version you bind. When rustc gains the ability to constrain const parameters with |
| 30 | /// integer bounds (`where API_COMPAT_VERSION >= 5`), implementations of this trait should be |
| 31 | /// provided by specifying a lower bound for the compat version in order to avoid requiring version |
| 32 | /// updates be done in lock-step. |
| 33 | pub trait ProvidesBoundGlobal<I: Proxy, const API_COMPAT_VERSION: u32> { |
| 34 | fn bound_global(&self) -> Result<I, GlobalError>; |
| 35 | fn with_min_version(&self, version: u32) -> Result<I, GlobalError> { |
| 36 | let proxy: I = self.bound_global()?; |
| 37 | if proxy.version() < version { |
| 38 | Err(GlobalError::InvalidVersion { |
| 39 | name: I::interface().name, |
| 40 | required: version, |
| 41 | available: proxy.version(), |
| 42 | }) |
| 43 | } else { |
| 44 | Ok(proxy) |
| 45 | } |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | /// A struct used as the UserData field for globals bound by SCTK. |
| 50 | /// |
| 51 | /// This is used instead of `()` to allow multiple `Dispatch` impls on the same object. |
| 52 | #[derive (Debug)] |
| 53 | pub struct GlobalData; |
| 54 | |