diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 43491d6b..89356b56 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -432,7 +432,7 @@ impl WlSeatGlobal { pub fn disable_pointer_constraint(&self) { if let Some(constraint) = self.constraint.get() { - constraint.deactivate(); + constraint.deactivate(true); if constraint.status.get() == SeatConstraintStatus::Inactive { constraint .status @@ -465,6 +465,7 @@ impl WlSeatGlobal { return; } candidate.status.set(SeatConstraintStatus::Active); + candidate.position_hint.take(); if let Some(owner) = candidate.owner.get() { owner.send_enabled(); } diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index 27f292f9..91d5eec5 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -526,7 +526,7 @@ impl WlSeatGlobal { let (x, y) = self.set_pointer_cursor_position(x, y); if let Some(c) = self.constraint.get() { if c.ty == ConstraintType::Lock || !c.contains(x.round_down(), y.round_down()) { - c.deactivate(); + c.deactivate(false); } } self.state.for_each_seat_tester(|t| { @@ -1285,7 +1285,7 @@ impl WlSeatGlobal { pub fn leave_surface(&self, n: &WlSurface) { let serial = n.client.next_serial(); for (_, constraint) in &n.constraints { - constraint.deactivate(); + constraint.deactivate(true); } self.surface_pointer_event(Version::ALL, n, |p| p.send_leave(serial, n.id)); self.surface_pointer_frame(n); diff --git a/src/ifs/wl_seat/zwp_pointer_constraints_v1.rs b/src/ifs/wl_seat/zwp_pointer_constraints_v1.rs index 52df6cf4..19051d79 100644 --- a/src/ifs/wl_seat/zwp_pointer_constraints_v1.rs +++ b/src/ifs/wl_seat/zwp_pointer_constraints_v1.rs @@ -61,12 +61,14 @@ pub struct SeatConstraint { pub one_shot: bool, pub status: Cell, pub ty: ConstraintType, + pub position_hint: Cell>, } impl SeatConstraint { - pub fn deactivate(&self) { + pub fn deactivate(&self, apply_position_hint: bool) { if self.status.get() == SeatConstraintStatus::Active { self.seat.constraint.take(); + self.handle_position_hint(apply_position_hint); if let Some(owner) = self.owner.get() { owner.send_disabled(); } @@ -78,6 +80,25 @@ impl SeatConstraint { } } + fn handle_position_hint(&self, apply: bool) { + let Some((x, y)) = self.position_hint.take() else { + return; + }; + if !apply { + return; + } + let buffer = self.surface.buffer_abs_pos.get(); + let (x_int, y_int) = buffer.translate_inv(x.round_down(), y.round_down()); + if !buffer.contains(x_int, y_int) { + return; + } + self.seat.motion_event_abs( + self.client.state.now_usec(), + x.apply_fract(x_int), + y.apply_fract(y_int), + ); + } + pub fn contains(&self, x: i32, y: i32) -> bool { let region = self.region.get(); if let Some(region) = region { @@ -119,7 +140,7 @@ impl SeatConstraint { } fn detach(&self) { - self.deactivate(); + self.deactivate(true); self.owner.take(); self.surface.constraints.remove(&self.seat.id); } @@ -221,6 +242,7 @@ impl ZwpPointerConstraintsV1 { one_shot, status: Cell::new(SeatConstraintStatus::Inactive), ty, + position_hint: Default::default(), })) } } diff --git a/src/ifs/wl_seat/zwp_pointer_constraints_v1/zwp_locked_pointer_v1.rs b/src/ifs/wl_seat/zwp_pointer_constraints_v1/zwp_locked_pointer_v1.rs index 64a5735f..51817c1d 100644 --- a/src/ifs/wl_seat/zwp_pointer_constraints_v1/zwp_locked_pointer_v1.rs +++ b/src/ifs/wl_seat/zwp_pointer_constraints_v1/zwp_locked_pointer_v1.rs @@ -30,9 +30,13 @@ impl ZwpLockedPointerV1RequestHandler for ZwpLockedPointerV1 { fn set_cursor_position_hint( &self, - _req: SetCursorPositionHint, + req: SetCursorPositionHint, _slf: &Rc, ) -> Result<(), Self::Error> { + let mut x = req.surface_x; + let mut y = req.surface_y; + client_wire_scale_to_logical!(self.constraint.client, x, y); + self.constraint.position_hint.set(Some((x, y))); Ok(()) } diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index eeb4c7b7..299199ad 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -1630,7 +1630,7 @@ impl WlSurface { pub fn detach_node(&self, set_invisible: bool) { for (_, constraint) in &self.constraints { - constraint.deactivate(); + constraint.deactivate(true); } for (_, inhibitor) in &self.idle_inhibitors { inhibitor.deactivate();