aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-08-16 11:43:52 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-08-16 11:43:52 +0400
commitb5e7782970ada5400985bce0f4bc1bf030f97346 (patch)
tree584e3f423f68f55e245ded8b82cff69b19d443a5
parent6e36ccb1bd4ca6a5e4374e1fa50e519599d7a060 (diff)
downloadniri-b5e7782970ada5400985bce0f4bc1bf030f97346.tar.gz
niri-b5e7782970ada5400985bce0f4bc1bf030f97346.tar.bz2
niri-b5e7782970ada5400985bce0f4bc1bf030f97346.zip
Implement tablet-manager
-rw-r--r--src/handlers/mod.rs6
-rw-r--r--src/input.rs142
-rw-r--r--src/niri.rs4
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,