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 withshell— layer-shell and overlay APIs for shell-like surfacesruntime— advanced runtime hooks, invalidation, channels, and runtime-free embedding viacore::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
Apptrait — implement this to define your application.Elementenum — the widget tree returned byApp::view.- Widgets, layouts and primitive types are listed below in their own
sidebar sections; the
widgets,layoutsandtypesmodules are concept-oriented landing pages thatcargo docexposes for the same set, grouped by category.
§Widgets
The interactive and decorative leaves of the Element tree:
- Buttons / activations —
button(),icon_button,pressable,window_button,list_item(). - Stateful binary controls —
toggle(),checkbox(),radio(). - Continuous controls —
slider(),vslider(),progress_bar(). - Text —
text(),text_edit(). - Decoration —
container(),separator(),img_widget(). - Clipping wrappers —
scroll(),viewport(),flex(). - Modal overlays —
dialog()(centered confirmation card with optional title, subtitle, custom body and action row; built-in scrim, ESC-to-cancel, and tap-outside-to-dismiss for the non-modal variant).
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:
Color,Rect,Point,Size,Corners,WidgetId.Length— a size/distance that may be absolute pixels (LengthBase::Px) or relative to the surface viewport (LengthBase::Vw/LengthBase::Vh/LengthBase::Vmin/LengthBase::Vmax) or to the root font size (LengthBase::Em). Every setter that takes a size, padding, spacing or font height now acceptsimpl Into<Length>, so legacy.size( 24.0 )keeps working while new code can write.size( Length::vmin( 4.0 ) .clamp( 16.0, 32.0 ) )for a typeface that scales with the screen.
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:
- Relative
Lengthvalues for font sizes, padding, spacing and spacer height/width. Default toLength::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. - Responsive typographic scale via
theme::typography::h0…theme::typography::body_xs— pre-calibratedLengthvalues coherent with the default Sora-based theme. Calibrated so a 1000-px smaller side reproduces the legacy px constants exactly. view()-level branching onsurface_width/surface_heightwhen the layout structure itself must change (e.g. sidebar → bottom-tabs below a breakpoint). Keep this for genuine restructuring, not for sizing —Lengthcovers 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 inthemes/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. Seethemes/default/cursors/README.md(what the set is and how it is used) andthemes/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§
pub use theme::Palette;pub use theme::ThemeMode;pub use theme::ThemePreference;pub use theme::ThemeError;pub use theme::ThemeDocument;pub use theme::Mode;pub use theme::SlotStore;pub use theme::WallpaperSpec;pub use theme::WallpaperFit;pub use theme::LauncherSpec;pub use theme::WindowControlsSpec;pub use theme::active_document;pub use theme::active_mode;pub use theme::active_theme_id;pub use theme::is_fallback_active;pub use theme::set_active_document;pub use theme::set_active_mode;pub use theme::tint_symbolic;pub use theme::color as theme_color;pub use theme::color_or as theme_color_or;pub use theme::paint as theme_paint;pub use theme::paint as theme_paint;pub use theme::shadows as theme_shadows;pub use theme::surface as theme_surface;pub use theme::surface as theme_surface;pub use theme::text_style as theme_text_style;pub use theme::text_style as theme_text_style;pub use theme::resolve_surface as theme_resolve_surface;pub use theme::palette as theme_palette;pub use theme::palette as theme_palette;pub use theme::window_controls as theme_window_controls;pub use theme::wallpaper as theme_wallpaper;pub use theme::lockscreen as theme_lockscreen;pub use theme::app_icon as theme_app_icon;pub use theme::app_default_icon as theme_app_default_icon;pub use theme::launcher_icon as theme_launcher_icon;pub use theme::logo as theme_logo;pub use theme::logo_square as theme_logo_square;pub use theme::logo_horizontal as theme_logo_horizontal;pub use theme::branding_asset as theme_branding_asset;pub use theme::branding_raster as theme_branding_raster;pub use theme::branding_image as theme_branding_image;pub use theme::decode_svg_bytes;pub use theme::icon_path as theme_icon_path;pub use theme::icon_rgba as theme_icon_rgba;pub use gles_render::BorrowedGlesTexture;pub use gles_render::GlesVersion;pub use wallpaper::WallpaperBundle;pub use wallpaper::ImageData;pub use chassis::set_default_theme;pub use chassis::theme_logo_rgba;pub use chassis::theme_icon_tinted;pub use chassis::branding_bundle_or_solid;pub use chassis::wallpaper_bundle_or_solid;pub use chassis::backdrop;pub use types::Color;pub use types::Corners;pub use types::CursorShape;pub use types::Length;pub use types::LengthBase;pub use types::Point;pub use types::Rect;pub use types::Size;pub use types::WidgetId;pub use types::design_reference;pub use types::set_design_reference;
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
themeandWallpaperBundle— 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
Elementtrees. - 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_editingprivate 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
Elementtree. - 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.
monthis 1–12,dayis 1–31 (further constrained bydays_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.
- 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
OverlayIdis returned fromApp::overlayson 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.
- 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.
- Stable identifier for a subsurface, used to diff the list returned by
App::subsurfacesbetween frames the same wayOverlayIddiffs 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
ElementwithSelf::build(or by.into()-ing it where anElementis expected). - A wall-clock time, no date / no timezone.
houris 0–23 (24-hour representation regardless ofTimePicker::twelve_hourdisplay mode),minuteandsecondare 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
Externalwidget can pull pixels from. - Horizontal alignment of a child within a
Stackrect. - Which surfaces a given
App::updatemutation can affect. - Layer-shell layer position.
- Reasons
crate::try_run(and thereforecrate::run) can fail to bring up the event loop. - Which axes a
Scrollviewport 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_rectformula for aSlider(horizontal) orcrate::widget::vslider::VSlider(vertical). - Which surface a
SubsurfaceSpecis composited as a child of.Main(the default position) parents to the app’s main surface;Overlay(id)parents to one of theApp::overlayssurfaces, so a slide can ride above app windows the way an overlay panel does. AnOverlayparent that is absent or not yet configured is skipped for that frame. - One of the surfaces an
Appcan target with an invalidation. Used insideInvalidationScope::Onlyto name the affected surfaces. - Wayland
ext-foreign-toplevel-list-v1event delivered to apps viaApp::on_toplevel_event.Openedfires after the compositor commits the firstdonefor a new handle (soapp_idis the value in effect at that point — the protocol allows the compositor to re-commit later, but most don’t).Closedfires when the compositor sendsclosedand the runtime is about to destroy the handle proxy. Both carry the sameid, 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
Stackrect. - Semantic role for a window-decoration button.
Traits§
- Trait that application types must implement to integrate with ltk.
Functions§
- Add
deltamonths to(year, month)with wraparound. Negative deltas walk backwards; year crosses are handled. - Create a
Checkboxin the given state. - Create a
ColorPickerstarting from the given colour. - Format a
Coloras#RRGGBB(or#RRGGBBAAwhenwith_alphais true and the colour is not fully opaque). Bytes are clamped to0..=255. - Create an empty column layout.
- Create a
DatePickerwith 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
monthofyear(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.
truewhenyearis a leap year in the proleptic Gregorian calendar.truewhen 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
ListItemwith 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 aColor. ReturnsNonefor malformed input. - Create a
ProgressBarat the given fraction (clamped to[0.0, 1.0]). - Create a
Radiooption 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; chainScroll::horizontalorScroll::bothto switch axes. - Create a default
Separator(theme divider colour, 1 px thickness). - Create a
Sliderwith the given value (clamped to[0.0, 1.0]). - Create a flexible spacer with weight 1.
- Create a
Spinnerwith default size and theme colour. - Create an empty
Stack. - Create a
TabBarfrom any iterable of label-likes. - Create a
TimePickerwith the given current time. - Create a
Toastwith the given message. - Create a
Togglein the given state. - Create a
Tooltipanchored to the widget tagged withanchor_id. - Run the application, returning a typed error on init failure.
- Create a clipped viewport wrapping
child. - Create a
VSliderat the given value (clamped to[0.0, 1.0]). - Build an
Externalwidget 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.