9.1 KiB
Wayscriber Codebase Overview (Except Configurator)
This document explains how the application boots, how user input travels through the system, and how the major modules fit together. Use it as a map when adding features or debugging. The configurator binary lives in configurator/ and is intentionally excluded here.
1. Execution Flow From main.rs
-
CLI parsing (
src/main.rs)- Uses
clapto parse--daemon,--active,--mode, and session management flags. - Verifies
WAYLAND_DISPLAYwhen a Wayland session is required.
- Uses
-
Mode selection
--daemon: instantiatedaemon::Daemonwith the optional initial board mode and callrun().--active: print usage/help tips, then callbackend::run_wayland.- No flags: print a usage summary and exit.
-
Shared subsystems automatically pulled in
config: loads user settings, key bindings, and drawing defaults.
2. Daemon Mode Lifecycle
Files: src/daemon.rs, src/backend/mod.rs, src/backend/wayland/*
Daemon::runstarts signal handlers (legacy SIGUSR1 toggle, SIGTERM/SIGINT exit).- Spawns a status tray (
ksni) for manual toggle/quit/configurator actions. - Maintains two atomics:
toggle_requested: set by signals or tray to show/hide overlay.should_quit: set by signals or tray quit item.
- On toggle:
- Launches (or terminates) the Wayland backend via
backend::run_wayland. - Keeps track of overlay state so repeated toggles do the right thing.
- Launches (or terminates) the Wayland backend via
- On exit:
- Signals the backend to shut down and joins the tray thread.
Daemon mode therefore provides a persistent background service that reacts to user keybinds (preferably configured to run wayscriber --daemon-toggle, which forwards to the daemon) or to tray actions.
3. Active Mode / Wayland Backend
Modules:
src/backend/mod.rs: exported API (run_wayland)src/backend/wayland/backend.rs: high-level bootstrappersrc/backend/wayland/state.rs: runtime state (surfaces, buffers, runtime handles)src/backend/wayland/handlers/*.rs: smithay trait impls (input, compositor, registry, etc.)
Flow:
backend::run_waylandcreatesWaylandBackend.WaylandBackend::run:- Connects to Wayland (
smithay-client-toolkit). - Binds compositor, layer shell, SHM, outputs, seats, registry.
- Loads configuration (color defaults, board settings, keybindings).
- Initializes
InputState(see section 4). - Creates the layer-shell overlay surface and enters the event loop.
- Connects to Wayland (
- Main loop responsibilities:
- Dispatch Wayland events via smithay handlers (keyboard, pointer, seat, compositor).
- Throttle rendering with frame callbacks / vsync support.
- Communicate with
capture::CaptureManagerfor screenshot actions. - Exit when
InputState.should_exitis set (Escape, tray close, etc.).
WaylandState centralizes everything the handlers need: current buffers, Cairo context, mouse positions, capture state, and tokio handle for async work.
4. Input Handling & Drawing State
Files: src/input/mod.rs, src/input/state/{core,actions,mouse,render}.rs, src/draw/*, src/ui.rs
-
Keyboard events (
handlers/keyboard.rs)- Translate Wayland keysyms to internal
Key. - Call
InputState::on_key_press/on_key_release. - Key presses can enqueue backend output work; the event loop drains
InputState::take_pending_backend_action.
- Translate Wayland keysyms to internal
-
Mouse events (
handlers/pointer.rs)- Update
current_mouse_x/y. - Call
InputState::on_mouse_press,on_mouse_motion,on_mouse_release. - Adjust pen thickness or font size via scroll wheel + modifiers.
- Update
-
InputStateresponsibilities- Holds canvas data (
draw::CanvasSet), current colors, thickness, fonts, modifier flags, andDrawingState(Idle/Drawing/TextInput). actions.rsmaps keybindings toActionenums and performs side effects (color changes, board mode switches, capture requests).mouse.rsconverts drag gestures into shapes (draw::Shapevariants).render.rsexposes provisional shape previews for live feedback.
- Holds canvas data (
-
Rendering to the overlay
WaylandState::renderuses Cairo + SHM buffers.- Draw order: board background → finalized shapes → provisional shape → text cursor preview → status bar (if enabled) → help overlay (if toggled).
uimodule encapsulates status/help overlays, whiledrawhandles actual vector geometry routines.
The result is a predictable pipeline: Wayland → handlers → InputState → CanvasSet/DrawingState → WaylandState::render.
5. Capture Pipeline
New structure (all under src/capture/):
| File/Folder | Purpose |
|---|---|
mod.rs |
Public exports and shared submodules. |
manager.rs |
CaptureManager – owns channel, status, tokio task. |
dependencies.rs |
Trait definitions (CaptureSource, CaptureFileSaver, CaptureClipboard) and default implementations. |
pipeline.rs |
perform_capture, deliver_image, deliver_document, and capture/delivery request definitions. |
sources/ |
Strategies for acquiring image bytes: Hyprland fast-path (hyprland.rs), portal fallback (portal.rs), and URI reader/cleanup (reader.rs). |
clipboard.rs, file.rs, portal.rs |
Support code reused by the pipeline. |
tests.rs |
Unit tests for the manager/pipeline, plus mocks. |
Runtime flow:
InputState::handle_actionsetspending_backend_actionfor screenshot capture and canvas export actions.- The Wayland event loop centrally drains the pending backend action, so keybindings, command-palette Return, and command-palette mouse clicks share the same dispatch path.
- Screenshot actions call
WaylandState::handle_capture_action; explicit canvas PNG export actions callWaylandState::handle_canvas_export_action; board PDF actions callWaylandState::handle_board_pdf_export_action. WaylandState::handle_capture_actionbuilds aCaptureRequest(type + destination + save config) and callsCaptureManager::request_capture.- Canvas export snapshots persisted board content in the current panned viewport, renders PNG bytes, and calls
CaptureManager::request_image_delivery. - Board PDF export snapshots active-board or all-board pages with per-page layout metadata, renders PDF bytes, and calls
CaptureManager::request_document_delivery. CaptureManager’s tokio task receives the request, updates status, and callsperform_capture,deliver_image, ordeliver_document.perform_capture:- Calls the configured
CaptureSource(default:sources::capture_imagewith Hyprland→portal fallback). - Optionally saves via
CaptureFileSaver. - Optionally copies to clipboard via
CaptureClipboard. - Returns
CaptureResultused for desktop notifications.
- Calls the configured
WaylandStatepollsCaptureManager::try_take_result()to restore the overlay and emit notifications once capture completes.
Notifications are sent via notification::send_notification_async, keeping all UI feedback on the event loop thread.
6. Configuration
src/config/handles loadingconfig.toml, validating fields, and building the keybinding map.
7. Utility Modules
src/draw/: Shape definitions, Cairo helpers, arrow geometry, fonts, and theCanvasSetabstraction (with undo/history per board mode).src/ui.rs: Composes the status bar and help overlay using Cairo.src/notification.rs: Tiny helper to send desktop notifications asynchronously (used after captures).src/util.rs: Misc helpers (color parsing, geometry math, etc.).tests/: Integration tests (CLI smoke tests, rendering sanity checks) live outsidesrc/.
8. Directory Map (excluding configurator)
| Path | Role |
|---|---|
src/main.rs |
CLI entry point, mode selection. |
src/daemon.rs |
Background daemon, tray menu, signal handling, overlay toggling. |
src/backend/ |
Wayland backend implementation split into bootstrap (mod.rs), runtime (state.rs), and input/render handlers. |
src/input/ |
Event/state machine for drawing tools, board modes, and capture triggers. |
src/draw/ |
Vector drawing primitives, canvases, fonts. |
src/ui.rs |
Status/help overlays. |
src/capture/ |
Screenshot pipeline (manager, dependencies, sources, clipboard/file helpers). |
src/config/ |
Config parsing, defaults, keybinding map. |
src/notification.rs |
Desktop notifications for capture results. |
src/util.rs |
Shared math/color utilities. |
tests/ |
CLI + rendering integration tests. |
9. Putting It Together
- Launch via CLI → choose daemon vs active.
- Daemon provides lifecycle management, tray integration, and toggles the backend on demand.
- Backend sets up Wayland surfaces and loops, forwarding input to
InputState. - InputState + draw/ui update the overlay contents and request renders.
- Capture subsystem handles screenshot actions asynchronously and notifies the user.
- Config module ensures user preferences are honored everywhere.
Use this document to trace any feature: locate the entry point (CLI, tray, keybinding), follow it through the backend/input/capture stacks, and consult the relevant modules listed above for details.