feat(abi): expose the host-resolved compositor to clients
ci / docs-site (push) Successful in 30s
apple / swift (push) Successful in 1m13s
ci / bench (push) Successful in 1m39s
ci / web (push) Successful in 30s
ci / rust (push) Successful in 2m3s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
deb / build-publish (push) Successful in 2m24s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 4m46s
docker / deploy-docs (push) Successful in 17s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m23s
ci / docs-site (push) Successful in 30s
apple / swift (push) Successful in 1m13s
ci / bench (push) Successful in 1m39s
ci / web (push) Successful in 30s
ci / rust (push) Successful in 2m3s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 5s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
deb / build-publish (push) Successful in 2m24s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 4m46s
docker / deploy-docs (push) Successful in 17s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 4m23s
Add punktfunk_connection_compositor() (mirrors punktfunk_connection_gamepad): a client getter for the compositor the host actually resolved for the session, read from Welcome.compositor and threaded through NativeClient.resolved_compositor. The Apple/Linux clients use it to enable the client-side cursor by default on gamescope sessions, whose PipeWire capture carries no cursor (verified upstream). Header regenerated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1294,6 +1294,35 @@ pub unsafe extern "C" fn punktfunk_connection_gamepad(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The compositor backend the host actually resolved for this session (one of the
|
||||||
|
/// `PUNKTFUNK_COMPOSITOR_*` values; the `Welcome`'s echo of the [`punktfunk_connect_ex`]
|
||||||
|
/// preference). `PUNKTFUNK_COMPOSITOR_AUTO` = an older host that didn't say. Clients use it for
|
||||||
|
/// compositor-specific behavior — e.g. a client-side cursor by default on
|
||||||
|
/// `PUNKTFUNK_COMPOSITOR_GAMESCOPE`, whose PipeWire capture carries no cursor. Safe any time after
|
||||||
|
/// connect.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// `c` is a valid connection handle; `compositor` is writable (NULL is skipped).
|
||||||
|
#[cfg(feature = "quic")]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn punktfunk_connection_compositor(
|
||||||
|
c: *const PunktfunkConnection,
|
||||||
|
compositor: *mut u32,
|
||||||
|
) -> PunktfunkStatus {
|
||||||
|
guard(|| {
|
||||||
|
let c = match unsafe { c.as_ref() } {
|
||||||
|
Some(c) => c,
|
||||||
|
None => return PunktfunkStatus::NullPointer,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
if !compositor.is_null() {
|
||||||
|
*compositor = c.inner.resolved_compositor.to_u8() as u32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PunktfunkStatus::Ok
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// The video encoder bitrate (kilobits per second) the host actually configured for this session
|
/// The video encoder bitrate (kilobits per second) the host actually configured for this session
|
||||||
/// — the [`punktfunk_connect_ex3`] request clamped to the host's range, or its default when `0`
|
/// — the [`punktfunk_connect_ex3`] request clamped to the host's range, or its default when `0`
|
||||||
/// was requested. `0` = an older host that didn't report it. Safe any time after connect.
|
/// was requested. `0` = an older host that didn't report it. Safe any time after connect.
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ enum CtrlRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// What the worker reports to [`NativeClient::connect`] once the handshake lands: the negotiated
|
/// What the worker reports to [`NativeClient::connect`] once the handshake lands: the negotiated
|
||||||
/// mode, the host-resolved gamepad backend, the host's certificate fingerprint, the resolved
|
/// mode, the host-resolved compositor backend, the host-resolved gamepad backend, the host's
|
||||||
/// encoder bitrate (kbps), and the host↔client clock offset (ns, host minus client; 0 = no skew
|
/// certificate fingerprint, the resolved encoder bitrate (kbps), and the host↔client clock offset
|
||||||
/// correction / an old host that didn't answer the handshake).
|
/// (ns, host minus client; 0 = no skew correction / an old host that didn't answer the handshake).
|
||||||
type Negotiated = (Mode, GamepadPref, [u8; 32], u32, i64);
|
type Negotiated = (Mode, CompositorPref, GamepadPref, [u8; 32], u32, i64);
|
||||||
|
|
||||||
/// Accumulated state of an in-flight / finished speed test. The data-plane pump folds each
|
/// Accumulated state of an in-flight / finished speed test. The data-plane pump folds each
|
||||||
/// received [`FLAG_PROBE`] access unit in; the control task records the host's [`ProbeResult`]
|
/// received [`FLAG_PROBE`] access unit in; the control task records the host's [`ProbeResult`]
|
||||||
@@ -135,6 +135,10 @@ pub struct NativeClient {
|
|||||||
/// SHA-256 fingerprint of the certificate the host actually presented. A TOFU caller
|
/// SHA-256 fingerprint of the certificate the host actually presented. A TOFU caller
|
||||||
/// (`pin = None`) persists this and passes it as the pin from then on.
|
/// (`pin = None`) persists this and passes it as the pin from then on.
|
||||||
pub host_fingerprint: [u8; 32],
|
pub host_fingerprint: [u8; 32],
|
||||||
|
/// The compositor backend the host actually resolved for this session ([`Welcome::compositor`]).
|
||||||
|
/// `Auto` = an older host that didn't say. Clients use it for compositor-specific behavior (e.g.
|
||||||
|
/// drawing a client-side cursor by default on gamescope, whose capture carries no cursor).
|
||||||
|
pub resolved_compositor: CompositorPref,
|
||||||
/// The virtual gamepad backend the host actually resolved ([`Welcome::gamepad`]).
|
/// The virtual gamepad backend the host actually resolved ([`Welcome::gamepad`]).
|
||||||
/// `Auto` = an older host that didn't say (assume X-Box 360, no DualSense feedback).
|
/// `Auto` = an older host that didn't say (assume X-Box 360, no DualSense feedback).
|
||||||
pub resolved_gamepad: GamepadPref,
|
pub resolved_gamepad: GamepadPref,
|
||||||
@@ -228,8 +232,14 @@ impl NativeClient {
|
|||||||
})
|
})
|
||||||
.map_err(PunktfunkError::Io)?;
|
.map_err(PunktfunkError::Io)?;
|
||||||
|
|
||||||
let (negotiated, resolved_gamepad, fingerprint, resolved_bitrate_kbps, clock_offset_ns) =
|
let (
|
||||||
match ready_rx.recv_timeout(timeout) {
|
negotiated,
|
||||||
|
resolved_compositor,
|
||||||
|
resolved_gamepad,
|
||||||
|
fingerprint,
|
||||||
|
resolved_bitrate_kbps,
|
||||||
|
clock_offset_ns,
|
||||||
|
) = match ready_rx.recv_timeout(timeout) {
|
||||||
Ok(Ok(t)) => t,
|
Ok(Ok(t)) => t,
|
||||||
Ok(Err(e)) => return Err(e),
|
Ok(Err(e)) => return Err(e),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
@@ -252,6 +262,7 @@ impl NativeClient {
|
|||||||
worker: Some(worker),
|
worker: Some(worker),
|
||||||
mode: mode_slot,
|
mode: mode_slot,
|
||||||
host_fingerprint: fingerprint,
|
host_fingerprint: fingerprint,
|
||||||
|
resolved_compositor,
|
||||||
resolved_gamepad,
|
resolved_gamepad,
|
||||||
resolved_bitrate_kbps,
|
resolved_bitrate_kbps,
|
||||||
clock_offset_ns,
|
clock_offset_ns,
|
||||||
@@ -661,6 +672,7 @@ async fn worker_main(args: WorkerArgs) {
|
|||||||
send,
|
send,
|
||||||
recv,
|
recv,
|
||||||
welcome.mode,
|
welcome.mode,
|
||||||
|
welcome.compositor,
|
||||||
welcome.gamepad,
|
welcome.gamepad,
|
||||||
fingerprint,
|
fingerprint,
|
||||||
welcome.bitrate_kbps,
|
welcome.bitrate_kbps,
|
||||||
@@ -674,6 +686,7 @@ async fn worker_main(args: WorkerArgs) {
|
|||||||
mut ctrl_send,
|
mut ctrl_send,
|
||||||
mut ctrl_recv,
|
mut ctrl_recv,
|
||||||
negotiated,
|
negotiated,
|
||||||
|
resolved_compositor,
|
||||||
resolved_gamepad,
|
resolved_gamepad,
|
||||||
fingerprint,
|
fingerprint,
|
||||||
resolved_bitrate_kbps,
|
resolved_bitrate_kbps,
|
||||||
@@ -687,6 +700,7 @@ async fn worker_main(args: WorkerArgs) {
|
|||||||
};
|
};
|
||||||
let _ = ready_tx.send(Ok((
|
let _ = ready_tx.send(Ok((
|
||||||
negotiated,
|
negotiated,
|
||||||
|
resolved_compositor,
|
||||||
resolved_gamepad,
|
resolved_gamepad,
|
||||||
fingerprint,
|
fingerprint,
|
||||||
resolved_bitrate_kbps,
|
resolved_bitrate_kbps,
|
||||||
|
|||||||
@@ -801,6 +801,19 @@ PunktfunkStatus punktfunk_connection_mode(const PunktfunkConnection *c,
|
|||||||
PunktfunkStatus punktfunk_connection_gamepad(const PunktfunkConnection *c, uint32_t *gamepad);
|
PunktfunkStatus punktfunk_connection_gamepad(const PunktfunkConnection *c, uint32_t *gamepad);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||||
|
// The compositor backend the host actually resolved for this session (one of the
|
||||||
|
// `PUNKTFUNK_COMPOSITOR_*` values; the `Welcome`'s echo of the [`punktfunk_connect_ex`]
|
||||||
|
// preference). `PUNKTFUNK_COMPOSITOR_AUTO` = an older host that didn't say. Clients use it for
|
||||||
|
// compositor-specific behavior — e.g. a client-side cursor by default on
|
||||||
|
// `PUNKTFUNK_COMPOSITOR_GAMESCOPE`, whose PipeWire capture carries no cursor. Safe any time after
|
||||||
|
// connect.
|
||||||
|
//
|
||||||
|
// # Safety
|
||||||
|
// `c` is a valid connection handle; `compositor` is writable (NULL is skipped).
|
||||||
|
PunktfunkStatus punktfunk_connection_compositor(const PunktfunkConnection *c, uint32_t *compositor);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||||
// The video encoder bitrate (kilobits per second) the host actually configured for this session
|
// The video encoder bitrate (kilobits per second) the host actually configured for this session
|
||||||
// — the [`punktfunk_connect_ex3`] request clamped to the host's range, or its default when `0`
|
// — the [`punktfunk_connect_ex3`] request clamped to the host's range, or its default when `0`
|
||||||
|
|||||||
Reference in New Issue
Block a user