ltk: subsurface slides over overlays, axis-locked swipes, physical-space layout, touch reset on resume
Subsurfaces can now be parented to an overlay surface, not just the main surface. `SubsurfaceSpec` gains `parent: SubsurfaceParent { Main, Overlay(id) }` so a sliding panel can ride above app windows the way an overlay panel does, and an optional `gpu: bool` so content that uses the `surface-panel` backdrop-filter glass (a GLES-only pass) keeps it while sliding instead of dropping to the software rasteriser. `reconcile_subsurfaces` resolves each spec's parent independently — skipping an `Overlay` parent that is absent, unconfigured, or zero-sized — tracks the rastered size on the slot, and commits each touched parent once per frame. The ~14 GLES shader programs are compiled once into a shared `AppData::subsurface_gles_canvas` reused across every subsurface, so a lazily re-created sliding panel never recompiles them (hundreds of ms on a mobile GPU).
Vertical and horizontal swipes are now mutually exclusive: a gesture locks onto its dominant axis within the first 8 px of travel (new `SwipeAxis`) and ignores the perpendicular axis for the rest of the gesture, so a vertical swipe that drifts sideways no longer also drives the pager (and vice-versa). The upward swipe progress is no longer clamped at 1.0 — follow-the-finger panels can keep tracking the finger past the commit threshold — and a release below threshold delivers a final `progress = 0.0` cancellation pulse. A vertical swipe also no longer re-rasters the full-screen main surface on every motion event: only the overlays it drives are refreshed, while the horizontal pager (which does move the main surface) still redraws it. Re-rastering the main on every frame of a vertical drag was wasted work that stalled the loop and made the gesture feel laggy to start on a slow GPU.
Layout-affecting `Length` values (widths, paddings, gaps, widget sizes, including `Vw` / `Vh`) now resolve against the physical viewport via the new `Canvas::viewport_layout()` — the space the layout tree is actually computed in — so a `Vw(100)` fills the surface on a HiDPI (scale 2) output instead of covering half of it. Font sizes are unchanged: they still resolve against the logical viewport and are scaled at raster time. Switched column, row, spacer, wrap_grid, container, image, and vslider over to it; `img_widget` and `vslider` now document `Length::vw` / `vh` sizing and the showcase example demonstrates a viewport-relative image.
Touch gesture state is reset when the touch capability is added or removed — suspend / resume on devices that power the touchscreen down. A yanked capability never delivers the pending `up` / `cancel`, so the shared `reset_touch_state()` (also used by the `wl_touch.cancel` handler) drops the stranded `primary_touch_id` / slot state across the main surface and every overlay, keeping the first post-resume gesture clean. Also drops an accidental duplicate `on_scale_changed` call from the scale-change handler.
This commit is contained in:
@@ -289,9 +289,30 @@ impl<A: App> TouchHandler for AppData<A>
|
||||
|
||||
fn cancel( &mut self, _conn: &Connection, _qh: &QueueHandle<Self>, _touch: &WlTouch )
|
||||
{
|
||||
// Snapshot every auxiliary slot's last position so the app
|
||||
// can be notified with a meaningful release point, then drop
|
||||
// every per-surface slot in one pass.
|
||||
self.reset_touch_state();
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: App> AppData<A>
|
||||
{
|
||||
/// Drop every in-flight touch gesture across all surfaces, notifying
|
||||
/// the app of any auxiliary slots that were still down. Shared by the
|
||||
/// `wl_touch.cancel` handler and the touch-capability add / remove path
|
||||
/// (suspend / resume on devices that power the touchscreen down): a
|
||||
/// yanked capability never delivers the pending `up` / `cancel`, so
|
||||
/// without this the stale `primary_touch_id` / gesture state strands and
|
||||
/// the first gesture after resume is misrouted and lost. Returns `true`
|
||||
/// when it actually had state to clear.
|
||||
pub( crate ) fn reset_touch_state( &mut self ) -> bool
|
||||
{
|
||||
let had_state = self.main.primary_touch_id.is_some()
|
||||
|| !self.main.touch_slots.is_empty()
|
||||
|| !self.touch_focus.is_empty()
|
||||
|| self.overlays.values().any( |ss| ss.primary_touch_id.is_some() || !ss.touch_slots.is_empty() );
|
||||
|
||||
// Snapshot every auxiliary slot's last position so the app can be
|
||||
// notified with a meaningful release point, then drop every
|
||||
// per-surface slot in one pass.
|
||||
let mut aux_releases: Vec<( i32, crate::types::Point )> = Vec::new();
|
||||
let collect = |ss: &mut SurfaceState<A::Message>, out: &mut Vec<( i32, crate::types::Point )>|
|
||||
{
|
||||
@@ -310,5 +331,6 @@ impl<A: App> TouchHandler for AppData<A>
|
||||
self.app.on_touch_up( id as i64, pos.x, pos.y );
|
||||
}
|
||||
self.stop_button_repeat();
|
||||
had_state
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user