winit-core:winit: add tablet input support
The API is integrated into the `WindowEvent::Pointer*` API and is present in form of `TabletTool` variant on corresponding data entries. For now implemented for Web, Windows, and with limitations for Wayland. Fixes #99. Co-authored-by: daxpedda <daxpedda@gmail.com>
This commit is contained in:
parent
ffcdf80192
commit
f046e778aa
23 changed files with 1206 additions and 204 deletions
|
|
@ -103,7 +103,14 @@ atom_manager! {
|
|||
_NET_SUPPORTED,
|
||||
_NET_SUPPORTING_WM_CHECK,
|
||||
_XEMBED,
|
||||
_XSETTINGS_SETTINGS
|
||||
_XSETTINGS_SETTINGS,
|
||||
|
||||
// Stylus Atoms
|
||||
ABS_X: b"Abs X",
|
||||
ABS_Y: b"Abs Y",
|
||||
ABS_PRESSURE: b"Abs Pressure",
|
||||
ABS_TILT_X: b"Abs Tilt X",
|
||||
ABS_TILT_Y: b"Abs Tilt Y"
|
||||
}
|
||||
|
||||
impl Index<AtomName> for Atoms {
|
||||
|
|
|
|||
|
|
@ -1006,6 +1006,15 @@ pub struct Device {
|
|||
// For master devices, this is the paired device (pointer <-> keyboard).
|
||||
// For slave devices, this is the master.
|
||||
pub(crate) attachment: c_int,
|
||||
pub(crate) r#type: DeviceType,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub(crate) enum DeviceType {
|
||||
Mouse,
|
||||
Touch,
|
||||
Pen,
|
||||
Eraser,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
|
@ -1022,9 +1031,10 @@ pub(crate) enum ScrollOrientation {
|
|||
}
|
||||
|
||||
impl Device {
|
||||
pub(crate) fn new(info: &ffi::XIDeviceInfo) -> Self {
|
||||
pub(crate) fn new(info: &ffi::XIDeviceInfo, atoms: &Atoms) -> Self {
|
||||
let name = unsafe { CStr::from_ptr(info.name).to_string_lossy() };
|
||||
let mut scroll_axes = Vec::new();
|
||||
let mut r#type = None;
|
||||
|
||||
if Device::physical_device(info) {
|
||||
// Identify scroll axes
|
||||
|
|
@ -1041,12 +1051,34 @@ impl Device {
|
|||
},
|
||||
position: 0.0,
|
||||
}));
|
||||
} else if ty == ffi::XITouchClass {
|
||||
r#type = Some(DeviceType::Touch);
|
||||
} else if r#type.is_none() && ty == ffi::XIValuatorClass {
|
||||
let info = unsafe { &*(class_ptr as *const ffi::XIValuatorClassInfo) };
|
||||
let atom = info.label as xproto::Atom;
|
||||
|
||||
if atom == atoms[ABS_X]
|
||||
|| atom == atoms[ABS_Y]
|
||||
|| atom == atoms[ABS_PRESSURE]
|
||||
|| atom == atoms[ABS_TILT_X]
|
||||
|| atom == atoms[ABS_TILT_Y]
|
||||
{
|
||||
if name.contains("eraser") {
|
||||
r#type = Some(DeviceType::Eraser);
|
||||
} else {
|
||||
r#type = Some(DeviceType::Pen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut device =
|
||||
Device { _name: name.into_owned(), scroll_axes, attachment: info.attachment };
|
||||
let mut device = Device {
|
||||
_name: name.into_owned(),
|
||||
scroll_axes,
|
||||
attachment: info.attachment,
|
||||
r#type: r#type.unwrap_or(DeviceType::Mouse),
|
||||
};
|
||||
device.reset_scroll_position(info);
|
||||
device
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ use xkbcommon_dl::xkb_mod_mask_t;
|
|||
use crate::atoms::*;
|
||||
use crate::dnd::{Dnd, DndState};
|
||||
use crate::event_loop::{
|
||||
mkdid, mkwid, ActiveEventLoop, CookieResultExt, Device, DeviceInfo, ScrollOrientation,
|
||||
ALL_DEVICES,
|
||||
mkdid, mkwid, ActiveEventLoop, CookieResultExt, Device, DeviceInfo, DeviceType,
|
||||
ScrollOrientation, ALL_DEVICES,
|
||||
};
|
||||
use crate::ime::{ImeEvent, ImeEventReceiver, ImeReceiver, ImeRequest};
|
||||
use crate::util;
|
||||
|
|
@ -323,8 +323,10 @@ impl EventProcessor {
|
|||
pub fn init_device(&self, device: xinput::DeviceId) {
|
||||
let mut devices = self.devices.borrow_mut();
|
||||
if let Some(info) = DeviceInfo::get(&self.target.xconn, device as _) {
|
||||
let atoms = self.target.x_connection().atoms();
|
||||
|
||||
for info in info.iter() {
|
||||
devices.insert(mkdid(info.deviceid as xinput::DeviceId), Device::new(info));
|
||||
devices.insert(mkdid(info.deviceid as xinput::DeviceId), Device::new(info, atoms));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -974,6 +976,15 @@ impl EventProcessor {
|
|||
// Set the timestamp.
|
||||
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
|
||||
let Some(DeviceType::Mouse) = self
|
||||
.devices
|
||||
.borrow()
|
||||
.get(&mkdid(event.sourceid as xinput::DeviceId))
|
||||
.map(|device| device.r#type)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Deliver multi-touch events instead of emulated mouse events.
|
||||
if (event.flags & xinput2::XIPointerEmulated) != 0 {
|
||||
return;
|
||||
|
|
@ -1051,6 +1062,15 @@ impl EventProcessor {
|
|||
// Set the timestamp.
|
||||
self.target.xconn.set_timestamp(event.time as xproto::Timestamp);
|
||||
|
||||
let Some(DeviceType::Mouse) = self
|
||||
.devices
|
||||
.borrow()
|
||||
.get(&mkdid(event.sourceid as xinput::DeviceId))
|
||||
.map(|device| device.r#type)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let device_id = Some(mkdid(event.deviceid as xinput::DeviceId));
|
||||
let window = event.event as xproto::Window;
|
||||
let window_id = mkwid(window);
|
||||
|
|
@ -1376,7 +1396,6 @@ impl EventProcessor {
|
|||
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);
|
||||
|
||||
let did = Some(mkdid(xev.deviceid as xinput::DeviceId));
|
||||
|
||||
let mask =
|
||||
unsafe { slice::from_raw_parts(xev.valuators.mask, xev.valuators.mask_len as usize) };
|
||||
let mut value = xev.raw_values;
|
||||
|
|
@ -1401,6 +1420,15 @@ impl EventProcessor {
|
|||
value = unsafe { value.offset(1) };
|
||||
}
|
||||
|
||||
let Some(DeviceType::Mouse) = self
|
||||
.devices
|
||||
.borrow()
|
||||
.get(&mkdid(xev.sourceid as xinput::DeviceId))
|
||||
.map(|device| device.r#type)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(mouse_delta) = mouse_delta.consume() {
|
||||
app.device_event(&self.target, did, DeviceEvent::PointerMotion { delta: mouse_delta });
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue