summaryrefslogtreecommitdiffhomepage
path: root/packages/ext-window-field/src/config.hpp
blob: a0182ed5f4816a1ac1ed824f782a903bdb6bd7aa (plain)
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
#pragma once

#include <string>
#include <string_view>
#include <vector>

// Pure decision core: the window-field config loader. Parses an unbox.toml
// document (as TEXT — file discovery/reading is an effect kept in the glue) into
// a ResizePolicy: how the field feeds a window's RCSS-computed tile size back to
// the client as a render resolution (ext-xdg-shell::Toplevel::set_size). toml++
// is the only dependency; no wlroots, no kernel. Doctest-covered in
// tests/test_config.cpp.
//
// SCHEMA (the [window-field] table; every key optional — absent => default):
//   [window-field]
//   resize_mode        = "settle"   # off | settle | continuous | debounced
//   resize_debounce_ms = 100        # used only when resize_mode = "debounced"
//
// resize_mode semantics (the tile size animates over an RCSS transition on every
// focus/map/unmap, so the question is WHEN to push the size to the client — each
// push makes the client reallocate + redraw):
//   off        — never resize: the client keeps its own size, letterbox-fit into
//                the tile by the RCSS `contain` decorator (the pre-feature look).
//   settle     — wait for the tile box to stop changing (the transition done),
//                then send ONE configure to the final size (~1 client redraw per
//                focus change; honours the precious GPU frame budget).
//   continuous — send a configure every frame the box changes (exact real-time
//                tracking, ~1 redraw per animation frame; heavy on this GPU).
//   debounced  — coalesce: configure at most once per resize_debounce_ms during
//                the animation, plus a final one on settle.

namespace unbox::ext_window_field::config {

// How the field pushes a tile's RCSS-computed size to its client.
enum class ResizeMode { off, settle, continuous, debounced };

// The parsed window-field policy. Defaults are the compiled-in fallback used
// when no config / no [window-field] table / a bad value is present.
struct ResizePolicy {
    ResizeMode mode = ResizeMode::settle; // default: one configure on settle
    int debounce_ms = 100;                // debounced only; clamped to >= 0
};

// The outcome of loading. `policy` is always populated (defaults where a key is
// absent or invalid). `warnings` holds one message per bad value or a single
// parse-error message. `parse_error` is true iff the document failed to parse
// (toml syntax error) — then `policy` is the pure default. NEVER throws (the
// toml parse error is caught here). An empty document / absent [window-field] is
// NOT an error — it yields defaults with parse_error=false and no warnings.
struct LoadResult {
    ResizePolicy policy;
    std::vector<std::string> warnings;
    bool parse_error = false;
};

// Parse `toml_text` and extract the [window-field] policy per the schema above.
// Each key is validated independently: an unknown resize_mode string, a
// non-string resize_mode, a negative/non-integer resize_debounce_ms falls back
// to that field's default with a warning and never aborts the rest.
[[nodiscard]] auto load_from_string(std::string_view toml_text) -> LoadResult;

} // namespace unbox::ext_window_field::config