diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2023-08-16 11:43:52 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2023-08-16 11:43:52 +0400 |
| commit | b5e7782970ada5400985bce0f4bc1bf030f97346 (patch) | |
| tree | 584e3f423f68f55e245ded8b82cff69b19d443a5 /src | |
| parent | 6e36ccb1bd4ca6a5e4374e1fa50e519599d7a060 (diff) | |
| download | niri-b5e7782970ada5400985bce0f4bc1bf030f97346.tar.gz niri-b5e7782970ada5400985bce0f4bc1bf030f97346.tar.bz2 niri-b5e7782970ada5400985bce0f4bc1bf030f97346.zip | |
Implement tablet-manager
Diffstat (limited to 'src')
| -rw-r--r-- | src/handlers/mod.rs | 6 | ||||
| -rw-r--r-- | src/input.rs | 142 | ||||
| -rw-r--r-- | src/niri.rs | 4 |
3 files changed, 139 insertions, 13 deletions
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index fecc3b32..a496b341 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -11,7 +11,10 @@ use smithay::wayland::data_device::{ set_data_device_focus, ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler, }; -use smithay::{delegate_data_device, delegate_output, delegate_presentation, delegate_seat}; +use smithay::{ + delegate_data_device, delegate_output, delegate_presentation, delegate_seat, + delegate_tablet_manager, +}; use crate::Niri; @@ -36,6 +39,7 @@ impl SeatHandler for Niri { } } delegate_seat!(Niri); +delegate_tablet_manager!(Niri); impl DataDeviceHandler for Niri { type SelectionUserData = (); diff --git a/src/input.rs b/src/input.rs index 986fc349..c5420623 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1,14 +1,16 @@ use std::process::Command; use smithay::backend::input::{ - AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent, - KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent, - TabletToolEvent, TabletToolTipEvent, TabletToolTipState, + AbsolutePositionEvent, Axis, AxisSource, ButtonState, Device, DeviceCapability, Event, + InputBackend, InputEvent, KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, + PointerMotionEvent, ProximityState, TabletToolButtonEvent, TabletToolEvent, + TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, }; use smithay::backend::libinput::LibinputInputBackend; use smithay::input::keyboard::{keysyms, FilterResult, KeysymHandle, ModifiersState}; use smithay::input::pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent}; use smithay::utils::SERIAL_COUNTER; +use smithay::wayland::tablet_manager::{TabletDescriptor, TabletSeatTrait}; use crate::niri::Niri; use crate::utils::get_monotonic_time; @@ -457,7 +459,7 @@ impl Niri { pointer.motion( self, - under, + under.clone(), &MotionEvent { location: pos, serial, @@ -465,22 +467,138 @@ impl Niri { }, ); + let tablet_seat = self.seat.tablet_seat(); + let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&event.device())); + let tool = tablet_seat.get_tool(&event.tool()); + if let (Some(tablet), Some(tool)) = (tablet, tool) { + if event.pressure_has_changed() { + tool.pressure(event.pressure()); + } + if event.distance_has_changed() { + tool.distance(event.distance()); + } + if event.tilt_has_changed() { + tool.tilt(event.tilt()); + } + if event.slider_has_changed() { + tool.slider_position(event.slider_position()); + } + if event.rotation_has_changed() { + tool.rotation(event.rotation()); + } + if event.wheel_has_changed() { + tool.wheel(event.wheel_delta(), event.wheel_delta_discrete()); + } + + tool.motion( + pos, + under, + &tablet, + SERIAL_COUNTER.next_serial(), + event.time_msec(), + ); + } + // Redraw to update the cursor position. // FIXME: redraw only outputs overlapping the cursor. self.queue_redraw_all(); } InputEvent::TabletToolTip { event, .. } => { + let tool = self.seat.tablet_seat().get_tool(&event.tool()); + + if let Some(tool) = tool { + match event.tip_state() { + TabletToolTipState::Down => { + let serial = SERIAL_COUNTER.next_serial(); + tool.tip_down(serial, event.time_msec()); + + let pointer = self.seat.get_pointer().unwrap(); + if !pointer.is_grabbed() { + if let Some(window) = self.window_under_cursor() { + let window = window.clone(); + self.monitor_set.activate_window(&window); + } else { + let output = self.output_under_cursor().unwrap(); + self.monitor_set.activate_output(&output); + } + }; + } + TabletToolTipState::Up => { + tool.tip_up(event.time_msec()); + } + } + } + } + InputEvent::TabletToolProximity { event, .. } => { + // FIXME: allow mapping tablet to different outputs. + let output = self.global_space.outputs().next().unwrap(); + + let output_geo = self.global_space.output_geometry(output).unwrap(); + + let pos = event.position_transformed(output_geo.size) + output_geo.loc.to_f64(); + + let serial = SERIAL_COUNTER.next_serial(); + let pointer = self.seat.get_pointer().unwrap(); - if event.tip_state() == TabletToolTipState::Down && !pointer.is_grabbed() { - if let Some(window) = self.window_under_cursor() { - let window = window.clone(); - self.monitor_set.activate_window(&window); - } else { - let output = self.output_under_cursor().unwrap(); - self.monitor_set.activate_output(&output); + let under = self.surface_under_and_global_space(pos); + + pointer.motion( + self, + under.clone(), + &MotionEvent { + location: pos, + serial, + time: event.time_msec(), + }, + ); + + let tablet_seat = self.seat.tablet_seat(); + let tool = tablet_seat.add_tool::<Self>(&self.display_handle, &event.tool()); + let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&event.device())); + if let (Some(under), Some(tablet)) = (under, tablet) { + match event.state() { + ProximityState::In => tool.proximity_in( + pos, + under, + &tablet, + SERIAL_COUNTER.next_serial(), + event.time_msec(), + ), + ProximityState::Out => tool.proximity_out(event.time_msec()), } - }; + } + } + InputEvent::TabletToolButton { event, .. } => { + let tool = self.seat.tablet_seat().get_tool(&event.tool()); + + if let Some(tool) = tool { + tool.button( + event.button(), + event.button_state(), + SERIAL_COUNTER.next_serial(), + event.time_msec(), + ); + } + } + InputEvent::DeviceAdded { device } => { + if device.has_capability(DeviceCapability::TabletTool) { + self.seat + .tablet_seat() + .add_tablet::<Self>(&self.display_handle, &TabletDescriptor::from(&device)); + } + } + InputEvent::DeviceRemoved { device } => { + if device.has_capability(DeviceCapability::TabletTool) { + let tablet_seat = self.seat.tablet_seat(); + + tablet_seat.remove_tablet(&TabletDescriptor::from(&device)); + + // If there are no tablets in seat we can remove all tools + if tablet_seat.count_tablets() == 0 { + tablet_seat.clear_tools(); + } + } } _ => {} } diff --git a/src/niri.rs b/src/niri.rs index 587a0f9b..05a2b3a4 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -39,6 +39,7 @@ use smithay::wayland::shell::wlr_layer::{Layer, WlrLayerShellState}; use smithay::wayland::shell::xdg::XdgShellState; use smithay::wayland::shm::ShmState; use smithay::wayland::socket::ListeningSocketSource; +use smithay::wayland::tablet_manager::TabletManagerState; use crate::backend::Backend; use crate::frame_clock::FrameClock; @@ -72,6 +73,7 @@ pub struct Niri { pub shm_state: ShmState, pub output_manager_state: OutputManagerState, pub seat_state: SeatState<Self>, + pub tablet_state: TabletManagerState, pub data_device_state: DataDeviceState, pub popups: PopupManager, pub presentation_state: PresentationState, @@ -114,6 +116,7 @@ impl Niri { let shm_state = ShmState::new::<Self>(&display_handle, vec![]); let output_manager_state = OutputManagerState::new_with_xdg_output::<Self>(&display_handle); let mut seat_state = SeatState::new(); + let tablet_state = TabletManagerState::new::<Self>(&display_handle); let data_device_state = DataDeviceState::new::<Self>(&display_handle); let presentation_state = PresentationState::new::<Self>(&display_handle, CLOCK_MONOTONIC as u32); @@ -175,6 +178,7 @@ impl Niri { shm_state, output_manager_state, seat_state, + tablet_state, data_device_state, popups: PopupManager::default(), presentation_state, |
