mirror of
https://github.com/Smithay/smithay.git
synced 2024-09-28 03:21:14 +02:00
add pointer location hint (#1551)
Some checks failed
Continuous Integration / format (push) Has been cancelled
Continuous Integration / clippy-check (push) Has been cancelled
Continuous Integration / smithay-check-features (push) Has been cancelled
Continuous Integration / check-msrv (push) Has been cancelled
Continuous Integration / check-minimal (push) Has been cancelled
Continuous Integration / smithay-tests (push) Has been cancelled
Continuous Integration / smallvil-check (push) Has been cancelled
Continuous Integration / anvil-check-features (push) Has been cancelled
Continuous Integration / WLCS: Bad Buffer Test (push) Has been cancelled
Continuous Integration / WLCS: Core tests (push) Has been cancelled
Continuous Integration / WLCS: Output tests (push) Has been cancelled
Continuous Integration / WLCS: Pointer input tests (push) Has been cancelled
Continuous Integration / Documentation on Github Pages (push) Has been cancelled
Some checks failed
Continuous Integration / format (push) Has been cancelled
Continuous Integration / clippy-check (push) Has been cancelled
Continuous Integration / smithay-check-features (push) Has been cancelled
Continuous Integration / check-msrv (push) Has been cancelled
Continuous Integration / check-minimal (push) Has been cancelled
Continuous Integration / smithay-tests (push) Has been cancelled
Continuous Integration / smallvil-check (push) Has been cancelled
Continuous Integration / anvil-check-features (push) Has been cancelled
Continuous Integration / WLCS: Bad Buffer Test (push) Has been cancelled
Continuous Integration / WLCS: Core tests (push) Has been cancelled
Continuous Integration / WLCS: Output tests (push) Has been cancelled
Continuous Integration / WLCS: Pointer input tests (push) Has been cancelled
Continuous Integration / Documentation on Github Pages (push) Has been cancelled
* add pointer location hint * describe why `PointerConstraint::commit()` returns a point * implement pointer location hint in anvil * set_location_hint -> set_location * add note that you should frequently be using `PointerHandle::motion`
This commit is contained in:
parent
3b0ecce6c1
commit
debffed7ec
3 changed files with 84 additions and 9 deletions
|
@ -365,6 +365,29 @@ impl<BackendData: Backend> PointerConstraintsHandler for AnvilState<BackendData>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cursor_position_hint(
|
||||||
|
&mut self,
|
||||||
|
surface: &WlSurface,
|
||||||
|
pointer: &PointerHandle<Self>,
|
||||||
|
location: Point<f64, Logical>,
|
||||||
|
) {
|
||||||
|
if with_pointer_constraint(surface, pointer, |constraint| {
|
||||||
|
constraint.map_or(false, |c| c.is_active())
|
||||||
|
}) {
|
||||||
|
let origin = self
|
||||||
|
.space
|
||||||
|
.elements()
|
||||||
|
.find_map(|window| {
|
||||||
|
(window.wl_surface().as_deref() == Some(surface)).then(|| window.geometry())
|
||||||
|
})
|
||||||
|
.unwrap_or_default()
|
||||||
|
.loc
|
||||||
|
.to_f64();
|
||||||
|
|
||||||
|
pointer.set_location(origin + location);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
delegate_pointer_constraints!(@<BackendData: Backend + 'static> AnvilState<BackendData>);
|
delegate_pointer_constraints!(@<BackendData: Backend + 'static> AnvilState<BackendData>);
|
||||||
|
|
||||||
|
|
|
@ -435,6 +435,26 @@ impl<D: SeatHandler + 'static> PointerHandle<D> {
|
||||||
self.inner.lock().unwrap().location
|
self.inner.lock().unwrap().location
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the current location of this pointer in the global space,
|
||||||
|
/// without sending any event and without updating the focus.
|
||||||
|
///
|
||||||
|
/// If you want to update the location, and update the focus,
|
||||||
|
/// and send events, use [Self::motion] instead of this.
|
||||||
|
///
|
||||||
|
/// This is useful when the pointer is only moved by relative events,
|
||||||
|
/// such as when a pointer lock is held by the focused surface.
|
||||||
|
/// The client can give us a cursor position hint, which corresponds to
|
||||||
|
/// the actual location the client may be rendering a pointer at.
|
||||||
|
/// This position hint should be used as the initial location
|
||||||
|
/// when the pointer lock is deactivated.
|
||||||
|
///
|
||||||
|
/// The next time [Self::motion] is called, the focus will be
|
||||||
|
/// updated accordingly as if this function was never called.
|
||||||
|
/// Clients will never be notified of a location hint.
|
||||||
|
pub fn set_location(&self, location: Point<f64, Logical>) {
|
||||||
|
self.inner.lock().unwrap().location = location;
|
||||||
|
}
|
||||||
|
|
||||||
/// Access the [`Serial`] of the last `pointer_enter` event, if that focus is still active.
|
/// Access the [`Serial`] of the last `pointer_enter` event, if that focus is still active.
|
||||||
///
|
///
|
||||||
/// In other words this will return `None` again, once a `pointer_leave` event occurred.
|
/// In other words this will return `None` again, once a `pointer_leave` event occurred.
|
||||||
|
|
|
@ -36,6 +36,18 @@ pub trait PointerConstraintsHandler: SeatHandler {
|
||||||
///
|
///
|
||||||
/// Use [`with_pointer_constraint`] to access the constraint.
|
/// Use [`with_pointer_constraint`] to access the constraint.
|
||||||
fn new_constraint(&mut self, surface: &WlSurface, pointer: &PointerHandle<Self>);
|
fn new_constraint(&mut self, surface: &WlSurface, pointer: &PointerHandle<Self>);
|
||||||
|
|
||||||
|
/// The client holding a LockedPointer has commited a cursor position hint.
|
||||||
|
///
|
||||||
|
/// This is emitted upon a surface commit if the cursor position hint has been updated.
|
||||||
|
///
|
||||||
|
/// Use [`with_pointer_constraint`] to access the constraint and check if it is active.
|
||||||
|
fn cursor_position_hint(
|
||||||
|
&mut self,
|
||||||
|
surface: &WlSurface,
|
||||||
|
pointer: &PointerHandle<Self>,
|
||||||
|
location: Point<f64, Logical>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constraint confining pointer to a region of the surface
|
/// Constraint confining pointer to a region of the surface
|
||||||
|
@ -171,14 +183,19 @@ impl PointerConstraint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit(&mut self) {
|
/// Commits the pending state of the constraint, and returns the cursor position hint if it has changed.
|
||||||
|
fn commit(&mut self) -> Option<Point<f64, Logical>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Confined(confined) => {
|
Self::Confined(confined) => {
|
||||||
confined.region.clone_from(&confined.pending_region);
|
confined.region.clone_from(&confined.pending_region);
|
||||||
|
None
|
||||||
}
|
}
|
||||||
Self::Locked(locked) => {
|
Self::Locked(locked) => {
|
||||||
locked.region.clone_from(&locked.pending_region);
|
locked.region.clone_from(&locked.pending_region);
|
||||||
locked.cursor_position_hint = locked.pending_cursor_position_hint;
|
locked.pending_cursor_position_hint.take().map(|hint| {
|
||||||
|
locked.cursor_position_hint = Some(hint);
|
||||||
|
hint
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,13 +260,28 @@ pub fn with_pointer_constraint<
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit_hook<D: SeatHandler + 'static>(_: &mut D, _dh: &DisplayHandle, surface: &WlSurface) {
|
fn commit_hook<D: SeatHandler + PointerConstraintsHandler + 'static>(
|
||||||
with_constraint_data::<D, _, _>(surface, |data| {
|
state: &mut D,
|
||||||
|
_dh: &DisplayHandle,
|
||||||
|
surface: &WlSurface,
|
||||||
|
) {
|
||||||
|
// `with_constraint_data` locks the pointer constraints,
|
||||||
|
// so we collect the hints first into a Vec, then release the mutex
|
||||||
|
// and only once the mutex is released, we call the handler method.
|
||||||
|
//
|
||||||
|
// This is to avoid deadlocks when the handler method might try to access the constraints again.
|
||||||
|
// It's not a hypothetical, it bit me while implementing the position hint functionality.
|
||||||
|
let position_hints = with_constraint_data::<D, _, _>(surface, |data| {
|
||||||
let data = data.unwrap();
|
let data = data.unwrap();
|
||||||
for constraint in data.constraints.values_mut() {
|
data.constraints
|
||||||
constraint.commit();
|
.iter_mut()
|
||||||
}
|
.filter_map(|(pointer, constraint)| constraint.commit().map(|hint| (pointer.clone(), hint)))
|
||||||
})
|
.collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
|
||||||
|
for (pointer, hint) in position_hints {
|
||||||
|
state.cursor_position_hint(surface, &pointer, hint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get `PointerConstraintData` associated with a surface, if any.
|
/// Get `PointerConstraintData` associated with a surface, if any.
|
||||||
|
@ -272,7 +304,7 @@ fn with_constraint_data<
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add constraint for surface, or raise protocol error if one exists
|
/// Add constraint for surface, or raise protocol error if one exists
|
||||||
fn add_constraint<D: SeatHandler + 'static>(
|
fn add_constraint<D: SeatHandler + PointerConstraintsHandler + 'static>(
|
||||||
pointer_constraints: &ZwpPointerConstraintsV1,
|
pointer_constraints: &ZwpPointerConstraintsV1,
|
||||||
surface: &WlSurface,
|
surface: &WlSurface,
|
||||||
pointer: &PointerHandle<D>,
|
pointer: &PointerHandle<D>,
|
||||||
|
|
Loading…
Reference in a new issue