Skip to content

Commit

Permalink
Make PointerTarget/KeyboardTarget object-safe; use in Anvil
Browse files Browse the repository at this point in the history
I've been thinking about how to simplify this code for a while.
Implementations of these traits become particularly verbose with a more
complicated shell like cosmic-comp:
https://github.com/pop-os/cosmic-comp/blob/master/src/shell/focus/target.rs.

It turns out it can be make object-safe, so we can have a `&dyn
PointerTarget`, if `PartialEq` and `Clone` requirements are moved out of
the trait itself.

I still wonder if it could be better to use enums for input events
instead of a million methods. Anyway, something to think about.

Leaving as a draft pending the other changes in input targets in
#1326.
  • Loading branch information
ids1024 committed Feb 16, 2024
1 parent 832dee8 commit 44173d9
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 101 deletions.
134 changes: 37 additions & 97 deletions anvil/src/focus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,73 +43,67 @@ impl From<FocusTarget> for WlSurface {
}
}

impl FocusTarget {
fn inner_keyboard_target<BackendData: Backend>(&self) -> &dyn KeyboardTarget<AnvilState<BackendData>> {
match self {
FocusTarget::Window(w) => w,
FocusTarget::LayerSurface(l) => l,
FocusTarget::Popup(p) => p.wl_surface(),
}
}

fn inner_pointer_target<BackendData: Backend>(&self) -> &dyn PointerTarget<AnvilState<BackendData>> {
match self {
FocusTarget::Window(w) => w,
FocusTarget::LayerSurface(l) => l,
FocusTarget::Popup(p) => p.wl_surface(),
}
}
}

impl<BackendData: Backend> PointerTarget<AnvilState<BackendData>> for FocusTarget {
fn enter(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &MotionEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::enter(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::enter(l, seat, data, event),
FocusTarget::Popup(p) => PointerTarget::enter(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().enter(seat, data, event)
}
fn motion(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &MotionEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::motion(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::motion(l, seat, data, event),
FocusTarget::Popup(p) => PointerTarget::motion(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().motion(seat, data, event)
}
fn relative_motion(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &RelativeMotionEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::relative_motion(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::relative_motion(l.wl_surface(), seat, data, event),
FocusTarget::Popup(p) => PointerTarget::relative_motion(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().relative_motion(seat, data, event)
}
fn button(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &ButtonEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::button(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::button(l, seat, data, event),
FocusTarget::Popup(p) => PointerTarget::button(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().button(seat, data, event)
}
fn axis(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
frame: AxisFrame,
) {
match self {
FocusTarget::Window(w) => PointerTarget::axis(w, seat, data, frame),
FocusTarget::LayerSurface(l) => PointerTarget::axis(l, seat, data, frame),
FocusTarget::Popup(p) => PointerTarget::axis(p.wl_surface(), seat, data, frame),
}
self.inner_pointer_target().axis(seat, data, frame)
}
fn frame(&self, seat: &Seat<AnvilState<BackendData>>, data: &mut AnvilState<BackendData>) {
match self {
FocusTarget::Window(w) => PointerTarget::frame(w, seat, data),
FocusTarget::LayerSurface(l) => PointerTarget::frame(l, seat, data),
FocusTarget::Popup(p) => PointerTarget::frame(p.wl_surface(), seat, data),
}
self.inner_pointer_target().frame(seat, data)
}
fn leave(
&self,
Expand All @@ -118,107 +112,71 @@ impl<BackendData: Backend> PointerTarget<AnvilState<BackendData>> for FocusTarge
serial: Serial,
time: u32,
) {
match self {
FocusTarget::Window(w) => PointerTarget::leave(w, seat, data, serial, time),
FocusTarget::LayerSurface(l) => PointerTarget::leave(l, seat, data, serial, time),
FocusTarget::Popup(p) => PointerTarget::leave(p.wl_surface(), seat, data, serial, time),
}
self.inner_pointer_target().leave(seat, data, serial, time)
}
fn gesture_swipe_begin(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &GestureSwipeBeginEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::gesture_swipe_begin(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::gesture_swipe_begin(l, seat, data, event),
FocusTarget::Popup(p) => PointerTarget::gesture_swipe_begin(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().gesture_swipe_begin(seat, data, event)
}
fn gesture_swipe_update(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &GestureSwipeUpdateEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::gesture_swipe_update(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::gesture_swipe_update(l, seat, data, event),
FocusTarget::Popup(p) => PointerTarget::gesture_swipe_update(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().gesture_swipe_update(seat, data, event)
}
fn gesture_swipe_end(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &GestureSwipeEndEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::gesture_swipe_end(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::gesture_swipe_end(l, seat, data, event),
FocusTarget::Popup(p) => PointerTarget::gesture_swipe_end(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().gesture_swipe_end(seat, data, event)
}
fn gesture_pinch_begin(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &GesturePinchBeginEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::gesture_pinch_begin(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::gesture_pinch_begin(l, seat, data, event),
FocusTarget::Popup(p) => PointerTarget::gesture_pinch_begin(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().gesture_pinch_begin(seat, data, event)
}
fn gesture_pinch_update(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &GesturePinchUpdateEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::gesture_pinch_update(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::gesture_pinch_update(l, seat, data, event),
FocusTarget::Popup(p) => PointerTarget::gesture_pinch_update(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().gesture_pinch_update(seat, data, event)
}
fn gesture_pinch_end(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &GesturePinchEndEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::gesture_pinch_end(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::gesture_pinch_end(l, seat, data, event),
FocusTarget::Popup(p) => PointerTarget::gesture_pinch_end(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().gesture_pinch_end(seat, data, event)
}
fn gesture_hold_begin(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &GestureHoldBeginEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::gesture_hold_begin(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::gesture_hold_begin(l, seat, data, event),
FocusTarget::Popup(p) => PointerTarget::gesture_hold_begin(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().gesture_hold_begin(seat, data, event)
}
fn gesture_hold_end(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
event: &GestureHoldEndEvent,
) {
match self {
FocusTarget::Window(w) => PointerTarget::gesture_hold_end(w, seat, data, event),
FocusTarget::LayerSurface(l) => PointerTarget::gesture_hold_end(l, seat, data, event),
FocusTarget::Popup(p) => PointerTarget::gesture_hold_end(p.wl_surface(), seat, data, event),
}
self.inner_pointer_target().gesture_hold_end(seat, data, event)
}
}

Expand All @@ -230,23 +188,15 @@ impl<BackendData: Backend> KeyboardTarget<AnvilState<BackendData>> for FocusTarg
keys: Vec<KeysymHandle<'_>>,
serial: Serial,
) {
match self {
FocusTarget::Window(w) => KeyboardTarget::enter(w, seat, data, keys, serial),
FocusTarget::LayerSurface(l) => KeyboardTarget::enter(l, seat, data, keys, serial),
FocusTarget::Popup(p) => KeyboardTarget::enter(p.wl_surface(), seat, data, keys, serial),
}
self.inner_keyboard_target().enter(seat, data, keys, serial)
}
fn leave(
&self,
seat: &Seat<AnvilState<BackendData>>,
data: &mut AnvilState<BackendData>,
serial: Serial,
) {
match self {
FocusTarget::Window(w) => KeyboardTarget::leave(w, seat, data, serial),
FocusTarget::LayerSurface(l) => KeyboardTarget::leave(l, seat, data, serial),
FocusTarget::Popup(p) => KeyboardTarget::leave(p.wl_surface(), seat, data, serial),
}
self.inner_keyboard_target().leave(seat, data, serial)
}
fn key(
&self,
Expand All @@ -257,13 +207,7 @@ impl<BackendData: Backend> KeyboardTarget<AnvilState<BackendData>> for FocusTarg
serial: Serial,
time: u32,
) {
match self {
FocusTarget::Window(w) => KeyboardTarget::key(w, seat, data, key, state, serial, time),
FocusTarget::LayerSurface(l) => KeyboardTarget::key(l, seat, data, key, state, serial, time),
FocusTarget::Popup(p) => {
KeyboardTarget::key(p.wl_surface(), seat, data, key, state, serial, time)
}
}
self.inner_keyboard_target().key(seat, data, key, state, serial, time)
}
fn modifiers(
&self,
Expand All @@ -272,11 +216,7 @@ impl<BackendData: Backend> KeyboardTarget<AnvilState<BackendData>> for FocusTarg
modifiers: ModifiersState,
serial: Serial,
) {
match self {
FocusTarget::Window(w) => KeyboardTarget::modifiers(w, seat, data, modifiers, serial),
FocusTarget::LayerSurface(l) => KeyboardTarget::modifiers(l, seat, data, modifiers, serial),
FocusTarget::Popup(p) => KeyboardTarget::modifiers(p.wl_surface(), seat, data, modifiers, serial),
}
self.inner_keyboard_target().modifiers(seat, data, modifiers, serial)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/input/keyboard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mod xkb_config;
pub use xkb_config::XkbConfig;

/// Trait representing object that can receive keyboard interactions
pub trait KeyboardTarget<D>: IsAlive + PartialEq + Clone + fmt::Debug + Send
pub trait KeyboardTarget<D>: IsAlive + fmt::Debug + Send
where
D: SeatHandler,
{
Expand Down
4 changes: 2 additions & 2 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ pub mod pointer;
/// Handler trait for Seats
pub trait SeatHandler: Sized {
/// Type used to represent the target currently holding the keyboard focus
type KeyboardFocus: KeyboardTarget<Self> + 'static;
type KeyboardFocus: KeyboardTarget<Self> + PartialEq + Clone + 'static;
/// Type used to represent the target currently holding the pointer focus
type PointerFocus: PointerTarget<Self> + 'static;
type PointerFocus: PointerTarget<Self> + PartialEq + Clone + 'static;

/// [SeatState] getter
fn seat_state(&mut self) -> &mut SeatState<Self>;
Expand Down
2 changes: 1 addition & 1 deletion src/input/pointer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl<D: SeatHandler> std::cmp::PartialEq for PointerHandle<D> {
impl<D: SeatHandler> std::cmp::Eq for PointerHandle<D> {}

/// Trait representing object that can receive pointer interactions
pub trait PointerTarget<D>: IsAlive + PartialEq + Clone + fmt::Debug + Send
pub trait PointerTarget<D>: IsAlive + fmt::Debug + Send
where
D: SeatHandler,
{
Expand Down

0 comments on commit 44173d9

Please sign in to comment.