Settings: allow `$options` to be populated at runtime
Summary
$options combobox values are declared in the mod source and fixed at install
time. That means a mod can't offer a picker over anything it discovers on the
machine. I'd like a way for a mod to supply options at runtime — for example an
optional export the settings UI calls, Wh_GetSettingOptions(name).
Filing this as the ambitious one of a small batch. It is clearly larger than the others and I'd understand it being declined or deferred; the ones alongside it stand on their own.
Why
$options is the right control whenever a value must be one of a known set.
But "known" currently means "known when the mod was written", which excludes
everything interesting about the machine the mod is running on:
- installed applications a mod can target
- files in a folder the mod reads
- connected monitors, audio devices, profiles
- window classes or processes discovered at runtime
For those, authors fall back to a free-text field the user must type exactly, which trades a discoverable, unmistakable control for one that silently does nothing when misspelled. The mod usually can't even validate it well, because by the time it reads the setting it isn't in a position to tell the user.
Evidence
I'm building toward a small patch registry: CSS patches live as files, and the user picks which to apply per application. The natural control is a checkbox list or a multi-select of the patches present on disk — which is precisely what can't be expressed, since the patch set changes whenever a file is added.
The workarounds available today, and why each falls short:
- Free-text patch ids. Typo-prone, and the mod can only report a mismatch to a log the user isn't reading.
- Bake
$optionsinto the source. Adding a patch then means editing and reinstalling the mod, which defeats the point of a file-driven registry. - A directory convention — apply everything in a folder, disable by
renaming with a leading
_.
I shipped (3). It works and needs no engine change, but the enable/disable affordance is now "rename a file in Explorer" rather than a checkbox in the settings UI, which is a real step down for anyone who isn't the author.
Note that alpha.2's relaxation of settings-array indices (undeclared rows are now writable — thank you, that was the other half of this problem) makes the storage side flexible. It is now only the presentation side that is fixed at install time.
Suggested shape
An optional export the settings UI calls when rendering, mirroring how mods already expose lifecycle functions:
// Called by the settings UI. Return NULL / do nothing to keep static $options.
BOOL Wh_GetSettingOptions(PCWSTR settingName, WH_SETTING_OPTIONS* out);Open questions I don't have a good answer to, and which may well make this not worth it:
- Where does it run? The settings UI is not inside a target process. Calling into a mod outside its injection context is the hard part of this request, and possibly the disqualifying one.
- What if it's slow or hangs? Needs a timeout and a fallback to static options.
- Refresh semantics. Once when the settings page opens is probably enough.
A cheaper alternative that captures much of the value: let a mod write a
candidate list to a known location, and let $options reference it —
$optionsFrom: "%LOCALAPPDATA%\\my-mod\\options.json". No cross-process call,
no lifetime questions, and the mod controls the contents. If the full version is
too invasive, this variant would still turn (1) and (3) above into a real
picker.
Tested on 2.0.0-alpha.2.
Source: ramensoftware/windhawk