implement virtual-pointer

This commit is contained in:
sodiboo
2024-08-26 06:10:57 +02:00
committed by Ivan Molodetskikh
parent 3ff900eab8
commit 79f22053b9
3 changed files with 437 additions and 43 deletions
+24 -2
View File
@@ -11,7 +11,7 @@ use std::time::Duration;
use smithay::backend::allocator::dmabuf::Dmabuf; use smithay::backend::allocator::dmabuf::Dmabuf;
use smithay::backend::drm::DrmNode; use smithay::backend::drm::DrmNode;
use smithay::backend::input::TabletToolDescriptor; use smithay::backend::input::{InputEvent, TabletToolDescriptor};
use smithay::desktop::{PopupKind, PopupManager}; use smithay::desktop::{PopupKind, PopupManager};
use smithay::input::pointer::{ use smithay::input::pointer::{
CursorIcon, CursorImageStatus, CursorImageSurfaceData, PointerHandle, CursorIcon, CursorImageStatus, CursorImageSurfaceData, PointerHandle,
@@ -79,7 +79,11 @@ use crate::protocols::gamma_control::{GammaControlHandler, GammaControlManagerSt
use crate::protocols::mutter_x11_interop::MutterX11InteropHandler; use crate::protocols::mutter_x11_interop::MutterX11InteropHandler;
use crate::protocols::output_management::{OutputManagementHandler, OutputManagementManagerState}; use crate::protocols::output_management::{OutputManagementHandler, OutputManagementManagerState};
use crate::protocols::screencopy::{Screencopy, ScreencopyHandler, ScreencopyManagerState}; use crate::protocols::screencopy::{Screencopy, ScreencopyHandler, ScreencopyManagerState};
use crate::protocols::virtual_pointer::{VirtualPointerHandler, VirtualPointerManagerState}; use crate::protocols::virtual_pointer::{
VirtualPointerAxisEvent, VirtualPointerButtonEvent, VirtualPointerHandler,
VirtualPointerInputBackend, VirtualPointerManagerState, VirtualPointerMotionAbsoluteEvent,
VirtualPointerMotionEvent,
};
use crate::utils::{output_size, send_scale_transform, with_toplevel_role}; use crate::utils::{output_size, send_scale_transform, with_toplevel_role};
use crate::{ use crate::{
delegate_foreign_toplevel, delegate_gamma_control, delegate_mutter_x11_interop, delegate_foreign_toplevel, delegate_gamma_control, delegate_mutter_x11_interop,
@@ -592,6 +596,24 @@ impl VirtualPointerHandler for State {
fn virtual_pointer_manager_state(&mut self) -> &mut VirtualPointerManagerState { fn virtual_pointer_manager_state(&mut self) -> &mut VirtualPointerManagerState {
&mut self.niri.virtual_pointer_state &mut self.niri.virtual_pointer_state
} }
fn on_virtual_pointer_motion(&mut self, event: VirtualPointerMotionEvent) {
self.process_input_event(InputEvent::<VirtualPointerInputBackend>::PointerMotion { event });
}
fn on_virtual_pointer_motion_absolute(&mut self, event: VirtualPointerMotionAbsoluteEvent) {
self.process_input_event(
InputEvent::<VirtualPointerInputBackend>::PointerMotionAbsolute { event },
);
}
fn on_virtual_pointer_button(&mut self, event: VirtualPointerButtonEvent) {
self.process_input_event(InputEvent::<VirtualPointerInputBackend>::PointerButton { event });
}
fn on_virtual_pointer_axis(&mut self, event: VirtualPointerAxisEvent) {
self.process_input_event(InputEvent::<VirtualPointerInputBackend>::PointerAxis { event });
}
} }
delegate_virtual_pointer!(State); delegate_virtual_pointer!(State);
+3 -1
View File
@@ -77,7 +77,9 @@ use smithay::wayland::fractional_scale::FractionalScaleManagerState;
use smithay::wayland::idle_inhibit::IdleInhibitManagerState; use smithay::wayland::idle_inhibit::IdleInhibitManagerState;
use smithay::wayland::idle_notify::IdleNotifierState; use smithay::wayland::idle_notify::IdleNotifierState;
use smithay::wayland::input_method::{InputMethodManagerState, InputMethodSeat}; use smithay::wayland::input_method::{InputMethodManagerState, InputMethodSeat};
use smithay::wayland::keyboard_shortcuts_inhibit::{KeyboardShortcutsInhibitState, KeyboardShortcutsInhibitor}; use smithay::wayland::keyboard_shortcuts_inhibit::{
KeyboardShortcutsInhibitState, KeyboardShortcutsInhibitor,
};
use smithay::wayland::output::OutputManagerState; use smithay::wayland::output::OutputManagerState;
use smithay::wayland::pointer_constraints::{with_pointer_constraint, PointerConstraintsState}; use smithay::wayland::pointer_constraints::{with_pointer_constraint, PointerConstraintsState};
use smithay::wayland::pointer_gestures::PointerGesturesState; use smithay::wayland::pointer_gestures::PointerGesturesState;
+408 -38
View File
@@ -1,13 +1,20 @@
use std::collections::HashMap; use std::collections::HashSet;
use std::fs::File; use std::sync::Mutex;
use std::io::Read;
use smithay::output::Output; use smithay::backend::input::{
AbsolutePositionEvent, Axis, AxisRelativeDirection, AxisSource, ButtonState, Device,
DeviceCapability, Event, InputBackend, PointerAxisEvent, PointerButtonEvent,
PointerMotionAbsoluteEvent, PointerMotionEvent, UnusedEvent,
};
use smithay::input::pointer::AxisFrame;
use smithay::reexports::wayland_protocols_wlr; use smithay::reexports::wayland_protocols_wlr;
use smithay::reexports::wayland_server::backend::ClientId; use smithay::reexports::wayland_server::protocol::wl_output::WlOutput;
use smithay::reexports::wayland_server::protocol::wl_pointer;
use smithay::reexports::wayland_server::protocol::wl_seat::WlSeat;
use smithay::reexports::wayland_server::{ use smithay::reexports::wayland_server::{
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
}; };
use wayland_backend::protocol::WEnum;
use wayland_protocols_wlr::virtual_pointer::v1::server::{ use wayland_protocols_wlr::virtual_pointer::v1::server::{
zwlr_virtual_pointer_manager_v1, zwlr_virtual_pointer_v1, zwlr_virtual_pointer_manager_v1, zwlr_virtual_pointer_v1,
}; };
@@ -17,25 +24,273 @@ use zwlr_virtual_pointer_v1::ZwlrVirtualPointerV1;
const VERSION: u32 = 2; const VERSION: u32 = 2;
pub struct VirtualPointerManagerState { pub struct VirtualPointerManagerState {
virtual_pointers: Vec<ZwlrVirtualPointerV1>, virtual_pointers: HashSet<ZwlrVirtualPointerV1>,
} }
pub struct VirtualPointerManagerGlobalData { pub struct VirtualPointerManagerGlobalData {
filter: Box<dyn for<'c> Fn(&'c Client) -> bool + Send + Sync>, filter: Box<dyn for<'c> Fn(&'c Client) -> bool + Send + Sync>,
} }
pub trait VirtualPointerHandler { pub struct VirtualPointerInputBackend;
fn virtual_pointer_manager_state(&mut self) -> &mut VirtualPointerManagerState;
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub struct VirtualPointer {
pointer: ZwlrVirtualPointerV1,
} }
pub struct VirtualPointerState {} #[derive(Debug)]
pub struct VirtualPointerUserData {
seat: Option<WlSeat>,
output: Option<WlOutput>,
axis_frame: Mutex<Option<AxisFrame>>,
}
impl VirtualPointer {
fn data(&self) -> &VirtualPointerUserData {
self.pointer.data().unwrap()
}
pub fn seat(&self) -> Option<&WlSeat> {
self.data().seat.as_ref()
}
pub fn output(&self) -> Option<&WlOutput> {
self.data().output.as_ref()
}
fn finish_axis_frame(&self) -> Option<AxisFrame> {
self.data().axis_frame.lock().unwrap().take()
}
fn mutate_axis_frame(&self, time: Option<u32>, f: impl FnOnce(AxisFrame) -> AxisFrame) {
let mut frame = self.data().axis_frame.lock().unwrap();
*frame = frame.or(time.map(AxisFrame::new)).map(f);
}
}
impl Device for VirtualPointer {
fn id(&self) -> String {
format!("wlr virtual pointer {}", self.pointer.id())
}
fn name(&self) -> String {
String::from("virtual pointer")
}
fn has_capability(&self, capability: DeviceCapability) -> bool {
matches!(capability, DeviceCapability::Pointer)
}
fn usb_id(&self) -> Option<(u32, u32)> {
None
}
fn syspath(&self) -> Option<std::path::PathBuf> {
None
}
}
pub struct VirtualPointerMotionEvent {
pointer: VirtualPointer,
time: u32,
dx: f64,
dy: f64,
}
impl Event<VirtualPointerInputBackend> for VirtualPointerMotionEvent {
fn time(&self) -> u64 {
self.time as u64 * 1000 // millis to micros
}
fn device(&self) -> VirtualPointer {
self.pointer.clone()
}
}
impl PointerMotionEvent<VirtualPointerInputBackend> for VirtualPointerMotionEvent {
fn delta_x(&self) -> f64 {
self.dx
}
fn delta_y(&self) -> f64 {
self.dy
}
fn delta_x_unaccel(&self) -> f64 {
self.dx
}
fn delta_y_unaccel(&self) -> f64 {
self.dy
}
}
pub struct VirtualPointerMotionAbsoluteEvent {
pointer: VirtualPointer,
time: u32,
x: u32,
y: u32,
x_extent: u32,
y_extent: u32,
}
impl Event<VirtualPointerInputBackend> for VirtualPointerMotionAbsoluteEvent {
fn time(&self) -> u64 {
self.time as u64 * 1000 // millis to micros
}
fn device(&self) -> VirtualPointer {
self.pointer.clone()
}
}
impl AbsolutePositionEvent<VirtualPointerInputBackend> for VirtualPointerMotionAbsoluteEvent {
fn x(&self) -> f64 {
self.x as f64 / self.x_extent as f64
}
fn y(&self) -> f64 {
self.y as f64 / self.y_extent as f64
}
fn x_transformed(&self, width: i32) -> f64 {
(self.x as i64 * width as i64) as f64 / self.x_extent as f64
}
fn y_transformed(&self, height: i32) -> f64 {
(self.y as i64 * height as i64) as f64 / self.y_extent as f64
}
}
pub struct VirtualPointerButtonEvent {
pointer: VirtualPointer,
time: u32,
button: u32,
state: ButtonState,
}
impl Event<VirtualPointerInputBackend> for VirtualPointerButtonEvent {
fn time(&self) -> u64 {
self.time as u64 * 1000 // millis to micros
}
fn device(&self) -> VirtualPointer {
self.pointer.clone()
}
}
impl PointerButtonEvent<VirtualPointerInputBackend> for VirtualPointerButtonEvent {
fn button_code(&self) -> u32 {
self.button
}
fn state(&self) -> ButtonState {
self.state
}
}
pub struct VirtualPointerAxisEvent {
pointer: VirtualPointer,
frame: AxisFrame,
}
impl Event<VirtualPointerInputBackend> for VirtualPointerAxisEvent {
fn time(&self) -> u64 {
self.frame.time as u64 * 1000 // millis to micros
}
fn device(&self) -> VirtualPointer {
self.pointer.clone()
}
}
fn tuple_axis<T>(tuple: (T, T), axis: Axis) -> T {
match axis {
Axis::Horizontal => tuple.0,
Axis::Vertical => tuple.1,
}
}
impl PointerAxisEvent<VirtualPointerInputBackend> for VirtualPointerAxisEvent {
fn amount(&self, axis: Axis) -> Option<f64> {
Some(tuple_axis(self.frame.axis, axis))
}
fn amount_v120(&self, axis: Axis) -> Option<f64> {
self.frame.v120.map(|v120| tuple_axis(v120, axis) as f64)
}
fn source(&self) -> AxisSource {
self.frame.source.unwrap_or_else(|| {
warn!("AxisSource: no source set, giving bogus value");
AxisSource::Continuous
})
}
fn relative_direction(&self, axis: Axis) -> AxisRelativeDirection {
tuple_axis(self.frame.relative_direction, axis)
}
}
impl PointerMotionAbsoluteEvent<VirtualPointerInputBackend> for VirtualPointerMotionAbsoluteEvent {}
impl InputBackend for VirtualPointerInputBackend {
type Device = VirtualPointer;
type KeyboardKeyEvent = UnusedEvent;
type PointerAxisEvent = VirtualPointerAxisEvent;
type PointerButtonEvent = VirtualPointerButtonEvent;
type PointerMotionEvent = VirtualPointerMotionEvent;
type PointerMotionAbsoluteEvent = VirtualPointerMotionAbsoluteEvent;
type GestureSwipeBeginEvent = UnusedEvent;
type GestureSwipeUpdateEvent = UnusedEvent;
type GestureSwipeEndEvent = UnusedEvent;
type GesturePinchBeginEvent = UnusedEvent;
type GesturePinchUpdateEvent = UnusedEvent;
type GesturePinchEndEvent = UnusedEvent;
type GestureHoldBeginEvent = UnusedEvent;
type GestureHoldEndEvent = UnusedEvent;
type TouchDownEvent = UnusedEvent;
type TouchUpEvent = UnusedEvent;
type TouchMotionEvent = UnusedEvent;
type TouchCancelEvent = UnusedEvent;
type TouchFrameEvent = UnusedEvent;
type TabletToolAxisEvent = UnusedEvent;
type TabletToolProximityEvent = UnusedEvent;
type TabletToolTipEvent = UnusedEvent;
type TabletToolButtonEvent = UnusedEvent;
type SwitchToggleEvent = UnusedEvent;
type SpecialEvent = UnusedEvent;
}
pub trait VirtualPointerHandler {
fn virtual_pointer_manager_state(&mut self) -> &mut VirtualPointerManagerState;
fn create_virtual_pointer(&mut self, pointer: VirtualPointer) {
let _ = pointer;
}
fn destroy_virtual_pointer(&mut self, pointer: VirtualPointer) {
let _ = pointer;
}
fn on_virtual_pointer_motion(&mut self, event: VirtualPointerMotionEvent);
fn on_virtual_pointer_motion_absolute(&mut self, event: VirtualPointerMotionAbsoluteEvent);
fn on_virtual_pointer_button(&mut self, event: VirtualPointerButtonEvent);
fn on_virtual_pointer_axis(&mut self, event: VirtualPointerAxisEvent);
}
impl VirtualPointerManagerState { impl VirtualPointerManagerState {
pub fn new<D, F>(display: &DisplayHandle, filter: F) -> Self pub fn new<D, F>(display: &DisplayHandle, filter: F) -> Self
where where
D: GlobalDispatch<ZwlrVirtualPointerManagerV1, VirtualPointerManagerGlobalData>, D: GlobalDispatch<ZwlrVirtualPointerManagerV1, VirtualPointerManagerGlobalData>,
D: Dispatch<ZwlrVirtualPointerManagerV1, ()>, D: Dispatch<ZwlrVirtualPointerManagerV1, ()>,
D: Dispatch<ZwlrVirtualPointerV1, VirtualPointerState>, D: Dispatch<ZwlrVirtualPointerV1, VirtualPointerUserData>,
D: VirtualPointerHandler, D: VirtualPointerHandler,
D: 'static, D: 'static,
F: for<'c> Fn(&'c Client) -> bool + Send + Sync + 'static, F: for<'c> Fn(&'c Client) -> bool + Send + Sync + 'static,
@@ -46,7 +301,7 @@ impl VirtualPointerManagerState {
display.create_global::<D, ZwlrVirtualPointerManagerV1, _>(VERSION, global_data); display.create_global::<D, ZwlrVirtualPointerManagerV1, _>(VERSION, global_data);
Self { Self {
virtual_pointers: Vec::new(), virtual_pointers: HashSet::new(),
} }
} }
} }
@@ -56,7 +311,7 @@ impl<D> GlobalDispatch<ZwlrVirtualPointerManagerV1, VirtualPointerManagerGlobalD
where where
D: GlobalDispatch<ZwlrVirtualPointerManagerV1, VirtualPointerManagerGlobalData>, D: GlobalDispatch<ZwlrVirtualPointerManagerV1, VirtualPointerManagerGlobalData>,
D: Dispatch<ZwlrVirtualPointerManagerV1, ()>, D: Dispatch<ZwlrVirtualPointerManagerV1, ()>,
D: Dispatch<ZwlrVirtualPointerV1, VirtualPointerState>, D: Dispatch<ZwlrVirtualPointerV1, VirtualPointerUserData>,
D: VirtualPointerHandler, D: VirtualPointerHandler,
D: 'static, D: 'static,
{ {
@@ -79,7 +334,7 @@ where
impl<D> Dispatch<ZwlrVirtualPointerManagerV1, (), D> for VirtualPointerManagerState impl<D> Dispatch<ZwlrVirtualPointerManagerV1, (), D> for VirtualPointerManagerState
where where
D: Dispatch<ZwlrVirtualPointerManagerV1, ()>, D: Dispatch<ZwlrVirtualPointerManagerV1, ()>,
D: Dispatch<ZwlrVirtualPointerV1, VirtualPointerState>, D: Dispatch<ZwlrVirtualPointerV1, VirtualPointerUserData>,
D: VirtualPointerHandler, D: VirtualPointerHandler,
D: 'static, D: 'static,
{ {
@@ -92,44 +347,63 @@ where
_dhandle: &DisplayHandle, _dhandle: &DisplayHandle,
data_init: &mut DataInit<'_, D>, data_init: &mut DataInit<'_, D>,
) { ) {
match request { let (id, seat, output) = match request {
zwlr_virtual_pointer_manager_v1::Request::CreateVirtualPointer { seat, id } => { zwlr_virtual_pointer_manager_v1::Request::CreateVirtualPointer { seat, id } => {
let virtual_pointer = data_init.init(id, VirtualPointerState {}); (id, seat, None)
state.virtual_pointer_manager_state().virtual_pointers.push(virtual_pointer);
} }
zwlr_virtual_pointer_manager_v1::Request::CreateVirtualPointerWithOutput { zwlr_virtual_pointer_manager_v1::Request::CreateVirtualPointerWithOutput {
seat, seat,
output, output,
id, id,
} => { } => (id, seat, output),
info!("CreateVirtualPointerWithOutput"); zwlr_virtual_pointer_manager_v1::Request::Destroy => return,
let virtual_pointer = data_init.init(id, VirtualPointerState {});
state.virtual_pointer_manager_state().virtual_pointers.push(virtual_pointer);
}
zwlr_virtual_pointer_manager_v1::Request::Destroy => {}
_ => unreachable!(), _ => unreachable!(),
} };
let pointer = data_init.init(
id,
VirtualPointerUserData {
seat,
output,
axis_frame: Mutex::new(None),
},
);
state
.virtual_pointer_manager_state()
.virtual_pointers
.insert(pointer.clone());
state.create_virtual_pointer(VirtualPointer { pointer });
} }
} }
impl<D> Dispatch<ZwlrVirtualPointerV1, VirtualPointerState, D> for VirtualPointerManagerState impl<D> Dispatch<ZwlrVirtualPointerV1, VirtualPointerUserData, D> for VirtualPointerManagerState
where where
D: Dispatch<ZwlrVirtualPointerV1, VirtualPointerState>, D: Dispatch<ZwlrVirtualPointerV1, VirtualPointerUserData>,
D: VirtualPointerHandler, D: VirtualPointerHandler,
D: 'static, D: 'static,
{ {
fn request( fn request(
state: &mut D, handler: &mut D,
_client: &Client, _client: &Client,
resource: &ZwlrVirtualPointerV1, resource: &ZwlrVirtualPointerV1,
request: <ZwlrVirtualPointerV1 as Resource>::Request, request: <ZwlrVirtualPointerV1 as Resource>::Request,
data: &VirtualPointerState, _data: &VirtualPointerUserData,
_dhandle: &DisplayHandle, _dhandle: &DisplayHandle,
_data_init: &mut DataInit<'_, D>, _data_init: &mut DataInit<'_, D>,
) { ) {
let pointer = VirtualPointer {
pointer: resource.clone(),
};
match request { match request {
zwlr_virtual_pointer_v1::Request::Motion { time, dx, dy } => { zwlr_virtual_pointer_v1::Request::Motion { time, dx, dy } => {
info!("Motion: {dx},{dy}"); let event = VirtualPointerMotionEvent {
pointer,
time,
dx,
dy,
};
handler.on_virtual_pointer_motion(event);
} }
zwlr_virtual_pointer_v1::Request::MotionAbsolute { zwlr_virtual_pointer_v1::Request::MotionAbsolute {
time, time,
@@ -138,26 +412,93 @@ where
x_extent, x_extent,
y_extent, y_extent,
} => { } => {
info!("MotionAbsolute: {x}({x_extent}),{y}({y_extent})"); let event = VirtualPointerMotionAbsoluteEvent {
pointer,
time,
x,
y,
x_extent,
y_extent,
};
handler.on_virtual_pointer_motion_absolute(event);
} }
zwlr_virtual_pointer_v1::Request::Button { zwlr_virtual_pointer_v1::Request::Button {
time, time,
button, button,
state, state,
} => { } => {
info!("Button: {button} / {state:?}"); // state is an enum but wlroots treats it as a C boolean (zero or nonzero)
// so we emulate that behaviour too. ButtonState::Pressed and any invalid value
// counts as pressed.
// https://gitlab.freedesktop.org/wlroots/wlroots/-/blob/3187479c07c34a4de82c06a316a763a36a0499da/types/wlr_virtual_pointer_v1.c#L74
let state = match state {
WEnum::Value(wl_pointer::ButtonState::Released) => ButtonState::Released,
_ => ButtonState::Pressed,
};
let event = VirtualPointerButtonEvent {
pointer,
time,
button,
state,
};
handler.on_virtual_pointer_button(event);
} }
zwlr_virtual_pointer_v1::Request::Axis { time, axis, value } => { zwlr_virtual_pointer_v1::Request::Axis { time, axis, value } => {
info!("Axis: {axis:?} / {value}"); let axis = match axis {
WEnum::Value(wl_pointer::Axis::VerticalScroll) => Axis::Vertical,
WEnum::Value(wl_pointer::Axis::HorizontalScroll) => Axis::Horizontal,
_ => {
warn!("Axis: invalid axis");
resource.post_error(
zwlr_virtual_pointer_v1::Error::InvalidAxis,
"invalid axis",
);
return;
}
};
pointer.mutate_axis_frame(Some(time), |frame| frame.value(axis, value));
} }
zwlr_virtual_pointer_v1::Request::Frame => { zwlr_virtual_pointer_v1::Request::Frame => {
info!("Frame"); if let Some(frame) = pointer.finish_axis_frame() {
let event = VirtualPointerAxisEvent { pointer, frame };
handler.on_virtual_pointer_axis(event);
}
} }
zwlr_virtual_pointer_v1::Request::AxisSource { axis_source } => { zwlr_virtual_pointer_v1::Request::AxisSource { axis_source } => {
info!("AxisSource: {axis_source:?}"); let axis_source = match axis_source {
WEnum::Value(wl_pointer::AxisSource::Wheel) => AxisSource::Wheel,
WEnum::Value(wl_pointer::AxisSource::Finger) => AxisSource::Finger,
WEnum::Value(wl_pointer::AxisSource::Continuous) => AxisSource::Continuous,
WEnum::Value(wl_pointer::AxisSource::WheelTilt) => AxisSource::WheelTilt,
_ => {
warn!("AxisSource: invalid axis source");
resource.post_error(
zwlr_virtual_pointer_v1::Error::InvalidAxisSource,
"invalid axis source",
);
return;
}
};
pointer.mutate_axis_frame(None, |frame| frame.source(axis_source));
} }
zwlr_virtual_pointer_v1::Request::AxisStop { time, axis } => { zwlr_virtual_pointer_v1::Request::AxisStop { time, axis } => {
info!("AxisStop: {axis:?}"); let axis = match axis {
WEnum::Value(wl_pointer::Axis::VerticalScroll) => Axis::Vertical,
WEnum::Value(wl_pointer::Axis::HorizontalScroll) => Axis::Horizontal,
_ => {
warn!("AxisStop: invalid axis");
resource.post_error(
zwlr_virtual_pointer_v1::Error::InvalidAxis,
"invalid axis",
);
return;
}
};
pointer.mutate_axis_frame(Some(time), |frame| frame.stop(axis));
} }
zwlr_virtual_pointer_v1::Request::AxisDiscrete { zwlr_virtual_pointer_v1::Request::AxisDiscrete {
time, time,
@@ -165,14 +506,43 @@ where
value, value,
discrete, discrete,
} => { } => {
info!("AxisDiscrete: {axis:?} / {value} / {discrete}"); let axis = match axis {
WEnum::Value(wl_pointer::Axis::VerticalScroll) => Axis::Vertical,
WEnum::Value(wl_pointer::Axis::HorizontalScroll) => Axis::Horizontal,
_ => {
warn!("AxisDiscrete: invalid axis");
resource.post_error(
zwlr_virtual_pointer_v1::Error::InvalidAxis,
"invalid axis",
);
return;
} }
zwlr_virtual_pointer_v1::Request::Destroy => { };
info!("Destroy"); pointer.mutate_axis_frame(Some(time), |frame| {
frame.value(axis, value).v120(axis, discrete)
});
} }
zwlr_virtual_pointer_v1::Request::Destroy => {}
_ => unreachable!(), _ => unreachable!(),
} }
} }
fn destroyed(
handler: &mut D,
_client: wayland_backend::server::ClientId,
resource: &ZwlrVirtualPointerV1,
_data: &VirtualPointerUserData,
) {
let pointer = VirtualPointer {
pointer: resource.clone(),
};
handler.destroy_virtual_pointer(pointer);
handler
.virtual_pointer_manager_state()
.virtual_pointers
.remove(resource);
}
} }
#[macro_export] #[macro_export]
@@ -187,7 +557,7 @@ macro_rules! delegate_virtual_pointer {
] => $crate::protocols::virtual_pointer::VirtualPointerManagerState); ] => $crate::protocols::virtual_pointer::VirtualPointerManagerState);
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
smithay::reexports::wayland_protocols_wlr::virtual_pointer::v1::server::zwlr_virtual_pointer_v1::ZwlrVirtualPointerV1: $crate::protocols::virtual_pointer::VirtualPointerState smithay::reexports::wayland_protocols_wlr::virtual_pointer::v1::server::zwlr_virtual_pointer_v1::ZwlrVirtualPointerV1: $crate::protocols::virtual_pointer::VirtualPointerUserData
] => $crate::protocols::virtual_pointer::VirtualPointerManagerState); ] => $crate::protocols::virtual_pointer::VirtualPointerManagerState);
}; };
} }