From ee24971c6d8ad4657409d4dc545418990de511eb Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Sat, 27 Apr 2024 17:56:14 +0200 Subject: [PATCH] wayland: implement pointer-gestures-unstable-v1 --- docs/features.md | 1 + release-notes.md | 1 + src/backend.rs | 40 +++ src/backends/metal/input.rs | 80 ++++++ src/cli/seat_test.rs | 117 ++++++++- src/globals.rs | 2 + src/ifs/jay_seat_events.rs | 98 +++++++ src/ifs/wl_seat.rs | 26 +- src/ifs/wl_seat/event_handling.rs | 234 ++++++++++++++++- src/ifs/wl_seat/gesture_owner.rs | 239 ++++++++++++++++++ .../wl_seat/zwp_pointer_gesture_hold_v1.rs | 74 ++++++ .../wl_seat/zwp_pointer_gesture_pinch_v1.rs | 93 +++++++ .../wl_seat/zwp_pointer_gesture_swipe_v1.rs | 84 ++++++ src/ifs/wl_seat/zwp_pointer_gestures_v1.rs | 135 ++++++++++ src/ifs/wl_surface.rs | 40 +++ src/libinput/event.rs | 80 +++++- src/libinput/sys.rs | 15 ++ src/tree.rs | 60 +++++ src/utils/bindings.rs | 52 +++- wire/jay_seat_events.txt | 56 ++++ wire/zwp_pointer_gesture_hold_v1.txt | 16 ++ wire/zwp_pointer_gesture_pinch_v1.txt | 24 ++ wire/zwp_pointer_gesture_swipe_v1.txt | 22 ++ wire/zwp_pointer_gestures_v1.txt | 18 ++ 24 files changed, 1589 insertions(+), 18 deletions(-) create mode 100644 src/ifs/wl_seat/gesture_owner.rs create mode 100644 src/ifs/wl_seat/zwp_pointer_gesture_hold_v1.rs create mode 100644 src/ifs/wl_seat/zwp_pointer_gesture_pinch_v1.rs create mode 100644 src/ifs/wl_seat/zwp_pointer_gesture_swipe_v1.rs create mode 100644 src/ifs/wl_seat/zwp_pointer_gestures_v1.rs create mode 100644 wire/zwp_pointer_gesture_hold_v1.txt create mode 100644 wire/zwp_pointer_gesture_pinch_v1.txt create mode 100644 wire/zwp_pointer_gesture_swipe_v1.txt create mode 100644 wire/zwp_pointer_gestures_v1.txt diff --git a/docs/features.md b/docs/features.md index 7942b959..b49073b5 100644 --- a/docs/features.md +++ b/docs/features.md @@ -162,6 +162,7 @@ Jay supports the following wayland protocols: | zwp_input_method_manager_v2 | 1 | Yes | | zwp_linux_dmabuf_v1 | 5 | | | zwp_pointer_constraints_v1 | 1 | | +| zwp_pointer_gestures_v1 | 3 | | | zwp_primary_selection_device_manager_v1 | 1 | | | zwp_relative_pointer_manager_v1 | 1 | | | zwp_text_input_manager_v3 | 1 | | diff --git a/release-notes.md b/release-notes.md index 5652ff38..2a4396d9 100644 --- a/release-notes.md +++ b/release-notes.md @@ -5,6 +5,7 @@ - Add support for ext-transient-seat-v1. - Add support for wp-drm-lease-v1. - Focus-follows-mouse can now be disabled. +- Add support for pointer-gestures-unstable-v1. # 1.1.0 (2024-04-22) diff --git a/src/backend.rs b/src/backend.rs index 1bee5779..e688a402 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -272,6 +272,46 @@ pub enum InputEvent { AxisFrame { time_usec: u64, }, + SwipeBegin { + time_usec: u64, + finger_count: u32, + }, + SwipeUpdate { + time_usec: u64, + dx: Fixed, + dy: Fixed, + dx_unaccelerated: Fixed, + dy_unaccelerated: Fixed, + }, + SwipeEnd { + time_usec: u64, + cancelled: bool, + }, + PinchBegin { + time_usec: u64, + finger_count: u32, + }, + PinchUpdate { + time_usec: u64, + dx: Fixed, + dy: Fixed, + dx_unaccelerated: Fixed, + dy_unaccelerated: Fixed, + scale: Fixed, + rotation: Fixed, + }, + PinchEnd { + time_usec: u64, + cancelled: bool, + }, + HoldBegin { + time_usec: u64, + finger_count: u32, + }, + HoldEnd { + time_usec: u64, + cancelled: bool, + }, } pub enum DrmEvent { diff --git a/src/backends/metal/input.rs b/src/backends/metal/input.rs index 0f168bf7..c73bab8e 100644 --- a/src/backends/metal/input.rs +++ b/src/backends/metal/input.rs @@ -91,6 +91,14 @@ impl MetalBackend { c::LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS => { self.handle_pointer_axis(event, AxisSource::Continuous) } + c::LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN => self.handle_gesture_swipe_begin(event), + c::LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE => self.handle_gesture_swipe_update(event), + c::LIBINPUT_EVENT_GESTURE_SWIPE_END => self.handle_gesture_swipe_end(event), + c::LIBINPUT_EVENT_GESTURE_PINCH_BEGIN => self.handle_gesture_pinch_begin(event), + c::LIBINPUT_EVENT_GESTURE_PINCH_UPDATE => self.handle_gesture_pinch_update(event), + c::LIBINPUT_EVENT_GESTURE_PINCH_END => self.handle_gesture_pinch_end(event), + c::LIBINPUT_EVENT_GESTURE_HOLD_BEGIN => self.handle_gesture_hold_begin(event), + c::LIBINPUT_EVENT_GESTURE_HOLD_END => self.handle_gesture_hold_end(event), _ => {} } } @@ -217,4 +225,76 @@ impl MetalBackend { dy_unaccelerated: Fixed::from_f64(dy_unaccelerated), }); } + + fn handle_gesture_swipe_begin(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, gesture_event); + dev.event(InputEvent::SwipeBegin { + time_usec: event.time_usec(), + finger_count: event.finger_count(), + }); + } + + fn handle_gesture_swipe_update(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, gesture_event); + dev.event(InputEvent::SwipeUpdate { + time_usec: event.time_usec(), + dx: Fixed::from_f64(event.dx()), + dy: Fixed::from_f64(event.dy()), + dx_unaccelerated: Fixed::from_f64(event.dx_unaccelerated()), + dy_unaccelerated: Fixed::from_f64(event.dy_unaccelerated()), + }); + } + + fn handle_gesture_swipe_end(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, gesture_event); + dev.event(InputEvent::SwipeEnd { + time_usec: event.time_usec(), + cancelled: event.cancelled(), + }); + } + + fn handle_gesture_pinch_begin(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, gesture_event); + dev.event(InputEvent::PinchBegin { + time_usec: event.time_usec(), + finger_count: event.finger_count(), + }); + } + + fn handle_gesture_pinch_update(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, gesture_event); + dev.event(InputEvent::PinchUpdate { + time_usec: event.time_usec(), + dx: Fixed::from_f64(event.dx()), + dy: Fixed::from_f64(event.dy()), + dx_unaccelerated: Fixed::from_f64(event.dx_unaccelerated()), + dy_unaccelerated: Fixed::from_f64(event.dy_unaccelerated()), + scale: Fixed::from_f64(event.scale()), + rotation: Fixed::from_f64(event.angle_delta()), + }); + } + + fn handle_gesture_pinch_end(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, gesture_event); + dev.event(InputEvent::PinchEnd { + time_usec: event.time_usec(), + cancelled: event.cancelled(), + }); + } + + fn handle_gesture_hold_begin(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, gesture_event); + dev.event(InputEvent::HoldBegin { + time_usec: event.time_usec(), + finger_count: event.finger_count(), + }); + } + + fn handle_gesture_hold_end(self: &Rc, event: LibInputEvent) { + let (event, dev) = unpack!(self, event, gesture_event); + dev.event(InputEvent::HoldEnd { + time_usec: event.time_usec(), + cancelled: event.cancelled(), + }); + } } diff --git a/src/cli/seat_test.rs b/src/cli/seat_test.rs index 431e01a6..d948279d 100644 --- a/src/cli/seat_test.rs +++ b/src/cli/seat_test.rs @@ -6,8 +6,9 @@ use { wire::{ jay_compositor::{GetSeats, Seat, SeatEvents}, jay_seat_events::{ - Axis120, AxisFrame, AxisInverted, AxisPx, AxisSource, AxisStop, Button, Key, - Modifiers, PointerAbs, PointerRel, + Axis120, AxisFrame, AxisInverted, AxisPx, AxisSource, AxisStop, Button, HoldBegin, + HoldEnd, Key, Modifiers, PinchBegin, PinchEnd, PinchUpdate, PointerAbs, PointerRel, + SwipeBegin, SwipeEnd, SwipeUpdate, }, }, }, @@ -211,6 +212,118 @@ async fn run(seat_test: Rc) { println!(); } }); + let st = seat_test.clone(); + SwipeBegin::handle(tc, se, (), move |_, ev| { + if all || ev.seat == seat { + if all { + print!("Seat: {}, ", st.name(ev.seat)); + } + println!( + "Time: {:.4}, Swipe Begin: {} fingers", + time(ev.time_usec), + ev.fingers, + ); + } + }); + let st = seat_test.clone(); + SwipeUpdate::handle(tc, se, (), move |_, ev| { + if all || ev.seat == seat { + if all { + print!("Seat: {}, ", st.name(ev.seat)); + } + println!( + "Time: {:.4}, Swipe Update: {}x{}, Unaccelerated: {}x{}", + time(ev.time_usec), + ev.dx, + ev.dy, + ev.dx_unaccelerated, + ev.dy_unaccelerated, + ); + } + }); + let st = seat_test.clone(); + SwipeEnd::handle(tc, se, (), move |_, ev| { + if all || ev.seat == seat { + if all { + print!("Seat: {}, ", st.name(ev.seat)); + } + print!("Time: {:.4}, Swipe End", time(ev.time_usec),); + if ev.cancelled != 0 { + print!(", cancelled"); + } + println!(); + } + }); + let st = seat_test.clone(); + PinchBegin::handle(tc, se, (), move |_, ev| { + if all || ev.seat == seat { + if all { + print!("Seat: {}, ", st.name(ev.seat)); + } + println!( + "Time: {:.4}, Pinch Begin: {} fingers", + time(ev.time_usec), + ev.fingers, + ); + } + }); + let st = seat_test.clone(); + PinchUpdate::handle(tc, se, (), move |_, ev| { + if all || ev.seat == seat { + if all { + print!("Seat: {}, ", st.name(ev.seat)); + } + println!( + "Time: {:.4}, Pinch Update: {}x{}, Unaccelerated: {}x{}, Scale: {}, Rotation: {}", + time(ev.time_usec), + ev.dx, + ev.dy, + ev.dx_unaccelerated, + ev.dy_unaccelerated, + ev.scale, + ev.rotation, + ); + } + }); + let st = seat_test.clone(); + PinchEnd::handle(tc, se, (), move |_, ev| { + if all || ev.seat == seat { + if all { + print!("Seat: {}, ", st.name(ev.seat)); + } + print!("Time: {:.4}, Pinch End", time(ev.time_usec)); + if ev.cancelled != 0 { + print!(", cancelled"); + } + println!(); + } + }); + let st = seat_test.clone(); + HoldBegin::handle(tc, se, (), move |_, ev| { + if all || ev.seat == seat { + if all { + print!("Seat: {}, ", st.name(ev.seat)); + } + println!( + "Time: {:.4}, Hold Begin: {} fingers", + time(ev.time_usec), + ev.fingers, + ); + } + }); + let st = seat_test.clone(); + HoldEnd::handle(tc, se, (), move |_, ev| { + if all || ev.seat == seat { + if all { + print!("Seat: {}, ", st.name(ev.seat)); + } + print!("Time: {:.4}, Hold End", time(ev.time_usec)); + if ev.cancelled != 0 { + print!(", cancelled"); + } + println!(); + } + }); pending::<()>().await; } diff --git a/src/globals.rs b/src/globals.rs index 41aeb925..8fef5937 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -23,6 +23,7 @@ use { zwp_text_input_manager_v3::ZwpTextInputManagerV3Global, }, zwp_pointer_constraints_v1::ZwpPointerConstraintsV1Global, + zwp_pointer_gestures_v1::ZwpPointerGesturesV1Global, zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1Global, zwp_virtual_keyboard_manager_v1::ZwpVirtualKeyboardManagerV1Global, WlSeatGlobal, @@ -192,6 +193,7 @@ impl Globals { add_singleton!(WpSecurityContextManagerV1Global); add_singleton!(XdgWmDialogV1Global); add_singleton!(ExtTransientSeatManagerV1Global); + add_singleton!(ZwpPointerGesturesV1Global); } pub fn add_backend_singletons(&self, backend: &Rc) { diff --git a/src/ifs/jay_seat_events.rs b/src/ifs/jay_seat_events.rs index 36a1ae62..4d3fac6c 100644 --- a/src/ifs/jay_seat_events.rs +++ b/src/ifs/jay_seat_events.rs @@ -122,6 +122,104 @@ impl JaySeatEvents { time_usec, }); } + + pub fn send_swipe_begin(&self, seat: SeatId, time_usec: u64, finger_count: u32) { + self.client.event(SwipeBegin { + self_id: self.id, + seat: seat.raw(), + time_usec, + fingers: finger_count, + }); + } + + pub fn send_swipe_update( + &self, + seat: SeatId, + time_usec: u64, + dx: Fixed, + dy: Fixed, + dx_unaccelerated: Fixed, + dy_unaccelerated: Fixed, + ) { + self.client.event(SwipeUpdate { + self_id: self.id, + seat: seat.raw(), + time_usec, + dx, + dy, + dx_unaccelerated, + dy_unaccelerated, + }); + } + + pub fn send_swipe_end(&self, seat: SeatId, time_usec: u64, cancelled: bool) { + self.client.event(SwipeEnd { + self_id: self.id, + seat: seat.raw(), + time_usec, + cancelled: cancelled as _, + }); + } + + pub fn send_pinch_begin(&self, seat: SeatId, time_usec: u64, finger_count: u32) { + self.client.event(PinchBegin { + self_id: self.id, + seat: seat.raw(), + time_usec, + fingers: finger_count, + }); + } + + pub fn send_pinch_update( + &self, + seat: SeatId, + time_usec: u64, + dx: Fixed, + dy: Fixed, + dx_unaccelerated: Fixed, + dy_unaccelerated: Fixed, + scale: Fixed, + rotation: Fixed, + ) { + self.client.event(PinchUpdate { + self_id: self.id, + seat: seat.raw(), + time_usec, + dx, + dy, + dx_unaccelerated, + dy_unaccelerated, + scale, + rotation, + }); + } + + pub fn send_pinch_end(&self, seat: SeatId, time_usec: u64, cancelled: bool) { + self.client.event(PinchEnd { + self_id: self.id, + seat: seat.raw(), + time_usec, + cancelled: cancelled as _, + }); + } + + pub fn send_hold_begin(&self, seat: SeatId, time_usec: u64, finger_count: u32) { + self.client.event(HoldBegin { + self_id: self.id, + seat: seat.raw(), + time_usec, + fingers: finger_count, + }); + } + + pub fn send_hold_end(&self, seat: SeatId, time_usec: u64, cancelled: bool) { + self.client.event(HoldEnd { + self_id: self.id, + seat: seat.raw(), + time_usec, + cancelled: cancelled as _, + }); + } } impl JaySeatEventsRequestHandler for JaySeatEvents { diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index eae653fa..42591b8b 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -1,6 +1,7 @@ mod event_handling; pub mod ext_transient_seat_manager_v1; pub mod ext_transient_seat_v1; +mod gesture_owner; mod kb_owner; mod pointer_owner; pub mod text_input; @@ -8,6 +9,10 @@ pub mod wl_keyboard; pub mod wl_pointer; pub mod wl_touch; pub mod zwp_pointer_constraints_v1; +pub mod zwp_pointer_gesture_hold_v1; +pub mod zwp_pointer_gesture_pinch_v1; +pub mod zwp_pointer_gesture_swipe_v1; +pub mod zwp_pointer_gestures_v1; pub mod zwp_relative_pointer_manager_v1; pub mod zwp_relative_pointer_v1; pub mod zwp_virtual_keyboard_manager_v1; @@ -37,6 +42,7 @@ use { DynDataSource, IpcError, }, wl_seat::{ + gesture_owner::GestureOwnerHolder, kb_owner::KbOwnerHolder, pointer_owner::PointerOwnerHolder, text_input::{ @@ -47,6 +53,9 @@ use { wl_pointer::WlPointer, wl_touch::WlTouch, zwp_pointer_constraints_v1::{SeatConstraint, SeatConstraintStatus}, + zwp_pointer_gesture_hold_v1::ZwpPointerGestureHoldV1, + zwp_pointer_gesture_pinch_v1::ZwpPointerGesturePinchV1, + zwp_pointer_gesture_swipe_v1::ZwpPointerGestureSwipeV1, zwp_relative_pointer_v1::ZwpRelativePointerV1, }, wl_surface::WlSurface, @@ -62,9 +71,9 @@ use { Node, OutputNode, ToplevelNode, WorkspaceNode, }, utils::{ - asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap, - errorfmt::ErrorFmt, linkedlist::LinkedNode, numcell::NumCell, rc_eq::rc_eq, - smallmap::SmallMap, transform_ext::TransformExt, + asyncevent::AsyncEvent, bindings::PerClientBindings, clonecell::CloneCell, + copyhashmap::CopyHashMap, errorfmt::ErrorFmt, linkedlist::LinkedNode, numcell::NumCell, + rc_eq::rc_eq, smallmap::SmallMap, transform_ext::TransformExt, }, wire::{ wl_seat::*, ExtIdleNotificationV1Id, WlDataDeviceId, WlKeyboardId, WlPointerId, @@ -164,6 +173,7 @@ pub struct WlSeatGlobal { primary_selection_serial: Cell, pointer_owner: PointerOwnerHolder, kb_owner: KbOwnerHolder, + gesture_owner: GestureOwnerHolder, dropped_dnd: RefCell>, shortcuts: RefCell>>, queue_link: Cell>>>, @@ -182,6 +192,9 @@ pub struct WlSeatGlobal { input_method_grab: CloneCell>>, forward: Cell, focus_follows_mouse: Cell, + swipe_bindings: PerClientBindings, + pinch_bindings: PerClientBindings, + hold_bindings: PerClientBindings, } const CHANGE_CURSOR_MOVED: u32 = 1 << 0; @@ -233,6 +246,7 @@ impl WlSeatGlobal { primary_selection_serial: Cell::new(0), pointer_owner: Default::default(), kb_owner: Default::default(), + gesture_owner: Default::default(), dropped_dnd: RefCell::new(None), shortcuts: Default::default(), queue_link: Cell::new(None), @@ -252,6 +266,9 @@ impl WlSeatGlobal { input_method_grab: Default::default(), forward: Cell::new(false), focus_follows_mouse: Cell::new(true), + swipe_bindings: Default::default(), + pinch_bindings: Default::default(), + hold_bindings: Default::default(), }); state.add_cursor_size(*DEFAULT_CURSOR_SIZE); let seat = slf.clone(); @@ -1081,6 +1098,9 @@ impl WlSeatGlobal { self.text_input.take(); self.input_method.take(); self.input_method_grab.take(); + self.swipe_bindings.clear(); + self.pinch_bindings.clear(); + self.hold_bindings.clear(); } pub fn id(&self) -> SeatId { diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index 4dc90780..9c6bdc12 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -49,6 +49,7 @@ use { pub struct NodeSeatState { pointer_foci: SmallMap, 1>, kb_foci: SmallMap, 1>, + gesture_foci: SmallMap, 1>, pointer_grabs: SmallMap, 1>, dnd_targets: SmallMap, 1>, } @@ -72,6 +73,14 @@ impl NodeSeatState { self.kb_foci.len() == 0 } + pub(super) fn gesture_begin(&self, seat: &Rc) { + self.gesture_foci.insert(seat.id, seat.clone()); + } + + pub(super) fn gesture_end(&self, seat: &WlSeatGlobal) { + self.gesture_foci.remove(&seat.id); + } + pub(super) fn add_pointer_grab(&self, seat: &Rc) { self.pointer_grabs.insert(seat.id, seat.clone()); } @@ -130,6 +139,9 @@ impl NodeSeatState { fn destroy_node2(&self, node: &dyn Node, focus_last: bool) { // NOTE: Also called by set_visible(false) + while let Some((_, seat)) = self.gesture_foci.pop() { + seat.gesture_owner.revert_to_default(&seat); + } while let Some((_, seat)) = self.pointer_grabs.pop() { seat.pointer_owner.revert_to_default(&seat); } @@ -180,7 +192,15 @@ impl WlSeatGlobal { | InputEvent::ConnectorPosition { time_usec, .. } | InputEvent::Motion { time_usec, .. } | InputEvent::Button { time_usec, .. } - | InputEvent::AxisFrame { time_usec, .. } => { + | InputEvent::AxisFrame { time_usec, .. } + | InputEvent::SwipeBegin { time_usec, .. } + | InputEvent::SwipeUpdate { time_usec, .. } + | InputEvent::SwipeEnd { time_usec, .. } + | InputEvent::PinchBegin { time_usec, .. } + | InputEvent::PinchUpdate { time_usec, .. } + | InputEvent::PinchEnd { time_usec, .. } + | InputEvent::HoldBegin { time_usec, .. } + | InputEvent::HoldEnd { time_usec, .. } => { self.last_input_usec.set(time_usec); if self.idle_notifications.is_not_empty() { for (_, notification) in self.idle_notifications.lock().drain() { @@ -231,6 +251,54 @@ impl WlSeatGlobal { } => self.pointer_owner.axis_px(dist, axis, inverted), InputEvent::AxisStop { axis } => self.pointer_owner.axis_stop(axis), InputEvent::AxisFrame { time_usec } => self.pointer_owner.frame(dev, self, time_usec), + InputEvent::SwipeBegin { + time_usec, + finger_count, + } => self.swipe_begin(time_usec, finger_count), + InputEvent::SwipeUpdate { + time_usec, + dx, + dy, + dx_unaccelerated, + dy_unaccelerated, + } => self.swipe_update(time_usec, dx, dy, dx_unaccelerated, dy_unaccelerated), + InputEvent::SwipeEnd { + time_usec, + cancelled, + } => self.swipe_end(time_usec, cancelled), + InputEvent::PinchBegin { + time_usec, + finger_count, + } => self.pinch_begin(time_usec, finger_count), + InputEvent::PinchUpdate { + time_usec, + dx, + dy, + dx_unaccelerated, + dy_unaccelerated, + scale, + rotation, + } => self.pinch_update( + time_usec, + dx, + dy, + dx_unaccelerated, + dy_unaccelerated, + scale, + rotation, + ), + InputEvent::PinchEnd { + time_usec, + cancelled, + } => self.pinch_end(time_usec, cancelled), + InputEvent::HoldBegin { + time_usec, + finger_count, + } => self.hold_begin(time_usec, finger_count), + InputEvent::HoldEnd { + time_usec, + cancelled, + } => self.hold_end(time_usec, cancelled), } } @@ -345,6 +413,97 @@ impl WlSeatGlobal { self.pointer_owner.button(self, time_usec, button, state); } + fn swipe_begin(self: &Rc, time_usec: u64, finger_count: u32) { + self.state.for_each_seat_tester(|t| { + t.send_swipe_begin(self.id, time_usec, finger_count); + }); + self.gesture_owner + .swipe_begin(self, time_usec, finger_count) + } + + fn swipe_update( + self: &Rc, + time_usec: u64, + dx: Fixed, + dy: Fixed, + dx_unaccelerated: Fixed, + dy_unaccelerated: Fixed, + ) { + self.state.for_each_seat_tester(|t| { + t.send_swipe_update( + self.id, + time_usec, + dx, + dy, + dx_unaccelerated, + dy_unaccelerated, + ); + }); + self.gesture_owner.swipe_update(self, time_usec, dx, dy) + } + + fn swipe_end(self: &Rc, time_usec: u64, cancelled: bool) { + self.state.for_each_seat_tester(|t| { + t.send_swipe_end(self.id, time_usec, cancelled); + }); + self.gesture_owner.swipe_end(self, time_usec, cancelled) + } + + fn pinch_begin(self: &Rc, time_usec: u64, finger_count: u32) { + self.state.for_each_seat_tester(|t| { + t.send_pinch_begin(self.id, time_usec, finger_count); + }); + self.gesture_owner + .pinch_begin(self, time_usec, finger_count) + } + + fn pinch_update( + self: &Rc, + time_usec: u64, + dx: Fixed, + dy: Fixed, + dx_unaccelerated: Fixed, + dy_unaccelerated: Fixed, + scale: Fixed, + rotation: Fixed, + ) { + self.state.for_each_seat_tester(|t| { + t.send_pinch_update( + self.id, + time_usec, + dx, + dy, + dx_unaccelerated, + dy_unaccelerated, + scale, + rotation, + ); + }); + self.gesture_owner + .pinch_update(self, time_usec, dx, dy, scale, rotation) + } + + fn pinch_end(self: &Rc, time_usec: u64, cancelled: bool) { + self.state.for_each_seat_tester(|t| { + t.send_pinch_end(self.id, time_usec, cancelled); + }); + self.gesture_owner.pinch_end(self, time_usec, cancelled) + } + + fn hold_begin(self: &Rc, time_usec: u64, finger_count: u32) { + self.state.for_each_seat_tester(|t| { + t.send_hold_begin(self.id, time_usec, finger_count); + }); + self.gesture_owner.hold_begin(self, time_usec, finger_count) + } + + fn hold_end(self: &Rc, time_usec: u64, cancelled: bool) { + self.state.for_each_seat_tester(|t| { + t.send_hold_end(self.id, time_usec, cancelled); + }); + self.gesture_owner.hold_end(self, time_usec, cancelled) + } + pub(super) fn key_event( self: &Rc, time_usec: u64, @@ -935,3 +1094,76 @@ impl WlSeatGlobal { // surface.client.flush(); } } + +// Gesture callbacks +impl WlSeatGlobal { + pub fn swipe_begin_surface(&self, n: &WlSurface, time_usec: u64, finger_count: u32) { + let serial = n.client.next_serial(); + self.swipe_bindings + .for_each(n.client.id, Version::ALL, |obj| { + obj.send_swipe_begin(n, serial, time_usec, finger_count) + }) + } + + pub fn swipe_update_surface(&self, n: &WlSurface, time_usec: u64, dx: Fixed, dy: Fixed) { + self.swipe_bindings + .for_each(n.client.id, Version::ALL, |obj| { + obj.send_swipe_update(time_usec, dx, dy) + }) + } + + pub fn swipe_end_surface(&self, n: &WlSurface, time_usec: u64, cancelled: bool) { + let serial = n.client.next_serial(); + self.swipe_bindings + .for_each(n.client.id, Version::ALL, |obj| { + obj.send_swipe_end(serial, time_usec, cancelled) + }) + } + + pub fn pinch_begin_surface(&self, n: &WlSurface, time_usec: u64, finger_count: u32) { + let serial = n.client.next_serial(); + self.pinch_bindings + .for_each(n.client.id, Version::ALL, |obj| { + obj.send_pinch_begin(n, serial, time_usec, finger_count) + }) + } + + pub fn pinch_update_surface( + &self, + n: &WlSurface, + time_usec: u64, + dx: Fixed, + dy: Fixed, + scale: Fixed, + rotation: Fixed, + ) { + self.pinch_bindings + .for_each(n.client.id, Version::ALL, |obj| { + obj.send_pinch_update(time_usec, dx, dy, scale, rotation) + }) + } + + pub fn pinch_end_surface(&self, n: &WlSurface, time_usec: u64, cancelled: bool) { + let serial = n.client.next_serial(); + self.pinch_bindings + .for_each(n.client.id, Version::ALL, |obj| { + obj.send_pinch_end(serial, time_usec, cancelled) + }) + } + + pub fn hold_begin_surface(&self, n: &WlSurface, time_usec: u64, finger_count: u32) { + let serial = n.client.next_serial(); + self.hold_bindings + .for_each(n.client.id, Version::ALL, |obj| { + obj.send_hold_begin(n, serial, time_usec, finger_count) + }) + } + + pub fn hold_end_surface(&self, n: &WlSurface, time_usec: u64, cancelled: bool) { + let serial = n.client.next_serial(); + self.hold_bindings + .for_each(n.client.id, Version::ALL, |obj| { + obj.send_hold_end(serial, time_usec, cancelled) + }) + } +} diff --git a/src/ifs/wl_seat/gesture_owner.rs b/src/ifs/wl_seat/gesture_owner.rs new file mode 100644 index 00000000..43f275c0 --- /dev/null +++ b/src/ifs/wl_seat/gesture_owner.rs @@ -0,0 +1,239 @@ +use { + crate::{ + fixed::Fixed, ifs::wl_seat::WlSeatGlobal, time::now_usec, tree::Node, + utils::clonecell::CloneCell, + }, + std::rc::Rc, +}; + +pub struct GestureOwnerHolder { + default: Rc, + owner: CloneCell>, +} + +impl Default for GestureOwnerHolder { + fn default() -> Self { + let default = Rc::new(NoGesture); + Self { + owner: CloneCell::new(default.clone()), + default, + } + } +} + +impl GestureOwnerHolder { + pub fn revert_to_default(&self, seat: &Rc) { + self.owner.get().revert_to_default(seat); + self.set_default_owner(); + } + + pub fn swipe_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + self.owner.get().swipe_begin(seat, time_usec, finger_count) + } + + pub fn swipe_update(&self, seat: &Rc, time_usec: u64, dx: Fixed, dy: Fixed) { + self.owner.get().swipe_update(seat, time_usec, dx, dy) + } + + pub fn swipe_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + self.owner.get().swipe_end(seat, time_usec, cancelled) + } + + pub fn pinch_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + self.owner.get().pinch_begin(seat, time_usec, finger_count) + } + + pub fn pinch_update( + &self, + seat: &Rc, + time_usec: u64, + dx: Fixed, + dy: Fixed, + scale: Fixed, + rotation: Fixed, + ) { + self.owner + .get() + .pinch_update(seat, time_usec, dx, dy, scale, rotation) + } + + pub fn pinch_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + self.owner.get().pinch_end(seat, time_usec, cancelled) + } + + pub fn hold_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + self.owner.get().hold_begin(seat, time_usec, finger_count) + } + + pub fn hold_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + self.owner.get().hold_end(seat, time_usec, cancelled) + } + + fn set_default_owner(&self) { + self.owner.set(self.default.clone()); + } +} + +trait GestureOwner { + fn revert_to_default(&self, seat: &Rc); + + fn swipe_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + let _ = seat; + let _ = time_usec; + let _ = finger_count; + } + + fn swipe_update(&self, seat: &Rc, time_usec: u64, dx: Fixed, dy: Fixed) { + let _ = seat; + let _ = time_usec; + let _ = dx; + let _ = dy; + } + + fn swipe_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + let _ = seat; + let _ = time_usec; + let _ = cancelled; + } + + fn pinch_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + let _ = seat; + let _ = time_usec; + let _ = finger_count; + } + + fn pinch_update( + &self, + seat: &Rc, + time_usec: u64, + dx: Fixed, + dy: Fixed, + scale: Fixed, + rotation: Fixed, + ) { + let _ = seat; + let _ = time_usec; + let _ = dx; + let _ = dy; + let _ = scale; + let _ = rotation; + } + + fn pinch_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + let _ = seat; + let _ = time_usec; + let _ = cancelled; + } + + fn hold_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + let _ = seat; + let _ = time_usec; + let _ = finger_count; + } + + fn hold_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + let _ = seat; + let _ = time_usec; + let _ = cancelled; + } +} + +struct NoGesture; + +impl GestureOwner for NoGesture { + fn revert_to_default(&self, seat: &Rc) { + let _ = seat; + } + + fn swipe_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + let Some(node) = seat.pointer_node() else { + return; + }; + node.node_seat_state().gesture_begin(seat); + node.node_on_swipe_begin(seat, time_usec, finger_count); + seat.gesture_owner.owner.set(Rc::new(SwipeGesture { node })); + } + + fn pinch_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + let Some(node) = seat.pointer_node() else { + return; + }; + node.node_seat_state().gesture_begin(seat); + node.node_on_pinch_begin(seat, time_usec, finger_count); + seat.gesture_owner.owner.set(Rc::new(PinchGesture { node })); + } + + fn hold_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + let Some(node) = seat.pointer_node() else { + return; + }; + node.node_seat_state().gesture_begin(seat); + node.node_on_hold_begin(seat, time_usec, finger_count); + seat.gesture_owner.owner.set(Rc::new(HoldGesture { node })); + } +} + +struct SwipeGesture { + node: Rc, +} + +impl GestureOwner for SwipeGesture { + fn revert_to_default(&self, seat: &Rc) { + self.swipe_end(seat, now_usec(), true); + } + + fn swipe_update(&self, seat: &Rc, time_usec: u64, dx: Fixed, dy: Fixed) { + self.node.node_on_swipe_update(seat, time_usec, dx, dy); + } + + fn swipe_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + self.node.node_on_swipe_end(seat, time_usec, cancelled); + self.node.node_seat_state().gesture_end(seat); + seat.gesture_owner.set_default_owner(); + } +} + +struct PinchGesture { + node: Rc, +} + +impl GestureOwner for PinchGesture { + fn revert_to_default(&self, seat: &Rc) { + self.pinch_end(seat, now_usec(), true); + } + + fn pinch_update( + &self, + seat: &Rc, + time_usec: u64, + dx: Fixed, + dy: Fixed, + scale: Fixed, + rotation: Fixed, + ) { + self.node + .node_on_pinch_update(seat, time_usec, dx, dy, scale, rotation) + } + + fn pinch_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + self.node.node_on_pinch_end(seat, time_usec, cancelled); + self.node.node_seat_state().gesture_end(seat); + seat.gesture_owner.set_default_owner(); + } +} + +struct HoldGesture { + node: Rc, +} + +impl GestureOwner for HoldGesture { + fn revert_to_default(&self, seat: &Rc) { + self.hold_end(seat, now_usec(), true); + } + + fn hold_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + self.node.node_on_hold_end(seat, time_usec, cancelled); + self.node.node_seat_state().gesture_end(seat); + seat.gesture_owner.set_default_owner(); + } +} diff --git a/src/ifs/wl_seat/zwp_pointer_gesture_hold_v1.rs b/src/ifs/wl_seat/zwp_pointer_gesture_hold_v1.rs new file mode 100644 index 00000000..2f29f124 --- /dev/null +++ b/src/ifs/wl_seat/zwp_pointer_gesture_hold_v1.rs @@ -0,0 +1,74 @@ +use { + crate::{ + client::{Client, ClientError}, + ifs::{wl_seat::WlSeatGlobal, wl_surface::WlSurface}, + leaks::Tracker, + object::{Object, Version}, + wire::{zwp_pointer_gesture_hold_v1::*, ZwpPointerGestureHoldV1Id}, + }, + std::rc::Rc, + thiserror::Error, +}; + +pub struct ZwpPointerGestureHoldV1 { + pub id: ZwpPointerGestureHoldV1Id, + pub client: Rc, + pub seat: Rc, + pub tracker: Tracker, + pub version: Version, +} + +impl ZwpPointerGestureHoldV1 { + fn detach(&self) { + self.seat.hold_bindings.remove(&self.client, self); + } + + pub fn send_hold_begin(&self, n: &WlSurface, serial: u32, time_usec: u64, finger_count: u32) { + self.client.event(Begin { + self_id: self.id, + serial, + time: (time_usec / 1000) as u32, + surface: n.id, + fingers: finger_count, + }); + } + + pub fn send_hold_end(&self, serial: u32, time_usec: u64, cancelled: bool) { + self.client.event(End { + self_id: self.id, + serial, + time: (time_usec / 1000) as u32, + cancelled: cancelled as _, + }); + } +} + +impl ZwpPointerGestureHoldV1RequestHandler for ZwpPointerGestureHoldV1 { + type Error = ZwpPointerGestureHoldV1Error; + + fn destroy(&self, _req: Destroy, _slf: &Rc) -> Result<(), Self::Error> { + self.detach(); + self.client.remove_obj(self)?; + Ok(()) + } +} + +object_base! { + self = ZwpPointerGestureHoldV1; + version = self.version; +} + +impl Object for ZwpPointerGestureHoldV1 { + fn break_loops(&self) { + self.detach(); + } +} + +simple_add_obj!(ZwpPointerGestureHoldV1); + +#[derive(Debug, Error)] +pub enum ZwpPointerGestureHoldV1Error { + #[error(transparent)] + ClientError(Box), +} +efrom!(ZwpPointerGestureHoldV1Error, ClientError); diff --git a/src/ifs/wl_seat/zwp_pointer_gesture_pinch_v1.rs b/src/ifs/wl_seat/zwp_pointer_gesture_pinch_v1.rs new file mode 100644 index 00000000..7c592d6b --- /dev/null +++ b/src/ifs/wl_seat/zwp_pointer_gesture_pinch_v1.rs @@ -0,0 +1,93 @@ +use { + crate::{ + client::{Client, ClientError}, + fixed::Fixed, + ifs::{wl_seat::WlSeatGlobal, wl_surface::WlSurface}, + leaks::Tracker, + object::{Object, Version}, + wire::{zwp_pointer_gesture_pinch_v1::*, ZwpPointerGesturePinchV1Id}, + }, + std::rc::Rc, + thiserror::Error, +}; + +pub struct ZwpPointerGesturePinchV1 { + pub id: ZwpPointerGesturePinchV1Id, + pub client: Rc, + pub seat: Rc, + pub tracker: Tracker, + pub version: Version, +} + +impl ZwpPointerGesturePinchV1 { + fn detach(&self) { + self.seat.pinch_bindings.remove(&self.client, self); + } + + pub fn send_pinch_begin(&self, n: &WlSurface, serial: u32, time_usec: u64, finger_count: u32) { + self.client.event(Begin { + self_id: self.id, + serial, + time: (time_usec / 1000) as u32, + surface: n.id, + fingers: finger_count, + }); + } + + pub fn send_pinch_update( + &self, + time_usec: u64, + dx: Fixed, + dy: Fixed, + scale: Fixed, + rotation: Fixed, + ) { + self.client.event(Update { + self_id: self.id, + time: (time_usec / 1000) as u32, + dx, + dy, + scale, + rotation, + }); + } + + pub fn send_pinch_end(&self, serial: u32, time_usec: u64, cancelled: bool) { + self.client.event(End { + self_id: self.id, + serial, + time: (time_usec / 1000) as u32, + cancelled: cancelled as _, + }); + } +} + +impl ZwpPointerGesturePinchV1RequestHandler for ZwpPointerGesturePinchV1 { + type Error = ZwpPointerGesturePinchV1Error; + + fn destroy(&self, _req: Destroy, _slf: &Rc) -> Result<(), Self::Error> { + self.detach(); + self.client.remove_obj(self)?; + Ok(()) + } +} + +object_base! { + self = ZwpPointerGesturePinchV1; + version = self.version; +} + +impl Object for ZwpPointerGesturePinchV1 { + fn break_loops(&self) { + self.detach(); + } +} + +simple_add_obj!(ZwpPointerGesturePinchV1); + +#[derive(Debug, Error)] +pub enum ZwpPointerGesturePinchV1Error { + #[error(transparent)] + ClientError(Box), +} +efrom!(ZwpPointerGesturePinchV1Error, ClientError); diff --git a/src/ifs/wl_seat/zwp_pointer_gesture_swipe_v1.rs b/src/ifs/wl_seat/zwp_pointer_gesture_swipe_v1.rs new file mode 100644 index 00000000..b8b8a198 --- /dev/null +++ b/src/ifs/wl_seat/zwp_pointer_gesture_swipe_v1.rs @@ -0,0 +1,84 @@ +use { + crate::{ + client::{Client, ClientError}, + fixed::Fixed, + ifs::{wl_seat::WlSeatGlobal, wl_surface::WlSurface}, + leaks::Tracker, + object::{Object, Version}, + wire::{zwp_pointer_gesture_swipe_v1::*, ZwpPointerGestureSwipeV1Id}, + }, + std::rc::Rc, + thiserror::Error, +}; + +pub struct ZwpPointerGestureSwipeV1 { + pub id: ZwpPointerGestureSwipeV1Id, + pub client: Rc, + pub seat: Rc, + pub tracker: Tracker, + pub version: Version, +} + +impl ZwpPointerGestureSwipeV1 { + fn detach(&self) { + self.seat.swipe_bindings.remove(&self.client, self); + } + + pub fn send_swipe_begin(&self, n: &WlSurface, serial: u32, time_usec: u64, finger_count: u32) { + self.client.event(Begin { + self_id: self.id, + serial, + time: (time_usec / 1000) as u32, + surface: n.id, + fingers: finger_count, + }); + } + + pub fn send_swipe_update(&self, time_usec: u64, dx: Fixed, dy: Fixed) { + self.client.event(Update { + self_id: self.id, + time: (time_usec / 1000) as u32, + dx, + dy, + }); + } + + pub fn send_swipe_end(&self, serial: u32, time_usec: u64, cancelled: bool) { + self.client.event(End { + self_id: self.id, + serial, + time: (time_usec / 1000) as u32, + cancelled: cancelled as _, + }); + } +} + +impl ZwpPointerGestureSwipeV1RequestHandler for ZwpPointerGestureSwipeV1 { + type Error = ZwpPointerGestureSwipeV1Error; + + fn destroy(&self, _req: Destroy, _slf: &Rc) -> Result<(), Self::Error> { + self.detach(); + self.client.remove_obj(self)?; + Ok(()) + } +} + +object_base! { + self = ZwpPointerGestureSwipeV1; + version = self.version; +} + +impl Object for ZwpPointerGestureSwipeV1 { + fn break_loops(&self) { + self.detach(); + } +} + +simple_add_obj!(ZwpPointerGestureSwipeV1); + +#[derive(Debug, Error)] +pub enum ZwpPointerGestureSwipeV1Error { + #[error(transparent)] + ClientError(Box), +} +efrom!(ZwpPointerGestureSwipeV1Error, ClientError); diff --git a/src/ifs/wl_seat/zwp_pointer_gestures_v1.rs b/src/ifs/wl_seat/zwp_pointer_gestures_v1.rs new file mode 100644 index 00000000..4c3fc766 --- /dev/null +++ b/src/ifs/wl_seat/zwp_pointer_gestures_v1.rs @@ -0,0 +1,135 @@ +use { + crate::{ + client::{Client, ClientError}, + globals::{Global, GlobalName}, + ifs::wl_seat::{ + zwp_pointer_gesture_hold_v1::ZwpPointerGestureHoldV1, + zwp_pointer_gesture_pinch_v1::ZwpPointerGesturePinchV1, + zwp_pointer_gesture_swipe_v1::ZwpPointerGestureSwipeV1, + }, + leaks::Tracker, + object::{Object, Version}, + wire::{zwp_pointer_gestures_v1::*, ZwpPointerGesturesV1Id}, + }, + std::rc::Rc, + thiserror::Error, +}; + +pub struct ZwpPointerGesturesV1Global { + pub name: GlobalName, +} + +pub struct ZwpPointerGesturesV1 { + pub id: ZwpPointerGesturesV1Id, + pub client: Rc, + pub tracker: Tracker, + pub version: Version, +} + +impl ZwpPointerGesturesV1Global { + pub fn new(name: GlobalName) -> Self { + Self { name } + } + + fn bind_( + self: Rc, + id: ZwpPointerGesturesV1Id, + client: &Rc, + version: Version, + ) -> Result<(), ZwpPointerGesturesV1Error> { + let obj = Rc::new(ZwpPointerGesturesV1 { + id, + client: client.clone(), + tracker: Default::default(), + version, + }); + track!(client, obj); + client.add_client_obj(&obj)?; + Ok(()) + } +} + +global_base!( + ZwpPointerGesturesV1Global, + ZwpPointerGesturesV1, + ZwpPointerGesturesV1Error +); + +impl Global for ZwpPointerGesturesV1Global { + fn singleton(&self) -> bool { + true + } + + fn version(&self) -> u32 { + 3 + } +} + +simple_add_global!(ZwpPointerGesturesV1Global); + +impl ZwpPointerGesturesV1RequestHandler for ZwpPointerGesturesV1 { + type Error = ZwpPointerGesturesV1Error; + + fn get_swipe_gesture(&self, req: GetSwipeGesture, _slf: &Rc) -> Result<(), Self::Error> { + let seat = self.client.lookup(req.pointer)?.seat.global.clone(); + let obj = Rc::new(ZwpPointerGestureSwipeV1 { + id: req.id, + client: self.client.clone(), + seat: seat.clone(), + tracker: Default::default(), + version: self.version, + }); + self.client.add_client_obj(&obj)?; + seat.swipe_bindings.add(&self.client, &obj); + Ok(()) + } + + fn get_pinch_gesture(&self, req: GetPinchGesture, _slf: &Rc) -> Result<(), Self::Error> { + let seat = self.client.lookup(req.pointer)?.seat.global.clone(); + let obj = Rc::new(ZwpPointerGesturePinchV1 { + id: req.id, + client: self.client.clone(), + seat: seat.clone(), + tracker: Default::default(), + version: self.version, + }); + self.client.add_client_obj(&obj)?; + seat.pinch_bindings.add(&self.client, &obj); + Ok(()) + } + + fn release(&self, _req: Release, _slf: &Rc) -> Result<(), Self::Error> { + self.client.remove_obj(self)?; + Ok(()) + } + + fn get_hold_gesture(&self, req: GetHoldGesture, _slf: &Rc) -> Result<(), Self::Error> { + let seat = self.client.lookup(req.pointer)?.seat.global.clone(); + let obj = Rc::new(ZwpPointerGestureHoldV1 { + id: req.id, + client: self.client.clone(), + seat: seat.clone(), + tracker: Default::default(), + version: self.version, + }); + self.client.add_client_obj(&obj)?; + seat.hold_bindings.add(&self.client, &obj); + Ok(()) + } +} + +object_base! { + self = ZwpPointerGesturesV1; + version = self.version; +} + +impl Object for ZwpPointerGesturesV1 {} + +simple_add_obj!(ZwpPointerGesturesV1); + +#[derive(Debug, Error)] +pub enum ZwpPointerGesturesV1Error { + #[error(transparent)] + ClientError(Box), +} +efrom!(ZwpPointerGesturesV1Error, ClientError); diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 778c7ea3..4311bf81 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -1507,6 +1507,46 @@ impl Node for WlSurface { fn node_is_xwayland_surface(&self) -> bool { self.client.is_xwayland } + + fn node_on_swipe_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + seat.swipe_begin_surface(self, time_usec, finger_count) + } + + fn node_on_swipe_update(&self, seat: &Rc, time_usec: u64, dx: Fixed, dy: Fixed) { + seat.swipe_update_surface(self, time_usec, dx, dy) + } + + fn node_on_swipe_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + seat.swipe_end_surface(self, time_usec, cancelled) + } + + fn node_on_pinch_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + seat.pinch_begin_surface(self, time_usec, finger_count) + } + + fn node_on_pinch_update( + &self, + seat: &Rc, + time_usec: u64, + dx: Fixed, + dy: Fixed, + scale: Fixed, + rotation: Fixed, + ) { + seat.pinch_update_surface(self, time_usec, dx, dy, scale, rotation) + } + + fn node_on_pinch_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + seat.pinch_end_surface(self, time_usec, cancelled) + } + + fn node_on_hold_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + seat.hold_begin_surface(self, time_usec, finger_count) + } + + fn node_on_hold_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + seat.hold_end_surface(self, time_usec, cancelled) + } } #[derive(Debug, Error)] diff --git a/src/libinput/event.rs b/src/libinput/event.rs index 90514e54..af5b182c 100644 --- a/src/libinput/event.rs +++ b/src/libinput/event.rs @@ -3,16 +3,21 @@ use { consts::{ButtonState, EventType, KeyState, PointerAxis}, device::LibInputDevice, sys::{ - libinput_event, libinput_event_destroy, libinput_event_get_device, - libinput_event_get_keyboard_event, libinput_event_get_pointer_event, - libinput_event_get_type, libinput_event_keyboard, libinput_event_keyboard_get_key, - libinput_event_keyboard_get_key_state, libinput_event_keyboard_get_time_usec, - libinput_event_pointer, libinput_event_pointer_get_button, - libinput_event_pointer_get_button_state, libinput_event_pointer_get_dx, - libinput_event_pointer_get_dx_unaccelerated, libinput_event_pointer_get_dy, - libinput_event_pointer_get_dy_unaccelerated, libinput_event_pointer_get_scroll_value, - libinput_event_pointer_get_scroll_value_v120, libinput_event_pointer_get_time_usec, - libinput_event_pointer_has_axis, + libinput_event, libinput_event_destroy, libinput_event_gesture, + libinput_event_gesture_get_angle_delta, libinput_event_gesture_get_cancelled, + libinput_event_gesture_get_dx, libinput_event_gesture_get_dx_unaccelerated, + libinput_event_gesture_get_dy, libinput_event_gesture_get_dy_unaccelerated, + libinput_event_gesture_get_finger_count, libinput_event_gesture_get_scale, + libinput_event_gesture_get_time_usec, libinput_event_get_device, + libinput_event_get_gesture_event, libinput_event_get_keyboard_event, + libinput_event_get_pointer_event, libinput_event_get_type, libinput_event_keyboard, + libinput_event_keyboard_get_key, libinput_event_keyboard_get_key_state, + libinput_event_keyboard_get_time_usec, libinput_event_pointer, + libinput_event_pointer_get_button, libinput_event_pointer_get_button_state, + libinput_event_pointer_get_dx, libinput_event_pointer_get_dx_unaccelerated, + libinput_event_pointer_get_dy, libinput_event_pointer_get_dy_unaccelerated, + libinput_event_pointer_get_scroll_value, libinput_event_pointer_get_scroll_value_v120, + libinput_event_pointer_get_time_usec, libinput_event_pointer_has_axis, }, }, std::marker::PhantomData, @@ -33,6 +38,11 @@ pub struct LibInputEventPointer<'a> { pub(super) _phantom: PhantomData<&'a ()>, } +pub struct LibInputEventGesture<'a> { + pub(super) event: *mut libinput_event_gesture, + pub(super) _phantom: PhantomData<&'a ()>, +} + impl<'a> Drop for LibInputEvent<'a> { fn drop(&mut self) { unsafe { @@ -76,6 +86,18 @@ impl<'a> LibInputEvent<'a> { }) } } + + pub fn gesture_event(&self) -> Option { + let res = unsafe { libinput_event_get_gesture_event(self.event) }; + if res.is_null() { + None + } else { + Some(LibInputEventGesture { + event: res, + _phantom: Default::default(), + }) + } + } } impl<'a> LibInputEventKeyboard<'a> { @@ -134,3 +156,41 @@ impl<'a> LibInputEventPointer<'a> { unsafe { libinput_event_pointer_get_time_usec(self.event) } } } + +impl<'a> LibInputEventGesture<'a> { + pub fn time_usec(&self) -> u64 { + unsafe { libinput_event_gesture_get_time_usec(self.event) } + } + + pub fn finger_count(&self) -> u32 { + unsafe { libinput_event_gesture_get_finger_count(self.event) as u32 } + } + + pub fn cancelled(&self) -> bool { + unsafe { libinput_event_gesture_get_cancelled(self.event) != 0 } + } + + pub fn dx(&self) -> f64 { + unsafe { libinput_event_gesture_get_dx(self.event) } + } + + pub fn dy(&self) -> f64 { + unsafe { libinput_event_gesture_get_dy(self.event) } + } + + pub fn dx_unaccelerated(&self) -> f64 { + unsafe { libinput_event_gesture_get_dx_unaccelerated(self.event) } + } + + pub fn dy_unaccelerated(&self) -> f64 { + unsafe { libinput_event_gesture_get_dy_unaccelerated(self.event) } + } + + pub fn scale(&self) -> f64 { + unsafe { libinput_event_gesture_get_scale(self.event) } + } + + pub fn angle_delta(&self) -> f64 { + unsafe { libinput_event_gesture_get_angle_delta(self.event) } + } +} diff --git a/src/libinput/sys.rs b/src/libinput/sys.rs index 77e90a1e..89861d4c 100644 --- a/src/libinput/sys.rs +++ b/src/libinput/sys.rs @@ -14,6 +14,8 @@ pub struct libinput_event(u8); pub struct libinput_event_keyboard(u8); #[repr(transparent)] pub struct libinput_event_pointer(u8); +#[repr(transparent)] +pub struct libinput_event_gesture(u8); #[link(name = "input")] extern "C" { @@ -140,6 +142,19 @@ extern "C" { // event: *mut libinput_event_pointer, // axis: libinput_pointer_axis, // ) -> f64; + + pub fn libinput_event_get_gesture_event( + event: *mut libinput_event, + ) -> *mut libinput_event_gesture; + pub fn libinput_event_gesture_get_time_usec(event: *mut libinput_event_gesture) -> u64; + pub fn libinput_event_gesture_get_finger_count(event: *mut libinput_event_gesture) -> c::c_int; + pub fn libinput_event_gesture_get_cancelled(event: *mut libinput_event_gesture) -> c::c_int; + pub fn libinput_event_gesture_get_dx(event: *mut libinput_event_gesture) -> f64; + pub fn libinput_event_gesture_get_dy(event: *mut libinput_event_gesture) -> f64; + pub fn libinput_event_gesture_get_dx_unaccelerated(event: *mut libinput_event_gesture) -> f64; + pub fn libinput_event_gesture_get_dy_unaccelerated(event: *mut libinput_event_gesture) -> f64; + pub fn libinput_event_gesture_get_scale(event: *mut libinput_event_gesture) -> f64; + pub fn libinput_event_gesture_get_angle_delta(event: *mut libinput_event_gesture) -> f64; } #[repr(C)] diff --git a/src/tree.rs b/src/tree.rs index edc13dec..33566120 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -284,6 +284,66 @@ pub trait Node: 'static { let _ = y; } + fn node_on_swipe_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + let _ = seat; + let _ = time_usec; + let _ = finger_count; + } + + fn node_on_swipe_update(&self, seat: &Rc, time_usec: u64, dx: Fixed, dy: Fixed) { + let _ = seat; + let _ = time_usec; + let _ = dx; + let _ = dy; + } + + fn node_on_swipe_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + let _ = seat; + let _ = time_usec; + let _ = cancelled; + } + + fn node_on_pinch_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + let _ = seat; + let _ = time_usec; + let _ = finger_count; + } + + fn node_on_pinch_update( + &self, + seat: &Rc, + time_usec: u64, + dx: Fixed, + dy: Fixed, + scale: Fixed, + rotation: Fixed, + ) { + let _ = seat; + let _ = time_usec; + let _ = dx; + let _ = dy; + let _ = scale; + let _ = rotation; + } + + fn node_on_pinch_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + let _ = seat; + let _ = time_usec; + let _ = cancelled; + } + + fn node_on_hold_begin(&self, seat: &Rc, time_usec: u64, finger_count: u32) { + let _ = seat; + let _ = time_usec; + let _ = finger_count; + } + + fn node_on_hold_end(&self, seat: &Rc, time_usec: u64, cancelled: bool) { + let _ = seat; + let _ = time_usec; + let _ = cancelled; + } + // TYPE CONVERTERS fn node_into_float(self: Rc) -> Option> { diff --git a/src/utils/bindings.rs b/src/utils/bindings.rs index 60134b01..c939f75b 100644 --- a/src/utils/bindings.rs +++ b/src/utils/bindings.rs @@ -1,10 +1,11 @@ use { crate::{ client::{Client, ClientId}, - object::{Object, ObjectId}, + object::{Object, ObjectId, Version}, utils::copyhashmap::{CopyHashMap, Locked}, }, - std::rc::Rc, + ahash::AHashMap, + std::{cell::RefCell, collections::hash_map::Entry, rc::Rc}, }; pub struct Bindings

{ @@ -37,3 +38,50 @@ impl Bindings

{ self.bindings.lock() } } + +pub struct PerClientBindings

{ + bindings: RefCell>>>, +} + +impl

Default for PerClientBindings

{ + fn default() -> Self { + Self { + bindings: Default::default(), + } + } +} + +impl PerClientBindings

{ + pub fn add(&self, client: &Client, obj: &Rc

) { + let prev = self + .bindings + .borrow_mut() + .entry(client.id) + .or_default() + .insert(obj.id(), obj.clone()); + assert!(prev.is_none()); + } + + pub fn remove(&self, client: &Client, obj: &P) { + if let Entry::Occupied(mut oe) = self.bindings.borrow_mut().entry(client.id) { + oe.get_mut().remove(&obj.id()); + if oe.get().is_empty() { + oe.remove(); + } + } + } + + pub fn clear(&self) { + self.bindings.borrow_mut().clear(); + } + + pub fn for_each(&self, client: ClientId, version: Version, mut f: impl FnMut(&P)) { + if let Some(bindings) = self.bindings.borrow().get(&client) { + for obj in bindings.values() { + if obj.version() >= version { + f(obj); + } + } + } + } +} diff --git a/wire/jay_seat_events.txt b/wire/jay_seat_events.txt index cb9d2a65..b2d1c901 100644 --- a/wire/jay_seat_events.txt +++ b/wire/jay_seat_events.txt @@ -69,3 +69,59 @@ event axis_inverted { inverted: u32, axis: u32, } + +event swipe_begin { + seat: u32, + time_usec: pod(u64), + fingers: u32, +} + +event swipe_update { + seat: u32, + time_usec: pod(u64), + dx: fixed, + dy: fixed, + dx_unaccelerated: fixed, + dy_unaccelerated: fixed, +} + +event swipe_end { + seat: u32, + time_usec: pod(u64), + cancelled: i32, +} + +event pinch_begin { + seat: u32, + time_usec: pod(u64), + fingers: u32, +} + +event pinch_update { + seat: u32, + time_usec: pod(u64), + dx: fixed, + dy: fixed, + dx_unaccelerated: fixed, + dy_unaccelerated: fixed, + scale: fixed, + rotation: fixed, +} + +event pinch_end { + seat: u32, + time_usec: pod(u64), + cancelled: i32, +} + +event hold_begin { + seat: u32, + time_usec: pod(u64), + fingers: u32, +} + +event hold_end { + seat: u32, + time_usec: pod(u64), + cancelled: i32, +} diff --git a/wire/zwp_pointer_gesture_hold_v1.txt b/wire/zwp_pointer_gesture_hold_v1.txt new file mode 100644 index 00000000..14c9cd11 --- /dev/null +++ b/wire/zwp_pointer_gesture_hold_v1.txt @@ -0,0 +1,16 @@ +request destroy (since = 3) { + +} + +event begin { + serial: u32, + time: u32, + surface: id(wl_surface), + fingers: u32, +} + +event end { + serial: u32, + time: u32, + cancelled: i32, +} diff --git a/wire/zwp_pointer_gesture_pinch_v1.txt b/wire/zwp_pointer_gesture_pinch_v1.txt new file mode 100644 index 00000000..2109d1fd --- /dev/null +++ b/wire/zwp_pointer_gesture_pinch_v1.txt @@ -0,0 +1,24 @@ +request destroy { + +} + +event begin { + serial: u32, + time: u32, + surface: id(wl_surface), + fingers: u32, +} + +event update { + time: u32, + dx: fixed, + dy: fixed, + scale: fixed, + rotation: fixed, +} + +event end { + serial: u32, + time: u32, + cancelled: i32, +} diff --git a/wire/zwp_pointer_gesture_swipe_v1.txt b/wire/zwp_pointer_gesture_swipe_v1.txt new file mode 100644 index 00000000..7519b2f3 --- /dev/null +++ b/wire/zwp_pointer_gesture_swipe_v1.txt @@ -0,0 +1,22 @@ +request destroy { + +} + +event begin { + serial: u32, + time: u32, + surface: id(wl_surface), + fingers: u32, +} + +event update { + time: u32, + dx: fixed, + dy: fixed, +} + +event end { + serial: u32, + time: u32, + cancelled: i32, +} diff --git a/wire/zwp_pointer_gestures_v1.txt b/wire/zwp_pointer_gestures_v1.txt new file mode 100644 index 00000000..a1a1b905 --- /dev/null +++ b/wire/zwp_pointer_gestures_v1.txt @@ -0,0 +1,18 @@ +request get_swipe_gesture { + id: id(zwp_pointer_gesture_swipe_v1), + pointer: id(wl_pointer), +} + +request get_pinch_gesture { + id: id(zwp_pointer_gesture_pinch_v1), + pointer: id(wl_pointer), +} + +request release (since = 2) { + +} + +request get_hold_gesture (since = 3) { + id: id(zwp_pointer_gesture_hold_v1), + pointer: id(wl_pointer), +}