Repository navigation
Architecture
One executable, three personalities (GUI, headless guard, CLI), two threads of real work
(UI and guard worker) plus transient update threads, and a UI-free engine core that could
be lifted into another shell tomorrow. This page maps modules, threads, IPC and data flow
as implemented at commit 124e849; line references point into that tree.
- Module map
- Thread model and event marshalling
- Startup sequence
- Reconcile pass data flow
- UI framework
- Persistence and atomicity
- Build system and CI gates
- Known rough edges
- See also
src/
├── main.cpp wWinMain: parse → headless or GUI
├── app/app.cpp bootstrap: mutex, IPC window, init order, wizard, loop
├── core/ engine — no UI includes
│ ├── registry.* thin Reg*W wrappers (get/set dword+string, delete, enum, clear)
│ ├── trayicons.* store: rescan, counts, SetPromoted, PromoteAll, RestoreDefaults,
│ │ exclusions, friendly names, HICON cache
│ ├── guard.* watcher thread, modes, stats, pause/resume, PromoteAllNow
│ ├── legacy.* EnableAutoTray belt, HideSCA cleanup, TrayNotify cache reset
│ ├── explorer.* safe shell restart
│ ├── backup.* schema-8 snapshots, prune, traversal-guarded delete
│ ├── autostart.* HKCU Run install/remove
│ ├── settings.* settings.json schema 8, clamps, atomic save, first-run
│ ├── log.* daily rotating file + 500-entry ring
│ ├── json.* dependency-free parser/writer (ordered objects)
│ ├── cli.* argv parsing, headless verbs, exit codes, IPC client
│ ├── update.* feed fetch, version compare, download, SHA-256, apply
│ ├── installer.* per-user install/uninstall (copy, lnk, uninstall key)
│ ├── os.* RtlGetVersion, theme/accent/language probes, DPI helpers
│ └── win_compat.h missing-constant shims for older mingw headers
├── ui/
│ ├── theme.* palette resolution (mode × accent), subscribers
│ ├── gfx.* GDI+ bootstrap, fonts, rounded rects, app-icon bitmap
│ ├── kit/ widget base + Button/IconButton/Toggle/Segmented/SearchBox/ScrollBar
│ ├── mainwindow.* shell: nav rail, top bar, status bar, input, DWM, anim timer
│ ├── trayicon.* own icon, menu, balloons, TaskbarCreated
│ ├── setupwizard.* first-run modal wizard
│ ├── pages/ dashboard, icons, guard, appearance, backups, activity, about
│ └── lang/ string ids, EN base, 29 sparse packs, resolver
└── util/ str (UTF-8↔UTF-16, wildcards, version compare), fs (paths, atomic IO)
Design rule from the project charter: the engine never includes UI headers; the UI thread owns every HWND and GDI+ object; workers communicate by PostMessage only.
| Thread | Lifetime | Work |
|---|---|---|
| UI (main) | process | message loop, all painting, settings writes, clipboard, dialogs |
| Guard worker | Start→Stop | arm registry watch → wait → debounce → reconcile pass → emit events |
| Update worker | one-shot | feed GET (auto-check or manual check), posts result messages |
| Download/apply worker | one-shot | binary GET + hash + apply, posts success/error |
Worker → UI channels: guard events via registered message TrayIconGuard.GuardEvent.v8
(fallback WM_APP+1) carrying a heap-copied wide string the UI deletes; update results via
WM_APP+60/63/64; “update applied, relaunch” via WM_APP+62; silent auto-check balloon via
WM_APP+61. Locks: SRWLOCK around guard sink+stats, store caches, and the log; settings
are touched from the UI thread only (the guard reads them).
External IPC: message-only window TrayIconGuard.Ipc.v8 accepting WM_COPYDATA with fixed constant
0x54494738 and verbs show|toggle-guard|exit; single-instance mutex
TrayIconGuard.SingleInstance.v8.
flowchart TD
A["wWinMain: SetErrorMode, argv"] --> B["cli::Parse"]
B -->|invalid| Z["IPC show + exit 1 (silent in published builds)"]
B -->|headless| H["cli::ExecuteHeadless"]
B -->|GUI/ui-test| C["mutex: already running? → IPC show, exit 0"]
C --> D["DPI PerMonitorV2, OleInitialize, GDI+ init"]
D --> E["settings::Load → l10n → log::Init → theme::Init"]
E --> F{"install mode unknown?"}
F -->|yes| G["setup wizard → install+relaunch | portable | cancel"]
F -->|no| I["store::Rescan, MainWindow::Create"]
G --> I
I --> J["IPC window, tray icon"]
J --> K{"first run?"}
K -->|yes| L["guardEnabled=true, promote-all once, welcome balloon"]
K -->|no| M["guard::Start if enabled"]
L --> M
M --> N["opt-in auto-check thread; autostart reconcile; message loop"]
RegNotifyChangeKeyValue (subtree, NAME|LAST_SET, async, auto-reset event) → wait (stop
event; timeout = pollMs, INFINITE when 0) → debounce wait → paused? re-arm : RunPass:
store::Rescan → desired state per mode (full / compact own-icon / custom minus
exclusions and user-hidden) → store::SetPromoted diffs → stats, log EVENT, UI event
N|names → optional cooldown-bounded Explorer restart → re-arm. See The Guard Watcher
for the wakeup defect in the published wait set and the shipped patch.
Retained-mode custom widgets: each owns Layout/Paint/OnMouse/OnKey/Tick; pages own widget
vectors and a content-height for the overlay scrollbar. Page-local coordinates are offset
into window space once per layout, so hit-testing and painting share one space. Paint order:
window background → page PaintBackground (cards, labels) → widgets → scrollbar; one
compatible DC double-buffers the whole window per WM_PAINT. Animations use exponential
approach with a 16 ms timer armed only while something moves. Native controls appear in
exactly two places: a borderless EDIT for search input (themed via WM_CTLCOLOREDIT) and
TaskDialogs for confirmations/save dialogs.
Settings and snapshots: write <path>.tmp then MoveFileExW(REPLACE_EXISTING) (snapshots
add WRITE_THROUGH). Logs: append-only daily files, pruned to 14 days at init. Registry:
values only, never tree deletions except the app's own uninstall key. Backup delete
validates names against path separators and ...
CMake ≥ 3.16, C++17, defines UNICODE _UNICODE WIN32_LEAN_AND_MEAN NOMINMAX WINVER=0x0A00 _WIN32_WINNT=0x0A00 NTDDI_VERSION=0x0A000006. GNU path: -Wall -Wextra -Wno-unused-parameter -O2 -ffunction-sections -fdata-sections, link -static -static-libgcc -static-libstdc++ -Wl,--gc-sections -s -municode; MSVC path: /W4 /permissive- /O2 /Gy plus /MANIFEST:NO because resources.rc embeds the manifest.
Libraries: gdiplus, comctl32, comdlg32, dwmapi, uxtheme, shlwapi, version, winhttp, ole32,
oleaut32, shell32, advapi32, gdi32, user32, kernel32, bcrypt. Threads are deliberately
Win32 (CreateThread, SRWLOCK) because mingw's win32 thread model lacks <thread>.
CI (.github/workflows/ci.yml): ubuntu-24.04 cross-build with a zero-warning gate and a
DLL allow-list audit (rejects any import outside the 16 system DLLs), packaging with
SHA256SUMS; windows-2022 MSVC build; release job on v* tags publishing exe, zip and
sums.
Audited and shipped as patches in this wiki's fix bundle: guard wakeup defect; Stop()
handle-lifetime edge; store snapshot race; log retention timezone skew; silent invalid-arg
exit; stale version strings; MIT copyright in the PE resource. Provenance: the v8.4.0
release binary cannot be reproduced from its tag. All detailed in [[Security and
Privacy]], The Guard Watcher and Changelog and Versioning.
- Building from Source — reproduce the binary and the gates
- The Guard Watcher — worker internals
- GUI Pages Guide — the UI framework from the user's side
- Configuration Reference — every knob the modules read
TrayIconGuard · feed 8.6.3 / source tree 8.6.3 (see Changelog and Versioning) · PolyForm Noncommercial 1.0.0 · Repository · Report an issue · Home · Glossary · FAQ · Troubleshooting
Every claim in this wiki is traced to a source line at commit 124e849 or reproduced by
executing the program (build + Wine battery, 2026-10-16); measured discrepancies between
documentation, source and shipped binaries are documented, not smoothed over.
Home Getting Started Features Overview Comparison with Alternatives
Installation and Deployment Configuration Reference Command-Line Interface
How Tray Visibility Works Legacy Script Editions The Guard Watcher
GUI Pages Guide Backups and Snapshots Localization and Themes Self-Updater Guide Security and Privacy Troubleshooting
Architecture Roadmap and Ideas Independent-Audits Testing and QA Building from Source Changelog and Versioning FAQ Glossary
8.6.3 feed / 8.6.3 source · PolyForm Noncommercial 1.0.0