Crate ltk

Source
Expand description

§ltk — Liberux ToolKit

A lightweight Wayland UI toolkit built on top of smithay-client-toolkit, tiny-skia and fontdue.

ltk is the UI toolkit for the Liberux desktop. The Liberux compositor (Forge) handles window management, decorations, and positioning — ltk focuses on rendering the content of each Wayland surface.

ltk is also a public library for third-party developers building native Wayland applications. If you are approaching the crate through cargo doc, the API is grouped conceptually into three navigation modules:

  • window — the basic application window path most apps should start with
  • shell — layer-shell and overlay APIs for shell-like surfaces
  • runtime — advanced runtime hooks, invalidation, channels, and runtime-free embedding via core::UiSurface

§Quick start

use ltk::{App, Element, column, text, button, spacer, Color, ButtonVariant};

#[derive(Clone)]
enum Msg { Quit }

struct MyApp;

impl App for MyApp
{
    type Message = Msg;

    fn view( &self ) -> Element<Msg>
    {
        column()
            .push( text( "Hello, ltk!" ).size( 32.0 ).color( Color::WHITE ) )
            .push( spacer() )
            .push( button( "Quit" ).on_press( Msg::Quit ) )
            .into()
    }

    fn update( &mut self, msg: Msg )
    {
        match msg { Msg::Quit => std::process::exit( 0 ) }
    }
}

fn main() { ltk::run( MyApp ); }

§Architecture

  • App trait — implement this to define your application.
  • Element enum — the widget tree returned by App::view.
  • Widgets, layouts and primitive types are listed below in their own sidebar sections; the widgets, layouts and types modules are concept-oriented landing pages that cargo doc exposes for the same set, grouped by category.

§Widgets

The interactive and decorative leaves of the Element tree:

See widgets for the grouped landing page and docs/widgets.md for the per-widget catalogue.

§Layouts

Composable arrangers for Element trees:

  • column() — vertical flow.
  • row() — horizontal flow.
  • stack() — z-order overlay with per-child alignment.
  • grid() — fixed-column-count wrapping grid.
  • spacer() — invisible flexible filler.

See layouts for the grouped landing page.

§Types

Geometry and primitive values that flow through every builder:

See types for the full module with //! description.

§Designing for multiple resolutions

ltk supports three approaches to making a layout adapt to the screen, ordered from most to least common:

  1. Relative Length values for font sizes, padding, spacing and spacer height/width. Default to Length::vmin( pct ).clamp( lo, hi ): the percentage tracks the surface’s smaller side (so portrait and landscape behave coherently), and the px clamps protect both ends of the spectrum from breaking the design.
  2. Responsive typographic scale via theme::typography::h0theme::typography::body_xs — pre-calibrated Length values coherent with the default Sora-based theme. Calibrated so a 1000-px smaller side reproduces the legacy px constants exactly.
  3. view()-level branching on surface_width / surface_height when the layout structure itself must change (e.g. sidebar → bottom-tabs below a breakpoint). Keep this for genuine restructuring, not for sizing — Length covers sizing.

§Runtime-free embedding

Use core::UiSurface when you need ltk’s layout, drawing and hit-testing without run() — typically for compositor-side decorations, embedding ltk widgets in another render loop, or offscreen rendering / previews.

§Licence and third-party assets

ltk itself is distributed under LGPL-2.1-only. The default theme bundles two third-party asset sets that travel under their own licences and must be credited when the toolkit (or a binary that embeds the default theme) is redistributed:

  • Symbolic icons under themes/default/icons/catalogue/ — Streamline’s Core Line Free set, CC BY 4.0, © Streamline. Some files modified for the symbolic-tinting pipeline; details in themes/default/icons/catalogue/LICENSE.md. Upstream: https://www.streamlinehq.com/icons/core-line-free.
  • Sora Regular (src/theme/fallback/Sora-Regular.otf) — the embedded font fallback, SIL OFL 1.1, © The Sora Project Authors, Jonathan Barnbrook, Julián Moncada.
  • Pointer cursors under themes/default/cursors/ — GNOME’s Adwaita cursor theme (the cursors GNOME Shell ships), bundled verbatim, © the GNOME Project. Offered upstream under CC BY-SA 3.0 or LGPL 3, and CC BY-SA 4.0 for the newer assets; any one option satisfies the licence. See themes/default/cursors/README.md (what the set is and how it is used) and themes/default/cursors/LICENSE.md (attribution). Upstream: https://gitlab.gnome.org/GNOME/adwaita-icon-theme.

The remaining artwork in the default theme (wallpapers, lockscreens, launcher logo, brand-mark variants, per-application icons) is original to Liberux Labs and travels under the toolkit’s own LGPL-2.1-only licence. The full Debian-style declaration lives in debian/copyright of the source tree.

Re-exports§

Modules§

  • Scaffolding shared by full-screen ambient surfaces (greeter, lock screen, kiosk): theme bring-up, branding/wallpaper loading and the wallpaper-backed view stack. Thin convenience over theme and WallpaperBundle — every app that paints a wallpaper behind centred content repeats this otherwise.
  • Runtime-free UI surface primitives.
  • EGL bootstrap for the GPU rendering path.
  • GPU-accelerated rendering backend using EGL + GLES2 / GLES3.
  • Layouts — composable arrangers for Element trees.
  • Advanced runtime and embedding API.
  • Shell and layer-surface API.
  • Text input field — single-line or multiline. The widget itself owns layout / draw; the runtime side of text editing (insert, delete, cursor movement, selection, clipboard) lives in the event_loop::text_editing private module.
  • Theming for ltk-based applications.
  • Geometry and primitive value types used across the public API.
  • Orientation-aware wallpaper helper.
  • Widget that hosts content rendered by an external GL producer.
  • Widgets — the interactive and decorative leaves of the Element tree.
  • Basic application-window API.

Structs§

  • Layer-shell anchor edges. Determines which screen edges the surface is attached to.
  • The sender end of a channel
  • A two-state opt-in control with a square box and a check glyph.
  • RGBA colour selector with sliders, hex input, preview swatch and a continuous hue strip.
  • A vertical layout container.
  • A combo / select / dropdown widget.
  • Application-owned state for a Combo.
  • A calendar date in the proleptic Gregorian calendar. No time component, no timezone. month is 1–12, day is 1–31 (further constrained by days_in_month).
  • Locale settings for the date picker. Month names and day-of-week labels are pulled from the i18n registry via [rust_i18n::t!] so changing the active locale (e.g. set_locale("es")) flips the calendar without recreating the widget. The remaining piece is the first day of the week, which varies independently of language (US starts on Sunday, ES / FR / DE on Monday) — that one stays as a builder field.
  • Calendar date selector.
  • A centered confirmation dialog with optional title, subtitle, body and action buttons.
  • A widget that defers its pixels to an external GL texture producer.
  • Wraps an Element so that a Row treats it like a Spacer for leftover-width distribution, but draws the child inside the allocated rect.
  • The keyboard symbol, often corresponding to a character.
  • A row inside a list with a primary label and optional subtitle / trailing text.
  • Paginated tab container.
  • One page of a Notebook — a label for the tab strip and the element to show when this page is active.
  • Stable identifier for an overlay surface. The runtime uses it to diff the overlay list between frames: if the same OverlayId is returned from App::overlays on consecutive frames the underlying Wayland surface and its internal state are kept; if it disappears the surface is destroyed.
  • Description of an additional layer-shell surface rendered on top of the main application surface.
  • Wraps any Element and emits a message on tap. Use when you want click-to-emit on something richer than a Button — for example a Container styled as a card holding a row of icon + labels.
  • A linear progress indicator for determinate operations.
  • One option inside a mutually-exclusive group.
  • A horizontal layout container.
  • A horizontal divider line.
  • A horizontal slider for selecting a value in a range.
  • A flexible, invisible spacer that expands to fill available space.
  • An indeterminate progress spinner.
  • A layout that draws all its children stacked on top of each other. Each child can be positioned within the Stack rect via HAlign/VAlign.
  • Stable identifier for a subsurface, used to diff the list returned by App::subsurfaces between frames the same way OverlayId diffs overlays.
  • An input-transparent child surface composited over the main surface and moved by the compositor.
  • Segmented horizontal tab selector. One row of pressable cells with the active cell painted as a filled pill and inactive cells as plain text. Build it from a slice of labels; produce an Element with Self::build (or by .into()-ing it where an Element is expected).
  • A wall-clock time, no date / no timezone. hour is 0–23 (24-hour representation regardless of TimePicker::twelve_hour display mode), minute and second are 0–59.
  • Time-of-day selector with up / down steppers per unit.
  • Builder for a transient bottom-anchored notification overlay.
  • A two-state on / off switch.
  • Builder for an xdg-popup-backed hint anchored to a widget.
  • A vertical slider — a rounded pill that fills from bottom to top to indicate its value.
  • A non-scrollable clipped viewport for revealing only part of a child tree.
  • Button styled for compositor / window decorations.
  • A grid layout that wraps children into rows of a fixed column count.

Enums§

  • Visual style of a text button.
  • Backends an External widget can pull pixels from.
  • Horizontal alignment of a child within a Stack rect.
  • Which surfaces a given App::update mutation can affect.
  • Layer-shell layer position.
  • Reasons crate::try_run (and therefore crate::run) can fail to bring up the event loop.
  • Which axes a Scroll viewport allows to move along. Determines whether the layout grows the child past the viewport width, the viewport height, or both, and which axis gesture / wheel deltas route to.
  • Wayland shell mode for the application surface.
  • Which axis a slider tracks. Used by input dispatch to pick the right value_from_*_in_rect formula for a Slider (horizontal) or crate::widget::vslider::VSlider (vertical).
  • Which surface a SubsurfaceSpec is composited as a child of. Main (the default position) parents to the app’s main surface; Overlay(id) parents to one of the App::overlays surfaces, so a slide can ride above app windows the way an overlay panel does. An Overlay parent that is absent or not yet configured is skipped for that frame.
  • One of the surfaces an App can target with an invalidation. Used inside InvalidationScope::Only to name the affected surfaces.
  • Wayland ext-foreign-toplevel-list-v1 event delivered to apps via App::on_toplevel_event. Opened fires after the compositor commits the first done for a new handle (so app_id is the value in effect at that point — the protocol allows the compositor to re-commit later, but most don’t). Closed fires when the compositor sends closed and the runtime is about to destroy the handle proxy. Both carry the same id, the Wayland protocol id of the handle, unique within the session and stable for the handle’s lifetime.
  • Vertical alignment of a child within a Stack rect.
  • Semantic role for a window-decoration button.

Traits§

  • Trait that application types must implement to integrate with ltk.

Functions§

  • Add delta months to (year, month) with wraparound. Negative deltas walk backwards; year crosses are handled.
  • Create a Checkbox in the given state.
  • Create a ColorPicker starting from the given colour.
  • Format a Color as #RRGGBB (or #RRGGBBAA when with_alpha is true and the colour is not fully opaque). Bytes are clamped to 0..=255.
  • Create an empty column layout.
  • Create a Combo over items driven by state.
  • Create a DatePicker with the given selected date.
  • Day of the week for (year, month, day). 0 = Sunday, 1 = Monday, …, 6 = Saturday. Uses Zeller’s congruence; undefined for years before AD 1.
  • Number of days in month of year (1-indexed month). Returns 0 for invalid month numbers.
  • Construct a Dialog. See the type’s documentation for the full builder API and the lowering details.
  • Create a grid layout with the given number of columns.
  • true when year is a leap year in the proleptic Gregorian calendar.
  • true when the active surfaces on this thread render through the software path. Used by view code that wants to avoid pipeline effects the software backend doesn’t implement.
  • Create a ListItem with the given primary label.
  • Create an empty Notebook.
  • Parse a hex colour string ("#RGB" / "#RGBA" / "#RRGGBB" / "#RRGGBBAA", with or without the leading #, case-insensitive) into a Color. Returns None for malformed input.
  • Create a ProgressBar at the given fraction (clamped to [0.0, 1.0]).
  • Create a Radio option in the given state.
  • Create an empty row layout.
  • Run the application. Blocks until the window is closed.
  • Create a scrollable viewport wrapping child. Defaults to vertical scrolling; chain Scroll::horizontal or Scroll::both to switch axes.
  • Create a default Separator (theme divider colour, 1 px thickness).
  • Create a Slider with the given value (clamped to [0.0, 1.0]).
  • Create a flexible spacer with weight 1.
  • Create a Spinner with default size and theme colour.
  • Create an empty Stack.
  • Create a TabBar from any iterable of label-likes.
  • Create a TimePicker with the given current time.
  • Create a Toast with the given message.
  • Create a Toggle in the given state.
  • Create a Tooltip anchored to the widget tagged with anchor_id.
  • Run the application, returning a typed error on init failure.
  • Create a clipped viewport wrapping child.
  • Create a VSlider at the given value (clamped to [0.0, 1.0]).
  • Build an External widget that hosts content rendered by a caller-managed GL texture producer.
  • Create a window-decoration button.
  • Create the standard minimize / maximize-or-restore / close control group.