| 1 | use wayland_client::{ |
| 2 | globals::GlobalList, |
| 3 | protocol::{wl_pointer, wl_region, wl_surface}, |
| 4 | Connection, Dispatch, QueueHandle, |
| 5 | }; |
| 6 | use wayland_protocols::wp::pointer_constraints::zv1::client::{ |
| 7 | zwp_confined_pointer_v1, zwp_locked_pointer_v1, zwp_pointer_constraints_v1, |
| 8 | }; |
| 9 | |
| 10 | use crate::{ |
| 11 | error::GlobalError, |
| 12 | globals::{GlobalData, ProvidesBoundGlobal}, |
| 13 | registry::GlobalProxy, |
| 14 | }; |
| 15 | |
| 16 | #[derive (Debug)] |
| 17 | pub struct PointerConstraintsState { |
| 18 | pointer_constraints: GlobalProxy<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1>, |
| 19 | } |
| 20 | |
| 21 | impl 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 | |
| 74 | impl 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 | |
| 84 | pub 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)] |
| 132 | pub struct PointerConstraintData { |
| 133 | surface: wl_surface::WlSurface, |
| 134 | pointer: wl_pointer::WlPointer, |
| 135 | } |
| 136 | |
| 137 | impl<D> Dispatch<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1, GlobalData, D> |
| 138 | for PointerConstraintsState |
| 139 | where |
| 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 | |
| 155 | impl<D> Dispatch<zwp_confined_pointer_v1::ZwpConfinedPointerV1, PointerConstraintData, D> |
| 156 | for PointerConstraintsState |
| 157 | where |
| 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 | |
| 181 | impl<D> Dispatch<zwp_locked_pointer_v1::ZwpLockedPointerV1, PointerConstraintData, D> |
| 182 | for PointerConstraintsState |
| 183 | where |
| 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 ] |
| 208 | macro_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 | |