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:
@@ -1,23 +1,43 @@
|
||||
//! `cargo run --example showcase`
|
||||
//!
|
||||
//! Shows button variants, container with background, a slider, plus the
|
||||
//! newer additions: a tab strip, a spinner driven by the wall clock, a
|
||||
//! multiline text edit, and on-demand toast / tooltip overlays.
|
||||
//! Shows button variants, container with background, a slider, a
|
||||
//! viewport-relative image, plus the newer additions: a tab strip, a spinner
|
||||
//! driven by the wall clock, a multiline text edit, and on-demand toast /
|
||||
//! tooltip overlays.
|
||||
//! Tab / Shift+Tab cycles keyboard focus. Enter or Space activates the
|
||||
//! focused button. Esc exits.
|
||||
//!
|
||||
//! NOTE: ltk is a Wayland layer-shell toolkit. This example requires a running
|
||||
//! Wayland compositor (e.g. sway, labwc, or a full desktop session).
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::{ Duration, Instant };
|
||||
|
||||
use ltk::{
|
||||
App, Element, Keysym, ButtonVariant, WidgetId,
|
||||
App, Element, Keysym, ButtonVariant, Length, WidgetId,
|
||||
OverlaySpec,
|
||||
button, column, row, stack, text, text_edit, spacer, container, slider, scroll,
|
||||
spinner, tabs, toast, tooltip,
|
||||
spinner, tabs, toast, tooltip, img_widget,
|
||||
};
|
||||
|
||||
const IMG_W: u32 = 64;
|
||||
const IMG_H: u32 = 64;
|
||||
|
||||
fn gradient_rgba() -> Arc<Vec<u8>>
|
||||
{
|
||||
let mut data = Vec::with_capacity( ( IMG_W * IMG_H * 4 ) as usize );
|
||||
for y in 0..IMG_H
|
||||
{
|
||||
for x in 0..IMG_W
|
||||
{
|
||||
let r = ( 255 * x / IMG_W ) as u8;
|
||||
let g = ( 255 * y / IMG_H ) as u8;
|
||||
data.extend_from_slice( &[ r, g, 180, 255 ] );
|
||||
}
|
||||
}
|
||||
Arc::new( data )
|
||||
}
|
||||
|
||||
// ── Messages ──────────────────────────────────────────────────────────────────
|
||||
|
||||
#[ derive( Clone ) ]
|
||||
@@ -43,6 +63,7 @@ struct ShowcaseApp
|
||||
started_at: Instant,
|
||||
toast_until: Option<Instant>,
|
||||
tooltip_visible: bool,
|
||||
image: Arc<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl ShowcaseApp
|
||||
@@ -58,6 +79,7 @@ impl ShowcaseApp
|
||||
started_at: Instant::now(),
|
||||
toast_until: None,
|
||||
tooltip_visible: false,
|
||||
image: gradient_rgba(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +149,13 @@ impl App for ShowcaseApp
|
||||
.radius( 12.0 )
|
||||
.padding( 16.0 );
|
||||
|
||||
// Viewport-relative image: 30 % of the surface width by 10 % of its
|
||||
// height, so it rescales with the window instead of staying fixed.
|
||||
let banner = column::<Message>()
|
||||
.spacing( 4.0 )
|
||||
.push( text( "img_widget().size( vw 30, vh 10 )" ).size( 12.0 ).color( secondary ) )
|
||||
.push( img_widget( self.image.clone(), IMG_W, IMG_H ).size( Length::vw( 30.0 ), Length::vh( 10.0 ) ) );
|
||||
|
||||
let vol_label = format!( "Volume: {:.0}%", self.slider_value * 100.0 );
|
||||
|
||||
// Spinner — phase comes straight from the wall clock so the arc
|
||||
@@ -163,6 +192,7 @@ impl App for ShowcaseApp
|
||||
.push( spacer() )
|
||||
.push( buttons )
|
||||
.push( card )
|
||||
.push( banner )
|
||||
.push( text( vol_label ).size( 13.0 ).color( secondary ) )
|
||||
.push( slider( self.slider_value ).on_change( Message::SliderChanged ) )
|
||||
.push( spin_row )
|
||||
|
||||
Reference in New Issue
Block a user