[ltk — src/input/gesture/mod.rs, src/input/gesture/tests.rs, src/widget/handlers.rs, src/input/keyboard/dispatch.rs, src/render/image.rs, docs/architecture.md, CHANGELOG.md] Keep a tap on a button while the finger rolls inside it, treat XF86Back like Escape, and convert ARGB8888 by whole pixels
Any travel past the slop turned a press into a vertical or horizontal drag and its release skipped the button, so a thumb that rolled on a large key lost the tap. `GestureState::on_move` now stays idle while the pressed widget fires on press (the new `WidgetHandlers::has_press`) and the finger is still inside its rect; the swipe machinery takes over from the original press point once the finger leaves. Presses inside a scroll viewport are unaffected, since a list of full-width rows is scrolled by dragging on them. Two tests cover the tap that survives motion inside the button and the swipe that arms once the finger leaves it; the architecture notes and the changelog describe the rule. The compositor now sends XF86Back for the Android back gesture, an inward swipe from either side edge. With a text input focused that keysym fell into `handle_key_default` and was swallowed, so an app never saw it. `XF86Back` now dispatches through `handle_key_escape`, so every ltk app gets the back gesture with Escape's layering: open popups, then the context menu, then a selection, then a dialog's cancel, and finally the focus drop and `on_key_with_modifiers` with the keysym, where an app can act on it. `SoftwareCanvas::write_to_wayland_buf` swapped red and blue with a byte-by-byte loop, unrolled by hand over sixteen bytes. It now reads each pixel as a `u32`, exchanges the two channels with masks and shifts, and leaves the vectorisation to the compiler. Compositors that offer `ABGR8888` never took this path.
This commit is contained in:
@@ -38,6 +38,7 @@ All notable changes to `ltk` are documented here. The format is based on [Keep a
|
||||
|
||||
### Changed
|
||||
|
||||
- **The software backend's ARGB8888 conversion works on whole pixels.** `SoftwareCanvas::write_to_wayland_buf` swapped red and blue with a byte-by-byte loop over the frame; it now reads each pixel as a `u32`, exchanges the two channels with masks and shifts, and lets the compiler vectorise it. Compositors that offer `ABGR8888` were never affected.
|
||||
- **Breaking: `App::app_id`, `App::save_state` and `App::restore_state` are new mandatory trait methods** — every implementor must add them (shell components: constant id, `None`, no-op). `xdg_toplevel.set_app_id` and the AccessKit application name now come from `app_id()` (previously `"ltk"` / `"ltk-app"`); the `app_id` element of the deprecated `window_config` tuple is ignored. Crate version bumped to 0.3.0.
|
||||
- **`Button::icon_size` takes `impl Into<Length>`** and resolves through `Canvas::resolve_geom`, joining `font_size` / `height` / `width`. A bare `f32` still means `Length::px` — every existing call keeps its exact size — but a caller can now pass `Length::widget( n )` to have an icon button follow the widget-scaling mode the way stock icons do. Without it an explicit `icon_size` was the one geometry setter that ignored the mode, so a 21 px back arrow sat next to a `list_item` chevron that fluid sizing had grown well past 21 and looked visibly smaller.
|
||||
- **`Length::dp` now applies the density at resolution time, not at construction.** The value carries its design pixels in a new `LengthBase::Dp` variant and `resolve` multiplies by the density in effect when it runs, so a `set_density` change takes effect on the next paint without rebuilding the view's lengths — previously a `dp` value was frozen to the density read when it was constructed. Behaviour is unchanged for code that sets density once at startup.
|
||||
@@ -52,6 +53,7 @@ All notable changes to `ltk` are documented here. The format is based on [Keep a
|
||||
|
||||
- **Fast two-thumb typing no longer drops taps.** A finger landing while another was still down went to the auxiliary slot and never reached the gesture machine, so on a touch keypad every overlapping tap was lost. A finger landing on a primary that is still a plain press (`GestureState::is_plain_press`: no drag, scroll, swipe or slider in flight) now commits that press as a tap at its last position and takes the primary slot; the earlier finger's release reports through `App::on_touch_up`. Presses that have become a drag keep the old behaviour, so a second finger during a pattern stroke or a slider drag still stays out of the gesture machine.
|
||||
- **`PatternGrid::on_node` fires once per node, not once per motion event.** Every touch motion within a node's snap radius re-emitted the node's message and requested a repaint, so drawing a pattern rebuilt and re-rastered the surface at the touchscreen's motion rate. The gesture machine now remembers the node the finger is over (`last_pattern_node`) and emits only on change; a `Slider` move outcome without a message no longer requests a redraw.
|
||||
- **A tap on a button survives finger motion inside the button.** Any travel past the slop turned the press into a vertical or horizontal drag and its release skipped the button, so a thumb that rolled on a large key lost the tap. While the pressed widget fires on press (`WidgetHandlers::has_press`) and the finger is still inside its rect, motion is ignored; the swipe machinery takes over from the original press point once the finger leaves, and presses inside a scroll viewport are unaffected.
|
||||
- **Gesture thresholds are logical pixels.** The 8 px travel that turns a press into a scroll, swipe or drag, and the 6 px stray that cancels a touch long-press, were compared against physical coordinates, so on a scale-2 panel they were 4 and 3 logical px and an ordinary thumb tap became a vertical drag whose release skipped the button. `SwipeConfig` now carries the surface's buffer `scale` and the machine reads the thresholds through `SwipeConfig::slop` / `stray`.
|
||||
- **A 1:1 opaque image is a row copy in the software renderer.** With the premultiplied copy cached, drawing it unscaled with no clip and full alpha now copies rows into the canvas instead of running tiny-skia's bilinear pipeline over every pixel, which is what a full-surface backdrop cost on every frame.
|
||||
- **The software renderer premultiplies an image once, not on every draw.** `SoftwareCanvas::draw_image_data` converted the whole source to premultiplied alpha in floating point on each call, so a full-surface backdrop cost a pass over every pixel per frame on top of the blit. Premultiplied copies are now kept in a 32 MiB least-recently-drawn cache keyed by size, content fingerprint and alpha, the same key the GLES texture cache uses (`fingerprint_rgba` moves to `render::helpers` to be shared).
|
||||
|
||||
Reference in New Issue
Block a user