ltk

Trait App

Source
pub trait App: 'static {
    type Message: Clone + 'static;

Show 59 methods // Required methods fn view(&self) -> Element<Self::Message>; fn update(&mut self, msg: Self::Message); // Provided methods fn invalidate_after(&self, _msg: &Self::Message) -> InvalidationScope { ... } fn overlays(&self) -> Vec<OverlaySpec<Self::Message>> { ... } fn subsurfaces(&self) -> Vec<SubsurfaceSpec<Self::Message>> { ... } fn poll_external(&mut self) -> Vec<Self::Message> { ... } fn on_first_frame_committed(&mut self) { ... } fn on_close_requested(&mut self) -> bool { ... } fn on_tap(&mut self) -> Option<Self::Message> { ... } fn on_key(&mut self, _keysym: Keysym) -> Option<Self::Message> { ... } fn on_key_with_modifiers( &mut self, keysym: Keysym, _ctrl: bool, _shift: bool, ) -> Option<Self::Message> { ... } fn on_swipe_up(&mut self) -> Option<Self::Message> { ... } fn on_swipe_progress(&mut self, _progress: f32) { ... } fn on_swipe_down(&mut self) -> Option<Self::Message> { ... } fn on_swipe_down_progress(&mut self, _progress: f32) { ... } fn swipe_threshold(&self) -> f32 { ... } fn swipe_down_threshold(&self) -> f32 { ... } fn swipe_down_edge(&self) -> f32 { ... } fn on_swipe_left(&mut self) -> Option<Self::Message> { ... } fn on_swipe_right(&mut self) -> Option<Self::Message> { ... } fn on_swipe_horizontal_progress(&mut self, _progress: f32) { ... } fn swipe_horizontal_threshold(&self) -> f32 { ... } fn long_press_duration(&self) -> Duration { ... } fn on_drag_move(&mut self, _x: f32, _y: f32) { ... } fn on_drop(&mut self, _x: f32, _y: f32) -> Option<Self::Message> { ... } fn on_text_input_focused(&mut self, _active: bool) { ... } fn on_toplevel_event(&self, _event: ToplevelEvent) -> Option<Self::Message> { ... } fn take_focus_request(&mut self) -> Option<WidgetId> { ... } fn on_pointer_move(&mut self, _x: f32, _y: f32) { ... } fn on_pointer_axis(&mut self, _x: f32, _y: f32, _dx: f32, _dy: f32) { ... } fn on_touch_down(&mut self, _id: i64, _x: f32, _y: f32) { ... } fn on_touch_move(&mut self, _id: i64, _x: f32, _y: f32) { ... } fn on_touch_up(&mut self, _id: i64, _x: f32, _y: f32) { ... } fn on_drop_motion(&mut self, _x: f32, _y: f32) { ... } fn on_drop_leave(&mut self) { ... } fn on_drop_received(&mut self, _x: f32, _y: f32, _mime: &str, _text: &str) { ... } fn on_pointer_button(&mut self, _x: f32, _y: f32, _pressed: bool) { ... } fn on_raw_key( &mut self, _keysym: Keysym, _keycode: u32, _pressed: bool, _ctrl: bool, _shift: bool, ) { ... } fn on_resize(&mut self, _width: u32, _height: u32) { ... } fn on_scale_changed(&mut self, _scale: u32) { ... } fn set_channel_sender(&mut self, _sender: ChannelSender<Self::Message>) { ... } fn poll_interval(&self) -> Option<Duration> { ... } fn key_repeat_delay(&self) -> Option<Duration> { ... } fn key_repeat_interval(&self) -> Option<Duration> { ... } fn cursor_override(&self) -> Option<CursorShape> { ... } fn key_repeats(&self, keysym: Keysym) -> bool { ... } fn is_animating(&self) -> bool { ... } fn subsurface_motion_only(&self) -> bool { ... } fn background_color(&self) -> Color { ... } fn input_region(&self) -> Option<Vec<Rect>> { ... } fn window_config(&self) -> Option<(&str, &str)> { ... } fn shell_mode(&self) -> ShellMode { ... } fn requested_exit(&self) -> bool { ... } fn window_size_hint(&self) -> Option<(u32, u32)> { ... } fn start_fullscreen(&self) -> bool { ... } fn exclusive_zone(&self) -> i32 { ... } fn layer_anchor(&self) -> Anchor { ... } fn layer_size(&self) -> (u32, u32) { ... } fn keyboard_exclusive(&self) -> bool { ... }
}
Expand description

Trait that application types must implement to integrate with ltk.

Required Associated Types§

Source

type Message: Clone + 'static

The message type produced by this application.

Required Methods§

Source

fn view(&self) -> Element<Self::Message>

Build the widget tree for the current frame.

Source

fn update(&mut self, msg: Self::Message)

Apply a message to the application state.

Provided Methods§

Source

fn invalidate_after(&self, _msg: &Self::Message) -> InvalidationScope

Tell the runtime which surfaces could have changed visibly as a result of update being called with this message.

Default is InvalidationScope::All — every surface is redrawn. A shell that knows, for example, that a SetVolume message only affects its quick-settings overlay can return InvalidationScope::Only( vec![ SurfaceTarget::Overlay( quick_id ) ] ) to skip pointless work on other surfaces.

Called before update (so it sees the message but not the post-update state). Side-effect free: must not mutate self.

Source

fn overlays(&self) -> Vec<OverlaySpec<Self::Message>>

Describe the auxiliary overlay surfaces that should be active this frame. Each entry becomes its own Wayland layer-shell surface independent from the main surface returned by view.

Return an empty Vec (the default) to disable multi-surface support — the app then renders only onto its main surface.

The runtime diffs the list across frames using OverlaySpec::id: stable IDs are kept alive, new IDs cause a surface to be created, and IDs that disappear cause the surface to be destroyed.

Source

fn subsurfaces(&self) -> Vec<SubsurfaceSpec<Self::Message>>

Describe the input-transparent child surfaces composited over the main surface this frame. Each becomes a wl_subsurface the compositor moves by position; see SubsurfaceSpec. Diffed across frames by SubsurfaceSpec::id. Default empty.

Source

fn poll_external(&mut self) -> Vec<Self::Message>

Return any pending messages from external sources (timers, async, etc.).

Source

fn on_first_frame_committed(&mut self)

Called once, immediately after the first buffer for the main surface has been rendered and committed to the compositor. Note: this is the client-side commit, not the compositor’s present — under VT switching the actual present can be deferred (no DRM master yet), so a handoff signal that fires here is enough to tell a parent “ready to be presented as soon as my VT becomes active”.

Source

fn on_close_requested(&mut self) -> bool

Called when the surface is asked to close (compositor request, titlebar button, layer-shell closed event). Return true to allow the application to exit, or false to cancel.

Default: true (always close).

Source

fn on_tap(&mut self) -> Option<Self::Message>

Called when tapping/clicking outside any widget.

Source

fn on_key(&mut self, _keysym: Keysym) -> Option<Self::Message>

Called on key press when no text input is focused.

Source

fn on_key_with_modifiers( &mut self, keysym: Keysym, _ctrl: bool, _shift: bool, ) -> Option<Self::Message>

Called on key press with modifier state. Override this instead of on_key when you need Ctrl/Shift/Alt awareness.

Source

fn on_swipe_up(&mut self) -> Option<Self::Message>

Called when a sufficient upward swipe gesture is detected.

Return a message to handle the swipe (e.g., opening an overview). The gesture is recognized when the user drags upward by at least swipe_threshold() × screen height and then releases.

Source

fn on_swipe_progress(&mut self, _progress: f32)

Called during an upward swipe gesture with progress ≥ 0.0.

Use this to create follow-the-finger animations. progress starts at 0.0 when the drag begins and increases as the finger moves upward, reaching 1.0 when the drag distance equals swipe_threshold() × screen height. It is not clamped at 1.0 — the value keeps growing if the finger drags further so that follow-the-finger panels can continue tracking the finger all the way up the screen. Clamp inside the handler if you need a bounded [0, 1] range for a visual indicator.

When the user releases without completing the gesture, this method is called once more with progress = 0.0 to signal cancellation.

Source

fn on_swipe_down(&mut self) -> Option<Self::Message>

Called when a sufficient downward swipe gesture is detected.

Return a message to handle the swipe (e.g., toggling quick settings). The gesture is recognized when the user drags downward by at least swipe_down_threshold() × screen height and then releases.

Source

fn on_swipe_down_progress(&mut self, _progress: f32)

Called during a downward swipe gesture with progress ≥ 0.0.

Use this to create follow-the-finger animations. progress starts at 0.0 when the drag begins and increases as the finger moves downward, reaching 1.0 when the drag distance equals swipe_down_threshold() × screen height. It is not clamped at 1.0 — the value keeps growing if the finger drags further so that follow-the-finger panels can continue tracking the finger all the way down the screen. Clamp inside the handler if you need a bounded [0, 1] range for a visual indicator.

When the user releases without completing the gesture, this method is called once more with progress = 0.0 to signal cancellation.

Source

fn swipe_threshold(&self) -> f32

Fraction of screen height required to trigger on_swipe_up.

Default: 0.6 (60% of screen height). Lower values make the gesture easier to trigger; higher values require more vertical travel.

Source

fn swipe_down_threshold(&self) -> f32

Fraction of screen height required to trigger on_swipe_down.

Default: 0.15 (15% of screen height). Typically lower than swipe_threshold() because downward swipes are often initiated from a small UI element like a top bar.

Source

fn swipe_down_edge(&self) -> f32

Top-edge band where a downward swipe may originate, as a fraction of screen height. Presses below this band never fire on_swipe_down nor on_swipe_down_progress.

Default: 1.0 (entire screen — any starting point is accepted). Set to a small value like 0.05 to restrict the gesture to the top edge, matching the usual system-panel pull-down UX.

Source

fn on_swipe_left(&mut self) -> Option<Self::Message>

Called when a sufficient leftward swipe gesture is detected.

Return a message to handle the swipe (e.g., paging to the next homescreen). Fires on release when the user dragged left by at least swipe_horizontal_threshold() × screen width. Unlike vertical swipes, horizontal swipes survive starting the press on an interactive widget: once the drag distance crosses an 8 px threshold the press is promoted to a horizontal drag and no tap will fire at release.

Source

fn on_swipe_right(&mut self) -> Option<Self::Message>

Called when a sufficient rightward swipe gesture is detected. Mirror of on_swipe_left for the other direction.

Source

fn on_swipe_horizontal_progress(&mut self, _progress: f32)

Called during a horizontal swipe with signed progress. Negative values mean the finger has moved left, positive values mean right. The value is dx / (threshold * width), so ±1.0 marks the commit threshold; it is not clamped so follow-the-finger panels can keep tracking past the threshold. When the user releases without completing the gesture this method is called once more with 0.0 to signal cancellation.

Source

fn swipe_horizontal_threshold(&self) -> f32

Fraction of screen width required to commit App::on_swipe_left / App::on_swipe_right. Default: 0.5 (half the screen). A shell that wants easier paging can lower this; one that wants to avoid accidental pages can raise it.

Source

fn long_press_duration(&self) -> Duration

Duration a press must remain stationary (within tolerance) before the widget’s long-press message fires and the gesture transitions into drag mode. Default: 500 ms.

Source

fn on_drag_move(&mut self, _x: f32, _y: f32)

Called on every pointer motion once a long-press has fired and the gesture has entered drag mode. x, y are in physical pixels of the surface that owned the original press.

Source

fn on_drop(&mut self, _x: f32, _y: f32) -> Option<Self::Message>

Called on release once a long-press has fired. Return a message to handle the drop (e.g., commit the drop target). x, y are in physical pixels of the surface that owned the original press. The regular tap / swipe handling is suppressed for this gesture.

Source

fn on_text_input_focused(&mut self, _active: bool)

Called when a text-input widget gains or loses focus.

Source

fn on_toplevel_event(&self, _event: ToplevelEvent) -> Option<Self::Message>

Translate a Wayland ext-foreign-toplevel-list-v1 event into an app message. The runtime binds the protocol globally and forwards every open / close it sees here; apps that ignore window state leave the default (return None) and pay nothing.

The id field is the Wayland object id of the toplevel handle — unique within the session, stable for the handle’s lifetime, the same value coming in on Closed as the matching Opened. app_id on Opened is the toplevel’s app_id event (may be empty if the compositor never sent one before the first done).

Source

fn take_focus_request(&mut self) -> Option<WidgetId>

Return Some(id) once to focus the widget with that WidgetId. The app must return None after the first call.

Source

fn on_pointer_move(&mut self, _x: f32, _y: f32)

Called on every pointer motion (mouse move, button press, button release). x, y are in physical pixels of the main surface, the same coordinate space as widget rects. Default: no-op.

Useful for embedding components that need to know the live pointer position without going through a full crate::widget::external::ExternalSource / WidgetHandlers dispatch path — for example forwarding clicks into an embedded WPE WebView.

Source

fn on_pointer_axis(&mut self, _x: f32, _y: f32, _dx: f32, _dy: f32)

Called on a wheel / touchpad scroll event whose position does not fall inside any LTK scroll viewport. x, y are in physical pixels (same coordinate space as Self::on_pointer_move); dx, dy are scroll deltas in the raw axis units the compositor delivered (AxisSource::Wheel gives ~10 px ticks, touchpads give continuous values). Default: no-op.

Useful for embeddings that take over scrolling for their own content — for example forwarding the event to a WPE view that owns a scrollable web page.

Source

fn on_touch_down(&mut self, _id: i64, _x: f32, _y: f32)

Raw multi-touch callbacks. Default: no-op.

The first finger to land becomes the primary slot and is fed through the regular gesture machine — on_pointer_*, swipe, scroll, long-press, drag-and-drop all run from that slot. Every additional finger fires on_touch_down / on_touch_move / on_touch_up instead, with id matching the wl_touch.id the compositor delivered.

Use this for app-defined multi-finger gestures (pinch-zoom, two-finger pan in a canvas, parallel keyboard keys) that the built-in single-slot machine cannot model. (x, y) are in physical pixels, matching the coordinate space of Self::on_pointer_move.

Source

fn on_touch_move(&mut self, _id: i64, _x: f32, _y: f32)

Source

fn on_touch_up(&mut self, _id: i64, _x: f32, _y: f32)

See Self::on_touch_down. x, y are the last known position of the finger (wl_touch.up does not carry one).

Source

fn on_drop_motion(&mut self, _x: f32, _y: f32)

Pointer of a cross-application drag-and-drop entered or moved inside the main surface. (x, y) is in logical pixels.

Source

fn on_drop_leave(&mut self)

The drag left without dropping.

Source

fn on_drop_received(&mut self, _x: f32, _y: f32, _mime: &str, _text: &str)

External drop payload landed on the surface. mime is the best mime the source offered (text/uri-list, text/plain, …) and text is the decoded payload (UTF-8). (x, y) is the release position in logical pixels.

Source

fn on_pointer_button(&mut self, _x: f32, _y: f32, _pressed: bool)

Called on every left-button mouse press / release before the regular gesture machine fires. pressed = true for press, false for release. (x, y) are in physical pixels (same coordinate space as Self::on_pointer_move). Default: no-op.

Lets embeddings see the raw button transitions without going through LTK’s tap/long-press/drag classification — needed for forwarding clicks AND drags to an embedded view, since the tap classifier collapses press+release into a single event.

Source

fn on_raw_key( &mut self, _keysym: Keysym, _keycode: u32, _pressed: bool, _ctrl: bool, _shift: bool, )

Called on every keyboard event (press and release) before the regular focus-aware dispatch (Self::on_key / Self::on_key_with_modifiers) runs. Default: no-op.

keycode is the raw hardware scancode straight from the compositor (wl_keyboard.key’s key argument); keysym is the xkb-translated keysym the user effectively pressed. Most consumers only care about keysym, but embeddings that forward into an inner window system (a WPE web view, an X11 emulator, …) typically need both — the inner system does its own keycode → keysym translation for layout-aware shortcuts.

This bypass exists for those embeddings: it fires in addition to the normal callbacks; consume or ignore at will.

Source

fn on_resize(&mut self, _width: u32, _height: u32)

Called when the surface is (re-)configured with a new size.

width and height are in physical pixels (the Wayland surface size multiplied by the current buffer scale). They therefore match the coordinate space used for layout and the pointer/touch callbacks (on_drag_move, on_drop, widget hit-testing). Also fired when the buffer scale changes, so apps can refresh any state keyed off the old physical dimensions.

Source

fn on_scale_changed(&mut self, _scale: u32)

Called when the compositor reports a new integer buffer scale for the main surface. scale is the integer buffer scale (1 = standard DPI, 2 = HiDPI ×2); physical pixels equal logical pixels × scale. The default is inert so apps that only care about physical pixels can keep using on_resize.

Source

fn set_channel_sender(&mut self, _sender: ChannelSender<Self::Message>)

Called once at startup with a channel sender that can be used from any thread to deliver messages into the event loop. Sending a message immediately wakes the event loop — no polling delay.

Source

fn poll_interval(&self) -> Option<Duration>

How often the event loop should call poll_external for periodic work such as clock ticks. Return None (the default) to disable the timer — poll_external will still be called after every Wayland event.

Source

fn key_repeat_delay(&self) -> Option<Duration>

Delay before the runtime starts repeating a held-down key.

Some(d) overrides whatever the compositor advertises through wl_keyboard.repeat_info; None (the default) means “use the compositor’s setting, or fall back to 500 ms when the compositor did not provide one”.

Returning Some(Duration::ZERO) effectively disables the wait before the first repeat — useful only for diagnostic builds.

Source

fn key_repeat_interval(&self) -> Option<Duration>

Interval between successive synthetic key events while a key is held down past the initial Self::key_repeat_delay.

Some(d) overrides the compositor’s wl_keyboard.repeat_info rate; None (the default) means “use the compositor’s setting, or fall back to 33 ms (~30 Hz) when the compositor did not provide one”. Pass Some(Duration::ZERO) to disable repeats entirely (or override the per-key gate via Self::key_repeats).

Source

fn cursor_override(&self) -> Option<CursorShape>

Override the pointer cursor shape globally. When Some(shape), the runtime sends that shape to the compositor regardless of which widget the pointer is over — useful for “the app is busy” states (return crate::CursorShape::Wait) or while the app is doing a long synchronous operation. Returning None (the default) lets per-widget defaults take effect.

The runtime calls this every frame, so flipping a loading boolean in Self::update propagates to the cursor on the next iteration without any extra wiring.

Source

fn key_repeats(&self, keysym: Keysym) -> bool

Decide whether a given key participates in held-key repeat.

Default: every non-modifier key repeats except Escape, Tab and ISO_Left_Tab — those drive one-shot UI semantics (dismiss / focus cycle) where a held key would multiply the effect in surprising ways. Override to widen or narrow the gate (a chess clock app, for example, might want even Tab to repeat).

Source

fn is_animating(&self) -> bool

Return true while a frame-by-frame animation is running. The event loop will keep requesting redraws at ~60 fps until this returns false.

Source

fn subsurface_motion_only(&self) -> bool

Return true when a finger-tracked swipe or an Self::is_animating slide only repositions the app’s input-transparent subsurfaces (Self::subsurfaces) while the main surface buffer stays unchanged. The runtime then skips the per-frame main re-raster that Self::on_swipe_progress and is_animating would otherwise force, keeping the animation pumped (motion events during the drag, a bare frame callback while is_animating) and letting the per-frame subsurface reconcile carry the motion. Use it for a slide-to-reveal panel over a static main surface.

Source

fn background_color(&self) -> Color

Return true while the next frame should swap the expensive Glass passes for cheap fallbacks — currently the backdrop-filter blur drops from a 41-tap kernel to a 9-tap kernel, with the snapshot region shrunk to match. The event loop sets this on the renderer right before drawing through an internal low-quality-paint flag.

Default: matches Self::is_animating, so a settle animation automatically downgrades. Override to include other “in motion” states the runtime cannot observe — e.g. a finger-tracked Background color for the canvas. Override to make the surface transparent or to deviate from the theme. Default: the active theme’s bg token, so the window matches the rest of the shell out of the box.

Source

fn input_region(&self) -> Option<Vec<Rect>>

Return the interactive input region as a list of rects (logical pixels). Only these areas receive pointer/touch input; the rest passes through. Return None (default) to receive input everywhere.

Source

fn window_config(&self) -> Option<(&str, &str)>

Return Some(( title, app_id )) to force an XDG toplevel window instead of layer-shell overlay. The compositor will display the title in the title bar and use the app_id for taskbar/icon matching. Return None (default) to use layer-shell when available.

Deprecated: Use shell_mode instead.

Source

fn shell_mode(&self) -> ShellMode

Specify the Wayland shell mode for this application.

For regular applications, use the default Window mode. For shell components (panels, backgrounds, overlays), use Layer. For a screen locker, use SessionLock and request the unlock by returning true from requested_exit.

Source

fn requested_exit(&self) -> bool

Return true to tear the surface down and exit the event loop. For a ShellMode::SessionLock surface the runtime calls unlock first, so the compositor lifts the lock instead of leaving the outputs blanked. Polled after every batch of updates.

Source

fn window_size_hint(&self) -> Option<(u32, u32)>

Suggest an initial size for an xdg-shell window in logical pixels.

Returning Some(( w, h )) makes ltk call both xdg_toplevel.set_min_size( w, h ) and xdg_toplevel.set_max_size( w, h ) before the first commit, which most compositors honour as an exact size for the configure they send back. The window is still resizable from the application’s point of view — if the compositor sends a different configure, the runtime adopts that size on the next frame.

Only applies to ShellMode::Window surfaces and to the xdg-shell fallback path used when wlr-layer-shell is missing. Ignored for layer-shell surfaces, which use Self::layer_size instead.

Default: None (let the compositor pick).

Source

fn start_fullscreen(&self) -> bool

Request fullscreen on the toplevel before its first commit.

When true, ltk calls xdg_toplevel.set_fullscreen( None ) so the compositor picks an output and maps the surface fullscreen from the start (no flicker through a windowed configure first). The compositor’s own decorations are suppressed for fullscreen surfaces; the built-in titlebar from Self::window_config is still painted by ltk on top of the surface unless the app opts out.

Only applies to ShellMode::Window surfaces and to the xdg-shell fallback path used when wlr-layer-shell is missing.

Default: false.

Source

fn exclusive_zone(&self) -> i32

Specify the exclusive zone for layer-shell surfaces.

The exclusive zone reserves screen space for this surface. For example, a top panel with height 50 should return 50 to prevent other windows from overlapping it.

  • > 0: Reserve this many pixels from the anchored edge
  • 0: No exclusive zone (default for overlays)
  • -1: Don’t reserve space but request focus

Only applies to ShellMode::Layer surfaces. Ignored for windows.

Source

fn layer_anchor(&self) -> Anchor

Specify which screen edges the layer-shell surface is anchored to.

Anchoring determines the position and size of the surface:

Default: Anchor::ALL (full screen)

Only applies to ShellMode::Layer surfaces. Ignored for windows.

Source

fn layer_size(&self) -> (u32, u32)

Specify the desired size for layer-shell surfaces.

Returns (width, height) where:

  • 0 means “fill available space in that dimension”
  • > 0 means “use this exact size in pixels”

Examples:

  • Top bar: (0, 50) - full width, 50px height
  • Bottom bar: (0, 40) - full width, 40px height
  • Side panel: (300, 0) - 300px width, full height
  • Full screen: (0, 0) - fill everything (default)

Default: (0, 0) (fill all available space)

Only applies to ShellMode::Layer surfaces. Ignored for windows.

Source

fn keyboard_exclusive(&self) -> bool

Request exclusive keyboard focus for this layer-shell surface.

When true, the compositor sends keyboard events to this surface without requiring a pointer click first. Useful for greeters, lock screens, and other surfaces that must capture input immediately.

Default: false (on-demand keyboard interactivity)

Only applies to ShellMode::Layer surfaces. Ignored for windows.

Implementors§