fix(session/console): a profile must not advertise a cursor channel the presenter isn't drawing
Found reviewing the P0 wiring. The console builds its window and input models ONCE, from
the global defaults, and they live across every launch — but each launch now re-resolves
the host's profile. So a profile that sets `mouse_mode: desktop` on a host, while the
global stays `capture`, made the session advertise `CLIENT_CAP_CURSOR` ("this client
draws the host cursor itself") to a presenter latched in capture mode, which draws no
cursor: the host stops compositing the pointer and the stream has no visible cursor at
all — the exact failure the capability's own doc comment warns about.
The advertisement now follows the LATCHED mouse model, which is the one that is actually
true of the presenter. Everything the host is told about the stream itself — mode,
bitrate, codec, audio, pad — keeps honoring the binding, and the comment says which
fields are latched and why, so the console's presentation-tier gap is documented rather
than rediscovered.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -137,6 +137,13 @@ pub fn run(target: Option<&str>) -> u8 {
|
|||||||
// `{"ready":true}` and restores on exit) — plain CLI/gamescope runs stay silent.
|
// `{"ready":true}` and restores on exit) — plain CLI/gamescope runs stay silent.
|
||||||
let json_status = arg_flag("--json-status");
|
let json_status = arg_flag("--json-status");
|
||||||
let settings_at_start = trust::Settings::load();
|
let settings_at_start = trust::Settings::load();
|
||||||
|
// The console's window and its input models are built ONCE, from the global defaults, and
|
||||||
|
// live across every launch — so the presentation-tier fields below (stats tier, touch and
|
||||||
|
// mouse model, match-window, render scale) are latched here and a per-host profile cannot
|
||||||
|
// move them in this mode. Everything the HOST is told (mode, bitrate, codec, audio, pad) is
|
||||||
|
// re-resolved per launch and does honor the binding. Closing that gap means rebuilding the
|
||||||
|
// presenter's models per launch — profiles P4 territory, not P0.
|
||||||
|
let latched_mouse = settings_at_start.mouse_mode();
|
||||||
|
|
||||||
// Request-access hand-off: the launch handler stamps this when it starts a delegated-approval
|
// Request-access hand-off: the launch handler stamps this when it starts a delegated-approval
|
||||||
// connect; `on_connected` reads it once the host lets us in and persists the host as PAIRED,
|
// connect; `on_connected` reads it once the host lets us in and persists the host as PAIRED,
|
||||||
@@ -221,6 +228,13 @@ pub fn run(target: Option<&str>) -> u8 {
|
|||||||
force_software,
|
force_software,
|
||||||
vulkan,
|
vulkan,
|
||||||
);
|
);
|
||||||
|
// …with ONE field that must follow the latched model rather than this
|
||||||
|
// launch's: the cursor-channel advertisement says "this client draws the
|
||||||
|
// host cursor itself", which is only true while the presenter is in desktop
|
||||||
|
// mouse mode. A profile that flips `mouse_mode` here would make the host
|
||||||
|
// stop compositing the pointer into a presenter that isn't drawing one —
|
||||||
|
// a stream with no visible cursor at all.
|
||||||
|
params.cursor_forward = latched_mouse == trust::MouseMode::Desktop;
|
||||||
if request_access {
|
if request_access {
|
||||||
// The host PARKS the connect until the operator approves — outlast its
|
// The host PARKS the connect until the operator approves — outlast its
|
||||||
// approval window (host `PENDING_APPROVAL_WAIT`), matching the desktop
|
// approval window (host `PENDING_APPROVAL_WAIT`), matching the desktop
|
||||||
|
|||||||
Reference in New Issue
Block a user