Skip to content

Commit 69a0dfc

Browse files
authored
Update mod.rs
1 parent 21b9785 commit 69a0dfc

1 file changed

Lines changed: 129 additions & 0 deletions

File tree

src/input/mod.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use smithay::{
44
KeyState, KeyboardKeyEvent,
55
PointerAxisEvent, PointerButtonEvent, PointerMotionEvent,
66
PointerMotionAbsoluteEvent,
7+
TouchDownEvent, TouchMotionEvent, TouchUpEvent, TouchCancelEvent, TouchEvent,
78
},
89
desktop::WindowSurfaceType,
910
input::{
@@ -13,6 +14,7 @@ use smithay::{
1314
GrabStartData as PointerGrabStartData,
1415
MotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent,
1516
},
17+
touch::{DownEvent as TouchDownData, MotionEvent as TouchMotionData, UpEvent as TouchUpData},
1618
},
1719
reexports::wayland_server::protocol::wl_surface::WlSurface,
1820
utils::{Logical, Point, Rectangle, Size, SERIAL_COUNTER},
@@ -32,6 +34,19 @@ pub fn handle_input<B: InputBackend>(state: &mut BlueState, event: InputEvent<B>
3234
}
3335
InputEvent::PointerButton { event } => handle_pointer_button(state, &event),
3436
InputEvent::PointerAxis { event } => handle_pointer_axis(state, &event),
37+
// Touch — was entirely absent before (fell into the wildcard
38+
// below and was silently dropped, along with the seat never
39+
// advertising the `touch` capability at all — see
40+
// `render/mod.rs`'s `add_touch()` calls, added alongside this).
41+
InputEvent::TouchDown { event } => handle_touch_down(state, &event),
42+
InputEvent::TouchMotion { event } => handle_touch_motion(state, &event),
43+
InputEvent::TouchUp { event } => handle_touch_up(state, &event),
44+
InputEvent::TouchCancel { event } => handle_touch_cancel(state, &event),
45+
InputEvent::TouchFrame { .. } => {
46+
if let Some(touch) = state.seat.get_touch() {
47+
touch.frame(state);
48+
}
49+
}
3550
_ => {}
3651
}
3752
}
@@ -731,6 +746,120 @@ pub fn start_resize_grab(
731746
);
732747
}
733748

749+
// ── Touch ────────────────────────────────────────────────────────────────
750+
//
751+
// New — this seat previously never advertised the `touch` capability at
752+
// all (see `render/mod.rs`'s `add_touch()` calls, added alongside this),
753+
// so every `InputEvent::Touch*` variant fell into `handle_input`'s
754+
// wildcard and was silently dropped, regardless of what hardware sent
755+
// them (a touchscreen, or the winit backend's own touch emulation when
756+
// nested inside a host compositor that has one).
757+
//
758+
// Written without a compiler available to verify the exact smithay
759+
// touch API surface at this pinned rev against (same caveat this file's
760+
// pointer/keyboard code doesn't need anymore having presumably been
761+
// fixed against real compile errors already, but genuinely applies here
762+
// since touch is new) — structured to mirror the pointer handlers
763+
// directly above as closely as the wl_touch protocol's actual semantics
764+
// allow, which is the one thing I'm confident about regardless of exact
765+
// method signatures: unlike wl_pointer, focus for a given touch point
766+
// is resolved *once*, at touch-down, from the touch point's position at
767+
// that moment — motion/up for that same touch id then keep going to
768+
// whatever surface was under it at down, even if the finger slides off
769+
// that surface's bounds entirely (real wl_touch protocol behavior, not
770+
// specific to this compositor).
771+
772+
/// Resolves which surface (if any) is under a global point — the same
773+
/// hit-testing `update_pointer_focus` above already does for the
774+
/// pointer, factored out so touch-down can reuse it without duplicating
775+
/// the `space.element_under` + `surface_under` dance.
776+
fn surface_under_point(state: &BlueState, pos: Point<f64, Logical>) -> Option<(WlSurface, Point<f64, Logical>)> {
777+
state
778+
.space
779+
.element_under(pos)
780+
.and_then(|(win, win_loc)| {
781+
let rel = pos - win_loc.to_f64();
782+
win.surface_under(rel, WindowSurfaceType::ALL)
783+
.map(|(s, sp)| (s, (win_loc + sp).to_f64()))
784+
})
785+
}
786+
787+
/// Touch is inherently absolute (a touchscreen's coordinate space maps
788+
/// directly onto the output, same reasoning as
789+
/// `PointerMotionAbsoluteEvent::position_transformed` above) — this
790+
/// mirrors `handle_pointer_motion_abs`'s own output-size lookup exactly
791+
/// rather than introducing a second way to get it.
792+
fn output_size_for_touch(state: &BlueState) -> Size<i32, Logical> {
793+
state
794+
.space
795+
.outputs()
796+
.next()
797+
.and_then(|o| state.space.output_geometry(o))
798+
.map(|g| g.size)
799+
.unwrap_or(Size::from((1920, 1080)))
800+
}
801+
802+
fn handle_touch_down<B: InputBackend, E: TouchDownEvent<B>>(state: &mut BlueState, event: &E) {
803+
let Some(touch) = state.seat.get_touch() else { return };
804+
let serial = SERIAL_COUNTER.next_serial();
805+
let size = output_size_for_touch(state);
806+
let position = event.position_transformed(size);
807+
let focus = surface_under_point(state, position);
808+
809+
touch.down(
810+
state,
811+
focus,
812+
&TouchDownData {
813+
slot: event.slot(),
814+
location: position,
815+
serial,
816+
time: event.time_msec(),
817+
},
818+
);
819+
}
820+
821+
fn handle_touch_motion<B: InputBackend, E: TouchMotionEvent<B>>(state: &mut BlueState, event: &E) {
822+
let Some(touch) = state.seat.get_touch() else { return };
823+
let size = output_size_for_touch(state);
824+
let position = event.position_transformed(size);
825+
// Per wl_touch semantics (see this section's own header note): focus
826+
// for this slot was already fixed at touch-down and isn't
827+
// re-resolved here — passed as `None` on the theory that smithay's
828+
// `TouchHandle::motion` looks up the slot's already-established
829+
// focus internally (mirroring how `PointerHandle::motion` is the
830+
// one that takes an explicit focus, but touch's per-slot routing is
831+
// a different enough model that it may not need it passed again).
832+
// Flagged clearly since this is the least-confident guess in this
833+
// whole section.
834+
touch.motion(
835+
state,
836+
None,
837+
&TouchMotionData {
838+
slot: event.slot(),
839+
location: position,
840+
time: event.time_msec(),
841+
},
842+
);
843+
}
844+
845+
fn handle_touch_up<B: InputBackend, E: TouchUpEvent<B>>(state: &mut BlueState, event: &E) {
846+
let Some(touch) = state.seat.get_touch() else { return };
847+
let serial = SERIAL_COUNTER.next_serial();
848+
touch.up(
849+
state,
850+
&TouchUpData {
851+
slot: event.slot(),
852+
serial,
853+
time: event.time_msec(),
854+
},
855+
);
856+
}
857+
858+
fn handle_touch_cancel<B: InputBackend, E: TouchCancelEvent<B>>(state: &mut BlueState, _event: &E) {
859+
let Some(touch) = state.seat.get_touch() else { return };
860+
touch.cancel(state);
861+
}
862+
734863
#[cfg(test)]
735864
mod resize_edges_tests {
736865
use super::ResizeEdges;

0 commit comments

Comments
 (0)