smithay_client_toolkit/seat/
pointer_constraints.rs

1use wayland_client::{
2    globals::GlobalList,
3    protocol::{wl_pointer, wl_region, wl_surface},
4    Connection, Dispatch, QueueHandle,
5};
6use wayland_protocols::wp::pointer_constraints::zv1::client::{
7    zwp_confined_pointer_v1, zwp_locked_pointer_v1, zwp_pointer_constraints_v1,
8};
9
10use crate::{
11    error::GlobalError,
12    globals::{GlobalData, ProvidesBoundGlobal},
13    registry::GlobalProxy,
14};
15
16#[derive(Debug)]
17pub struct PointerConstraintsState {
18    pointer_constraints: GlobalProxy<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1>,
19}
20
21impl PointerConstraintsState {
22    /// Bind `zwp_pointer_constraints_v1` global, if it exists
23    pub fn bind<D>(globals: &GlobalList, qh: &QueueHandle<D>) -> Self
24    where
25        D: Dispatch<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1, GlobalData> + 'static,
26    {
27        let pointer_constraints = GlobalProxy::from(globals.bind(qh, 1..=1, GlobalData));
28        Self { pointer_constraints }
29    }
30
31    /// Request that the compositor confine the pointer to a region
32    ///
33    /// It is a protocol error to call when a constraint already exists for a pointer on the seat.
34    pub fn confine_pointer<D>(
35        &self,
36        surface: &wl_surface::WlSurface,
37        pointer: &wl_pointer::WlPointer,
38        region: Option<&wl_region::WlRegion>,
39        lifetime: zwp_pointer_constraints_v1::Lifetime,
40        qh: &QueueHandle<D>,
41    ) -> Result<zwp_confined_pointer_v1::ZwpConfinedPointerV1, GlobalError>
42    where
43        D: Dispatch<zwp_confined_pointer_v1::ZwpConfinedPointerV1, PointerConstraintData> + 'static,
44    {
45        let udata = PointerConstraintData { surface: surface.clone(), pointer: pointer.clone() };
46        Ok(self
47            .pointer_constraints
48            .get()?
49            .confine_pointer(surface, pointer, region, lifetime, qh, udata))
50    }
51
52    /// Request that the compositor lock the pointer in place
53    ///
54    /// It is a protocol error to call when a constraint already exists for a pointer on the seat.
55    pub fn lock_pointer<D>(
56        &self,
57        surface: &wl_surface::WlSurface,
58        pointer: &wl_pointer::WlPointer,
59        region: Option<&wl_region::WlRegion>,
60        lifetime: zwp_pointer_constraints_v1::Lifetime,
61        qh: &QueueHandle<D>,
62    ) -> Result<zwp_locked_pointer_v1::ZwpLockedPointerV1, GlobalError>
63    where
64        D: Dispatch<zwp_locked_pointer_v1::ZwpLockedPointerV1, PointerConstraintData> + 'static,
65    {
66        let udata = PointerConstraintData { surface: surface.clone(), pointer: pointer.clone() };
67        Ok(self
68            .pointer_constraints
69            .get()?
70            .lock_pointer(surface, pointer, region, lifetime, qh, udata))
71    }
72}
73
74impl ProvidesBoundGlobal<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1, 1>
75    for PointerConstraintsState
76{
77    fn bound_global(
78        &self,
79    ) -> Result<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1, GlobalError> {
80        self.pointer_constraints.get().cloned()
81    }
82}
83
84pub trait PointerConstraintsHandler: Sized {
85    /// Pointer confinement activated by compositor
86    fn confined(
87        &mut self,
88        conn: &Connection,
89        qh: &QueueHandle<Self>,
90        confined_pointer: &zwp_confined_pointer_v1::ZwpConfinedPointerV1,
91        surface: &wl_surface::WlSurface,
92        pointer: &wl_pointer::WlPointer,
93    );
94
95    /// Pointer confinement deactivated by compositor
96    ///
97    /// For `Oneshot` constraints, it will not be reactivated.
98    fn unconfined(
99        &mut self,
100        conn: &Connection,
101        qh: &QueueHandle<Self>,
102        confined_pointer: &zwp_confined_pointer_v1::ZwpConfinedPointerV1,
103        surface: &wl_surface::WlSurface,
104        pointer: &wl_pointer::WlPointer,
105    );
106
107    /// Pointer lock activated by compositor
108    fn locked(
109        &mut self,
110        conn: &Connection,
111        qh: &QueueHandle<Self>,
112        locked_pointer: &zwp_locked_pointer_v1::ZwpLockedPointerV1,
113        surface: &wl_surface::WlSurface,
114        pointer: &wl_pointer::WlPointer,
115    );
116
117    /// Pointer lock deactivated by compositor
118    ///
119    /// For `Oneshot` constraints, it will not be reactivated.
120    fn unlocked(
121        &mut self,
122        conn: &Connection,
123        qh: &QueueHandle<Self>,
124        locked_pointer: &zwp_locked_pointer_v1::ZwpLockedPointerV1,
125        surface: &wl_surface::WlSurface,
126        pointer: &wl_pointer::WlPointer,
127    );
128}
129
130#[doc(hidden)]
131#[derive(Debug)]
132pub struct PointerConstraintData {
133    surface: wl_surface::WlSurface,
134    pointer: wl_pointer::WlPointer,
135}
136
137impl<D> Dispatch<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1, GlobalData, D>
138    for PointerConstraintsState
139where
140    D: Dispatch<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1, GlobalData>
141        + PointerConstraintsHandler,
142{
143    fn event(
144        _data: &mut D,
145        _constraints: &zwp_pointer_constraints_v1::ZwpPointerConstraintsV1,
146        _event: zwp_pointer_constraints_v1::Event,
147        _: &GlobalData,
148        _conn: &Connection,
149        _qh: &QueueHandle<D>,
150    ) {
151        unreachable!()
152    }
153}
154
155impl<D> Dispatch<zwp_confined_pointer_v1::ZwpConfinedPointerV1, PointerConstraintData, D>
156    for PointerConstraintsState
157where
158    D: Dispatch<zwp_confined_pointer_v1::ZwpConfinedPointerV1, PointerConstraintData>
159        + PointerConstraintsHandler,
160{
161    fn event(
162        data: &mut D,
163        confined_pointer: &zwp_confined_pointer_v1::ZwpConfinedPointerV1,
164        event: zwp_confined_pointer_v1::Event,
165        udata: &PointerConstraintData,
166        conn: &Connection,
167        qh: &QueueHandle<D>,
168    ) {
169        match event {
170            zwp_confined_pointer_v1::Event::Confined => {
171                data.confined(conn, qh, confined_pointer, &udata.surface, &udata.pointer)
172            }
173            zwp_confined_pointer_v1::Event::Unconfined => {
174                data.unconfined(conn, qh, confined_pointer, &udata.surface, &udata.pointer)
175            }
176            _ => unreachable!(),
177        }
178    }
179}
180
181impl<D> Dispatch<zwp_locked_pointer_v1::ZwpLockedPointerV1, PointerConstraintData, D>
182    for PointerConstraintsState
183where
184    D: Dispatch<zwp_locked_pointer_v1::ZwpLockedPointerV1, PointerConstraintData>
185        + PointerConstraintsHandler,
186{
187    fn event(
188        data: &mut D,
189        locked_pointer: &zwp_locked_pointer_v1::ZwpLockedPointerV1,
190        event: zwp_locked_pointer_v1::Event,
191        udata: &PointerConstraintData,
192        conn: &Connection,
193        qh: &QueueHandle<D>,
194    ) {
195        match event {
196            zwp_locked_pointer_v1::Event::Locked => {
197                data.locked(conn, qh, locked_pointer, &udata.surface, &udata.pointer)
198            }
199            zwp_locked_pointer_v1::Event::Unlocked => {
200                data.unlocked(conn, qh, locked_pointer, &udata.surface, &udata.pointer)
201            }
202            _ => unreachable!(),
203        }
204    }
205}
206
207#[macro_export]
208macro_rules! delegate_pointer_constraints {
209    ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
210        $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
211            $crate::reexports::protocols::wp::pointer_constraints::zv1::client::zwp_pointer_constraints_v1::ZwpPointerConstraintsV1: $crate::globals::GlobalData
212        ] => $crate::seat::pointer_constraints::PointerConstraintsState);
213        $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
214            $crate::reexports::protocols::wp::pointer_constraints::zv1::client::zwp_confined_pointer_v1::ZwpConfinedPointerV1: $crate::seat::pointer_constraints::PointerConstraintData
215        ] => $crate::seat::pointer_constraints::PointerConstraintsState);
216        $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
217            $crate::reexports::protocols::wp::pointer_constraints::zv1::client::zwp_locked_pointer_v1::ZwpLockedPointerV1: $crate::seat::pointer_constraints::PointerConstraintData
218        ] => $crate::seat::pointer_constraints::PointerConstraintsState);
219    };
220}