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