1
0
Fork 0
forked from wry/wry

Merge pull request #188 from mahkoh/jorth/gestures

wayland: implement pointer-gestures-unstable-v1
This commit is contained in:
mahkoh 2024-04-27 22:16:33 +02:00 committed by GitHub
commit 55d55bf161
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 1589 additions and 18 deletions

View file

@ -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 | |

View file

@ -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)

View file

@ -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 {

View file

@ -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<Self>, 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<Self>, 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<Self>, 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<Self>, 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<Self>, 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<Self>, 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<Self>, 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<Self>, event: LibInputEvent) {
let (event, dev) = unpack!(self, event, gesture_event);
dev.event(InputEvent::HoldEnd {
time_usec: event.time_usec(),
cancelled: event.cancelled(),
});
}
}

View file

@ -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<SeatTest>) {
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;
}

View file

@ -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<dyn Backend>) {

View file

@ -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 {

View file

@ -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<u32>,
pointer_owner: PointerOwnerHolder,
kb_owner: KbOwnerHolder,
gesture_owner: GestureOwnerHolder,
dropped_dnd: RefCell<Option<DroppedDnd>>,
shortcuts: RefCell<AHashMap<u32, SmallMap<u32, u32, 2>>>,
queue_link: Cell<Option<LinkedNode<Rc<Self>>>>,
@ -182,6 +192,9 @@ pub struct WlSeatGlobal {
input_method_grab: CloneCell<Option<Rc<ZwpInputMethodKeyboardGrabV2>>>,
forward: Cell<bool>,
focus_follows_mouse: Cell<bool>,
swipe_bindings: PerClientBindings<ZwpPointerGestureSwipeV1>,
pinch_bindings: PerClientBindings<ZwpPointerGesturePinchV1>,
hold_bindings: PerClientBindings<ZwpPointerGestureHoldV1>,
}
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 {

View file

@ -49,6 +49,7 @@ use {
pub struct NodeSeatState {
pointer_foci: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
kb_foci: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
gesture_foci: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
pointer_grabs: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
dnd_targets: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
}
@ -72,6 +73,14 @@ impl NodeSeatState {
self.kb_foci.len() == 0
}
pub(super) fn gesture_begin(&self, seat: &Rc<WlSeatGlobal>) {
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<WlSeatGlobal>) {
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<Self>, 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<Self>,
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<Self>, 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<Self>, 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<Self>,
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<Self>, 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<Self>, 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<Self>, 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<F>(
self: &Rc<Self>,
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)
})
}
}

View file

@ -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<NoGesture>,
owner: CloneCell<Rc<dyn GestureOwner>>,
}
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<WlSeatGlobal>) {
self.owner.get().revert_to_default(seat);
self.set_default_owner();
}
pub fn swipe_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
self.owner.get().swipe_begin(seat, time_usec, finger_count)
}
pub fn swipe_update(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, dx: Fixed, dy: Fixed) {
self.owner.get().swipe_update(seat, time_usec, dx, dy)
}
pub fn swipe_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
self.owner.get().swipe_end(seat, time_usec, cancelled)
}
pub fn pinch_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
self.owner.get().pinch_begin(seat, time_usec, finger_count)
}
pub fn pinch_update(
&self,
seat: &Rc<WlSeatGlobal>,
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<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
self.owner.get().pinch_end(seat, time_usec, cancelled)
}
pub fn hold_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
self.owner.get().hold_begin(seat, time_usec, finger_count)
}
pub fn hold_end(&self, seat: &Rc<WlSeatGlobal>, 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<WlSeatGlobal>);
fn swipe_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
let _ = seat;
let _ = time_usec;
let _ = finger_count;
}
fn swipe_update(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, dx: Fixed, dy: Fixed) {
let _ = seat;
let _ = time_usec;
let _ = dx;
let _ = dy;
}
fn swipe_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
let _ = seat;
let _ = time_usec;
let _ = cancelled;
}
fn pinch_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
let _ = seat;
let _ = time_usec;
let _ = finger_count;
}
fn pinch_update(
&self,
seat: &Rc<WlSeatGlobal>,
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<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
let _ = seat;
let _ = time_usec;
let _ = cancelled;
}
fn hold_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
let _ = seat;
let _ = time_usec;
let _ = finger_count;
}
fn hold_end(&self, seat: &Rc<WlSeatGlobal>, 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<WlSeatGlobal>) {
let _ = seat;
}
fn swipe_begin(&self, seat: &Rc<WlSeatGlobal>, 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<WlSeatGlobal>, 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<WlSeatGlobal>, 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<dyn Node>,
}
impl GestureOwner for SwipeGesture {
fn revert_to_default(&self, seat: &Rc<WlSeatGlobal>) {
self.swipe_end(seat, now_usec(), true);
}
fn swipe_update(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, dx: Fixed, dy: Fixed) {
self.node.node_on_swipe_update(seat, time_usec, dx, dy);
}
fn swipe_end(&self, seat: &Rc<WlSeatGlobal>, 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<dyn Node>,
}
impl GestureOwner for PinchGesture {
fn revert_to_default(&self, seat: &Rc<WlSeatGlobal>) {
self.pinch_end(seat, now_usec(), true);
}
fn pinch_update(
&self,
seat: &Rc<WlSeatGlobal>,
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<WlSeatGlobal>, 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<dyn Node>,
}
impl GestureOwner for HoldGesture {
fn revert_to_default(&self, seat: &Rc<WlSeatGlobal>) {
self.hold_end(seat, now_usec(), true);
}
fn hold_end(&self, seat: &Rc<WlSeatGlobal>, 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();
}
}

View file

@ -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<Client>,
pub seat: Rc<WlSeatGlobal>,
pub tracker: Tracker<Self>,
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<Self>) -> 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<ClientError>),
}
efrom!(ZwpPointerGestureHoldV1Error, ClientError);

View file

@ -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<Client>,
pub seat: Rc<WlSeatGlobal>,
pub tracker: Tracker<Self>,
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<Self>) -> 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<ClientError>),
}
efrom!(ZwpPointerGesturePinchV1Error, ClientError);

View file

@ -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<Client>,
pub seat: Rc<WlSeatGlobal>,
pub tracker: Tracker<Self>,
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<Self>) -> 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<ClientError>),
}
efrom!(ZwpPointerGestureSwipeV1Error, ClientError);

View file

@ -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<Client>,
pub tracker: Tracker<Self>,
pub version: Version,
}
impl ZwpPointerGesturesV1Global {
pub fn new(name: GlobalName) -> Self {
Self { name }
}
fn bind_(
self: Rc<Self>,
id: ZwpPointerGesturesV1Id,
client: &Rc<Client>,
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<Self>) -> 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<Self>) -> 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<Self>) -> Result<(), Self::Error> {
self.client.remove_obj(self)?;
Ok(())
}
fn get_hold_gesture(&self, req: GetHoldGesture, _slf: &Rc<Self>) -> 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<ClientError>),
}
efrom!(ZwpPointerGesturesV1Error, ClientError);

View file

@ -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<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
seat.swipe_begin_surface(self, time_usec, finger_count)
}
fn node_on_swipe_update(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, dx: Fixed, dy: Fixed) {
seat.swipe_update_surface(self, time_usec, dx, dy)
}
fn node_on_swipe_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
seat.swipe_end_surface(self, time_usec, cancelled)
}
fn node_on_pinch_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
seat.pinch_begin_surface(self, time_usec, finger_count)
}
fn node_on_pinch_update(
&self,
seat: &Rc<WlSeatGlobal>,
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<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
seat.pinch_end_surface(self, time_usec, cancelled)
}
fn node_on_hold_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
seat.hold_begin_surface(self, time_usec, finger_count)
}
fn node_on_hold_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
seat.hold_end_surface(self, time_usec, cancelled)
}
}
#[derive(Debug, Error)]

View file

@ -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<LibInputEventGesture> {
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) }
}
}

View file

@ -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)]

View file

@ -284,6 +284,66 @@ pub trait Node: 'static {
let _ = y;
}
fn node_on_swipe_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
let _ = seat;
let _ = time_usec;
let _ = finger_count;
}
fn node_on_swipe_update(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, dx: Fixed, dy: Fixed) {
let _ = seat;
let _ = time_usec;
let _ = dx;
let _ = dy;
}
fn node_on_swipe_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
let _ = seat;
let _ = time_usec;
let _ = cancelled;
}
fn node_on_pinch_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
let _ = seat;
let _ = time_usec;
let _ = finger_count;
}
fn node_on_pinch_update(
&self,
seat: &Rc<WlSeatGlobal>,
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<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
let _ = seat;
let _ = time_usec;
let _ = cancelled;
}
fn node_on_hold_begin(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, finger_count: u32) {
let _ = seat;
let _ = time_usec;
let _ = finger_count;
}
fn node_on_hold_end(&self, seat: &Rc<WlSeatGlobal>, time_usec: u64, cancelled: bool) {
let _ = seat;
let _ = time_usec;
let _ = cancelled;
}
// TYPE CONVERTERS
fn node_into_float(self: Rc<Self>) -> Option<Rc<FloatNode>> {

View file

@ -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<P> {
@ -37,3 +38,50 @@ impl<P: Object> Bindings<P> {
self.bindings.lock()
}
}
pub struct PerClientBindings<P> {
bindings: RefCell<AHashMap<ClientId, AHashMap<ObjectId, Rc<P>>>>,
}
impl<P> Default for PerClientBindings<P> {
fn default() -> Self {
Self {
bindings: Default::default(),
}
}
}
impl<P: Object> PerClientBindings<P> {
pub fn add(&self, client: &Client, obj: &Rc<P>) {
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);
}
}
}
}
}

View file

@ -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,
}

View file

@ -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,
}

View file

@ -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,
}

View file

@ -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,
}

View file

@ -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),
}