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