mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
implement virtual-pointer
This commit is contained in:
committed by
Ivan Molodetskikh
parent
3ff900eab8
commit
79f22053b9
+24
-2
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user