First commit. Version 0.1.0
This commit is contained in:
Executable
+429
@@ -0,0 +1,429 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-only
|
||||
// Copyright (C) 2026 Liberux Labs, S. L. <info@liberux.net>
|
||||
|
||||
// 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 ) ]
|
||||
|
||||
//! # 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
|
||||
//! [fontdue](https://crates.io/crates/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
|
||||
//!
|
||||
//! ```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 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:
|
||||
//!
|
||||
//! - **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`].
|
||||
//!
|
||||
//! See [`types`] for the full module with `//!` description.
|
||||
//!
|
||||
//! ## 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: <https://www.streamlinehq.com/icons/core-line-free>.
|
||||
//! - **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.
|
||||
//!
|
||||
//! 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" );
|
||||
|
||||
pub mod types;
|
||||
pub( crate ) mod render;
|
||||
pub( crate ) mod system_fonts;
|
||||
pub( crate ) mod widget;
|
||||
pub( crate ) mod layout;
|
||||
pub( crate ) mod app;
|
||||
pub mod theme;
|
||||
pub mod wallpaper;
|
||||
|
||||
pub( crate ) mod tree;
|
||||
pub( crate ) mod draw;
|
||||
pub( crate ) mod input;
|
||||
pub( crate ) mod event_loop;
|
||||
pub( crate ) mod secure_mem;
|
||||
pub mod gles_render;
|
||||
pub mod egl_context;
|
||||
pub mod core;
|
||||
|
||||
pub use app::
|
||||
{
|
||||
Anchor, App, ChannelSender, ShellMode, Layer, OverlayId, OverlaySpec,
|
||||
InvalidationScope, SurfaceTarget,
|
||||
};
|
||||
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 wallpaper::{ WallpaperBundle, ImageData };
|
||||
pub use types::{ Color, Corners, CursorShape, Point, Rect, Size, WidgetId };
|
||||
pub use widget::{ Element, button, icon_button, text_edit, image as img_widget, text, container };
|
||||
pub use widget::button::ButtonVariant;
|
||||
pub use widget::slider::{ Slider, slider, SliderAxis };
|
||||
pub use widget::vslider::{ VSlider, vslider };
|
||||
pub use widget::text::TextAlign;
|
||||
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::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 };
|
||||
pub use widget::scroll::scroll;
|
||||
pub use widget::viewport::{ Viewport, viewport };
|
||||
pub use app::run;
|
||||
pub use app::{ try_run, RunError };
|
||||
pub use smithay_client_toolkit::seat::keyboard::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,
|
||||
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<Msg>`
|
||||
/// tree.
|
||||
pub mod layouts
|
||||
{
|
||||
pub use crate::
|
||||
{
|
||||
Column, column,
|
||||
Row, row,
|
||||
Stack, stack, HAlign, VAlign,
|
||||
WrapGrid, grid,
|
||||
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,
|
||||
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, spacer,
|
||||
TextAlign, SliderAxis,
|
||||
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)]` for the same reason.
|
||||
#[ 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, SliderAxis };
|
||||
pub use crate::widget::vslider::value_from_y_in_rect;
|
||||
pub use crate::event_loop::diff_overlay_ids;
|
||||
}
|
||||
Reference in New Issue
Block a user