Skip to content

Commit

Permalink
input: allow to override default touch grab
Browse files Browse the repository at this point in the history
the default touch grab will invoke the touch
down grab which will keep the focus on a single
surface. while this is a sane default downstream
might want to override this behavior.
  • Loading branch information
cmeissl committed Feb 18, 2024
1 parent a624a43 commit 54f4047
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 21 deletions.
22 changes: 20 additions & 2 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,15 @@ use std::{

use tracing::{info_span, instrument};

use self::pointer::{CursorImageStatus, PointerHandle, PointerTarget};
use self::touch::TouchTarget;
use self::{
keyboard::{Error as KeyboardError, KeyboardHandle, KeyboardTarget, LedState},
touch::TouchHandle,
};
use self::{
pointer::{CursorImageStatus, PointerHandle, PointerTarget},
touch::TouchGrab,
};
use crate::utils::user_data::UserDataMap;

pub mod keyboard;
Expand Down Expand Up @@ -592,8 +595,23 @@ impl<D: SeatHandler + 'static> Seat<D> {
/// let touch_handle = seat.add_touch();
/// ```
pub fn add_touch(&mut self) -> TouchHandle<D> {
Self::add_touch_with_default_grab(self, || Box::new(touch::DefaultGrab))
}

/// Adds the touch capability to this seat and allows the use of a custom default [`TouchGrab`]
///
/// The default grab is used in case no other grab is currently active. When using [`Seat::add_touch`]
/// it will use [`touch::DefaultGrab`] which will install [`touch::TouchDownGrab`] on the first touch point.
/// [`touch::TouchDownGrab`] makes sure all further touch points will use the same target until all touch
/// points are released again.
///
/// See [`Seat::add_touch`] for more information
pub fn add_touch_with_default_grab<F>(&mut self, defaut_grab: F) -> TouchHandle<D>
where
F: Fn() -> Box<dyn TouchGrab<D>> + Send + 'static,
{
let mut inner = self.arc.inner.lock().unwrap();
let touch = TouchHandle::new();
let touch = TouchHandle::new(defaut_grab);
if inner.touch.is_some() {
// If there's already a tocuh device, remove it notify the clients about the change.
inner.touch = None;
Expand Down
36 changes: 24 additions & 12 deletions src/input/touch/grab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,9 @@ impl<D> fmt::Debug for GrabStatus<D> {
}
}

// The default grab, the behavior when no particular grab is in progress
pub(super) struct DefaultGrab;
/// The default grab, the behavior when no particular grab is in progress
#[derive(Debug)]
pub struct DefaultGrab;

impl<D: SeatHandler + 'static> TouchGrab<D> for DefaultGrab {
fn down(
Expand All @@ -160,7 +161,7 @@ impl<D: SeatHandler + 'static> TouchGrab<D> for DefaultGrab {
handle.set_grab(
data,
event.serial,
ClickGrab {
TouchDownGrab {
start_data: GrabStartData {
focus,
slot: event.slot,
Expand Down Expand Up @@ -199,17 +200,28 @@ impl<D: SeatHandler + 'static> TouchGrab<D> for DefaultGrab {
}
}

// A click grab, basic grab started when an user clicks a surface
// to maintain it focused until the user releases the click.
//
// In case the user maintains several simultaneous clicks, release
// the grab once all are released.
struct ClickGrab<D: SeatHandler> {
start_data: GrabStartData<D>,
touch_points: usize,
/// A touch down grab, basic grab started when an user touches a surface
/// to maintain it focused until the user releases the touch.
///
/// In case the user maintains several simultaneous touch points, release
/// the grab once all are released.
pub struct TouchDownGrab<D: SeatHandler> {
/// Start date for this grab
pub start_data: GrabStartData<D>,
/// Currently active touch points
pub touch_points: usize,
}

impl<D: SeatHandler + 'static> fmt::Debug for TouchDownGrab<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TouchDownGrab")
.field("start_data", &self.start_data)
.field("touch_points", &self.touch_points)
.finish()
}
}

impl<D: SeatHandler + 'static> TouchGrab<D> for ClickGrab<D> {
impl<D: SeatHandler + 'static> TouchGrab<D> for TouchDownGrab<D> {
fn down(
&mut self,
data: &mut D,
Expand Down
24 changes: 17 additions & 7 deletions src/input/touch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use tracing::{info_span, instrument};
use crate::backend::input::TouchSlot;
use crate::utils::{IsAlive, Logical, Point, Serial, SerialCounter};

use self::grab::{DefaultGrab, GrabStatus};
pub use grab::{GrabStartData, TouchGrab};
use self::grab::GrabStatus;
pub use grab::{DefaultGrab, GrabStartData, TouchDownGrab, TouchGrab};

use super::{Seat, SeatHandler};

Expand Down Expand Up @@ -78,6 +78,7 @@ impl<D: SeatHandler> std::cmp::Eq for TouchHandle<D> {}
pub(crate) struct TouchInternal<D: SeatHandler> {
focus: HashMap<TouchSlot, TouchSlotState<D>>,
seq_counter: SerialCounter,
default_grab: Box<dyn Fn() -> Box<dyn TouchGrab<D>> + Send + 'static>,
grab: GrabStatus<D>,
}

Expand Down Expand Up @@ -210,9 +211,12 @@ where
}

impl<D: SeatHandler + 'static> TouchHandle<D> {
pub(crate) fn new() -> TouchHandle<D> {
pub(crate) fn new<F>(default_grab: F) -> TouchHandle<D>
where
F: Fn() -> Box<dyn TouchGrab<D>> + Send + 'static,
{
TouchHandle {
inner: Arc::new(Mutex::new(TouchInternal::new())),
inner: Arc::new(Mutex::new(TouchInternal::new(default_grab))),
#[cfg(feature = "wayland_frontend")]
known_instances: Arc::new(Mutex::new(Vec::new())),
span: info_span!("input_touch"),
Expand Down Expand Up @@ -449,10 +453,14 @@ impl<'a, D: SeatHandler + 'static> TouchInnerHandle<'a, D> {
}

impl<D: SeatHandler + 'static> TouchInternal<D> {
fn new() -> Self {
fn new<F>(default_grab: F) -> Self
where
F: Fn() -> Box<dyn TouchGrab<D>> + Send + 'static,
{
Self {
focus: Default::default(),
seq_counter: SerialCounter::new(),
default_grab: Box::new(default_grab),
grab: GrabStatus::None,
}
}
Expand Down Expand Up @@ -563,14 +571,16 @@ impl<D: SeatHandler + 'static> TouchInternal<D> {
if let Some((ref focus, _)) = handler.start_data().focus {
if !focus.alive() {
self.grab = GrabStatus::None;
f(&mut TouchInnerHandle { inner: self, seat }, &mut DefaultGrab);
let mut default_grab = (self.default_grab)();
f(&mut TouchInnerHandle { inner: self, seat }, &mut *default_grab);
return;
}
}
f(&mut TouchInnerHandle { inner: self, seat }, &mut **handler);
}
GrabStatus::None => {
f(&mut TouchInnerHandle { inner: self, seat }, &mut DefaultGrab);
let mut default_grab = (self.default_grab)();
f(&mut TouchInnerHandle { inner: self, seat }, &mut *default_grab);
}
}

Expand Down

0 comments on commit 54f4047

Please sign in to comment.