Refine Window::set_cursor_grab API

This commit renames `Window::set_cursor_grab` to
`Window::set_cursor_grab_mode`. The new API now accepts enumeration
to control the way cursor grab is performed. The value could be: `lock`,
`confine`, or `none`.

This commit also implements `Window::set_cursor_position` for Wayland,
since it's tied to locked cursor.

Implements API from #1677.
This commit is contained in:
Kirill Chibisov 2022-06-13 09:43:14 +03:00 committed by GitHub
parent 8ef9fe44c7
commit 9e6f666616
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 359 additions and 131 deletions

View file

@ -5,8 +5,9 @@ use std::rc::Rc;
use sctk::reexports::client::protocol::wl_surface::WlSurface;
use sctk::reexports::client::Attached;
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_pointer_constraints_v1::{ZwpPointerConstraintsV1};
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_pointer_constraints_v1::ZwpPointerConstraintsV1;
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_confined_pointer_v1::ZwpConfinedPointerV1;
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_locked_pointer_v1::ZwpLockedPointerV1;
use crate::event::{ModifiersState, TouchPhase};
@ -25,6 +26,7 @@ pub(super) struct PointerData {
pub pointer_constraints: Option<Attached<ZwpPointerConstraintsV1>>,
pub confined_pointer: Rc<RefCell<Option<ZwpConfinedPointerV1>>>,
pub locked_pointer: Rc<RefCell<Option<ZwpLockedPointerV1>>>,
/// Latest observed serial in pointer events.
pub latest_serial: Rc<Cell<u32>>,
@ -39,6 +41,7 @@ pub(super) struct PointerData {
impl PointerData {
pub fn new(
confined_pointer: Rc<RefCell<Option<ZwpConfinedPointerV1>>>,
locked_pointer: Rc<RefCell<Option<ZwpLockedPointerV1>>>,
pointer_constraints: Option<Attached<ZwpPointerConstraintsV1>>,
modifiers_state: Rc<RefCell<ModifiersState>>,
) -> Self {
@ -47,6 +50,7 @@ impl PointerData {
latest_serial: Rc::new(Cell::new(0)),
latest_enter_serial: Rc::new(Cell::new(0)),
confined_pointer,
locked_pointer,
modifiers_state,
pointer_constraints,
axis_data: AxisData::new(),

View file

@ -60,6 +60,7 @@ pub(super) fn handle_pointer(
let winit_pointer = WinitPointer {
pointer,
confined_pointer: Rc::downgrade(&pointer_data.confined_pointer),
locked_pointer: Rc::downgrade(&pointer_data.locked_pointer),
pointer_constraints: pointer_data.pointer_constraints.clone(),
latest_serial: pointer_data.latest_serial.clone(),
latest_enter_serial: pointer_data.latest_enter_serial.clone(),
@ -104,6 +105,7 @@ pub(super) fn handle_pointer(
let winit_pointer = WinitPointer {
pointer,
confined_pointer: Rc::downgrade(&pointer_data.confined_pointer),
locked_pointer: Rc::downgrade(&pointer_data.locked_pointer),
pointer_constraints: pointer_data.pointer_constraints.clone(),
latest_serial: pointer_data.latest_serial.clone(),
latest_enter_serial: pointer_data.latest_enter_serial.clone(),

View file

@ -11,6 +11,7 @@ use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_rela
use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_relative_pointer_v1::ZwpRelativePointerV1;
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_pointer_constraints_v1::{ZwpPointerConstraintsV1, Lifetime};
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_confined_pointer_v1::ZwpConfinedPointerV1;
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_locked_pointer_v1::ZwpLockedPointerV1;
use sctk::seat::pointer::{ThemeManager, ThemedPointer};
use sctk::window::Window;
@ -35,9 +36,13 @@ pub struct WinitPointer {
/// Cursor to handle confine requests.
confined_pointer: Weak<RefCell<Option<ZwpConfinedPointerV1>>>,
/// Cursor to handle locked requests.
locked_pointer: Weak<RefCell<Option<ZwpLockedPointerV1>>>,
/// Latest observed serial in pointer events.
/// used by Window::start_interactive_move()
latest_serial: Rc<Cell<u32>>,
/// Latest observed serial in pointer enter events.
/// used by Window::set_cursor()
latest_enter_serial: Rc<Cell<u32>>,
@ -157,6 +162,52 @@ impl WinitPointer {
}
}
pub fn lock(&self, surface: &WlSurface) {
let pointer_constraints = match &self.pointer_constraints {
Some(pointer_constraints) => pointer_constraints,
None => return,
};
let locked_pointer = match self.locked_pointer.upgrade() {
Some(locked_pointer) => locked_pointer,
// A pointer is gone.
None => return,
};
*locked_pointer.borrow_mut() = Some(init_locked_pointer(
pointer_constraints,
surface,
&*self.pointer,
));
}
pub fn unlock(&self) {
let locked_pointer = match self.locked_pointer.upgrade() {
Some(locked_pointer) => locked_pointer,
// A pointer is gone.
None => return,
};
let mut locked_pointer = locked_pointer.borrow_mut();
if let Some(locked_pointer) = locked_pointer.take() {
locked_pointer.destroy();
}
}
pub fn set_cursor_position(&self, surface_x: u32, surface_y: u32) {
let locked_pointer = match self.locked_pointer.upgrade() {
Some(locked_pointer) => locked_pointer,
// A pointer is gone.
None => return,
};
let locked_pointer = locked_pointer.borrow_mut();
if let Some(locked_pointer) = locked_pointer.as_ref() {
locked_pointer.set_cursor_position_hint(surface_x.into(), surface_y.into());
}
}
pub fn drag_window(&self, window: &Window<WinitFrame>) {
// WlPointer::setart_interactive_move() expects the last serial of *any*
// pointer event (compare to set_cursor()).
@ -174,6 +225,9 @@ pub(super) struct Pointers {
/// Confined pointer.
confined_pointer: Rc<RefCell<Option<ZwpConfinedPointerV1>>>,
/// Locked pointer.
locked_pointer: Rc<RefCell<Option<ZwpLockedPointerV1>>>,
}
impl Pointers {
@ -185,11 +239,15 @@ impl Pointers {
modifiers_state: Rc<RefCell<ModifiersState>>,
) -> Self {
let confined_pointer = Rc::new(RefCell::new(None));
let locked_pointer = Rc::new(RefCell::new(None));
let pointer_data = Rc::new(RefCell::new(PointerData::new(
confined_pointer.clone(),
locked_pointer.clone(),
pointer_constraints.clone(),
modifiers_state,
)));
let pointer_seat = seat.detach();
let pointer = theme_manager.theme_pointer_with_impl(
seat,
@ -216,6 +274,7 @@ impl Pointers {
pointer,
relative_pointer,
confined_pointer,
locked_pointer,
}
}
}
@ -232,6 +291,11 @@ impl Drop for Pointers {
confined_pointer.destroy();
}
// Drop lock ponter.
if let Some(locked_pointer) = self.locked_pointer.borrow_mut().take() {
locked_pointer.destroy();
}
// Drop the pointer itself in case it's possible.
if self.pointer.as_ref().version() >= 3 {
self.pointer.release();
@ -264,3 +328,16 @@ pub(super) fn init_confined_pointer(
confined_pointer.detach()
}
pub(super) fn init_locked_pointer(
pointer_constraints: &Attached<ZwpPointerConstraintsV1>,
surface: &WlSurface,
pointer: &WlPointer,
) -> ZwpLockedPointerV1 {
let locked_pointer =
pointer_constraints.lock_pointer(surface, pointer, None, Lifetime::Persistent);
locked_pointer.quick_assign(move |_, _, _| {});
locked_pointer.detach()
}