1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
//! A shared layer for window-based backends (software, GL, wgpu).
//!
//! # Architecture
//!
//! [`retroglyph_core::backend::Input`] and [`retroglyph_core::backend::Output`] are two
//! independent facets of [`Backend`](retroglyph_core::backend::Backend), which fits a terminal process
//! (one type implements both) but not a window: there, an event loop owns input and a renderer
//! owns output separately. This crate keeps that split ([`Presenter`] is an `Output` supertrait,
//! [`WindowBackend`] owns its own `Input` event queue) and reassembles both into one `Backend`:
//!
//! ```text
//! ┌─────────────────────────────┐
//! │ event loop (winit or │
//! │ a custom driver) │
//! └──────────────┬───────────────┘
//! translated events
//! │
//! v
//! ┌────────────────────────────────────────────────────┐
//! │ WindowBackend<P: Presenter> │
//! │ (implements Backend: owns the input event queue, │
//! │ delegates output to P) │
//! └───────────────────────┬──────────────────────────────┘
//! │ draw / flush / resize / present
//! v
//! ┌───────────────────────────────┐
//! │ P: Presenter │
//! │ (retroglyph-software today; │
//! │ wgpu/GL renderers planned) │
//! └───────────────────────────────┘
//! ```
//!
//! - [`Presenter`] is `Output` plus the surface lifecycle
//! (`init_surface`/`resize_surface`/`present`/`cell_size`). Renderer crates implement only this
//! trait, which gives them `Output` for free.
//! - <code>[WindowBackend]<P: Presenter></code> implements `Output` (by delegating to `P`),
//! `Input` (via its own event queue), and the no-op default `Cursor` (windowed backends have no
//! text cursor), which together give it `Backend` generically.
//! - The `winit` module (feature-gated, see below) drives the event loop that fills that queue
//! and calls `Presenter::present` each frame.
//!
//! # Features
//!
//! <!-- gen-features:start -->
//! Default features: `winit`.
//!
//! ### `default-font`
//!
//! ⚪ Optional.
//!
//! Embeds the Unscii 16 default font (`font::unscii16`).
//!
//! Off by default so a consumer that supplies its own bitmap font pays nothing for the ~4 KB atlas;
//! the graphical backends' own `default-font` features forward to this one.
//!
//! ### `dev`
//!
//! ⚪ Optional.
//!
//! Forwards `retroglyph-core`'s `dev` feature, which forces development diagnostics on in a build
//! that would otherwise compile them out (see [`retroglyph_core::dev`]).
//!
//! Forwarded so a consumer of this crate can turn them on without adding a direct dependency on
//! core just to reach the flag.
//!
//! ### `legacy-computing`
//!
//! ⚪ Optional.
//!
//! Embeds a generated block-elements/braille fallback font (`font::legacy_computing`): the 10
//! quadrant, 60 sextant, and 256 braille glyphs CP437 (and so `unscii16`) has no mapping for.
//!
//! A separate opt-in from `default-font` rather than folded into it: this repertoire is a much more
//! niche/specialized addition (subcell image rendering, braille density tricks) than the base text
//! font, so a consumer that only wants CP437 text shouldn't pay for it. Computed at compile time by
//! a `const fn`, so this adds no font asset and no new dependency.
//!
//! ### `tilesets`
//!
//! ⚪ Optional.
//!
//! Shared PNG sprite/tileset support (`tileset` + `sprite_cache` modules, issue #366).
//!
//! Both graphical backends' own `tilesets` features forward to this one.
//!
//! ### `winit`
//!
//! 🟢 Enabled by default.
//!
//! The winit event loop and event translation (`run`, `translate`, `run_windowed`/`run_app`).
//!
//! Renderer crates that only implement [`Presenter`] can disable this and depend solely on
//! `raw-window-handle`; loops other than winit (SDL2, tao, custom) bring their own driver against
//! `Presenter` + `WindowBackend`.
//! <!-- gen-features:end -->
//!
//! # Feature flags
//!
//! [`Presenter`], [`WindowBackend`], and [`WindowHandle`] depend only on
//! [`raw-window-handle`](raw_window_handle) and are always available. The `winit` feature
//! (default on) additionally provides the `winit` module: the event loop, event translation, and
//! the `run_windowed`/`run_app` drivers. Disable it to implement or drive `Presenter` with a
//! different windowing library (SDL2, tao, a custom loop) without pulling in winit.
//!
//! # DPI, scale, and the resize contract
//!
//! [`Presenter::cell_size`] returns the cell size in **physical pixels** (the same pixel
//! space as `winit::dpi::PhysicalSize`), not logical/DPI-scaled ("CSS" or "point") pixels.
//! This crate performs no automatic DPI scaling of it: nothing here changes `cell_size()` in
//! response to a display's scale factor. `SoftwareRenderer`'s cell size, for example, is
//! fixed at construction (glyph size × its integer `scale` config) and never changes on a
//! [`Presenter::scale_factor_changed`] notification. A presenter that wants larger cells on a
//! `HiDPI` display has to opt into that itself from `scale_factor_changed` (e.g. regenerating a
//! font atlas at a new pixel density); until one does, the grid renders at a fixed physical
//! pixel size on every display, `HiDPI` or not.
//!
//! Window resize is clamped to whole cells: a physical size that isn't an exact multiple of
//! `cell_size()` has its sub-cell remainder truncated, not centered or cleared, and the OS
//! window is never resized to compensate: see [`Presenter::resize_surface`]'s doc comment
//! for the full contract, including the unpainted trailing strip this can leave on screen.
//!
//! # Threading model
//!
//! The windowed drivers (`winit::run_windowed`, `winit::run_app`, and their `_with_proxy`
//! variants) are single-threaded: the event loop, every [`Presenter`] call, and the app
//! closure/[`App`](retroglyph_core::app::App) callback all run on the one thread that calls
//! `run_windowed`/`run_app`: the main thread, on platforms (e.g. macOS) that require it for
//! windowing. Neither [`Presenter`] nor [`WindowBackend`] carries a `Send`/`Sync` bound
//! anywhere in this crate, and a presenter is free to hold thread-affine state accordingly
//! (an `Rc`, a non-`Send` GPU context handle). The only supported way to reach the loop from
//! another thread is `winit::EventProxy<T>`, which is `Send + Sync + Clone` for any
//! `T: Send + 'static`: it does not give another thread direct access to the `Presenter` or
//! `Terminal`. With the default `T = u64` (`winit::run_windowed_with_proxy`/
//! `run_app_with_proxy`), the payload surfaces as an opaque
//! [`Event::Custom`](retroglyph_core::event::Event::Custom); a custom `T`
//! (`winit::run_windowed_with_typed_proxy`/`run_app_with_typed_proxy`) bypasses `Event` entirely
//! and goes straight to a caller-supplied handler, since `Event::Custom` itself stays fixed to
//! `u64`.
// clippy::too_long_first_doc_paragraph is a known-noisy nursery lint (rust-lang/rust-clippy#13441):
// it mis-attributes its span across this outer doc comment plus `backend`'s own inner module doc,
// which grew past the threshold once its intra-doc links became fully qualified (retroglyph#1035).
/// The generic [`Backend`](retroglyph_core::backend::Backend) for windowed presenters.
/// System clipboard read/write ([`Clipboard`], [`SystemClipboard`] on native targets).
/// Shared cell/surface pixel geometry ([`CellGeometry`](geometry::CellGeometry)).
/// Canonical default colors ([`DEFAULT_FG`](palette::DEFAULT_FG),
/// [`DEFAULT_BG`](palette::DEFAULT_BG)) shared by the graphical backends.
/// The [`Presenter`] trait and [`WindowHandle`](presenter::WindowHandle).
/// The [`PresenterBuilder`] trait shared by the software/GL/wgpu backend builders.
/// Locates winit's `<canvas>` element via the DOM ([`web::winit_canvas`]).
/// The winit event loop, event translation, and app drivers.
// Compile the code blocks in this crate's own README as doctests so its quick start is
// type-checked on every test run and cannot silently rot. The `cfg(doctest)` gate keeps this out
// of the rendered crate documentation: see `retroglyph-crossterm`'s matching include for the
// same pattern applied to the workspace root README.
;
pub use WindowBackend;
pub use SystemClipboard;
pub use ;
pub use CellGeometry;
pub use ;
pub use PresenterBuilder;
// Re-exported so presenters can name the handle traits without adding their
// own raw-window-handle dependency (and so versions can't drift apart).
pub use raw_window_handle;