brewery
notashelf /
fb590c1645035cc2537f826f025ac7ea12f5e514

beer

public

A terminal worth pouring time into

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/beer.git

Commit fb590c164503

tarball

NotAShelf <raf@notashelf.dev> · 2026-06-26 08:57 UTC

unverified2 files changed+122-2
wayland: one-finger touch drag scrolls the viewport

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I58396f87fbe47cb3a552bf53d45e7e836a6a6964
diff --git a/src/wayland/handlers.rs b/src/wayland/handlers.rsindex 4ca5233..e1c93c9 100644--- a/src/wayland/handlers.rs+++ b/src/wayland/handlers.rs@@ -141,6 +141,12 @@ impl SeatHandler for App {                 Err(err) => tracing::warn!("get pointer: {err}"),             }         }+        if capability == Capability::Touch && self.seats[i].touch.is_none() {+            match self.seat_state.get_touch(qh, &seat) {+                Ok(touch) => self.seats[i].touch = Some(touch),+                Err(err) => tracing::warn!("get touch: {err}"),+            }+        }     }      fn remove_capability(@@ -165,6 +171,12 @@ impl SeatHandler for App {                     pointer.release();                 }             }+            Capability::Touch => {+                if let Some(touch) = s.touch.take() {+                    touch.release();+                }+                self.touch_scroll = None;+            }             _ => {}         }     }@@ -437,6 +449,96 @@ impl PointerHandler for App {     } } +// Touch drives one-finger drag-to-scroll of the scrollback viewport. Taps and+// multi-finger gestures are ignored; only the first touch point is tracked.+impl TouchHandler for App {+    fn down(+        &mut self,+        _: &Connection,+        _: &QueueHandle<Self>,+        _: &wl_touch::WlTouch,+        _serial: u32,+        _time: u32,+        _surface: wl_surface::WlSurface,+        id: i32,+        position: (f64, f64),+    ) {+        if self.touch_scroll.is_none() {+            self.touch_scroll = Some(TouchScroll {+                id,+                last_y: position.1,+                acc: 0.0,+            });+        }+    }++    fn up(+        &mut self,+        _: &Connection,+        _: &QueueHandle<Self>,+        _: &wl_touch::WlTouch,+        _serial: u32,+        _time: u32,+        id: i32,+    ) {+        if self.touch_scroll.as_ref().is_some_and(|t| t.id == id) {+            self.touch_scroll = None;+        }+    }++    fn motion(+        &mut self,+        _: &Connection,+        _: &QueueHandle<Self>,+        _: &wl_touch::WlTouch,+        _time: u32,+        id: i32,+        position: (f64, f64),+    ) {+        let cell_h = self.renderer.metrics().height as f64;+        let Some(touch) = self.touch_scroll.as_mut().filter(|t| t.id == id) else {+            return;+        };+        touch.acc += position.1 - touch.last_y;+        touch.last_y = position.1;+        // Dragging down (positive delta) reveals older lines, matching the+        // viewport's "positive scrolls back" convention.+        let lines = (touch.acc / cell_h) as isize;+        if lines != 0 {+            touch.acc -= lines as f64 * cell_h;+            if let Some(session) = self.session.as_mut() {+                session.term.scroll_view(lines);+                self.needs_draw = true;+            }+        }+    }++    fn shape(+        &mut self,+        _: &Connection,+        _: &QueueHandle<Self>,+        _: &wl_touch::WlTouch,+        _: i32,+        _: f64,+        _: f64,+    ) {+    }++    fn orientation(+        &mut self,+        _: &Connection,+        _: &QueueHandle<Self>,+        _: &wl_touch::WlTouch,+        _: i32,+        _: f64,+    ) {+    }++    fn cancel(&mut self, _: &Connection, _: &QueueHandle<Self>, _: &wl_touch::WlTouch) {+        self.touch_scroll = None;+    }+}+ impl OutputHandler for App {     fn output_state(&mut self) -> &mut OutputState {         &mut self.output_state@@ -757,6 +859,7 @@ delegate_shm!(App); delegate_seat!(App); delegate_keyboard!(App); delegate_pointer!(App);+delegate_touch!(App); delegate_xdg_shell!(App); delegate_xdg_window!(App); delegate_data_device!(App);diff --git a/src/wayland/mod.rs b/src/wayland/mod.rsindex a20c7e7..446eb46 100644--- a/src/wayland/mod.rs+++ b/src/wayland/mod.rs@@ -46,7 +46,7 @@ use smithay_client_toolkit::{         delegate_activation, delegate_compositor, delegate_data_device, delegate_keyboard,     delegate_output,     delegate_pointer, delegate_primary_selection, delegate_registry, delegate_seat, delegate_shm,-    delegate_xdg_shell, delegate_xdg_window,+    delegate_touch, delegate_xdg_shell, delegate_xdg_window,     output::{OutputHandler, OutputState},     primary_selection::{         PrimarySelectionManagerState,@@ -62,6 +62,7 @@ use smithay_client_toolkit::{             BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, PointerEvent, PointerEventKind, PointerHandler,             cursor_shape::CursorShapeManager,         },+        touch::TouchHandler,     },     shell::{         WaylandSurface,@@ -81,7 +82,7 @@ use wayland_client::{     protocol::{         wl_data_device::WlDataDevice, wl_data_device_manager::DndAction,         wl_data_source::WlDataSource, wl_keyboard, wl_output, wl_pointer, wl_seat, wl_shm,-        wl_surface,+        wl_surface, wl_touch,     }, }; use wayland_protocols::wp::content_type::v1::client::{@@ -289,6 +290,7 @@ pub fn run(config: Config, config_path: Option<std::path::PathBuf>) -> anyhow::R         url_input: String::new(),         unicode_input: None,         keys_down: std::collections::HashSet::new(),+        touch_scroll: None,         focused: true,         exit: false,         exit_code: ExitCode::SUCCESS,@@ -394,6 +396,18 @@ struct SeatData {     primary_device: Option<PrimarySelectionDevice>,     /// text-input-v3 handle for IME preedit/commit, if the compositor offers it.     text_input: Option<ZwpTextInputV3>,+    touch: Option<wl_touch::WlTouch>,+}++/// A single-finger touch drag in progress, used to scroll the viewport.+#[derive(Debug)]+struct TouchScroll {+    /// Touch point id we are tracking (the first finger down).+    id: i32,+    /// Surface-local y of the last motion, to take per-event deltas.+    last_y: f64,+    /// Sub-cell pixel remainder carried between motions.+    acc: f64, }  /// Window + Wayland client state shared across all protocol handlers.@@ -514,6 +528,8 @@ struct App {     /// Raw key codes currently held, to tell press from repeat for the kitty     /// keyboard protocol's event-type reporting.     keys_down: std::collections::HashSet<u32>,+    /// A single-finger touch drag in progress (scrolls the viewport).+    touch_scroll: Option<TouchScroll>,     /// Whether the toplevel currently has keyboard focus (drives the cursor).     focused: bool,     exit: bool,@@ -1205,6 +1221,7 @@ impl App {             data_device: None,             primary_device: None,             text_input: None,+            touch: None,         });         self.seats.len() - 1     }