// SPDX-License-Identifier: LGPL-2.1-only // Copyright (C) 2026 Liberux Labs, S. L. // Inside `unsafe fn` bodies, every unsafe op must still be wrapped in // its own `unsafe { ... }` block. Without this lint the compiler treats // the whole body as one implicit `unsafe` scope and a SAFETY: comment // per call site becomes impossible to enforce — the kind of drift that // hides UB in renderer code where every glow::* call is `unsafe fn`. #![ deny( unsafe_op_in_unsafe_fn ) ] // Without a backend there is no runtime to use the helpers it shares with the core. #![ cfg_attr( not( backend ), allow( dead_code, unused_imports ) ) ] // Wayland drives the whole runtime, so its build is where dead code shows; a backend that drives part of it would warn about the rest. #![ cfg_attr( all( backend, not( feature = "wayland" ) ), allow( dead_code ) ) ] // Drawing and damage passes take the geometry and state of a surface as plain arguments, and caches are keyed by tuples; splitting either up for the lint would only add types. The quick start keeps its `fn main` to show how an app starts. #![ allow( clippy::too_many_arguments, clippy::type_complexity, clippy::needless_doctest_main ) ] //! # ltk — Liberux ToolKit //! //! A lightweight Wayland UI toolkit built on top of //! [smithay-client-toolkit](https://crates.io/crates/smithay-client-toolkit), //! [tiny-skia](https://crates.io/crates/tiny-skia) and //! [rustybuzz](https://crates.io/crates/rustybuzz). //! //! 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 //! //! ```rust,no_run //! 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 app_id( &self ) -> &str { "net.example.Hello" } //! //! // Nothing worth restoring in a one-button app. //! fn save_state( &self ) -> Option> { None } //! fn restore_state( &mut self, _state: Vec ) {} //! //! fn view( &self ) -> Element //! { //! 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. //! //! ## Rendering backends //! //! All drawing goes through a single [`Canvas`], which is one of two interchangeable backends exposing the same API. The GLES backend (`GlesCanvas`) is the default when an EGL/OpenGL ES context is available and renders on the GPU; the software backend (`SoftwareCanvas`) rasterises on the CPU with tiny-skia and is the fallback when there is no GL context (and what offscreen/preview rendering uses). The two are kept at visual parity for the common primitives, with a few backend-specific traits documented per method (e.g. multi-rect [`Canvas::set_clip_rects`] is an exact mask on software but a bounding-box scissor on GLES, and [`Canvas::is_software`] lets a caller branch on a real path clip vs a bounding rect). [`run()`] selects the backend automatically; [`core::UiSurface`] lets an embedder force one. //! //! ## 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()`], [`pattern_grid()`]. //! - **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; [`grid_min_cell()`] //! derives the column count from the width instead. //! - [`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`]), relative to the surface viewport //! ([`LengthBase::Vw`] / [`LengthBase::Vh`] / [`LengthBase::Vmin`] / //! [`LengthBase::Vmax`] / [`LengthBase::Orient`]), to the root font //! size ([`LengthBase::Em`]) or to the pixel density //! ([`LengthBase::Dp`]). Every setter that takes a size, padding, //! spacing or font height now accepts `impl Into`, 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 **Responsive design** below. //! //! See [`types`] for the full module with `//!` description. //! //! ## Responsive design: one UI from phone to desktop //! //! A core goal of ltk is that a **single view** reads coherently across //! a portrait phone, a tablet and a landscape desktop window — no //! per-target forks, no media-query soup. The mechanism is **fluid //! sizing**: express sizes as a fraction of the surface so the whole //! design breathes with the screen, instead of freezing at one pixel //! size that only looks right on one device. //! //! ### The core rule — fluid, but clamped //! //! Default to `Length::vmin( pct ).clamp( lo, hi )` for every font size, //! padding, spacing and spacer: //! //! - the percentage tracks the surface's **smaller** side, so portrait //! and landscape stay coherent — an element keeps the same fraction of //! the narrow axis whichever way the device is held; //! - the px `clamp` bounds the fluid range so the design never collapses //! on a watch-sized surface nor balloons on a 4K monitor. //! //! The clamp is not optional polish: it is what turns *pure* proportional //! sizing (fragile at the extremes) into *bounded* proportional sizing //! (robust everywhere). Treat "always clamp a fluid value" as the rule, //! not the exception. //! //! ### Orientation-dependent proportion — [`Length::orient`] //! //! Sometimes the right *proportion* differs by orientation, not merely //! the reference axis. A logo may want 40 % of the width in portrait — //! there is vertical room to spare — but only 5 % of the height in //! landscape, where vertical room is scarce. //! [`Length::orient`]`( portrait, landscape )` expresses exactly that: //! `portrait` % of the **width** when the surface is portrait, //! `landscape` % of the **height** when it is landscape (the short side //! of each orientation, but with its own proportion). //! //! When the *structure* of the layout should change with the //! orientation — a row of panels in landscape, the same panels stacked //! in portrait — branch the view on [`orientation()`] (backed by //! [`viewport_size()`], recorded by the runtime on every configure and //! sharing `orient`'s square-counts-as-portrait rule). See //! `examples/clip_path.rs`. //! //! For images, pair it with //! [`Image::short_side`](widget::image::Image::short_side), which sizes //! the image along the screen's short side and lets the other axis follow //! the source aspect ratio: //! //! ```rust,no_run //! # use std::sync::Arc; //! # use ltk::{ img_widget, Length, Element }; //! # #[ derive( Clone ) ] enum Msg {} //! # fn _ex( rgba: Arc>, w: u32, h: u32 ) -> Element { //! // 40 % of the width in portrait, 5 % of the height in landscape. //! img_widget( rgba, w, h ).short_side( Length::orient( 40.0, 5.0 ) ).into() //! # } //! ``` //! //! ### When constant *physical* size matters instead //! //! Fluid units scale with the screen's pixels, not with real-world //! millimetres — and legibility is a function of physical (angular) size, //! not of what fraction of the screen a glyph fills. When a size must stay //! a **constant physical size** across very different displays, use the //! other mode: [`Length::dp`] (a density-independent pixel — `n ×` the //! pixel density, applied when the value is resolved — the mainstream //! HiDPI unit), or [`LengthBase::Em`] for text //! relative to the root font size. The pre-calibrated //! [`theme::typography`] scale //! ([`theme::typography::h0`]…[`theme::typography::body_xs`]) is built on //! clamped `vmin`, so it stays fluid while respecting a readable px floor //! and ceiling — a good default for running text. //! //! ### The two modes, and choosing per app //! //! ltk offers both strategies as first-class citizens and lets the app //! pick — per value, or process-wide for every stock widget: //! //! - **Fluid** — [`Length::fluid`] and the raw `vmin` / `vmax` / `vw` / //! `vh` / `orient` units. Surface-proportional; tracks the short side //! (width in portrait, height in landscape). Best for full-screen system //! surfaces on known hardware (lock screen, greeter, splash, kiosk, //! launcher). //! - **Physical** — [`Length::dp`] plus [`set_density`] / [`density`]. //! Constant real-world size, HiDPI-aware. Best for conventional windowed //! apps across an open-ended device set. //! //! Stock widgets carry one design pixel per dimension and resolve it //! through the process-wide [`WidgetScaling`] mode //! ([`set_widget_scaling`]): [`WidgetScaling::Fluid`] (the default) reads //! it as [`Length::fluid`], [`WidgetScaling::Physical`] as [`Length::dp`]. //! An explicit [`Length`] on a widget always overrides the mode. //! //! ### Structural changes — branch in `view()` //! //! When the layout *structure* must change (sidebar → bottom tabs, two //! columns → one) rather than merely resize, branch in `view()` on //! `surface_width` / `surface_height`. Keep this for genuine //! restructuring; [`Length`] covers all pure 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](https://creativecommons.org/licenses/by/4.0/), //! © Streamline. Some files modified for the symbolic-tinting //! pipeline; details in `themes/default/icons/catalogue/LICENSE.md`. //! Upstream: . //! - **Sora Regular** (`src/theme/fallback/Sora-Regular.otf`) — the //! embedded font fallback, [SIL OFL 1.1](https://scripts.sil.org/OFL), //! © 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](https://creativecommons.org/licenses/by-sa/3.0/) *or* //! [LGPL 3](https://www.gnu.org/licenses/lgpl-3.0.html), and //! [CC BY-SA 4.0](https://creativecommons.org/licenses/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: . //! //! 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. // Load YAML locale files from `ltk/locales/*.yaml`. The `t!()` macro is // re-exported (see below) so consuming applications can also use it; their // own `i18n!()` invocations merge into the same runtime registry. The // fallback locale is English — built-in widget strings always have an // English entry. rust_i18n::i18n!( "locales", fallback = "en" ); /// Serialises tests across modules that read or mutate the process-wide /// density / [`WidgetScaling`] globals, so parallel test threads never /// observe each other's transient state. #[ cfg( test ) ] pub( crate ) static TEST_GLOBALS_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new( () ); pub mod types; pub mod font_face; pub mod osk; pub( crate ) mod render; pub( crate ) mod system_fonts; pub( crate ) mod text_shaping; pub( crate ) mod a11y; pub( crate ) mod widget; pub( crate ) mod layout; pub( crate ) mod app; pub( crate ) mod channel; pub mod theme; pub mod wallpaper; pub mod chassis; pub mod nav_stack; pub( crate ) mod tree; pub( crate ) mod draw; #[ cfg( backend ) ] pub( crate ) mod input; #[ cfg( backend ) ] pub( crate ) mod event_loop; #[ cfg( backend ) ] pub( crate ) mod platform; #[ cfg( feature = "wayland" ) ] pub( crate ) mod protocol; #[ cfg( feature = "wayland" ) ] pub( crate ) mod session_state; pub( crate ) mod secure_mem; pub( crate ) mod resources; pub mod time; pub mod vfs; pub mod gles_render; #[ cfg( not( target_arch = "wasm32" ) ) ] pub mod egl_context; pub mod core; pub use app:: { Anchor, App, BackAtRoot, BackResponse, ChannelSender, ShellMode, Layer, OverlayId, OverlaySpec, SubsurfaceId, SubsurfaceSpec, SubsurfaceParent, InvalidationScope, MouseButton, MouseButtonEvent, RawKey, SelectionKind, SurfaceTarget, ToplevelEvent, }; pub use theme:: { Palette, ThemeMode, ThemePreference, ThemeError, ThemeDocument, Mode, SlotStore, WallpaperSpec, WallpaperFit, LauncherSpec, WindowControlsSpec, active_document, active_mode, active_theme_id, is_fallback_active, set_active_document, set_active_mode, tint_symbolic, }; pub use theme::{ color as theme_color, color_or as theme_color_or }; pub use theme::{ paint as theme_paint, shadows as theme_shadows }; pub use theme::{ surface as theme_surface, 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::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, icon_path as theme_icon_path, icon_rgba as theme_icon_rgba }; pub use gles_render::{ BorrowedGlesTexture, GlesVersion }; pub use render::is_software_render; pub use render::Canvas; pub use font_face::{ ColorGlyph, FontFace, LineMetrics, Metrics, OutlineBounds }; pub use osk::Purpose as InputPurpose; pub use wallpaper::{ WallpaperBundle, ImageData }; pub use nav_stack::NavStack; pub use chassis::{ set_default_theme, theme_logo_rgba, theme_icon_tinted, branding_bundle_or_solid, wallpaper_bundle_or_solid, backdrop }; pub use types::{ Color, CompositeMode, Corners, CursorShape, Length, LengthBase, PathCmd, Point, Rect, Size, WidgetId }; pub use types::{ WidgetScaling, FLUID_MIN, FLUID_MAX }; pub use types::{ fluid_reference, set_fluid_reference }; pub use types::{ density, set_density }; pub use types::{ set_text_scale, text_scale }; pub use types::{ widget_scaling, set_widget_scaling }; pub use types::{ Orientation, orientation, viewport_size, set_viewport_size }; pub use types::{ output_logical_size, set_output_logical_size }; pub use widget::{ Element, button, icon_button, text_edit, image as img_widget, text, container }; pub use text_shaping::{ caret_offsets, caret_offsets_with_font, line_metrics, measure_text }; pub use widget::rich_text::{ rich_text, RichText, LinkSpan }; pub use widget::button::ButtonVariant; pub use widget::slider::{ Slider, slider, SliderAxis }; pub use widget::vslider::{ VSlider, vslider }; pub use widget::pattern_grid::{ PatternGrid, pattern_grid }; pub use widget::text::{ TextAlign, WRAP_PAD as TEXT_WRAP_PAD }; pub use widget::toggle::{ Toggle, toggle }; pub use widget::separator::{ Separator, separator }; pub use widget::progress_bar::{ ProgressBar, progress_bar }; pub use widget::checkbox::{ Checkbox, checkbox }; pub use widget::radio::{ Radio, radio }; pub use widget::list_item::{ ListItem, list_item }; pub use widget::window_button::{ WindowButton, WindowButtonKind, window_button, window_controls }; pub use widget::pressable::{ Pressable, pressable }; pub use widget::flex::{ Flex, flex }; pub use widget::combo::{ Combo, ComboState, combo }; pub use widget::spinner::{ Spinner, spinner }; pub use widget::tab_bar::{ TabBar, tabs }; pub use widget::anchored_overlay::{ anchored, AnchoredOverlay }; pub use widget::tab_strip::{ TabItem, TabLayout, TabMotion, TabOverview, TabStrip, TabStripColors, tab, tab_overview, tab_strip }; pub use widget::toast::{ Toast, toast }; pub use widget::tooltip::{ Tooltip, tooltip }; pub use widget::notebook::{ Notebook, NotebookPage, notebook }; pub use widget::external::{ External, ExternalSource }; pub use widget::external as widget_external; pub use widget::date_picker:: { Date, DatePicker, Locale as DateLocale, date_picker, is_leap_year, days_in_month, day_of_week, add_months, }; pub use widget::time_picker::{ Time, TimePicker, time_picker }; pub use widget::color_picker:: { ColorPicker, color_picker, color_to_hex, parse_hex, }; pub use widget::dialog::{ Dialog, dialog }; pub use layout::spacer::{ Spacer, spacer }; pub use layout::column::{ Column, column }; pub use layout::row::{ Row, row }; pub use layout::stack::{ Stack, stack, HAlign, VAlign }; // push_aligned_margin is available as a method on Stack — no separate re-export needed. pub use layout::wrap_grid::{ WrapGrid, grid, grid_min_cell }; pub use widget::scroll::{ scroll, ScrollAxis }; pub use widget::viewport::{ Viewport, viewport }; pub use widget::carousel::{ Carousel, carousel }; #[ cfg( backend ) ] pub use app::{ run, try_run, RunError }; #[ cfg( feature = "android" ) ] pub use platform::android::{ keep_running, set_android_app, AndroidApp }; /// What only the browser backend offers. #[ cfg( feature = "web" ) ] pub mod web { pub use crate::platform::web::{ load_resources, load_tree, set_canvas, set_shell_listener, shell_send }; } pub use resources::{ resource_dir, set_resource_dir }; pub use xkeysym::Keysym; /// Widgets — the interactive and decorative leaves of the [`Element`] /// tree. /// /// Concept-oriented sidebar entry: every widget the toolkit ships is also /// available at the crate root (`ltk::button`, `ltk::toggle`, …); this /// module groups them so `cargo doc` shows a single landing page when you /// are looking for "what controls can I draw". /// /// See [`docs/widgets.md`](https://github.com/liberux/ltk/blob/master/docs/widgets.md) /// for the per-widget catalogue with usage notes and minimal examples. pub mod widgets { pub use crate:: { // Buttons / activations button, icon_button, Pressable, pressable, WindowButton, WindowButtonKind, window_button, window_controls, ListItem, list_item, // Stateful binary controls Toggle, toggle, Checkbox, checkbox, Radio, radio, // Continuous controls Slider, slider, SliderAxis, VSlider, vslider, PatternGrid, pattern_grid, ProgressBar, progress_bar, // Composite picker Combo, ComboState, combo, // Activity / hint indicators Spinner, spinner, // Segmented selector + paginated tabs TabBar, tabs, Notebook, NotebookPage, notebook, // Date / time / color pickers Date, DatePicker, DateLocale, date_picker, Time, TimePicker, time_picker, ColorPicker, color_picker, color_to_hex, parse_hex, // Transient overlays (return OverlaySpec) Toast, toast, Tooltip, tooltip, // Modal / non-modal centered overlays Dialog, dialog, // Text input and display text, text_edit, TextAlign, // Decoration and chrome container, Separator, separator, img_widget, // Clipping wrappers scroll, Viewport, viewport, Flex, flex, // Button styling token ButtonVariant, }; } /// Layouts — composable arrangers for [`Element`] trees. /// /// Concept-oriented sidebar entry. Each layout has a free constructor /// (`column()`, `row()`, …) and a builder-style API for spacing, padding /// and alignment. Layouts and [widgets] share the same `Element` /// tree. pub mod layouts { pub use crate:: { Column, column, Row, row, Stack, stack, HAlign, VAlign, WrapGrid, grid, grid_min_cell, Spacer, spacer, }; } /// Basic application-window API. /// /// Start here if you are building a normal Wayland client window. /// /// This module is documentation-first: it re-exports the common entry points /// that most applications need so `cargo doc` presents a smaller and more /// approachable surface before the user gets into overlays, gestures, and /// shell-specific features. /// /// The default path is: /// /// 1. implement [`App`] /// 2. return an [`Element`] tree from [`App::view`] /// 3. mutate state in [`App::update`] /// 4. start the event loop with [`run`] /// /// If you are looking for layer-shell, overlays, or advanced runtime hooks, /// move on to [`crate::shell`] or [`crate::runtime`]. pub mod window { pub use crate:: { App, ButtonVariant, Color, Element, Keysym, Point, Rect, Size, BackAtRoot, BackResponse, NavStack, Column, Row, Stack, WrapGrid, Spacer, button, icon_button, text, text_edit, img_widget, container, checkbox, radio, toggle, separator, progress_bar, list_item, slider, vslider, scroll, viewport, column, row, stack, grid, grid_min_cell, spacer, TextAlign, SliderAxis, }; #[ cfg( backend ) ] pub use crate::run; } /// Shell and layer-surface API. /// /// Use this module when you are building shell-like surfaces rather than a /// plain application window: /// /// - panels /// - docks /// - homescreens /// - greeters /// - lock screens /// - transient overlays /// /// These items are also available at the crate root; this module exists so /// `cargo doc` exposes a concept-oriented entry point for layer-shell users. pub mod shell { pub use crate:: { Anchor, App, Layer, OverlayId, OverlaySpec, ShellMode, SurfaceTarget, InvalidationScope, WindowButton, WindowButtonKind, window_button, window_controls, }; } /// Advanced runtime and embedding API. /// /// This module groups the hooks that are useful once the basic app-window flow /// is no longer enough: /// /// - external wakeups via [`ChannelSender`] /// - redraw narrowing via [`InvalidationScope`] /// - surface-level invalidation targets via [`SurfaceTarget`] /// - runtime-free embedding with [`crate::core::UiSurface`] /// - direct theme/runtime state access /// /// Most applications do not need to start here. pub mod runtime { pub use crate:: { ChannelSender, InvalidationScope, SurfaceTarget, Palette, ThemeDocument, ThemeError, ThemeMode, ThemePreference, WallpaperBundle, ImageData, active_document, active_mode, active_theme_id, is_fallback_active, set_active_document, set_active_mode, theme_color, theme_color_or, theme_paint, theme_palette, theme_resolve_surface, theme_shadows, theme_surface, theme_text_style, theme_wallpaper, theme_lockscreen, theme_window_controls, theme_branding_asset, theme_branding_raster, theme_branding_image, tint_symbolic, }; pub use crate::core::{ RenderOptions, RenderOutput, UiSurface }; } /// Internal helpers re-exported for the integration tests under `tests/` and /// the criterion benches under `benches/`. The items themselves are `pub` but /// live inside `pub(crate)` modules, so the only path that reaches them from /// outside the crate is `ltk::test_support::*` — which is exactly what test /// crates (and benches, which are also external) need. /// /// **Not part of the stable public API.** Anything in here may change between /// patch releases without notice. Hidden from generated docs via /// `#[doc(hidden)]`, and gated behind the `test-support` feature so it is /// absent from third-party builds entirely (ltk's own `make test` enables it). #[ cfg( feature = "test-support" ) ] #[ doc( hidden ) ] pub mod test_support { pub use crate::tree::{ find_widget_at, find_widget, find_handlers, next_focusable_index }; pub use crate::widget::{ LaidOutWidget, WidgetHandlers }; pub use crate::widget::slider::{ value_from_x_in_rect, value_from_pos_in_rect, thumb_design_px, SliderAxis }; pub use crate::widget::vslider::value_from_y_in_rect; #[ cfg( backend ) ] pub use crate::event_loop::diff_overlay_ids; }