Merge pull request #435 from mahkoh/jorth/tablet-v2
tablet: implement version 2
This commit is contained in:
commit
4b9e5e3d25
26 changed files with 427 additions and 34 deletions
|
|
@ -188,7 +188,7 @@ Jay supports the following wayland protocols:
|
|||
| zwp_pointer_gestures_v1 | 3 | |
|
||||
| zwp_primary_selection_device_manager_v1 | 1 | |
|
||||
| zwp_relative_pointer_manager_v1 | 1 | |
|
||||
| zwp_tablet_manager_v2 | 1 | |
|
||||
| zwp_tablet_manager_v2 | 2 | |
|
||||
| zwp_text_input_manager_v3 | 1 | |
|
||||
| zwp_virtual_keyboard_manager_v1 | 1 | Yes |
|
||||
| zxdg_decoration_manager_v1 | 1 | |
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
- Floating windows can now be configured to be shown above fullscreen windows
|
||||
by using the `enable-float-above-fullscreen` action.
|
||||
- Implement xdg-toplevel-tag-v1.
|
||||
- Implement tablet-v2 version 2.
|
||||
|
||||
# 1.10.0 (2025-04-22)
|
||||
|
||||
|
|
|
|||
|
|
@ -430,6 +430,12 @@ pub enum InputEvent {
|
|||
source: Option<TabletStripEventSource>,
|
||||
position: Option<f64>,
|
||||
},
|
||||
TabletPadDial {
|
||||
time_usec: u64,
|
||||
pad: TabletPadId,
|
||||
dial: u32,
|
||||
value120: i32,
|
||||
},
|
||||
TouchDown {
|
||||
time_usec: u64,
|
||||
id: i32,
|
||||
|
|
|
|||
|
|
@ -697,6 +697,7 @@ impl InputDevice for MetalInputDevice {
|
|||
name: dev.name(),
|
||||
pid: dev.product(),
|
||||
vid: dev.vendor(),
|
||||
bustype: dev.bustype(),
|
||||
path: self.syspath.as_bytes().as_bstr().to_string(),
|
||||
}))
|
||||
}
|
||||
|
|
@ -718,6 +719,7 @@ impl InputDevice for MetalInputDevice {
|
|||
let buttons = dev.pad_num_buttons();
|
||||
let strips = dev.pad_num_strips();
|
||||
let rings = dev.pad_num_rings();
|
||||
let dials = dev.pad_num_dials();
|
||||
let mut groups = vec![];
|
||||
for n in 0..dev.pad_num_mode_groups() {
|
||||
let Some(group) = dev.pad_mode_group(n) else {
|
||||
|
|
@ -727,6 +729,7 @@ impl InputDevice for MetalInputDevice {
|
|||
buttons: (0..buttons).filter(|b| group.has_button(*b)).collect(),
|
||||
rings: (0..rings).filter(|b| group.has_ring(*b)).collect(),
|
||||
strips: (0..strips).filter(|b| group.has_strip(*b)).collect(),
|
||||
dials: (0..dials).filter(|b| group.has_dial(*b)).collect(),
|
||||
modes: group.num_modes(),
|
||||
mode: group.mode(),
|
||||
});
|
||||
|
|
@ -738,6 +741,7 @@ impl InputDevice for MetalInputDevice {
|
|||
buttons,
|
||||
strips,
|
||||
rings,
|
||||
dials,
|
||||
groups,
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ impl MetalBackend {
|
|||
break;
|
||||
}
|
||||
Ok(n) if n.intersects(c::POLLERR | c::POLLHUP) => {
|
||||
log::error!("libinput fd fd is in an error state");
|
||||
log::error!("libinput fd is in an error state");
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -121,6 +121,7 @@ impl MetalBackend {
|
|||
c::LIBINPUT_EVENT_TABLET_PAD_BUTTON => self.handle_tablet_pad_button(event),
|
||||
c::LIBINPUT_EVENT_TABLET_PAD_RING => self.handle_tablet_pad_ring(event),
|
||||
c::LIBINPUT_EVENT_TABLET_PAD_STRIP => self.handle_tablet_pad_strip(event),
|
||||
c::LIBINPUT_EVENT_TABLET_PAD_DIAL => self.handle_tablet_pad_dial(event),
|
||||
c::LIBINPUT_EVENT_TOUCH_DOWN => self.handle_touch_down(event),
|
||||
c::LIBINPUT_EVENT_TOUCH_UP => self.handle_touch_up(event),
|
||||
c::LIBINPUT_EVENT_TOUCH_MOTION => self.handle_touch_motion(event),
|
||||
|
|
@ -545,6 +546,25 @@ impl MetalBackend {
|
|||
});
|
||||
}
|
||||
|
||||
fn handle_tablet_pad_dial(self: &Rc<Self>, event: LibInputEvent) {
|
||||
let (event, dev) = unpack!(self, event, tablet_pad_event);
|
||||
let Some(dial) = event.dial_number() else {
|
||||
return;
|
||||
};
|
||||
let Some(value120) = event.dial_delta_v120() else {
|
||||
return;
|
||||
};
|
||||
dev.event(InputEvent::TabletPadDial {
|
||||
time_usec: event.time_usec(),
|
||||
pad: match dev.tablet_pad_id.get() {
|
||||
None => return,
|
||||
Some(id) => id,
|
||||
},
|
||||
dial,
|
||||
value120: value120 as _,
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_touch_down(self: &Rc<Self>, event: LibInputEvent) {
|
||||
let (event, dev) = unpack!(self, event, touch_event);
|
||||
dev.event(InputEvent::TouchDown {
|
||||
|
|
|
|||
|
|
@ -12,13 +12,13 @@ use {
|
|||
Axis120, AxisFrame, AxisInverted, AxisPx, AxisSource, AxisStop, Button, HoldBegin,
|
||||
HoldEnd, Key, Modifiers, PinchBegin, PinchEnd, PinchUpdate, PointerAbs, PointerRel,
|
||||
SwipeBegin, SwipeEnd, SwipeUpdate, SwitchEvent, TabletPadButton,
|
||||
TabletPadModeSwitch, TabletPadRingAngle, TabletPadRingFrame, TabletPadRingSource,
|
||||
TabletPadRingStop, TabletPadStripFrame, TabletPadStripPosition,
|
||||
TabletPadStripSource, TabletPadStripStop, TabletToolButton, TabletToolDistance,
|
||||
TabletToolDown, TabletToolFrame, TabletToolMotion, TabletToolPressure,
|
||||
TabletToolProximityIn, TabletToolProximityOut, TabletToolRotation,
|
||||
TabletToolSlider, TabletToolTilt, TabletToolUp, TabletToolWheel, TouchCancel,
|
||||
TouchDown, TouchMotion, TouchUp,
|
||||
TabletPadDialDelta, TabletPadDialFrame, TabletPadModeSwitch, TabletPadRingAngle,
|
||||
TabletPadRingFrame, TabletPadRingSource, TabletPadRingStop, TabletPadStripFrame,
|
||||
TabletPadStripPosition, TabletPadStripSource, TabletPadStripStop, TabletToolButton,
|
||||
TabletToolDistance, TabletToolDown, TabletToolFrame, TabletToolMotion,
|
||||
TabletToolPressure, TabletToolProximityIn, TabletToolProximityOut,
|
||||
TabletToolRotation, TabletToolSlider, TabletToolTilt, TabletToolUp,
|
||||
TabletToolWheel, TouchCancel, TouchDown, TouchMotion, TouchUp,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -82,6 +82,11 @@ pub struct PendingTabletPadRing {
|
|||
stop: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Copy, Clone)]
|
||||
pub struct PendingTabletPadDial {
|
||||
value120: Option<i32>,
|
||||
}
|
||||
|
||||
async fn run(seat_test: Rc<SeatTest>) {
|
||||
let tc = &seat_test.tc;
|
||||
let comp = tc.jay_compositor().await;
|
||||
|
|
@ -586,6 +591,30 @@ async fn run(seat_test: Rc<SeatTest>) {
|
|||
}
|
||||
println!();
|
||||
});
|
||||
let tt = Rc::new(RefCell::new(PendingTabletPadDial::default()));
|
||||
TabletPadDialDelta::handle(tc, se, tt.clone(), move |tt, ev| {
|
||||
tt.borrow_mut().value120 = Some(ev.value120);
|
||||
});
|
||||
let st = seat_test.clone();
|
||||
TabletPadDialFrame::handle(tc, se, tt.clone(), move |tt, ev| {
|
||||
let tt = tt.take();
|
||||
if !all && ev.seat != seat {
|
||||
return;
|
||||
}
|
||||
if all {
|
||||
print!("Seat: {}, ", st.name(ev.seat));
|
||||
}
|
||||
print!(
|
||||
"Time: {:.4}, Device: {}, Dial: {}",
|
||||
time(ev.time_usec),
|
||||
ev.input_device,
|
||||
ev.dial,
|
||||
);
|
||||
if let Some(val) = tt.value120 {
|
||||
print!(", delta: {val}/120");
|
||||
}
|
||||
println!();
|
||||
});
|
||||
let st = seat_test.clone();
|
||||
TouchDown::handle(tc, se, (), move |_, ev| {
|
||||
if all || ev.seat == seat {
|
||||
|
|
|
|||
|
|
@ -470,6 +470,27 @@ impl JaySeatEvents {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn send_tablet_pad_dial(
|
||||
&self,
|
||||
seat: SeatId,
|
||||
pad: InputDeviceId,
|
||||
time_usec: u64,
|
||||
value120: i32,
|
||||
dial: u32,
|
||||
) {
|
||||
self.client.event(TabletPadDialDelta {
|
||||
self_id: self.id,
|
||||
value120,
|
||||
});
|
||||
self.client.event(TabletPadDialFrame {
|
||||
self_id: self.id,
|
||||
seat: seat.raw(),
|
||||
time_usec,
|
||||
input_device: pad.raw(),
|
||||
dial,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_touch_down(&self, seat: SeatId, time_usec: u64, id: i32, x: Fixed, y: Fixed) {
|
||||
self.client.event(TouchDown {
|
||||
self_id: self.id,
|
||||
|
|
|
|||
|
|
@ -266,6 +266,7 @@ impl WlSeatGlobal {
|
|||
| InputEvent::TabletPadModeSwitch { time_usec, .. }
|
||||
| InputEvent::TabletPadRing { time_usec, .. }
|
||||
| InputEvent::TabletPadStrip { time_usec, .. }
|
||||
| InputEvent::TabletPadDial { time_usec, .. }
|
||||
| InputEvent::TouchFrame { time_usec, .. } => {
|
||||
self.last_input_usec.set(time_usec);
|
||||
if self.idle_notifications.is_not_empty() {
|
||||
|
|
@ -314,6 +315,7 @@ impl WlSeatGlobal {
|
|||
InputEvent::TabletPadModeSwitch { .. } => {}
|
||||
InputEvent::TabletPadRing { .. } => {}
|
||||
InputEvent::TabletPadStrip { .. } => {}
|
||||
InputEvent::TabletPadDial { .. } => {}
|
||||
InputEvent::TouchDown { .. } => {}
|
||||
InputEvent::TouchUp { .. } => {}
|
||||
InputEvent::TouchMotion { .. } => {}
|
||||
|
|
@ -458,6 +460,12 @@ impl WlSeatGlobal {
|
|||
source,
|
||||
position,
|
||||
} => self.tablet_event_pad_strip(pad, strip, source, position, time_usec),
|
||||
InputEvent::TabletPadDial {
|
||||
time_usec,
|
||||
pad,
|
||||
dial,
|
||||
value120,
|
||||
} => self.tablet_event_pad_dial(pad, dial, value120, time_usec),
|
||||
InputEvent::TouchDown {
|
||||
time_usec,
|
||||
id,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ use {
|
|||
WlSeatGlobal,
|
||||
tablet::{
|
||||
pad_owner::PadOwnerHolder, tablet_bindings::TabletBindings,
|
||||
tool_owner::ToolOwnerHolder, zwp_tablet_pad_group_v2::ZwpTabletPadGroupV2,
|
||||
tool_owner::ToolOwnerHolder, zwp_tablet_pad_dial_v2::ZwpTabletPadDialV2,
|
||||
zwp_tablet_pad_group_v2::ZwpTabletPadGroupV2,
|
||||
zwp_tablet_pad_ring_v2::ZwpTabletPadRingV2,
|
||||
zwp_tablet_pad_strip_v2::ZwpTabletPadStripV2,
|
||||
zwp_tablet_pad_v2::ZwpTabletPadV2, zwp_tablet_seat_v2::ZwpTabletSeatV2,
|
||||
|
|
@ -35,6 +36,7 @@ mod tablet_bindings;
|
|||
mod tool;
|
||||
pub mod tool_owner;
|
||||
pub mod zwp_tablet_manager_v2;
|
||||
pub mod zwp_tablet_pad_dial_v2;
|
||||
pub mod zwp_tablet_pad_group_v2;
|
||||
pub mod zwp_tablet_pad_ring_v2;
|
||||
pub mod zwp_tablet_pad_strip_v2;
|
||||
|
|
@ -58,6 +60,7 @@ pub struct TabletInit {
|
|||
pub name: String,
|
||||
pub pid: u32,
|
||||
pub vid: u32,
|
||||
pub bustype: Option<u32>,
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
|
|
@ -79,6 +82,7 @@ pub struct TabletPadInit {
|
|||
pub buttons: u32,
|
||||
pub strips: u32,
|
||||
pub rings: u32,
|
||||
pub dials: u32,
|
||||
pub groups: Vec<TabletPadGroupInit>,
|
||||
}
|
||||
|
||||
|
|
@ -87,6 +91,7 @@ pub struct TabletPadGroupInit {
|
|||
pub buttons: Vec<u32>,
|
||||
pub rings: Vec<u32>,
|
||||
pub strips: Vec<u32>,
|
||||
pub dials: Vec<u32>,
|
||||
pub modes: u32,
|
||||
pub mode: u32,
|
||||
}
|
||||
|
|
@ -112,6 +117,7 @@ pub struct Tablet {
|
|||
name: String,
|
||||
pid: u32,
|
||||
vid: u32,
|
||||
bustype: Option<u32>,
|
||||
path: String,
|
||||
bindings: TabletBindings<ZwpTabletV2>,
|
||||
tools: CopyHashMap<TabletToolId, Rc<TabletTool>>,
|
||||
|
|
@ -186,6 +192,7 @@ pub struct TabletPad {
|
|||
groups: Vec<Rc<TabletPadGroup>>,
|
||||
strips: Vec<Rc<TabletPadStrip>>,
|
||||
rings: Vec<Rc<TabletPadRing>>,
|
||||
dials: Vec<Rc<TabletPadDial>>,
|
||||
node: CloneCell<Rc<dyn Node>>,
|
||||
pub(super) pad_owner: PadOwnerHolder,
|
||||
}
|
||||
|
|
@ -196,6 +203,7 @@ pub struct TabletPadGroup {
|
|||
modes: u32,
|
||||
rings: Vec<u32>,
|
||||
strips: Vec<u32>,
|
||||
dials: Vec<u32>,
|
||||
bindings: TabletBindings<ZwpTabletPadGroupV2>,
|
||||
}
|
||||
|
||||
|
|
@ -207,6 +215,10 @@ pub struct TabletPadRing {
|
|||
bindings: TabletBindings<ZwpTabletPadRingV2>,
|
||||
}
|
||||
|
||||
pub struct TabletPadDial {
|
||||
bindings: TabletBindings<ZwpTabletPadDialV2>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum TabletRingEventSource {
|
||||
Finger,
|
||||
|
|
@ -269,6 +281,7 @@ impl WlSeatGlobal {
|
|||
name: init.name.clone(),
|
||||
pid: init.pid,
|
||||
vid: init.vid,
|
||||
bustype: init.bustype,
|
||||
path: init.path.clone(),
|
||||
bindings: Default::default(),
|
||||
tools: Default::default(),
|
||||
|
|
@ -319,6 +332,9 @@ impl WlSeatGlobal {
|
|||
for strips in &pad.strips {
|
||||
strips.bindings.clear();
|
||||
}
|
||||
for dials in &pad.dials {
|
||||
dials.bindings.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ use {
|
|||
wl_seat::{
|
||||
WlSeatGlobal,
|
||||
tablet::{
|
||||
PadButtonState, TabletPad, TabletPadGroup, TabletPadId, TabletPadInit,
|
||||
TabletPadRing, TabletPadStrip, TabletRingEventSource, TabletStripEventSource,
|
||||
normalizeu, zwp_tablet_pad_v2::ZwpTabletPadV2, zwp_tablet_v2::ZwpTabletV2,
|
||||
PadButtonState, TabletPad, TabletPadDial, TabletPadGroup, TabletPadId,
|
||||
TabletPadInit, TabletPadRing, TabletPadStrip, TabletRingEventSource,
|
||||
TabletStripEventSource, normalizeu, zwp_tablet_pad_v2::ZwpTabletPadV2,
|
||||
zwp_tablet_v2::ZwpTabletV2,
|
||||
},
|
||||
},
|
||||
wl_surface::WlSurface,
|
||||
|
|
@ -33,6 +34,12 @@ impl WlSeatGlobal {
|
|||
bindings: Default::default(),
|
||||
}));
|
||||
}
|
||||
let mut dials = Vec::new();
|
||||
for _ in 0..init.dials {
|
||||
dials.push(Rc::new(TabletPadDial {
|
||||
bindings: Default::default(),
|
||||
}));
|
||||
}
|
||||
let mut groups = Vec::new();
|
||||
for group_init in &init.groups {
|
||||
groups.push(Rc::new(TabletPadGroup {
|
||||
|
|
@ -41,6 +48,7 @@ impl WlSeatGlobal {
|
|||
modes: group_init.modes,
|
||||
rings: group_init.rings.clone(),
|
||||
strips: group_init.strips.clone(),
|
||||
dials: group_init.dials.clone(),
|
||||
bindings: Default::default(),
|
||||
}));
|
||||
}
|
||||
|
|
@ -56,6 +64,7 @@ impl WlSeatGlobal {
|
|||
groups,
|
||||
strips,
|
||||
rings,
|
||||
dials,
|
||||
node: CloneCell::new(self.state.root.clone()),
|
||||
pad_owner: Default::default(),
|
||||
});
|
||||
|
|
@ -161,6 +170,26 @@ impl WlSeatGlobal {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tablet_event_pad_dial(
|
||||
self: &Rc<Self>,
|
||||
pad: TabletPadId,
|
||||
dial: u32,
|
||||
value120: i32,
|
||||
time_usec: u64,
|
||||
) {
|
||||
if let Some(pad) = self.tablet.pads.get(&pad) {
|
||||
self.state.for_each_seat_tester(|t| {
|
||||
t.send_tablet_pad_dial(self.id, pad.dev, time_usec, value120, dial)
|
||||
});
|
||||
if pad.tablet.is_some() {
|
||||
if let Some(dial) = pad.dials.get(dial as usize) {
|
||||
let node = self.keyboard_node.get();
|
||||
node.node_on_tablet_pad_dial(&pad, dial, value120, time_usec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TabletPad {
|
||||
|
|
@ -235,6 +264,22 @@ impl TabletPad {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn surface_dial(
|
||||
self: &Rc<Self>,
|
||||
n: &WlSurface,
|
||||
dial: &Rc<TabletPadDial>,
|
||||
value120: i32,
|
||||
time_usec: u64,
|
||||
) {
|
||||
let time = usec_to_msec(time_usec);
|
||||
self.seat.tablet_for_each_seat(n, |s| {
|
||||
if let Some(dial) = dial.bindings.get(&s) {
|
||||
dial.send_delta(value120);
|
||||
dial.send_frame(time);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn surface_strip(
|
||||
self: &Rc<Self>,
|
||||
n: &WlSurface,
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ impl Global for ZwpTabletManagerV2Global {
|
|||
}
|
||||
|
||||
fn version(&self) -> u32 {
|
||||
1
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
74
src/ifs/wl_seat/tablet/zwp_tablet_pad_dial_v2.rs
Normal file
74
src/ifs/wl_seat/tablet/zwp_tablet_pad_dial_v2.rs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
use {
|
||||
crate::{
|
||||
client::{Client, ClientError},
|
||||
ifs::wl_seat::tablet::{TabletPadDial, zwp_tablet_seat_v2::ZwpTabletSeatV2},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
wire::{ZwpTabletPadDialV2Id, zwp_tablet_pad_dial_v2::*},
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct ZwpTabletPadDialV2 {
|
||||
pub id: ZwpTabletPadDialV2Id,
|
||||
pub client: Rc<Client>,
|
||||
pub tracker: Tracker<Self>,
|
||||
pub version: Version,
|
||||
pub seat: Rc<ZwpTabletSeatV2>,
|
||||
pub dial: Rc<TabletPadDial>,
|
||||
}
|
||||
|
||||
impl ZwpTabletPadDialV2 {
|
||||
pub fn detach(&self) {
|
||||
self.dial.bindings.remove(&self.seat);
|
||||
}
|
||||
|
||||
pub fn send_delta(&self, value120: i32) {
|
||||
self.client.event(Delta {
|
||||
self_id: self.id,
|
||||
value120,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_frame(&self, time: u32) {
|
||||
self.client.event(Frame {
|
||||
self_id: self.id,
|
||||
time,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl ZwpTabletPadDialV2RequestHandler for ZwpTabletPadDialV2 {
|
||||
type Error = ZwpTabletPadDialV2Error;
|
||||
|
||||
fn set_feedback(&self, _req: SetFeedback<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.detach();
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
self = ZwpTabletPadDialV2;
|
||||
version = self.version;
|
||||
}
|
||||
|
||||
impl Object for ZwpTabletPadDialV2 {
|
||||
fn break_loops(&self) {
|
||||
self.detach();
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_obj!(ZwpTabletPadDialV2);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ZwpTabletPadDialV2Error {
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(ZwpTabletPadDialV2Error, ClientError);
|
||||
|
|
@ -2,7 +2,8 @@ use {
|
|||
crate::{
|
||||
client::{Client, ClientError},
|
||||
ifs::wl_seat::tablet::{
|
||||
TabletPadGroup, zwp_tablet_pad_ring_v2::ZwpTabletPadRingV2,
|
||||
TabletPadGroup, zwp_tablet_pad_dial_v2::ZwpTabletPadDialV2,
|
||||
zwp_tablet_pad_ring_v2::ZwpTabletPadRingV2,
|
||||
zwp_tablet_pad_strip_v2::ZwpTabletPadStripV2, zwp_tablet_seat_v2::ZwpTabletSeatV2,
|
||||
},
|
||||
leaks::Tracker,
|
||||
|
|
@ -48,6 +49,13 @@ impl ZwpTabletPadGroupV2 {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn send_dial(&self, dial: &ZwpTabletPadDialV2) {
|
||||
self.client.event(Dial {
|
||||
self_id: self.id,
|
||||
dial: dial.id,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_modes(&self, modes: u32) {
|
||||
self.client.event(Modes {
|
||||
self_id: self.id,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ use {
|
|||
ifs::wl_seat::{
|
||||
WlSeatGlobal,
|
||||
tablet::{
|
||||
Tablet, TabletPad, TabletTool, zwp_tablet_pad_group_v2::ZwpTabletPadGroupV2,
|
||||
Tablet, TabletPad, TabletTool, zwp_tablet_pad_dial_v2::ZwpTabletPadDialV2,
|
||||
zwp_tablet_pad_group_v2::ZwpTabletPadGroupV2,
|
||||
zwp_tablet_pad_ring_v2::ZwpTabletPadRingV2,
|
||||
zwp_tablet_pad_strip_v2::ZwpTabletPadStripV2, zwp_tablet_pad_v2::ZwpTabletPadV2,
|
||||
zwp_tablet_tool_v2::ZwpTabletToolV2, zwp_tablet_v2::ZwpTabletV2,
|
||||
|
|
@ -18,6 +19,9 @@ use {
|
|||
thiserror::Error,
|
||||
};
|
||||
|
||||
const BUSTYPE_SINCE: Version = Version(2);
|
||||
const DIALS_SINCE: Version = Version(2);
|
||||
|
||||
pub struct ZwpTabletSeatV2 {
|
||||
pub id: ZwpTabletSeatV2Id,
|
||||
pub client: Rc<Client>,
|
||||
|
|
@ -53,6 +57,11 @@ impl ZwpTabletSeatV2 {
|
|||
obj.send_name(&tablet.name);
|
||||
obj.send_id(tablet.vid, tablet.pid);
|
||||
obj.send_path(&tablet.path);
|
||||
if obj.version >= BUSTYPE_SINCE {
|
||||
if let Some(bustype) = tablet.bustype {
|
||||
obj.send_bustype(bustype);
|
||||
}
|
||||
}
|
||||
obj.send_done();
|
||||
tablet.bindings.add(self, &obj);
|
||||
}
|
||||
|
|
@ -161,6 +170,25 @@ impl ZwpTabletSeatV2 {
|
|||
group_obj.send_strip(&strip_obj);
|
||||
strip.bindings.add(self, &strip_obj);
|
||||
}
|
||||
if self.version >= DIALS_SINCE {
|
||||
for dial in &group.dials {
|
||||
let Some(dial) = pad.dials.get(*dial as usize) else {
|
||||
continue;
|
||||
};
|
||||
let dial_obj = Rc::new(ZwpTabletPadDialV2 {
|
||||
id: id!(),
|
||||
client: self.client.clone(),
|
||||
seat: self.clone(),
|
||||
tracker: Default::default(),
|
||||
version: self.version,
|
||||
dial: dial.clone(),
|
||||
});
|
||||
track!(self.client, dial_obj);
|
||||
self.client.add_server_obj(&dial_obj);
|
||||
group_obj.send_dial(&dial_obj);
|
||||
dial.bindings.add(self, &dial_obj);
|
||||
}
|
||||
}
|
||||
group_obj.send_done();
|
||||
}
|
||||
obj.send_done();
|
||||
|
|
|
|||
|
|
@ -53,6 +53,13 @@ impl ZwpTabletV2 {
|
|||
pub fn send_removed(&self) {
|
||||
self.client.event(Removed { self_id: self.id });
|
||||
}
|
||||
|
||||
pub fn send_bustype(&self, bustype: u32) {
|
||||
self.client.event(Bustype {
|
||||
self_id: self.id,
|
||||
bustype,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl ZwpTabletV2RequestHandler for ZwpTabletV2 {
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@ use {
|
|||
wl_seat::{
|
||||
Dnd, NodeSeatState, SeatId, WlSeatGlobal,
|
||||
tablet::{
|
||||
PadButtonState, TabletPad, TabletPadGroup, TabletPadRing, TabletPadStrip,
|
||||
TabletRingEventSource, TabletStripEventSource, TabletTool, TabletToolChanges,
|
||||
ToolButtonState,
|
||||
PadButtonState, TabletPad, TabletPadDial, TabletPadGroup, TabletPadRing,
|
||||
TabletPadStrip, TabletRingEventSource, TabletStripEventSource, TabletTool,
|
||||
TabletToolChanges, ToolButtonState,
|
||||
},
|
||||
text_input::TextInputConnection,
|
||||
wl_pointer::PendingScroll,
|
||||
|
|
@ -2016,6 +2016,16 @@ impl Node for WlSurface {
|
|||
pad.surface_strip(self, strip, source, position, time_usec);
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_dial(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
dial: &Rc<TabletPadDial>,
|
||||
value120: i32,
|
||||
time_usec: u64,
|
||||
) {
|
||||
pad.surface_dial(self, dial, value120, time_usec);
|
||||
}
|
||||
|
||||
fn node_on_tablet_tool_leave(&self, tool: &Rc<TabletTool>, time_usec: u64) {
|
||||
tool.surface_leave(self, time_usec);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ cenum! {
|
|||
LIBINPUT_EVENT_TABLET_PAD_RING = 701,
|
||||
LIBINPUT_EVENT_TABLET_PAD_STRIP = 702,
|
||||
LIBINPUT_EVENT_TABLET_PAD_KEY = 703,
|
||||
LIBINPUT_EVENT_TABLET_PAD_DIAL = 704,
|
||||
LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN = 800,
|
||||
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE = 801,
|
||||
LIBINPUT_EVENT_GESTURE_SWIPE_END = 802,
|
||||
|
|
|
|||
|
|
@ -25,18 +25,19 @@ use {
|
|||
libinput_device_config_tap_set_drag_enabled,
|
||||
libinput_device_config_tap_set_drag_lock_enabled,
|
||||
libinput_device_config_tap_set_enabled, libinput_device_get_device_group,
|
||||
libinput_device_get_id_product, libinput_device_get_id_vendor,
|
||||
libinput_device_get_name, libinput_device_get_user_data, libinput_device_group,
|
||||
libinput_device_group_get_user_data, libinput_device_group_set_user_data,
|
||||
libinput_device_has_capability, libinput_device_set_user_data,
|
||||
libinput_device_tablet_pad_get_mode_group, libinput_device_tablet_pad_get_num_buttons,
|
||||
libinput_device_get_id_bustype, libinput_device_get_id_product,
|
||||
libinput_device_get_id_vendor, libinput_device_get_name, libinput_device_get_user_data,
|
||||
libinput_device_group, libinput_device_group_get_user_data,
|
||||
libinput_device_group_set_user_data, libinput_device_has_capability,
|
||||
libinput_device_set_user_data, libinput_device_tablet_pad_get_mode_group,
|
||||
libinput_device_tablet_pad_get_num_buttons, libinput_device_tablet_pad_get_num_dials,
|
||||
libinput_device_tablet_pad_get_num_mode_groups,
|
||||
libinput_device_tablet_pad_get_num_rings, libinput_device_tablet_pad_get_num_strips,
|
||||
libinput_device_unref, libinput_path_remove_device, libinput_tablet_pad_mode_group,
|
||||
libinput_tablet_pad_mode_group_get_index, libinput_tablet_pad_mode_group_get_mode,
|
||||
libinput_tablet_pad_mode_group_get_num_modes,
|
||||
libinput_tablet_pad_mode_group_has_button, libinput_tablet_pad_mode_group_has_ring,
|
||||
libinput_tablet_pad_mode_group_has_strip,
|
||||
libinput_tablet_pad_mode_group_has_button, libinput_tablet_pad_mode_group_has_dial,
|
||||
libinput_tablet_pad_mode_group_has_ring, libinput_tablet_pad_mode_group_has_strip,
|
||||
},
|
||||
},
|
||||
bstr::ByteSlice,
|
||||
|
|
@ -223,6 +224,10 @@ impl<'a> LibInputDevice<'a> {
|
|||
unsafe { libinput_device_get_id_vendor(self.dev) as u32 }
|
||||
}
|
||||
|
||||
pub fn bustype(&self) -> Option<u32> {
|
||||
libinput_device_get_id_bustype.map(|f| unsafe { f(self.dev) as u32 })
|
||||
}
|
||||
|
||||
pub fn pad_num_buttons(&self) -> u32 {
|
||||
match unsafe { libinput_device_tablet_pad_get_num_buttons(self.dev) } {
|
||||
-1 => 0,
|
||||
|
|
@ -244,6 +249,17 @@ impl<'a> LibInputDevice<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pad_num_dials(&self) -> u32 {
|
||||
match unsafe {
|
||||
libinput_device_tablet_pad_get_num_dials
|
||||
.map(|f| f(self.dev))
|
||||
.unwrap_or_default()
|
||||
} {
|
||||
-1 => 0,
|
||||
n => n as u32,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pad_num_mode_groups(&self) -> u32 {
|
||||
match unsafe { libinput_device_tablet_pad_get_num_mode_groups(self.dev) } {
|
||||
-1 => 0,
|
||||
|
|
@ -316,6 +332,15 @@ impl<'a> LibInputTabletPadModeGroup<'a> {
|
|||
pub fn has_strip(&self, strip: u32) -> bool {
|
||||
unsafe { libinput_tablet_pad_mode_group_has_strip(self.group, strip as _) != 0 }
|
||||
}
|
||||
|
||||
pub fn has_dial(&self, dial: u32) -> bool {
|
||||
unsafe {
|
||||
libinput_tablet_pad_mode_group_has_dial
|
||||
.map(|f| f(self.group, dial as _))
|
||||
.unwrap_or_default()
|
||||
!= 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RegisteredDevice {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ use {
|
|||
libinput_event_switch, libinput_event_switch_get_switch,
|
||||
libinput_event_switch_get_switch_state, libinput_event_switch_get_time_usec,
|
||||
libinput_event_tablet_pad, libinput_event_tablet_pad_get_button_number,
|
||||
libinput_event_tablet_pad_get_button_state, libinput_event_tablet_pad_get_mode,
|
||||
libinput_event_tablet_pad_get_button_state,
|
||||
libinput_event_tablet_pad_get_dial_delta_v120,
|
||||
libinput_event_tablet_pad_get_dial_number, libinput_event_tablet_pad_get_mode,
|
||||
libinput_event_tablet_pad_get_mode_group, libinput_event_tablet_pad_get_ring_number,
|
||||
libinput_event_tablet_pad_get_ring_position, libinput_event_tablet_pad_get_ring_source,
|
||||
libinput_event_tablet_pad_get_strip_number,
|
||||
|
|
@ -459,6 +461,14 @@ impl<'a> LibInputEventTabletPad<'a> {
|
|||
unsafe { TabletPadStripAxisSource(libinput_event_tablet_pad_get_strip_source(self.event)) }
|
||||
}
|
||||
|
||||
pub fn dial_number(&self) -> Option<u32> {
|
||||
libinput_event_tablet_pad_get_dial_number.map(|f| unsafe { f(self.event) as u32 })
|
||||
}
|
||||
|
||||
pub fn dial_delta_v120(&self) -> Option<f64> {
|
||||
libinput_event_tablet_pad_get_dial_delta_v120.map(|f| unsafe { f(self.event) })
|
||||
}
|
||||
|
||||
pub fn button_number(&self) -> u32 {
|
||||
unsafe { libinput_event_tablet_pad_get_button_number(self.event) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use uapi::c;
|
||||
use {libloading::os::unix::Library, std::sync::LazyLock, uapi::c};
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/libinput_tys.rs"));
|
||||
|
||||
|
|
@ -393,3 +393,38 @@ pub struct libinput_interface {
|
|||
) -> c::c_int,
|
||||
pub close_restricted: unsafe extern "C" fn(fd: c::c_int, user_data: *mut c::c_void),
|
||||
}
|
||||
|
||||
macro_rules! dynload {
|
||||
(
|
||||
$(
|
||||
fn $name:ident($($arg:ident: $ty:ty),* $(,)?) -> $ret:ty;
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
#[expect(non_upper_case_globals)]
|
||||
pub static $name: LazyLock<Option<unsafe extern "C" fn($($arg: $ty),*) -> $ret>> = LazyLock::new(|| {
|
||||
unsafe {
|
||||
Library::this()
|
||||
.get(concat!(stringify!($name), "\0").as_bytes())
|
||||
.ok()
|
||||
.map(|sym| *sym)
|
||||
}
|
||||
});
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
dynload! {
|
||||
fn libinput_device_get_id_bustype(device: *mut libinput_device) -> c::c_uint;
|
||||
|
||||
fn libinput_event_tablet_pad_get_dial_delta_v120(event: *mut libinput_event_tablet_pad) -> f64;
|
||||
|
||||
fn libinput_event_tablet_pad_get_dial_number(event: *mut libinput_event_tablet_pad) -> c::c_uint;
|
||||
|
||||
fn libinput_device_tablet_pad_get_num_dials(device: *mut libinput_device) -> c::c_int;
|
||||
|
||||
fn libinput_tablet_pad_mode_group_has_dial(
|
||||
group: *mut libinput_tablet_pad_mode_group,
|
||||
dial: c::c_uint,
|
||||
) -> c::c_int;
|
||||
}
|
||||
|
|
|
|||
19
src/tree.rs
19
src/tree.rs
|
|
@ -7,9 +7,9 @@ use {
|
|||
wl_seat::{
|
||||
Dnd, NodeSeatState, WlSeatGlobal,
|
||||
tablet::{
|
||||
PadButtonState, TabletPad, TabletPadGroup, TabletPadRing, TabletPadStrip,
|
||||
TabletRingEventSource, TabletStripEventSource, TabletTool, TabletToolChanges,
|
||||
ToolButtonState,
|
||||
PadButtonState, TabletPad, TabletPadDial, TabletPadGroup, TabletPadRing,
|
||||
TabletPadStrip, TabletRingEventSource, TabletStripEventSource, TabletTool,
|
||||
TabletToolChanges, ToolButtonState,
|
||||
},
|
||||
wl_pointer::PendingScroll,
|
||||
},
|
||||
|
|
@ -464,6 +464,19 @@ pub trait Node: 'static {
|
|||
let _ = position;
|
||||
}
|
||||
|
||||
fn node_on_tablet_pad_dial(
|
||||
&self,
|
||||
pad: &Rc<TabletPad>,
|
||||
dial: &Rc<TabletPadDial>,
|
||||
value120: i32,
|
||||
time_usec: u64,
|
||||
) {
|
||||
let _ = pad;
|
||||
let _ = time_usec;
|
||||
let _ = dial;
|
||||
let _ = value120;
|
||||
}
|
||||
|
||||
fn node_on_tablet_tool_leave(&self, tool: &Rc<TabletTool>, time_usec: u64) {
|
||||
let _ = tool;
|
||||
let _ = time_usec;
|
||||
|
|
|
|||
|
|
@ -100,9 +100,7 @@ impl Action {
|
|||
SimpleCommand::SetFloatAboveFullscreen(bool) => {
|
||||
B::new(move || set_float_above_fullscreen(bool))
|
||||
}
|
||||
SimpleCommand::ToggleFloatAboveFullscreen => {
|
||||
B::new(|| toggle_float_above_fullscreen())
|
||||
}
|
||||
SimpleCommand::ToggleFloatAboveFullscreen => B::new(toggle_float_above_fullscreen),
|
||||
},
|
||||
Action::Multi { actions } => {
|
||||
let actions: Vec<_> = actions.into_iter().map(|a| a.into_fn(state)).collect();
|
||||
|
|
|
|||
|
|
@ -267,3 +267,14 @@ event touch_cancel {
|
|||
time_usec: pod(u64),
|
||||
id: i32,
|
||||
}
|
||||
|
||||
event tablet_pad_dial_delta {
|
||||
value120: i32,
|
||||
}
|
||||
|
||||
event tablet_pad_dial_frame {
|
||||
seat: u32,
|
||||
time_usec: pod(u64),
|
||||
input_device: u32,
|
||||
dial: u32,
|
||||
}
|
||||
|
|
|
|||
15
wire/zwp_tablet_pad_dial_v2.txt
Normal file
15
wire/zwp_tablet_pad_dial_v2.txt
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
request set_feedback {
|
||||
description: str,
|
||||
serial: u32,
|
||||
}
|
||||
|
||||
request destroy {
|
||||
}
|
||||
|
||||
event delta {
|
||||
value120: i32,
|
||||
}
|
||||
|
||||
event frame {
|
||||
time: u32,
|
||||
}
|
||||
|
|
@ -25,3 +25,7 @@ event mode_switch {
|
|||
serial: u32,
|
||||
mode: u32,
|
||||
}
|
||||
|
||||
event dial {
|
||||
dial: id(zwp_tablet_pad_dial_v2),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,3 +19,7 @@ event done {
|
|||
|
||||
event removed {
|
||||
}
|
||||
|
||||
event bustype {
|
||||
bustype: u32,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue