Added README
This commit is contained in:
parent
40cb952c26
commit
3e1c412fea
3 changed files with 757 additions and 0 deletions
95
AGENTS.md
Normal file
95
AGENTS.md
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
## Project intent
|
||||||
|
|
||||||
|
This repository is for building a Rust Wayland tiling compositor, not an X11 window manager.
|
||||||
|
|
||||||
|
The intended progression is:
|
||||||
|
|
||||||
|
1. nested compositor first
|
||||||
|
2. single output first
|
||||||
|
3. single workspace first
|
||||||
|
4. single tiling layout first
|
||||||
|
5. standalone session later
|
||||||
|
|
||||||
|
Use `smithay` as the foundation unless the user explicitly directs otherwise.
|
||||||
|
|
||||||
|
## Working rules
|
||||||
|
|
||||||
|
- Prefer small, staged changes that match the roadmap in `README.md` and `GUIDE.md`.
|
||||||
|
- Do not jump straight to DRM/KMS, multi-monitor, XWayland, animations, or IPC unless the current lower stage is already solid.
|
||||||
|
- Keep compositor integration code near the edges of the codebase.
|
||||||
|
- Keep layout, workspace, and focus logic in plain Rust types that are testable without Smithay-heavy setup.
|
||||||
|
- Prefer one feature-complete path over many half-implemented systems.
|
||||||
|
|
||||||
|
## Early priorities
|
||||||
|
|
||||||
|
When implementing the compositor, the preferred order is:
|
||||||
|
|
||||||
|
1. event loop boots
|
||||||
|
2. Wayland client connects
|
||||||
|
3. XDG toplevel maps
|
||||||
|
4. one surface renders
|
||||||
|
5. keyboard and pointer input work
|
||||||
|
6. one tiling layout works
|
||||||
|
7. workspaces work
|
||||||
|
8. multi-output works
|
||||||
|
9. standalone session works
|
||||||
|
|
||||||
|
## Dependency guidance
|
||||||
|
|
||||||
|
Expected direct crates for the early stages:
|
||||||
|
|
||||||
|
- `smithay`
|
||||||
|
- `calloop`
|
||||||
|
- `tracing`
|
||||||
|
- `tracing-subscriber`
|
||||||
|
- `xkbcommon`
|
||||||
|
- `anyhow`
|
||||||
|
- `thiserror`
|
||||||
|
- `bitflags`
|
||||||
|
|
||||||
|
Possible later crates:
|
||||||
|
|
||||||
|
- `serde`
|
||||||
|
- `toml`
|
||||||
|
- `clap`
|
||||||
|
- `zbus`
|
||||||
|
|
||||||
|
## Code structure guidance
|
||||||
|
|
||||||
|
Prefer a layout like:
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/
|
||||||
|
main.rs
|
||||||
|
app.rs
|
||||||
|
state.rs
|
||||||
|
backend/
|
||||||
|
input/
|
||||||
|
layout/
|
||||||
|
shell/
|
||||||
|
render/
|
||||||
|
workspace/
|
||||||
|
config/
|
||||||
|
```
|
||||||
|
|
||||||
|
Guidelines:
|
||||||
|
|
||||||
|
- `backend/` should isolate nested vs tty/session-specific code.
|
||||||
|
- `layout/` should not depend heavily on Smithay types.
|
||||||
|
- `shell/` should handle XDG/toplevel lifecycle.
|
||||||
|
- `render/` should translate compositor state into frame output.
|
||||||
|
- `workspace/` should own workspace and window placement policy.
|
||||||
|
|
||||||
|
## Documentation guidance
|
||||||
|
|
||||||
|
- If the architecture changes materially, update `README.md`.
|
||||||
|
- If the build progression or crate recommendations change materially, update `GUIDE.md`.
|
||||||
|
- Keep docs practical and staged rather than aspirational.
|
||||||
|
|
||||||
|
## Validation guidance
|
||||||
|
|
||||||
|
- Prefer targeted checks over broad guesses.
|
||||||
|
- If code is added, run the narrowest useful verification command available.
|
||||||
|
- If verification is not possible, state that explicitly.
|
||||||
420
GUIDE.md
Normal file
420
GUIDE.md
Normal file
|
|
@ -0,0 +1,420 @@
|
||||||
|
# Build a Rust Tile Manager, Step by Step
|
||||||
|
|
||||||
|
This is a small, Codecrafters-style roadmap for building a Wayland desktop tile manager in Rust, in the same general family as Hyprland or niri.
|
||||||
|
|
||||||
|
The simplest practical path is:
|
||||||
|
|
||||||
|
1. Build a Wayland compositor, not an X11 window manager.
|
||||||
|
2. Use `smithay` as the foundation.
|
||||||
|
3. Start with one monitor, one keyboard, one pointer, one tiled layout.
|
||||||
|
4. Add polish only after mapping, focus, input, and rendering work.
|
||||||
|
|
||||||
|
## What You Are Actually Building
|
||||||
|
|
||||||
|
At a high level, your app needs to do five jobs:
|
||||||
|
|
||||||
|
1. Start a Wayland server and accept client connections.
|
||||||
|
2. Track outputs, seats, windows, focus, and layout state.
|
||||||
|
3. Process input events from keyboard and pointer devices.
|
||||||
|
4. Render client surfaces to one or more outputs.
|
||||||
|
5. Apply a tiling policy when windows are created, resized, focused, or closed.
|
||||||
|
|
||||||
|
If you want something "like Hyprland or niri", that does not mean cloning their code structure. It means building these capabilities in order:
|
||||||
|
|
||||||
|
1. Working compositor loop.
|
||||||
|
2. Window mapping and focus.
|
||||||
|
3. Basic tiling.
|
||||||
|
4. Multi-monitor support.
|
||||||
|
5. Animations, gestures, rules, and IPC.
|
||||||
|
|
||||||
|
## Direct Crates You Will Likely Add
|
||||||
|
|
||||||
|
These are the direct dependencies worth adding to your own `Cargo.toml`.
|
||||||
|
|
||||||
|
### Core crates
|
||||||
|
|
||||||
|
- `smithay`
|
||||||
|
What it does: the main compositor toolkit. It provides Wayland protocol helpers, backend abstractions, input handling, output handling, rendering helpers, and optional XWayland support.
|
||||||
|
- `calloop`
|
||||||
|
What it does: callback-based event loop. Smithay is designed around it.
|
||||||
|
- `tracing`
|
||||||
|
What it does: structured logging. Smithay uses it internally, so using it yourself keeps diagnostics consistent.
|
||||||
|
- `tracing-subscriber`
|
||||||
|
What it does: prints and filters `tracing` logs.
|
||||||
|
- `anyhow`
|
||||||
|
What it does: fast application-level error handling while the project is still evolving.
|
||||||
|
- `thiserror`
|
||||||
|
What it does: typed errors for your own subsystems once the codebase grows.
|
||||||
|
- `bitflags`
|
||||||
|
What it does: ergonomic flag types for key modifiers, window state, output capabilities, and internal options.
|
||||||
|
- `xkbcommon`
|
||||||
|
What it does: keyboard layout and keymap handling through `libxkbcommon`.
|
||||||
|
|
||||||
|
### Optional but common
|
||||||
|
|
||||||
|
- `serde`
|
||||||
|
What it does: config file parsing and IPC payloads.
|
||||||
|
- `toml`
|
||||||
|
What it does: TOML config parsing.
|
||||||
|
- `clap`
|
||||||
|
What it does: command-line flags like `--config`, `--socket`, `--debug`.
|
||||||
|
- `tracing-appender`
|
||||||
|
What it does: file logging.
|
||||||
|
|
||||||
|
### Optional later-stage crates
|
||||||
|
|
||||||
|
- `smithay` with XWayland-related features
|
||||||
|
What it does: lets X11 apps run through XWayland.
|
||||||
|
- `zbus`
|
||||||
|
What it does: DBus integration for desktop services.
|
||||||
|
- `async-channel` or `crossbeam-channel`
|
||||||
|
What it does: internal message passing if you split rendering, IPC, or config reload paths.
|
||||||
|
|
||||||
|
## Minimum `Cargo.toml` Shape
|
||||||
|
|
||||||
|
Use this as a starting point, then adjust feature flags to match the backend you choose:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1"
|
||||||
|
bitflags = "2"
|
||||||
|
calloop = "0.14"
|
||||||
|
smithay = "0.7"
|
||||||
|
thiserror = "2"
|
||||||
|
tracing = { version = "0.1", features = ["max_level_trace", "release_max_level_info"] }
|
||||||
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
||||||
|
xkbcommon = "0.9"
|
||||||
|
```
|
||||||
|
|
||||||
|
Important: `smithay` feature selection matters more than the exact crate list. You will eventually enable only the backends you are actually using.
|
||||||
|
|
||||||
|
## System Dependencies
|
||||||
|
|
||||||
|
Rust crates are not the whole story. A Wayland compositor also needs Linux graphics/input stack libraries installed on the system.
|
||||||
|
|
||||||
|
Expect to need some combination of:
|
||||||
|
|
||||||
|
- `libwayland`
|
||||||
|
- `libxkbcommon`
|
||||||
|
- `libudev`
|
||||||
|
- `libinput`
|
||||||
|
- `libdrm`
|
||||||
|
- `gbm`
|
||||||
|
- `egl` / `gles2`
|
||||||
|
- `pixman`
|
||||||
|
- `xwayland` if you want X11 app support
|
||||||
|
|
||||||
|
The exact set depends on whether you target:
|
||||||
|
|
||||||
|
- `winit` backend first
|
||||||
|
Easier for learning and debugging.
|
||||||
|
- `udev`/DRM backend
|
||||||
|
Required for a real standalone desktop session.
|
||||||
|
|
||||||
|
## The Learning Order
|
||||||
|
|
||||||
|
Treat each stage as a checkpoint. Do not skip ahead.
|
||||||
|
|
||||||
|
### Stage 0: Pick the first target
|
||||||
|
|
||||||
|
Start with a nested compositor using Smithay's easier development path.
|
||||||
|
|
||||||
|
Goal:
|
||||||
|
|
||||||
|
- Run your compositor inside an existing desktop session.
|
||||||
|
- Open a test client.
|
||||||
|
- See logs and state changes.
|
||||||
|
|
||||||
|
Why:
|
||||||
|
|
||||||
|
- This avoids debugging KMS/DRM, seat management, and GPU initialization on day one.
|
||||||
|
|
||||||
|
### Stage 1: Boot the event loop
|
||||||
|
|
||||||
|
Build the smallest app that:
|
||||||
|
|
||||||
|
1. Initializes `tracing`.
|
||||||
|
2. Creates a `calloop::EventLoop`.
|
||||||
|
3. Creates Wayland display state.
|
||||||
|
4. Registers the core Smithay globals you need.
|
||||||
|
5. Enters the dispatch loop.
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- The process starts cleanly and stays alive.
|
||||||
|
|
||||||
|
### Stage 2: Accept clients and map surfaces
|
||||||
|
|
||||||
|
Add the core Wayland protocol pieces:
|
||||||
|
|
||||||
|
1. Compositor state.
|
||||||
|
2. Shared-memory buffer support.
|
||||||
|
3. XDG shell support.
|
||||||
|
4. Seat support.
|
||||||
|
|
||||||
|
Track:
|
||||||
|
|
||||||
|
- New toplevel windows.
|
||||||
|
- Window title and app id.
|
||||||
|
- Configure/commit lifecycle.
|
||||||
|
- Mapped vs unmapped state.
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- A client can connect and create a toplevel surface.
|
||||||
|
|
||||||
|
### Stage 3: Build your internal model
|
||||||
|
|
||||||
|
Before fancy rendering, define your own data structures.
|
||||||
|
|
||||||
|
You need types roughly like:
|
||||||
|
|
||||||
|
- `CompositorState`
|
||||||
|
- `OutputState`
|
||||||
|
- `SeatState`
|
||||||
|
- `Workspace`
|
||||||
|
- `TileTree` or `ColumnLayout`
|
||||||
|
- `WindowId`
|
||||||
|
- `ManagedWindow`
|
||||||
|
|
||||||
|
Store:
|
||||||
|
|
||||||
|
- Which workspace a window belongs to.
|
||||||
|
- Whether the window is tiled, floating, fullscreen, or urgent.
|
||||||
|
- Focus order.
|
||||||
|
- Geometry requested by your layout engine.
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- You can print a stable snapshot of layout state after every window event.
|
||||||
|
|
||||||
|
### Stage 4: Render one output
|
||||||
|
|
||||||
|
Now connect your scene state to rendering.
|
||||||
|
|
||||||
|
Keep it simple:
|
||||||
|
|
||||||
|
1. Support one output first.
|
||||||
|
2. Draw a background color.
|
||||||
|
3. Render mapped client surfaces.
|
||||||
|
4. Present frames continuously or when damaged.
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- One client window is visible on screen.
|
||||||
|
|
||||||
|
### Stage 5: Keyboard and pointer input
|
||||||
|
|
||||||
|
Wire up:
|
||||||
|
|
||||||
|
1. Pointer motion.
|
||||||
|
2. Pointer button press.
|
||||||
|
3. Keyboard key press.
|
||||||
|
4. Modifiers through `xkbcommon`.
|
||||||
|
|
||||||
|
Implement:
|
||||||
|
|
||||||
|
- Focus follows click, or focus follows keyboard only.
|
||||||
|
- A compositor modifier key.
|
||||||
|
- At least three commands: spawn terminal, close focused window, cycle focus.
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- You can interact with a client and trigger compositor actions.
|
||||||
|
|
||||||
|
### Stage 6: First tiling layout
|
||||||
|
|
||||||
|
Do not start with dynamic animations or fancy trees. Start with one deterministic layout.
|
||||||
|
|
||||||
|
Best beginner layouts:
|
||||||
|
|
||||||
|
1. Master-stack.
|
||||||
|
2. Equal vertical columns.
|
||||||
|
3. Niri-style scrolling columns.
|
||||||
|
|
||||||
|
Recommended first choice:
|
||||||
|
|
||||||
|
- Equal vertical columns or a simple master-stack.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
1. When a new tiled window appears, insert it into the active workspace.
|
||||||
|
2. Recompute all tile rectangles.
|
||||||
|
3. Send configure events with the new size.
|
||||||
|
4. Render using those computed rectangles.
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- Opening a second and third window retile the workspace correctly.
|
||||||
|
|
||||||
|
### Stage 7: Workspaces
|
||||||
|
|
||||||
|
Add:
|
||||||
|
|
||||||
|
1. Multiple workspaces per output.
|
||||||
|
2. Active workspace switching.
|
||||||
|
3. Move focused window to another workspace.
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- You can switch workspaces and preserve layout state independently.
|
||||||
|
|
||||||
|
### Stage 8: Multi-output support
|
||||||
|
|
||||||
|
Track:
|
||||||
|
|
||||||
|
- Connected outputs.
|
||||||
|
- Per-output current workspace.
|
||||||
|
- Output geometry and scale.
|
||||||
|
|
||||||
|
Implement:
|
||||||
|
|
||||||
|
- New windows land on the focused output.
|
||||||
|
- Workspaces are attached either globally or per output.
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- Two monitors work without corrupting focus or layout state.
|
||||||
|
|
||||||
|
### Stage 9: Real standalone session
|
||||||
|
|
||||||
|
After the nested version works, move toward a real desktop session.
|
||||||
|
|
||||||
|
This is where backend complexity increases:
|
||||||
|
|
||||||
|
1. DRM/KMS
|
||||||
|
2. GBM/EGL or another rendering path
|
||||||
|
3. Libinput
|
||||||
|
4. Session/seat handling
|
||||||
|
5. VT switching
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- The compositor can run on a TTY as the main desktop session.
|
||||||
|
|
||||||
|
### Stage 10: Quality-of-life features
|
||||||
|
|
||||||
|
Only now add polish:
|
||||||
|
|
||||||
|
1. Config file.
|
||||||
|
2. IPC socket.
|
||||||
|
3. Window rules.
|
||||||
|
4. Floating windows.
|
||||||
|
5. Fullscreen.
|
||||||
|
6. Pointer constraints.
|
||||||
|
7. Layer-shell panels and wallpapers.
|
||||||
|
8. Screencopy.
|
||||||
|
9. Idle inhibit.
|
||||||
|
10. Animations.
|
||||||
|
|
||||||
|
## A Good Project Structure
|
||||||
|
|
||||||
|
Once the prototype starts working, split it like this:
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/
|
||||||
|
main.rs
|
||||||
|
app.rs
|
||||||
|
state.rs
|
||||||
|
backend/
|
||||||
|
mod.rs
|
||||||
|
nested.rs
|
||||||
|
tty.rs
|
||||||
|
input/
|
||||||
|
mod.rs
|
||||||
|
keyboard.rs
|
||||||
|
pointer.rs
|
||||||
|
bindings.rs
|
||||||
|
layout/
|
||||||
|
mod.rs
|
||||||
|
columns.rs
|
||||||
|
master.rs
|
||||||
|
shell/
|
||||||
|
mod.rs
|
||||||
|
xdg.rs
|
||||||
|
window.rs
|
||||||
|
render/
|
||||||
|
mod.rs
|
||||||
|
scene.rs
|
||||||
|
workspace/
|
||||||
|
mod.rs
|
||||||
|
config/
|
||||||
|
mod.rs
|
||||||
|
```
|
||||||
|
|
||||||
|
The important rule is simple:
|
||||||
|
|
||||||
|
- Smithay-facing code should stay near the edges.
|
||||||
|
- Your layout and workspace logic should be mostly your own plain Rust types.
|
||||||
|
|
||||||
|
## What Each Crate Does in the Architecture
|
||||||
|
|
||||||
|
Think of the crates like this:
|
||||||
|
|
||||||
|
- `smithay`: Wayland compositor plumbing and backend integration.
|
||||||
|
- `calloop`: the main event loop that everything runs inside.
|
||||||
|
- `xkbcommon`: keyboard interpretation and modifiers.
|
||||||
|
- `tracing` + `tracing-subscriber`: logs, spans, filtering, debugging.
|
||||||
|
- `anyhow`: ergonomic top-level errors during rapid iteration.
|
||||||
|
- `thiserror`: precise library-style errors for your own modules.
|
||||||
|
- `bitflags`: compact internal state flags.
|
||||||
|
- `serde` + `toml`: config loading.
|
||||||
|
- `clap`: startup options.
|
||||||
|
- `zbus`: desktop integration later.
|
||||||
|
|
||||||
|
## Suggested Milestone Checklist
|
||||||
|
|
||||||
|
If you want a clean progression, build in this exact order:
|
||||||
|
|
||||||
|
1. Process boots and enters event loop.
|
||||||
|
2. Wayland client connects.
|
||||||
|
3. XDG toplevel appears.
|
||||||
|
4. One window renders.
|
||||||
|
5. Focus works.
|
||||||
|
6. Keyboard shortcuts work.
|
||||||
|
7. Two windows tile correctly.
|
||||||
|
8. Workspaces work.
|
||||||
|
9. Multi-output works.
|
||||||
|
10. Standalone TTY session works.
|
||||||
|
11. XWayland works.
|
||||||
|
12. Config and IPC work.
|
||||||
|
|
||||||
|
## Practical Advice
|
||||||
|
|
||||||
|
- Build a nested compositor first. This is the highest-leverage simplification.
|
||||||
|
- Keep layout logic pure. A layout engine should accept windows and output rectangles and return tile rectangles.
|
||||||
|
- Add exactly one layout first.
|
||||||
|
- Keep a strong debug log for every surface map, unmap, commit, focus change, output change, and configure.
|
||||||
|
- Do not implement animations until you trust your state model.
|
||||||
|
- Do not add XWayland until native Wayland windows are solid.
|
||||||
|
|
||||||
|
## Recommended References
|
||||||
|
|
||||||
|
These are the most relevant primary sources I used:
|
||||||
|
|
||||||
|
- Smithay crate docs: https://docs.rs/smithay/latest/smithay/
|
||||||
|
- Smithay project docs: https://smithay.github.io/smithay/smithay/
|
||||||
|
- Smithay `wayland` module docs: https://docs.rs/smithay/latest/smithay/wayland/
|
||||||
|
- Smithay `xwayland` module docs: https://docs.rs/smithay/latest/smithay/xwayland/
|
||||||
|
- `wayland_server` docs: https://smithay.github.io/wayland-rs/wayland_server/
|
||||||
|
- `calloop` docs: https://docs.rs/calloop/latest/calloop/
|
||||||
|
- `tracing` docs: https://docs.rs/crate/tracing/latest
|
||||||
|
- `anyhow` docs: https://docs.rs/crate/anyhow/latest
|
||||||
|
- `thiserror` docs: https://docs.rs/crate/thiserror/latest
|
||||||
|
- `bitflags` docs: https://docs.rs/bitflags
|
||||||
|
- `xkbcommon` docs: https://docs.rs/xkbcommon/latest/xkbcommon/
|
||||||
|
|
||||||
|
## Final Recommendation
|
||||||
|
|
||||||
|
If your goal is "a simple tile manager similar to Hyprland or niri", the best first version is:
|
||||||
|
|
||||||
|
1. Rust
|
||||||
|
2. Wayland
|
||||||
|
3. `smithay`
|
||||||
|
4. `calloop`
|
||||||
|
5. one output
|
||||||
|
6. one workspace
|
||||||
|
7. one tiling layout
|
||||||
|
8. nested backend first
|
||||||
|
|
||||||
|
That path is realistic. Starting with standalone DRM, multi-monitor, XWayland, animations, and IPC all at once is not.
|
||||||
242
README.md
Normal file
242
README.md
Normal file
|
|
@ -0,0 +1,242 @@
|
||||||
|
# tile-manager
|
||||||
|
|
||||||
|
A Rust Wayland tiling compositor project, built in small stages.
|
||||||
|
|
||||||
|
The target is a simple desktop tile manager in the same general space as Hyprland or niri, but with a much narrower first scope:
|
||||||
|
|
||||||
|
1. nested compositor first
|
||||||
|
2. one output first
|
||||||
|
3. one workspace first
|
||||||
|
4. one tiling layout first
|
||||||
|
|
||||||
|
This project should grow in the same order a Codecrafters-style guide would teach it: build the minimum working compositor, then add input, tiling, workspaces, multi-output, and finally standalone session support and polish.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This is not an X11 window manager.
|
||||||
|
|
||||||
|
It is intended to become a Wayland compositor that can:
|
||||||
|
|
||||||
|
1. accept Wayland clients
|
||||||
|
2. track windows, focus, outputs, and workspaces
|
||||||
|
3. process keyboard and pointer input
|
||||||
|
4. render surfaces
|
||||||
|
5. apply a tiling layout
|
||||||
|
|
||||||
|
## Planned Stack
|
||||||
|
|
||||||
|
Primary Rust crates:
|
||||||
|
|
||||||
|
- `smithay`: Wayland compositor foundation
|
||||||
|
- `calloop`: event loop
|
||||||
|
- `xkbcommon`: keyboard layout and modifiers
|
||||||
|
- `tracing`: structured logging
|
||||||
|
- `tracing-subscriber`: log output/filtering
|
||||||
|
- `anyhow`: application-level error handling
|
||||||
|
- `thiserror`: typed internal errors
|
||||||
|
- `bitflags`: internal state flags
|
||||||
|
|
||||||
|
Likely later additions:
|
||||||
|
|
||||||
|
- `serde` + `toml`: config loading
|
||||||
|
- `clap`: CLI flags
|
||||||
|
- `zbus`: desktop integration
|
||||||
|
- XWayland-related Smithay features: X11 app support
|
||||||
|
|
||||||
|
## Development Order
|
||||||
|
|
||||||
|
### Stage 0: Nested compositor
|
||||||
|
|
||||||
|
Start inside an existing desktop session before touching DRM/KMS.
|
||||||
|
|
||||||
|
Goal:
|
||||||
|
|
||||||
|
- boot the compositor
|
||||||
|
- open a Wayland client
|
||||||
|
- confirm logs and state changes
|
||||||
|
|
||||||
|
### Stage 1: Event loop and Wayland server
|
||||||
|
|
||||||
|
Implement:
|
||||||
|
|
||||||
|
1. logging setup
|
||||||
|
2. `calloop::EventLoop`
|
||||||
|
3. Wayland display state
|
||||||
|
4. core Smithay globals
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- the process starts and stays alive cleanly
|
||||||
|
|
||||||
|
### Stage 2: XDG toplevel support
|
||||||
|
|
||||||
|
Implement:
|
||||||
|
|
||||||
|
1. compositor state
|
||||||
|
2. shared memory support
|
||||||
|
3. XDG shell support
|
||||||
|
4. seat support
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- a client can create a toplevel surface
|
||||||
|
|
||||||
|
### Stage 3: Internal state model
|
||||||
|
|
||||||
|
Add plain Rust types for:
|
||||||
|
|
||||||
|
- compositor state
|
||||||
|
- outputs
|
||||||
|
- seats
|
||||||
|
- workspaces
|
||||||
|
- windows
|
||||||
|
- tile layout state
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- stable state snapshots after every map/unmap/focus/layout event
|
||||||
|
|
||||||
|
### Stage 4: Render one output
|
||||||
|
|
||||||
|
Implement:
|
||||||
|
|
||||||
|
1. one output
|
||||||
|
2. solid background
|
||||||
|
3. mapped surface rendering
|
||||||
|
4. frame presentation
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- one client is visible on screen
|
||||||
|
|
||||||
|
### Stage 5: Input and bindings
|
||||||
|
|
||||||
|
Implement:
|
||||||
|
|
||||||
|
1. keyboard input
|
||||||
|
2. pointer input
|
||||||
|
3. compositor modifier handling
|
||||||
|
4. a few core commands
|
||||||
|
|
||||||
|
Minimum commands:
|
||||||
|
|
||||||
|
- spawn terminal
|
||||||
|
- close focused window
|
||||||
|
- cycle focus
|
||||||
|
|
||||||
|
### Stage 6: Tiling
|
||||||
|
|
||||||
|
Start with one layout only.
|
||||||
|
|
||||||
|
Recommended first layouts:
|
||||||
|
|
||||||
|
1. equal columns
|
||||||
|
2. master-stack
|
||||||
|
|
||||||
|
Deliverable:
|
||||||
|
|
||||||
|
- new windows retile the workspace correctly
|
||||||
|
|
||||||
|
### Stage 7: Workspaces
|
||||||
|
|
||||||
|
Implement:
|
||||||
|
|
||||||
|
1. workspace switching
|
||||||
|
2. moving windows between workspaces
|
||||||
|
3. independent workspace layout state
|
||||||
|
|
||||||
|
### Stage 8: Multi-output
|
||||||
|
|
||||||
|
Implement:
|
||||||
|
|
||||||
|
1. output tracking
|
||||||
|
2. per-output active workspace
|
||||||
|
3. correct focus and new-window placement
|
||||||
|
|
||||||
|
### Stage 9: Standalone session
|
||||||
|
|
||||||
|
Only after the nested compositor is solid, add:
|
||||||
|
|
||||||
|
1. DRM/KMS
|
||||||
|
2. libinput
|
||||||
|
3. session/seat handling
|
||||||
|
4. VT switching
|
||||||
|
|
||||||
|
### Stage 10: Polish
|
||||||
|
|
||||||
|
Later features:
|
||||||
|
|
||||||
|
- config file
|
||||||
|
- IPC
|
||||||
|
- floating windows
|
||||||
|
- fullscreen
|
||||||
|
- layer-shell support
|
||||||
|
- screencopy
|
||||||
|
- animations
|
||||||
|
- XWayland
|
||||||
|
|
||||||
|
## Suggested Layout
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/
|
||||||
|
main.rs
|
||||||
|
app.rs
|
||||||
|
state.rs
|
||||||
|
backend/
|
||||||
|
mod.rs
|
||||||
|
nested.rs
|
||||||
|
tty.rs
|
||||||
|
input/
|
||||||
|
mod.rs
|
||||||
|
keyboard.rs
|
||||||
|
pointer.rs
|
||||||
|
bindings.rs
|
||||||
|
layout/
|
||||||
|
mod.rs
|
||||||
|
columns.rs
|
||||||
|
master.rs
|
||||||
|
shell/
|
||||||
|
mod.rs
|
||||||
|
xdg.rs
|
||||||
|
window.rs
|
||||||
|
render/
|
||||||
|
mod.rs
|
||||||
|
scene.rs
|
||||||
|
workspace/
|
||||||
|
mod.rs
|
||||||
|
config/
|
||||||
|
mod.rs
|
||||||
|
```
|
||||||
|
|
||||||
|
Guiding rule:
|
||||||
|
|
||||||
|
- keep Smithay integration near the edges
|
||||||
|
- keep layout and workspace logic in plain Rust types
|
||||||
|
|
||||||
|
## System Dependencies
|
||||||
|
|
||||||
|
The final compositor will also need Linux graphics/input libraries, depending on backend choice:
|
||||||
|
|
||||||
|
- `libwayland`
|
||||||
|
- `libxkbcommon`
|
||||||
|
- `libudev`
|
||||||
|
- `libinput`
|
||||||
|
- `libdrm`
|
||||||
|
- `gbm`
|
||||||
|
- `egl` / `gles2`
|
||||||
|
- `pixman`
|
||||||
|
- `xwayland` for X11 clients
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- Smithay docs: https://docs.rs/smithay/latest/smithay/
|
||||||
|
- Smithay project docs: https://smithay.github.io/smithay/smithay/
|
||||||
|
- wayland-server docs: https://smithay.github.io/wayland-rs/wayland_server/
|
||||||
|
- calloop docs: https://docs.rs/calloop/latest/calloop/
|
||||||
|
- xkbcommon docs: https://docs.rs/xkbcommon/latest/xkbcommon/
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Right now the repo is still at the very beginning. The current documentation is the roadmap.
|
||||||
|
|
||||||
|
For a fuller step-by-step build guide, see [GUIDE.md](/home/henry/rust-projects/tile-manager/GUIDE.md).
|
||||||
Loading…
Add table
Add a link
Reference in a new issue