Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Pointer/Touch/KeyboardHandle::with_grab() and downcasting #1567

Merged
merged 4 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/input/keyboard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate::backend::input::KeyState;
use crate::utils::{IsAlive, Serial, SERIAL_COUNTER};
use downcast_rs::{impl_downcast, Downcast};
use std::collections::HashSet;
#[cfg(feature = "wayland_frontend")]
use std::sync::RwLock;
Expand Down Expand Up @@ -590,7 +591,7 @@ impl<D: SeatHandler + 'static> Clone for GrabStartData<D> {
/// When your grab ends (either as you requested it or if it was forcefully cancelled by the server),
/// the struct implementing this trait will be dropped. As such you should put clean-up logic in the destructor,
/// rather than trying to guess when the grab will end.
pub trait KeyboardGrab<D: SeatHandler> {
pub trait KeyboardGrab<D: SeatHandler>: Downcast {
/// An input was reported.
///
/// `modifiers` are only passed when their state actually changes. The modifier must be
Expand Down Expand Up @@ -623,6 +624,8 @@ pub trait KeyboardGrab<D: SeatHandler> {
fn unset(&mut self, data: &mut D);
}

impl_downcast!(KeyboardGrab<D> where D: SeatHandler);

/// An handle to a keyboard handler
///
/// It can be cloned and all clones manipulate the same internal state.
Expand Down Expand Up @@ -918,6 +921,16 @@ impl<D: SeatHandler + 'static> KeyboardHandle<D> {
}
}

/// Calls `f` with the active grab, if any.
pub fn with_grab<T>(&self, f: impl FnOnce(Serial, &dyn KeyboardGrab<D>) -> T) -> Option<T> {
let guard = self.arc.internal.lock().unwrap();
if let GrabStatus::Active(s, g) = &guard.grab {
Some(f(*s, &**g))
} else {
None
}
}

/// Handle a keystroke
///
/// All keystrokes from the input backend should be fed _in order_ to this method of the
Expand Down
26 changes: 19 additions & 7 deletions src/input/pointer/grab.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::fmt;

use downcast_rs::{impl_downcast, Downcast};

use crate::{
backend::input::ButtonState,
input::SeatHandler,
Expand Down Expand Up @@ -32,7 +34,7 @@ use super::{
/// When your grab ends (either as you requested it or if it was forcefully cancelled by the server),
/// the struct implementing this trait will be dropped. As such you should put clean-up logic in the destructor,
/// rather than trying to guess when the grab will end.
pub trait PointerGrab<D: SeatHandler>: Send {
pub trait PointerGrab<D: SeatHandler>: Send + Downcast {
/// A motion was reported
///
/// This method allows you attach additional behavior to a motion event, possibly altering it.
Expand Down Expand Up @@ -170,6 +172,8 @@ pub trait PointerGrab<D: SeatHandler>: Send {
fn unset(&mut self, data: &mut D);
}

impl_downcast!(PointerGrab<D> where D: SeatHandler);

/// Data about the event that started the grab.
pub struct GrabStartData<D: SeatHandler> {
/// The focused surface and its location, if any, at the start of the grab.
Expand Down Expand Up @@ -332,15 +336,23 @@ impl<D: SeatHandler + 'static> PointerGrab<D> for DefaultGrab {
fn unset(&mut self, _data: &mut D) {}
}

// 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> {
/// 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.
pub struct ClickGrab<D: SeatHandler> {
start_data: GrabStartData<D>,
}

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

impl<D: SeatHandler + 'static> PointerGrab<D> for ClickGrab<D> {
fn motion(
&mut self,
Expand Down
12 changes: 11 additions & 1 deletion src/input/pointer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub use cursor_image::{CursorImageAttributes, CursorImageStatus, CursorImageSurf

mod grab;
use grab::DefaultGrab;
pub use grab::{GrabStartData, PointerGrab};
pub use grab::{ClickGrab, GrabStartData, PointerGrab};
use tracing::{info_span, instrument};

/// An handle to a pointer handler
Expand Down Expand Up @@ -207,6 +207,16 @@ impl<D: SeatHandler + 'static> PointerHandle<D> {
}
}

/// Calls `f` with the active grab, if any.
pub fn with_grab<T>(&self, f: impl FnOnce(Serial, &dyn PointerGrab<D>) -> T) -> Option<T> {
let guard = self.inner.lock().unwrap();
if let GrabStatus::Active(s, g) = &guard.grab {
Some(f(*s, &**g))
} else {
None
}
}

/// Notify that the pointer moved
///
/// You provide the new location of the pointer, in the form of:
Expand Down
6 changes: 5 additions & 1 deletion src/input/touch/grab.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::fmt;

use downcast_rs::{impl_downcast, Downcast};

use crate::{
backend::input::TouchSlot,
input::SeatHandler,
Expand Down Expand Up @@ -28,7 +30,7 @@ use super::{DownEvent, MotionEvent, OrientationEvent, ShapeEvent, TouchInnerHand
/// When your grab ends (either as you requested it or if it was forcefully cancelled by the server),
/// the struct implementing this trait will be dropped. As such you should put clean-up logic in the destructor,
/// rather than trying to guess when the grab will end.
pub trait TouchGrab<D: SeatHandler>: Send {
pub trait TouchGrab<D: SeatHandler>: Send + Downcast {
/// A new touch point appeared
///
/// This method allows you attach additional behavior to a down event, possibly altering it.
Expand Down Expand Up @@ -110,6 +112,8 @@ pub trait TouchGrab<D: SeatHandler>: Send {
fn unset(&mut self, data: &mut D);
}

impl_downcast!(TouchGrab<D> where D: SeatHandler);

/// Data about the event that started the grab.
pub struct GrabStartData<D: SeatHandler> {
/// The focused surface and its location, if any, at the start of the grab.
Expand Down
10 changes: 10 additions & 0 deletions src/input/touch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,16 @@ impl<D: SeatHandler + 'static> TouchHandle<D> {
}
}

/// Calls `f` with the active grab, if any.
pub fn with_grab<T>(&self, f: impl FnOnce(Serial, &dyn TouchGrab<D>) -> T) -> Option<T> {
let guard = self.inner.lock().unwrap();
if let GrabStatus::Active(s, g) = &guard.grab {
Some(f(*s, &**g))
} else {
None
}
}

/// Notify that a new touch point appeared
///
/// You provide the location of the touch, in the form of:
Expand Down
2 changes: 1 addition & 1 deletion src/wayland/input_method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ use crate::{
};

pub use input_method_handle::{InputMethodHandle, InputMethodUserData};
pub use input_method_keyboard_grab::InputMethodKeyboardUserData;
pub use input_method_keyboard_grab::{InputMethodKeyboardGrab, InputMethodKeyboardUserData};
pub use input_method_popup_surface::InputMethodPopupSurfaceUserData;

use super::text_input::TextInputHandle;
Expand Down
21 changes: 20 additions & 1 deletion src/wayland/selection/data_device/dnd_grab.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{
cell::RefCell,
fmt,
os::unix::io::{AsFd, OwnedFd},
sync::{Arc, Mutex},
};
Expand Down Expand Up @@ -32,7 +33,8 @@ use crate::{

use super::{with_source_metadata, ClientDndGrabHandler, DataDeviceHandler};

pub(crate) struct DnDGrab<D: SeatHandler> {
/// Grab during a client-initiated DnD operation.
pub struct DnDGrab<D: SeatHandler> {
dh: DisplayHandle,
pointer_start_data: Option<PointerGrabStartData<D>>,
touch_start_data: Option<TouchGrabStartData<D>>,
Expand All @@ -45,6 +47,23 @@ pub(crate) struct DnDGrab<D: SeatHandler> {
seat: Seat<D>,
}

impl<D: SeatHandler + 'static> fmt::Debug for DnDGrab<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DnDGrab")
.field("dh", &self.dh)
.field("pointer_start_data", &self.pointer_start_data)
.field("touch_start_data", &self.touch_start_data)
.field("data_source", &self.data_source)
.field("current_focus", &self.current_focus)
.field("pending_offers", &self.pending_offers)
.field("offer_data", &self.offer_data)
.field("icon", &self.icon)
.field("origin", &self.origin)
.field("seat", &self.seat)
.finish()
}
}

impl<D: SeatHandler> DnDGrab<D> {
pub(crate) fn new_pointer(
dh: &DisplayHandle,
Expand Down
2 changes: 2 additions & 0 deletions src/wayland/selection/data_device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ mod server_dnd_grab;
mod source;

pub use device::{DataDeviceUserData, DND_ICON_ROLE};
pub use dnd_grab::DnDGrab;
pub use server_dnd_grab::ServerDnDGrab;
pub use source::{with_source_metadata, DataSourceUserData, SourceMetadata};

use super::{
Expand Down
19 changes: 18 additions & 1 deletion src/wayland/selection/data_device/server_dnd_grab.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{
cell::RefCell,
fmt,
os::unix::io::OwnedFd,
sync::{Arc, Mutex},
};
Expand Down Expand Up @@ -33,7 +34,8 @@ use crate::{

use super::{DataDeviceHandler, DataDeviceUserData, ServerDndGrabHandler, SourceMetadata};

pub(crate) struct ServerDnDGrab<D: SeatHandler> {
/// Grab during a compositor-initiated DnD operation.
pub struct ServerDnDGrab<D: SeatHandler> {
dh: DisplayHandle,
pointer_start_data: Option<PointerGrabStartData<D>>,
touch_start_data: Option<TouchGrabStartData<D>>,
Expand All @@ -44,6 +46,21 @@ pub(crate) struct ServerDnDGrab<D: SeatHandler> {
seat: Seat<D>,
}

impl<D: SeatHandler + 'static> fmt::Debug for ServerDnDGrab<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ServerDnDGrab")
.field("dh", &self.dh)
.field("pointer_start_data", &self.pointer_start_data)
.field("touch_start_data", &self.touch_start_data)
.field("metadata", &self.metadata)
.field("current_focus", &self.current_focus)
.field("pending_offers", &self.pending_offers)
.field("offer_data", &self.offer_data)
.field("seat", &self.seat)
.finish()
}
}

impl<D: SeatHandler> ServerDnDGrab<D> {
pub(crate) fn new_pointer(
dh: &DisplayHandle,
Expand Down
Loading