aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/input.rs138
-rw-r--r--src/niri.rs14
2 files changed, 146 insertions, 6 deletions
diff --git a/src/input.rs b/src/input.rs
index 3d470eba..41ac7888 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -8,7 +8,7 @@ use smithay::backend::input::{
GestureBeginEvent, GestureEndEvent, GesturePinchUpdateEvent as _, GestureSwipeUpdateEvent as _,
InputBackend, InputEvent, KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent,
PointerMotionEvent, ProximityState, TabletToolButtonEvent, TabletToolEvent,
- TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState,
+ TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TouchEvent,
};
use smithay::backend::libinput::LibinputInputBackend;
use smithay::input::keyboard::{keysyms, FilterResult, Keysym, ModifiersState};
@@ -17,6 +17,7 @@ use smithay::input::pointer::{
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, RelativeMotionEvent,
};
+use smithay::input::touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent};
use smithay::utils::{Logical, Point, SERIAL_COUNTER};
use smithay::wayland::pointer_constraints::{with_pointer_constraint, PointerConstraint};
use smithay::wayland::tablet_manager::{TabletDescriptor, TabletSeatTrait};
@@ -101,11 +102,11 @@ impl State {
GesturePinchEnd { event } => self.on_gesture_pinch_end::<I>(event),
GestureHoldBegin { event } => self.on_gesture_hold_begin::<I>(event),
GestureHoldEnd { event } => self.on_gesture_hold_end::<I>(event),
- TouchDown { .. } => (),
- TouchMotion { .. } => (),
- TouchUp { .. } => (),
- TouchCancel { .. } => (),
- TouchFrame { .. } => (),
+ TouchDown { event } => self.on_touch_down::<I>(event),
+ TouchMotion { event } => self.on_touch_motion::<I>(event),
+ TouchUp { event } => self.on_touch_up::<I>(event),
+ TouchCancel { event } => self.on_touch_cancel::<I>(event),
+ TouchFrame { event } => self.on_touch_frame::<I>(event),
SwitchToggle { .. } => (),
Special(_) => (),
}
@@ -154,9 +155,14 @@ impl State {
}
}
+ if device.has_capability(input::DeviceCapability::Touch) {
+ self.niri.touch.insert(device.clone());
+ }
+
apply_libinput_settings(&self.niri.config.borrow().input, device);
}
InputEvent::DeviceRemoved { device } => {
+ self.niri.touch.remove(device);
self.niri.tablets.remove(device);
self.niri.devices.remove(device);
}
@@ -171,6 +177,9 @@ impl State {
let desc = TabletDescriptor::from(&device);
tablet_seat.add_tablet::<Self>(&self.niri.display_handle, &desc);
}
+ if device.has_capability(DeviceCapability::Touch) && self.niri.seat.get_touch().is_none() {
+ self.niri.seat.add_touch();
+ }
}
fn on_device_removed(&mut self, device: impl Device) {
@@ -185,6 +194,9 @@ impl State {
tablet_seat.clear_tools();
}
}
+ if device.has_capability(DeviceCapability::Touch) && self.niri.touch.is_empty() {
+ self.niri.seat.remove_touch();
+ }
}
/// Computes the cursor position for the tablet event.
@@ -283,6 +295,10 @@ impl State {
return;
}
+ if let Some(touch) = self.niri.seat.get_touch() {
+ touch.cancel(self);
+ }
+
match action {
Action::Quit(skip_confirmation) => {
if !skip_confirmation {
@@ -1354,6 +1370,116 @@ impl State {
},
);
}
+
+ /// Computes the cursor position for the touch event.
+ ///
+ /// This function handles the touch output mapping, as well as coordinate transform
+ fn compute_touch_location<I: InputBackend, E: AbsolutePositionEvent<I>>(
+ &self,
+ evt: &E,
+ ) -> Option<Point<f64, Logical>> {
+ let output = self.niri.output_for_touch()?;
+ let output_geo = self.niri.global_space.output_geometry(output).unwrap();
+ let transform = output.current_transform();
+ let size = transform.invert().transform_size(output_geo.size);
+ Some(
+ transform.transform_point_in(evt.position_transformed(size), &size.to_f64())
+ + output_geo.loc.to_f64(),
+ )
+ }
+
+ fn on_touch_down<I: InputBackend>(&mut self, evt: I::TouchDownEvent) {
+ let Some(handle) = self.niri.seat.get_touch() else {
+ return;
+ };
+ let Some(touch_location) = self.compute_touch_location(&evt) else {
+ return;
+ };
+
+ if !handle.is_grabbed() {
+ let output_under_touch = self
+ .niri
+ .global_space
+ .output_under(touch_location)
+ .next()
+ .cloned();
+ if let Some(window) = self.niri.window_under(touch_location) {
+ let window = window.clone();
+ self.niri.layout.activate_window(&window);
+
+ // FIXME: granular.
+ self.niri.queue_redraw_all();
+ } else if let Some(output) = output_under_touch {
+ self.niri.layout.activate_output(&output);
+
+ // FIXME: granular.
+ self.niri.queue_redraw_all();
+ };
+ };
+
+ let serial = SERIAL_COUNTER.next_serial();
+ let under = self
+ .niri
+ .surface_under_and_global_space(touch_location)
+ .map(|under| under.surface);
+ handle.down(
+ self,
+ under,
+ &DownEvent {
+ slot: evt.slot(),
+ location: touch_location,
+ serial,
+ time: evt.time_msec(),
+ },
+ );
+ }
+ fn on_touch_up<I: InputBackend>(&mut self, evt: I::TouchUpEvent) {
+ let Some(handle) = self.niri.seat.get_touch() else {
+ return;
+ };
+ let serial = SERIAL_COUNTER.next_serial();
+ handle.up(
+ self,
+ &UpEvent {
+ slot: evt.slot(),
+ serial,
+ time: evt.time_msec(),
+ },
+ )
+ }
+ fn on_touch_motion<I: InputBackend>(&mut self, evt: I::TouchMotionEvent) {
+ let Some(handle) = self.niri.seat.get_touch() else {
+ return;
+ };
+ let Some(touch_location) = self.compute_touch_location(&evt) else {
+ return;
+ };
+ let under = self
+ .niri
+ .surface_under_and_global_space(touch_location)
+ .map(|under| under.surface);
+ handle.motion(
+ self,
+ under,
+ &TouchMotionEvent {
+ slot: evt.slot(),
+ location: touch_location,
+ time: evt.time_msec(),
+ },
+ );
+ }
+ fn on_touch_frame<I: InputBackend>(&mut self, _evt: I::TouchFrameEvent) {
+ let Some(handle) = self.niri.seat.get_touch() else {
+ return;
+ };
+ handle.frame(self);
+ }
+ fn on_touch_cancel<I: InputBackend>(&mut self, _evt: I::TouchCancelEvent) {
+ let Some(handle) = self.niri.seat.get_touch() else {
+ return;
+ };
+ handle.cancel(self);
+ }
}
/// Check whether the key should be intercepted and mark intercepted
diff --git a/src/niri.rs b/src/niri.rs
index 5b2491d9..418ef6d0 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -144,6 +144,7 @@ pub struct Niri {
pub devices: HashSet<input::Device>,
pub tablets: HashMap<input::Device, TabletData>,
+ pub touch: HashSet<input::Device>,
// Smithay state.
pub compositor_state: CompositorState,
@@ -702,6 +703,10 @@ impl State {
self.niri.reposition_outputs(None);
self.backend.on_output_config_changed(&mut self.niri);
+
+ if let Some(touch) = self.niri.seat.get_touch() {
+ touch.cancel(self);
+ }
}
// Can't really update xdg-decoration settings since we have to hide the globals for CSD
@@ -1002,6 +1007,7 @@ impl Niri {
devices: HashSet::new(),
tablets: HashMap::new(),
+ touch: HashSet::new(),
compositor_state,
xdg_shell_state,
@@ -1602,6 +1608,14 @@ impl Niri {
.or_else(|| self.global_space.outputs().next())
}
+ pub fn output_for_touch(&self) -> Option<&Output> {
+ let config = self.config.borrow();
+ let map_to_output = config.input.touch.map_to_output.as_ref();
+ map_to_output
+ .and_then(|name| self.output_by_name.get(name))
+ .or_else(|| self.global_space.outputs().next())
+ }
+
pub fn output_for_root(&self, root: &WlSurface) -> Option<&Output> {
// Check the main layout.
let win_out = self.layout.find_window_and_output(root);