use wayland_client::{
globals::GlobalList,
protocol::{wl_pointer, wl_region, wl_surface},
Connection, Dispatch, QueueHandle,
};
use wayland_protocols::wp::pointer_constraints::zv1::client::{
zwp_confined_pointer_v1, zwp_locked_pointer_v1, zwp_pointer_constraints_v1,
};
use crate::{
dispatch2::Dispatch2,
error::GlobalError,
globals::{GlobalData, ProvidesBoundGlobal},
registry::GlobalProxy,
};
#[derive(Debug)]
pub struct PointerConstraintsState {
pointer_constraints: GlobalProxy<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1>,
}
impl PointerConstraintsState {
pub fn bind<D>(globals: &GlobalList, qh: &QueueHandle<D>) -> Self
where
D: Dispatch<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1, GlobalData> + 'static,
{
let pointer_constraints = GlobalProxy::from(globals.bind(qh, 1..=1, GlobalData));
Self { pointer_constraints }
}
pub fn confine_pointer<D>(
&self,
surface: &wl_surface::WlSurface,
pointer: &wl_pointer::WlPointer,
region: Option<&wl_region::WlRegion>,
lifetime: zwp_pointer_constraints_v1::Lifetime,
qh: &QueueHandle<D>,
) -> Result<zwp_confined_pointer_v1::ZwpConfinedPointerV1, GlobalError>
where
D: Dispatch<zwp_confined_pointer_v1::ZwpConfinedPointerV1, PointerConstraintData> + 'static,
{
let udata = PointerConstraintData { surface: surface.clone(), pointer: pointer.clone() };
Ok(self
.pointer_constraints
.get()?
.confine_pointer(surface, pointer, region, lifetime, qh, udata))
}
pub fn lock_pointer<D>(
&self,
surface: &wl_surface::WlSurface,
pointer: &wl_pointer::WlPointer,
region: Option<&wl_region::WlRegion>,
lifetime: zwp_pointer_constraints_v1::Lifetime,
qh: &QueueHandle<D>,
) -> Result<zwp_locked_pointer_v1::ZwpLockedPointerV1, GlobalError>
where
D: Dispatch<zwp_locked_pointer_v1::ZwpLockedPointerV1, PointerConstraintData> + 'static,
{
let udata = PointerConstraintData { surface: surface.clone(), pointer: pointer.clone() };
Ok(self
.pointer_constraints
.get()?
.lock_pointer(surface, pointer, region, lifetime, qh, udata))
}
}
impl ProvidesBoundGlobal<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1, 1>
for PointerConstraintsState
{
fn bound_global(
&self,
) -> Result<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1, GlobalError> {
self.pointer_constraints.get().cloned()
}
}
pub trait PointerConstraintsHandler: Sized {
fn confined(
&mut self,
conn: &Connection,
qh: &QueueHandle<Self>,
confined_pointer: &zwp_confined_pointer_v1::ZwpConfinedPointerV1,
surface: &wl_surface::WlSurface,
pointer: &wl_pointer::WlPointer,
);
fn unconfined(
&mut self,
conn: &Connection,
qh: &QueueHandle<Self>,
confined_pointer: &zwp_confined_pointer_v1::ZwpConfinedPointerV1,
surface: &wl_surface::WlSurface,
pointer: &wl_pointer::WlPointer,
);
fn locked(
&mut self,
conn: &Connection,
qh: &QueueHandle<Self>,
locked_pointer: &zwp_locked_pointer_v1::ZwpLockedPointerV1,
surface: &wl_surface::WlSurface,
pointer: &wl_pointer::WlPointer,
);
fn unlocked(
&mut self,
conn: &Connection,
qh: &QueueHandle<Self>,
locked_pointer: &zwp_locked_pointer_v1::ZwpLockedPointerV1,
surface: &wl_surface::WlSurface,
pointer: &wl_pointer::WlPointer,
);
}
#[doc(hidden)]
#[derive(Debug)]
pub struct PointerConstraintData {
surface: wl_surface::WlSurface,
pointer: wl_pointer::WlPointer,
}
impl<D> Dispatch2<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1, D> for GlobalData
where
D: PointerConstraintsHandler,
{
fn event(
&self,
_data: &mut D,
_constraints: &zwp_pointer_constraints_v1::ZwpPointerConstraintsV1,
_event: zwp_pointer_constraints_v1::Event,
_conn: &Connection,
_qh: &QueueHandle<D>,
) {
unreachable!()
}
}
impl<D> Dispatch2<zwp_confined_pointer_v1::ZwpConfinedPointerV1, D> for PointerConstraintData
where
D: PointerConstraintsHandler,
{
fn event(
&self,
data: &mut D,
confined_pointer: &zwp_confined_pointer_v1::ZwpConfinedPointerV1,
event: zwp_confined_pointer_v1::Event,
conn: &Connection,
qh: &QueueHandle<D>,
) {
match event {
zwp_confined_pointer_v1::Event::Confined => {
data.confined(conn, qh, confined_pointer, &self.surface, &self.pointer)
}
zwp_confined_pointer_v1::Event::Unconfined => {
data.unconfined(conn, qh, confined_pointer, &self.surface, &self.pointer)
}
_ => unreachable!(),
}
}
}
impl<D> Dispatch2<zwp_locked_pointer_v1::ZwpLockedPointerV1, D> for PointerConstraintData
where
D: PointerConstraintsHandler,
{
fn event(
&self,
data: &mut D,
locked_pointer: &zwp_locked_pointer_v1::ZwpLockedPointerV1,
event: zwp_locked_pointer_v1::Event,
conn: &Connection,
qh: &QueueHandle<D>,
) {
match event {
zwp_locked_pointer_v1::Event::Locked => {
data.locked(conn, qh, locked_pointer, &self.surface, &self.pointer)
}
zwp_locked_pointer_v1::Event::Unlocked => {
data.unlocked(conn, qh, locked_pointer, &self.surface, &self.pointer)
}
_ => unreachable!(),
}
}
}