First commit. Version 0.1.0
This commit is contained in:
375
README.md
375
README.md
@@ -1,3 +1,376 @@
|
||||
# ltk
|
||||
|
||||
Liberux ToolKit
|
||||
`ltk` is a public Rust UI toolkit for Wayland applications.
|
||||
|
||||
It is developed by Liberux as part of the Eydos stack, where it powers
|
||||
shell and application surfaces, but it is published as a reusable library for
|
||||
third-party developers building their own Wayland software.
|
||||
|
||||
Being written in Rust is also part of the project's value proposition:
|
||||
|
||||
- memory safety without a garbage collector
|
||||
- predictable resource lifetimes through ownership and borrowing
|
||||
- good control over allocations and data movement in rendering-heavy code
|
||||
- a strong fit for low-level UI, graphics, and system-integration work
|
||||
|
||||
For a Wayland toolkit, that combination is useful in practice: it reduces an
|
||||
entire class of memory-management bugs common in lower-level UI stacks while
|
||||
still allowing tight control over performance-sensitive paths.
|
||||
|
||||
## What It Is
|
||||
|
||||
`ltk` is a lightweight, declarative toolkit with an Elm-shaped model:
|
||||
|
||||
- implement `App`
|
||||
- return an `Element<Msg>` tree from `view()`
|
||||
- update your state in `update()`
|
||||
- run the event loop with `ltk::run(app)`
|
||||
|
||||
The runtime handles layout, drawing, input dispatch, focus, overlays, and
|
||||
backend selection between GLES and software rendering.
|
||||
|
||||
## What It Is Not
|
||||
|
||||
`ltk` is not:
|
||||
|
||||
- a browser UI toolkit
|
||||
- a cross-platform desktop toolkit
|
||||
- a general-purpose web-style framework
|
||||
|
||||
Today it is specifically a Wayland toolkit. If you are building native Wayland
|
||||
applications, panels, launchers, lock screens, or other shell-adjacent
|
||||
surfaces, it is in scope. If you need Windows, macOS, or browser targets, it
|
||||
is not.
|
||||
|
||||
## Project Status
|
||||
|
||||
`ltk` is a public library intended for third-party use, but it is still shaped
|
||||
by real production needs inside the Liberux / Eydos ecosystem.
|
||||
|
||||
That means:
|
||||
|
||||
- the API is usable for external applications today
|
||||
- the project is optimized first for native Wayland workloads
|
||||
- some advanced APIs are still more shell-oriented than app-oriented
|
||||
- public documentation and examples are present, but the project is not trying
|
||||
to present itself as a cross-platform beginner toolkit
|
||||
|
||||
If you are evaluating `ltk` for a third-party application, the right mental
|
||||
model is "public Wayland toolkit with production consumers" rather than
|
||||
"experimental demo crate".
|
||||
|
||||
## Why Third Parties Might Use It
|
||||
|
||||
`ltk` is designed around a few practical goals:
|
||||
|
||||
- low idle wakeups and event-driven redraws
|
||||
- partial redraws and damage tracking
|
||||
- a simple declarative tree instead of retained widgets
|
||||
- direct support for normal windows and layer-shell surfaces
|
||||
- a runtime-free core (`ltk::core::UiSurface`) for embedding layout and drawing
|
||||
without `ltk::run()`
|
||||
|
||||
This makes it especially relevant for:
|
||||
|
||||
- Wayland applications
|
||||
- mobile-first Linux shells
|
||||
- launchers and dashboards
|
||||
- greeters and lock screens
|
||||
- compositor-side or embedded UI surfaces
|
||||
|
||||
## Quick Start
|
||||
|
||||
Add `ltk` to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
ltk = { path = "../ltk" }
|
||||
```
|
||||
|
||||
Minimal app:
|
||||
|
||||
```rust
|
||||
use ltk::{ App, Element, button, column, spacer, text };
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Msg
|
||||
{
|
||||
Increment,
|
||||
}
|
||||
|
||||
struct CounterApp
|
||||
{
|
||||
value: u32,
|
||||
}
|
||||
|
||||
impl App for CounterApp
|
||||
{
|
||||
type Message = Msg;
|
||||
|
||||
fn view( &self ) -> Element<Msg>
|
||||
{
|
||||
column::<Msg>()
|
||||
.padding( 32.0 )
|
||||
.spacing( 16.0 )
|
||||
.center_y( true )
|
||||
.push( text( "Hello from ltk" ).size( 28.0 ) )
|
||||
.push( text( format!( "Count: {}", self.value ) ).size( 18.0 ) )
|
||||
.push( spacer() )
|
||||
.push( button( "Increment" ).on_press( Msg::Increment ) )
|
||||
.into()
|
||||
}
|
||||
|
||||
fn update( &mut self, msg: Msg )
|
||||
{
|
||||
match msg
|
||||
{
|
||||
Msg::Increment => self.value += 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main()
|
||||
{
|
||||
ltk::run( CounterApp { value: 0 } );
|
||||
}
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
`ltk` currently assumes:
|
||||
|
||||
- **Rust 1.85** or newer (the toolchain shipped with Debian stable; declared
|
||||
as `rust-version` in `Cargo.toml`).
|
||||
- A running **Wayland** session — there is no X11 backend.
|
||||
- System headers for `libwayland`, `libegl` and `libxkbcommon` at compile
|
||||
time. On Debian / Ubuntu:
|
||||
```bash
|
||||
sudo apt-get install libwayland-dev libegl-dev libxkbcommon-dev pkg-config
|
||||
```
|
||||
- A usable system font (`fonts-sora`, `fonts-liberation`, `fonts-dejavu`,
|
||||
…). If none is installed `ltk` falls back to an embedded Sora Regular
|
||||
build with a stderr warning.
|
||||
- A theme named `default`, installed system-wide (the
|
||||
`ltk-theme-default` Debian package drops it under
|
||||
`/usr/share/ltk/themes/default/`) or exposed through
|
||||
`LTK_THEMES_DIR` for development.
|
||||
|
||||
Rendering backend selection is automatic:
|
||||
|
||||
- **GLES** when EGL is available (every modern Wayland compositor).
|
||||
- **Software** fallback otherwise.
|
||||
- Set `LTK_FORCE_SOFTWARE=1` to force the software path even when EGL is
|
||||
available — useful for headless test runs and for diagnosing
|
||||
driver-specific bugs.
|
||||
|
||||
For development inside this repository:
|
||||
|
||||
```bash
|
||||
export LTK_THEMES_DIR="$PWD/themes"
|
||||
cargo run --example showcase
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Useful entry points in this repository:
|
||||
|
||||
- `cargo run --example showcase`
|
||||
- `cargo run --example widgets`
|
||||
- `cargo run --example inputs`
|
||||
- `cargo run --example scroll`
|
||||
- `cargo run --example mini_shell`
|
||||
|
||||
In general:
|
||||
|
||||
- start with `showcase` for a regular app window
|
||||
- use `widgets` to see the core controls
|
||||
- use `mini_shell` if you need overlays, theme switching, or shell-style
|
||||
composition
|
||||
|
||||
## Public API Overview
|
||||
|
||||
Most applications should start with this subset:
|
||||
|
||||
- `App`
|
||||
- `Element<Msg>`
|
||||
- widgets such as `button`, `text`, `text_edit`, `image`
|
||||
- layouts such as `column`, `row`, `stack`, `grid`, `spacer`
|
||||
- `Color`
|
||||
- `run`
|
||||
|
||||
More advanced APIs are available when needed:
|
||||
|
||||
- `overlays()`
|
||||
- `shell_mode()` and layer-shell controls
|
||||
- `set_channel_sender()` and `poll_external()`
|
||||
- gesture hooks such as `on_swipe_*`
|
||||
- `core::UiSurface`
|
||||
- runtime theme APIs
|
||||
|
||||
## Windows and Shell Surfaces
|
||||
|
||||
By default, `ltk` creates a regular `xdg-shell` window.
|
||||
|
||||
That is the right starting point for:
|
||||
|
||||
- normal applications
|
||||
- internal tools
|
||||
- prototypes
|
||||
|
||||
Switch to layer-shell only when you are building shell surfaces such as:
|
||||
|
||||
- top bars
|
||||
- docks
|
||||
- homescreens
|
||||
- notifications
|
||||
- greeters
|
||||
- lock screens
|
||||
|
||||
## Performance Notes
|
||||
|
||||
`ltk` is designed to sleep when idle and redraw only on real work.
|
||||
|
||||
The main rules for downstream applications are:
|
||||
|
||||
- keep `view()` pure and cheap
|
||||
- do not perform I/O inside `view()`
|
||||
- use `poll_interval()` sparingly
|
||||
- return `true` from `is_animating()` only while something is actually moving
|
||||
- cache decoded images and expensive derived state in your app
|
||||
|
||||
The library already provides:
|
||||
|
||||
- event-driven redraw scheduling
|
||||
- per-surface invalidation
|
||||
- partial redraws for interaction-only changes
|
||||
- GPU and software backends behind the same widget API
|
||||
|
||||
## Backend Differences
|
||||
|
||||
The public API is the same across backends, but visual parity is not perfect
|
||||
yet. The widget tree, layout, hit-testing, text, images, fills, strokes,
|
||||
clipping and gradients all paint identically on both paths. The gap is in the
|
||||
shadow / backdrop pipeline.
|
||||
|
||||
Effects that currently render only on the **GLES** backend, and are silent
|
||||
no-ops on the **Software** backend:
|
||||
|
||||
- **Outer drop shadows** (`Canvas::fill_shadow_outer`) — themed surfaces that
|
||||
declare a `Shadow` slot show the soft halo on GLES and a flat fill on
|
||||
software.
|
||||
- **Inner / inset shadows** (`Canvas::fill_shadow_inset`) — `InsetShadow`
|
||||
slots paint nothing on software.
|
||||
- **Inset shadow blend modes** — `PlusLighter`, `Multiply`, `Screen` and
|
||||
`Overlay` are GLES-only; the GLES `Overlay` path snapshots the framebuffer
|
||||
and computes the CSS Overlay formula in-shader, which has no software
|
||||
equivalent today.
|
||||
|
||||
Calls to these APIs are safe on both backends — they simply produce a flatter
|
||||
appearance under software. No widget panics, returns an error, or skips
|
||||
unrelated drawing.
|
||||
|
||||
If your application leans heavily on shadows or inset effects, validate both
|
||||
rendering paths before shipping. Force the software path with:
|
||||
|
||||
```bash
|
||||
LTK_FORCE_SOFTWARE=1 cargo run --example showcase
|
||||
```
|
||||
|
||||
Closing this gap (porting the shadow / inset-shadow pipeline to tiny-skia) is
|
||||
on the post-v0.1 roadmap.
|
||||
|
||||
## Documentation
|
||||
|
||||
| File | When to read it |
|
||||
| --- | --- |
|
||||
| [`docs/onboarding.md`](docs/onboarding.md) | First hour with the library — environment, first app, what to ignore at first. |
|
||||
| [`docs/architecture.md`](docs/architecture.md) | Runtime model, overlays, animation, theming, performance and where the cost of a frame lives. |
|
||||
| [`docs/widgets.md`](docs/widgets.md) | Per-widget catalogue: what each one is, when to use it, minimal example, see-also. |
|
||||
| [`docs/theming.md`](docs/theming.md) | JSON theme schema, slot conventions, runtime APIs. |
|
||||
| [`docs/cookbook.md`](docs/cookbook.md) | Concrete recipes — slide-in panels, password fields, runtime theme toggle, channel-driven state, embedding without `ltk::run`. |
|
||||
| `cargo doc --open` | Per-item rustdoc for the public API. |
|
||||
| [`SECURITY.md`](SECURITY.md) | How to report a vulnerability and what is in / out of scope. |
|
||||
| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Build, test, code style, patch shape. |
|
||||
|
||||
Recommended reading order for a new contributor:
|
||||
|
||||
1. run `examples/showcase.rs`
|
||||
2. read `docs/onboarding.md`
|
||||
3. browse `docs/widgets.md` for the catalogue
|
||||
4. dip into `docs/cookbook.md` when you hit a specific shape
|
||||
5. open `docs/architecture.md` once you need overlays, animations, or
|
||||
runtime theming.
|
||||
|
||||
## Relationship to Liberux and Eydos
|
||||
|
||||
Liberux is the promoter and primary maintainer of `ltk`.
|
||||
|
||||
The project exists because Eydos needs a native Wayland toolkit for its
|
||||
own shell and application stack, but `ltk` is intentionally published as a
|
||||
public library rather than kept as a private internal component. Third-party
|
||||
developers are part of the intended audience.
|
||||
|
||||
That origin matters because it explains the current priorities:
|
||||
|
||||
- strong Wayland focus
|
||||
- support for layer-shell and shell-style overlays
|
||||
- attention to mobile power usage
|
||||
- theming and runtime surfaces that fit an operating system environment
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under `LGPL-2.1-only`.
|
||||
|
||||
That means third parties can use `ltk` in their own applications, including
|
||||
proprietary ones, subject to the obligations of the GNU Lesser General Public
|
||||
License v2.1. If you are planning a commercial or closed-source product, read
|
||||
the license text carefully and make sure your distribution model complies with
|
||||
it.
|
||||
|
||||
See [LICENSE](./LICENSE).
|
||||
|
||||
## Third-party assets
|
||||
|
||||
`ltk`'s default theme bundles two third-party asset sets that travel under
|
||||
their own licences. Anyone redistributing the toolkit (or a binary that
|
||||
embeds the default theme) must propagate the attributions below.
|
||||
|
||||
- **Symbolic icons** under `themes/default/icons/catalogue/` come from
|
||||
Streamline's *Core Line Free* set, distributed under
|
||||
[Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/)
|
||||
(CC BY 4.0). © Streamline. Some files have been modified for the
|
||||
symbolic-tinting pipeline; details in
|
||||
[`themes/default/icons/catalogue/LICENSE.md`](./themes/default/icons/catalogue/LICENSE.md).
|
||||
Upstream: <https://www.streamlinehq.com/icons/core-line-free>.
|
||||
- **Sora Regular** (`src/theme/fallback/Sora-Regular.otf`) is the
|
||||
embedded font fallback, distributed under
|
||||
[SIL Open Font Licence 1.1](https://scripts.sil.org/OFL).
|
||||
© 2019-2020 The Sora Project Authors, Jonathan Barnbrook, Julián Moncada.
|
||||
Upstream: <https://github.com/sora-xor/sora-font>.
|
||||
|
||||
The remaining artwork in the default theme — wallpapers, lockscreens,
|
||||
launcher logo, brand-mark variants and 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 of every asset and its licence lives
|
||||
in [`debian/copyright`](./debian/copyright); that is the file the `.deb`
|
||||
ships under `/usr/share/doc/libltk*/copyright`.
|
||||
|
||||
## Contributing
|
||||
|
||||
Patches and bug reports are welcome. Read
|
||||
[`CONTRIBUTING.md`](CONTRIBUTING.md) for the practical mechanics: build
|
||||
prerequisites, how to run tests, the project's Modified Allman code
|
||||
style, and what shape a pull request should take.
|
||||
|
||||
For security-sensitive issues see [`SECURITY.md`](SECURITY.md) — please
|
||||
do not file those through the public issue tracker.
|
||||
|
||||
If you are evaluating `ltk` for a third-party product and are unsure
|
||||
whether your use case is in scope, open a discussion before writing
|
||||
code. That is especially useful when you are:
|
||||
|
||||
- missing an app-facing example,
|
||||
- blocked by a shell-oriented assumption in the API,
|
||||
- trying to understand whether a given platform target is realistic.
|
||||
|
||||
Reference in New Issue
Block a user