Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/backend/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ pub use xkbcommon::xkb::Keycode;
mod tablet;

pub use tablet::{
ProximityState, TabletToolAxisEvent, TabletToolButtonEvent, TabletToolCapabilities, TabletToolDescriptor,
TabletToolEvent, TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TabletToolType,
ProximityState, TabletPadButtonEvent, TabletPadEvent, TabletToolAxisEvent, TabletToolButtonEvent,
TabletToolCapabilities, TabletToolDescriptor, TabletToolEvent, TabletToolProximityEvent,
TabletToolTipEvent, TabletToolTipState, TabletToolType,
};

#[cfg(feature = "wayland_frontend")]
Expand Down Expand Up @@ -671,6 +672,8 @@ pub trait InputBackend: Sized {
type TabletToolTipEvent: TabletToolTipEvent<Self>;
/// Type representing button events on tablet tool devices
type TabletToolButtonEvent: TabletToolButtonEvent<Self>;
/// Type representing button events on tablet pad devices
type TabletPadButtonEvent: TabletPadButtonEvent<Self>;
/// Type representing switch toggle events
type SwitchToggleEvent: SwitchToggleEvent<Self>;

Expand Down Expand Up @@ -809,6 +812,12 @@ pub enum InputEvent<B: InputBackend> {
event: B::TabletToolButtonEvent,
},

/// A tablet pad button was pressed or released
TabletPadButton {
/// The pad button event
event: B::TabletPadButtonEvent,
},

/// A switch was toggled
SwitchToggle {
/// The switch toggle event
Expand Down
30 changes: 30 additions & 0 deletions src/backend/input/tablet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,33 @@ impl<B: InputBackend> TabletToolButtonEvent<B> for UnusedEvent {
match *self {}
}
}

/// Common functions all TabletPad-Events implement.
pub trait TabletPadEvent {
/// Returns the mode the button, ring, or strip that triggered this event is in, at the time of the event.
fn mode(&self) -> u32;
}

impl TabletPadEvent for UnusedEvent {
fn mode(&self) -> u32 {
match *self {}
}
}

/// Signals that a pad has changed a logical button state on a device with the DeviceCapability::TabletPad capability.
pub trait TabletPadButtonEvent<B: InputBackend>: TabletPadEvent + Event<B> {
/// Return the button that triggered this event.
fn button(&self) -> u32;
/// Return the button state of the event.
fn button_state(&self) -> ButtonState;
}

impl<B: InputBackend> TabletPadButtonEvent<B> for UnusedEvent {
fn button(&self) -> u32 {
match *self {}
}

fn button_state(&self) -> ButtonState {
match *self {}
}
}
10 changes: 10 additions & 0 deletions src/backend/libinput/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ impl InputBackend for LibinputInputBackend {
type TabletToolProximityEvent = event::tablet_tool::TabletToolProximityEvent;
type TabletToolTipEvent = event::tablet_tool::TabletToolTipEvent;
type TabletToolButtonEvent = event::tablet_tool::TabletToolButtonEvent;
type TabletPadButtonEvent = event::tablet_pad::TabletPadButtonEvent;

type SwitchToggleEvent = event::switch::SwitchToggleEvent;

Expand Down Expand Up @@ -857,6 +858,15 @@ impl EventSource for LibinputInputBackend {
trace!("Unknown libinput tablet event");
}
},
libinput::Event::TabletPad(tablet_event) => match tablet_event {
event::TabletPadEvent::Button(event) => {
callback(InputEvent::TabletPadButton { event }, &mut ());
}
event::TabletPadEvent::Ring(_) => {}
event::TabletPadEvent::Strip(_) => {}
event::TabletPadEvent::Key(_) => {}
_ => {}
},
libinput::Event::Switch(switch_event) => match switch_event {
event::SwitchEvent::Toggle(event) => {
callback(InputEvent::SwitchToggle { event }, &mut ());
Expand Down
28 changes: 27 additions & 1 deletion src/backend/libinput/tablet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::backend::input::{

use input as libinput;
use input::event;
use input::event::{tablet_tool, EventTrait};
use input::event::{tablet_pad, tablet_tool, EventTrait};

use super::LibinputInputBackend;

Expand All @@ -29,6 +29,16 @@ where
}
}

impl backend::Event<LibinputInputBackend> for tablet_pad::TabletPadButtonEvent {
fn time(&self) -> u64 {
tablet_pad::TabletPadEventTrait::time_usec(self)
}

fn device(&self) -> <LibinputInputBackend as backend::InputBackend>::Device {
event::EventTrait::device(self)
}
}

impl backend::TabletToolAxisEvent<LibinputInputBackend> for tablet_tool::TabletToolAxisEvent {}

impl backend::TabletToolProximityEvent<LibinputInputBackend> for tablet_tool::TabletToolProximityEvent {
Expand Down Expand Up @@ -192,3 +202,19 @@ impl backend::TabletToolButtonEvent<LibinputInputBackend> for tablet_tool::Table
tablet_tool::TabletToolButtonEvent::button_state(self).into()
}
}

impl<E: tablet_pad::TabletPadEventTrait> backend::TabletPadEvent for E {
fn mode(&self) -> u32 {
tablet_pad::TabletPadEventTrait::mode(self)
}
}

impl backend::TabletPadButtonEvent<LibinputInputBackend> for tablet_pad::TabletPadButtonEvent {
fn button(&self) -> u32 {
tablet_pad::TabletPadButtonEvent::button_number(self)
}

fn button_state(&self) -> backend::ButtonState {
tablet_pad::TabletPadButtonEvent::button_state(self).into()
}
}
1 change: 1 addition & 0 deletions src/backend/winit/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ impl InputBackend for WinitInput {
type TabletToolProximityEvent = UnusedEvent;
type TabletToolTipEvent = UnusedEvent;
type TabletToolButtonEvent = UnusedEvent;
type TabletPadButtonEvent = UnusedEvent;

type SwitchToggleEvent = UnusedEvent;

Expand Down
1 change: 1 addition & 0 deletions src/backend/x11/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ impl InputBackend for X11Input {
type TabletToolProximityEvent = UnusedEvent;
type TabletToolTipEvent = UnusedEvent;
type TabletToolButtonEvent = UnusedEvent;
type TabletPadButtonEvent = UnusedEvent;

type SwitchToggleEvent = UnusedEvent;

Expand Down
16 changes: 13 additions & 3 deletions src/wayland/tablet_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
use crate::input::{Seat, SeatHandler};
use wayland_protocols::wp::tablet::zv2::server::{
zwp_tablet_manager_v2::{self, ZwpTabletManagerV2},
zwp_tablet_pad_v2::ZwpTabletPadV2,
zwp_tablet_seat_v2::ZwpTabletSeatV2,
zwp_tablet_tool_v2::ZwpTabletToolV2,
zwp_tablet_v2::ZwpTabletV2,
Expand All @@ -108,10 +109,12 @@ use wayland_server::{backend::GlobalId, Client, DataInit, Dispatch, DisplayHandl
const MANAGER_VERSION: u32 = 1;

mod tablet;
mod tablet_pad;
mod tablet_seat;
pub(crate) mod tablet_tool;

pub use tablet::{TabletDescriptor, TabletHandle, TabletUserData};
pub use tablet_pad::{TabletPadDescriptor, TabletPadHandle, TabletPadUserData};
pub use tablet_seat::{TabletSeatHandle, TabletSeatHandler, TabletSeatUserData};
pub use tablet_tool::{TabletToolHandle, TabletToolUserData};

Expand Down Expand Up @@ -183,6 +186,7 @@ where
D: Dispatch<ZwpTabletSeatV2, TabletSeatUserData>,
D: Dispatch<ZwpTabletV2, TabletUserData>,
D: Dispatch<ZwpTabletToolV2, TabletToolUserData>,
D: Dispatch<ZwpTabletPadV2, TabletPadUserData>,
D: SeatHandler + TabletSeatHandler + 'static,
D: CompositorHandler,
{
Expand Down Expand Up @@ -228,13 +232,14 @@ macro_rules! delegate_tablet_manager {
use $crate::{
reexports::{
wayland_protocols::wp::tablet::zv2::server::{
zwp_tablet_manager_v2::ZwpTabletManagerV2, zwp_tablet_seat_v2::ZwpTabletSeatV2,
zwp_tablet_tool_v2::ZwpTabletToolV2, zwp_tablet_v2::ZwpTabletV2,
zwp_tablet_manager_v2::ZwpTabletManagerV2, zwp_tablet_pad_v2::ZwpTabletPadV2,
zwp_tablet_seat_v2::ZwpTabletSeatV2, zwp_tablet_tool_v2::ZwpTabletToolV2,
zwp_tablet_v2::ZwpTabletV2,
},
wayland_server::{delegate_dispatch, delegate_global_dispatch},
},
wayland::tablet_manager::{
TabletManagerState, TabletSeatUserData, TabletToolUserData, TabletUserData,
TabletManagerState, TabletPadUserData, TabletSeatUserData, TabletToolUserData, TabletUserData,
},
};

Expand All @@ -258,6 +263,11 @@ macro_rules! delegate_tablet_manager {
$ty: [ZwpTabletToolV2: TabletToolUserData] => TabletManagerState
);

delegate_dispatch!(
$(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
$ty: [ZwpTabletPadV2: TabletPadUserData] => TabletManagerState
);

delegate_dispatch!(
$(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
$ty: [ZwpTabletV2: TabletUserData] => TabletManagerState
Expand Down
178 changes: 178 additions & 0 deletions src/wayland/tablet_manager/tablet_pad.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
use std::{
path::PathBuf,
sync::{Arc, Mutex},
};

use wayland_backend::server::ClientId;
use wayland_protocols::wp::tablet::zv2::server::{
zwp_tablet_pad_v2::{self, ZwpTabletPadV2},
zwp_tablet_seat_v2::ZwpTabletSeatV2,
};
use wayland_server::{
protocol::wl_surface::WlSurface, Client, DataInit, Dispatch, DisplayHandle, Resource, Weak,
};

use crate::{backend::input::Device, wayland::tablet_manager::TabletManagerState};

/// Description of graphics tablet pad group
#[derive(Debug, Clone)]
pub struct TabletPadGroupDescriptor {
/// Buttons available in the group
pub buttons: Vec<u32>,
}

/// Description of graphics tablet pad device
#[derive(Debug, Clone)]
pub struct TabletPadDescriptor {
/// Unique id of the device at a point in time.
pub id: String,
/// Tablet device name
pub name: String,
/// Tablet device USB (product,vendor) id
pub usb_id: Option<(u32, u32)>,
/// Path to the device
pub syspath: Option<PathBuf>,
/// The number of buttons on a device
pub number_of_buttons: u32,
/// Most devices only provide a single mode group, however devices
/// such as the Wacom Cintiq 22HD provide two mode groups.
pub groups: Vec<TabletPadGroupDescriptor>,
}

impl From<&input::Device> for TabletPadDescriptor {
#[inline]
fn from(device: &input::Device) -> Self {
let number_of_buttons = device.tablet_pad_number_of_buttons().max(0) as u32;
let _number_of_rings = device.tablet_pad_number_of_rings().max(0) as u32;
let _number_of_strips = device.tablet_pad_number_of_strips().max(0) as u32;

let groups = (0..device.tablet_pad_number_of_mode_groups().max(0) as u32)
.map(|idx| {
let group = device.tablet_pad_mode_group(idx).unwrap();

let mut buttons = Vec::new();

for idx in 0..number_of_buttons {
if group.has_button(idx) {
buttons.push(idx);
}
}

// let mut rings = Vec::new();
// for idx in 0..number_of_rings {
// if group.has_ring(idx) {
// rings.push(idx);
// }
// }

// let mut strips = Vec::new();
// for idx in 0..number_of_strips {
// if group.has_strip(idx) {
// strips.push(idx);
// }
// }

// No modes support for now
let _number_of_modes = group.number_of_modes();

TabletPadGroupDescriptor { buttons }
})
.collect();

Self {
id: device.id(),
name: device.name().into(),
syspath: device.syspath(),
usb_id: device.usb_id(),
number_of_buttons,
groups,
}
}
}

#[derive(Debug, Default)]
struct TabletPad {
instances: Vec<Weak<ZwpTabletPadV2>>,
}

/// Handle to a tablet pad device
#[derive(Debug, Clone)]
pub struct TabletPadHandle {
inner: Arc<Mutex<TabletPad>>,
desc: TabletPadDescriptor,
}

impl TabletPadHandle {
pub(super) fn new(desc: TabletPadDescriptor) -> Self {
Self {
inner: Default::default(),
desc,
}
}

pub(super) fn new_instance<D>(&mut self, client: &Client, dh: &DisplayHandle, seat: &ZwpTabletSeatV2)
where
D: Dispatch<ZwpTabletPadV2, TabletPadUserData>,
D: 'static,
{
let wl_tablet_pad = client
.create_resource::<ZwpTabletPadV2, _, D>(
dh,
seat.version(),
TabletPadUserData { handle: self.clone() },
)
.unwrap();

seat.pad_added(&wl_tablet_pad);

wl_tablet_pad.buttons(self.desc.number_of_buttons);

if let Some(syspath) = self.desc.syspath.as_ref().and_then(|p| p.to_str()) {
wl_tablet_pad.path(syspath.to_owned());
}

for _grp in self.desc.groups.iter() {
// TODO
}

wl_tablet_pad.done();

self.inner
.lock()
.unwrap()
.instances
.push(wl_tablet_pad.downgrade());
}
}

/// User data of ZwpTabletPadV2 object
#[derive(Debug)]
pub struct TabletPadUserData {
handle: TabletPadHandle,
}

impl<D> Dispatch<ZwpTabletPadV2, TabletPadUserData, D> for TabletManagerState
where
D: Dispatch<ZwpTabletPadV2, TabletPadUserData>,
D: 'static,
{
fn request(
_state: &mut D,
_client: &Client,
_tablet: &ZwpTabletPadV2,
_request: zwp_tablet_pad_v2::Request,
_data: &TabletPadUserData,
_dh: &DisplayHandle,
_data_init: &mut DataInit<'_, D>,
) {
}

fn destroyed(_state: &mut D, _client: ClientId, pad: &ZwpTabletPadV2, data: &TabletPadUserData) {
data.handle
.inner
.lock()
.unwrap()
.instances
.retain(|i| i.id() != Resource::id(pad));
}
}
Loading
Loading