Adopts punktfunk_connect_ex from the compositor-selection batch: a Compositor enum on PunktfunkConnection (auto/kwin/wlroots/mutter/gamescope, with the host's name aliases for env parsing), a "Host compositor" picker in Settings (default Automatic — a concrete choice is honored only if that backend is available host-side), and PUNKTFUNK_COMPOSITOR / PUNKTFUNK_REMOTE_COMPOSITOR pass-throughs for the autoconnect dev hook and the remote first-light test. The wire change is backward-compatible (optional trailing byte), so no behavior changes at the default. Validated live against the box: host with no compositor env (auto-detect = KWin) logged "honoring client compositor request compositor=gamescope" and streamed 60/60 decoded frames from the spawned gamescope. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ struct ContentView: View {
|
||||
@AppStorage("punktfunk.width") private var width = 1920
|
||||
@AppStorage("punktfunk.height") private var height = 1080
|
||||
@AppStorage("punktfunk.hz") private var hz = 60
|
||||
@AppStorage("punktfunk.compositor") private var compositor = 0
|
||||
@State private var showAddHost = false
|
||||
@State private var pairingTarget: StoredHost?
|
||||
|
||||
@@ -196,7 +197,9 @@ struct ContentView: View {
|
||||
model.connect(
|
||||
to: host,
|
||||
width: UInt32(clamping: width), height: UInt32(clamping: height),
|
||||
hz: UInt32(clamping: hz))
|
||||
hz: UInt32(clamping: hz),
|
||||
compositor: PunktfunkConnection.Compositor(
|
||||
rawValue: UInt32(clamping: compositor)) ?? .auto)
|
||||
}
|
||||
|
||||
// MARK: - Trust on first use
|
||||
@@ -303,7 +306,8 @@ struct ContentView: View {
|
||||
|
||||
/// PUNKTFUNK_AUTOCONNECT=host[:port] connects immediately (trust-on-first-use,
|
||||
/// auto-confirmed — dev only) at the saved or PUNKTFUNK_MODE=WxHxHz mode, without
|
||||
/// touching the saved host list. (IPv4/hostname only.)
|
||||
/// touching the saved host list. PUNKTFUNK_COMPOSITOR=kwin|gamescope|… overrides the
|
||||
/// compositor preference (same names as the host env knob). (IPv4/hostname only.)
|
||||
private func autoConnectIfAsked() {
|
||||
guard let target = ProcessInfo.processInfo.environment["PUNKTFUNK_AUTOCONNECT"],
|
||||
!target.isEmpty, model.phase == .idle
|
||||
@@ -319,10 +323,17 @@ struct ContentView: View {
|
||||
hz = dims[2]
|
||||
}
|
||||
}
|
||||
var pref = PunktfunkConnection.Compositor(
|
||||
rawValue: UInt32(clamping: compositor)) ?? .auto
|
||||
if let name = ProcessInfo.processInfo.environment["PUNKTFUNK_COMPOSITOR"],
|
||||
let c = PunktfunkConnection.Compositor(name: name) {
|
||||
pref = c
|
||||
}
|
||||
model.connect(
|
||||
to: host,
|
||||
width: UInt32(clamping: width), height: UInt32(clamping: height),
|
||||
hz: UInt32(clamping: hz),
|
||||
compositor: pref,
|
||||
autoTrust: true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ final class SessionModel: ObservableObject {
|
||||
var isBusy: Bool { phase != .idle }
|
||||
|
||||
func connect(to host: StoredHost, width: UInt32, height: UInt32, hz: UInt32,
|
||||
compositor: PunktfunkConnection.Compositor = .auto,
|
||||
autoTrust: Bool = false) {
|
||||
guard phase == .idle else { return }
|
||||
phase = .connecting
|
||||
@@ -78,7 +79,7 @@ final class SessionModel: ObservableObject {
|
||||
let result = Result { try PunktfunkConnection(
|
||||
host: host.address, port: host.port,
|
||||
width: width, height: height, refreshHz: hz,
|
||||
pinSHA256: pin, identity: identity) }
|
||||
pinSHA256: pin, identity: identity, compositor: compositor) }
|
||||
await MainActor.run { [weak self] in
|
||||
guard let self else { return }
|
||||
switch result {
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
// App settings (⌘,): the stream mode. The host creates a native virtual output at
|
||||
// exactly this size/refresh — there is no scaling anywhere in the pipeline.
|
||||
// App settings (⌘,): the stream mode + the host compositor. The host creates a native
|
||||
// virtual output at exactly this size/refresh — there is no scaling anywhere in the
|
||||
// pipeline.
|
||||
|
||||
import AppKit
|
||||
import PunktfunkKit
|
||||
import SwiftUI
|
||||
|
||||
struct SettingsView: View {
|
||||
@AppStorage("punktfunk.width") private var width = 1920
|
||||
@AppStorage("punktfunk.height") private var height = 1080
|
||||
@AppStorage("punktfunk.hz") private var hz = 60
|
||||
@AppStorage("punktfunk.compositor") private var compositor = 0
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
@@ -30,6 +33,23 @@ struct SettingsView: View {
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
Section {
|
||||
Picker("Compositor", selection: $compositor) {
|
||||
Text("Automatic").tag(0)
|
||||
Text("KWin (KDE Plasma)").tag(1)
|
||||
Text("wlroots (Sway / Hyprland)").tag(2)
|
||||
Text("Mutter (GNOME)").tag(3)
|
||||
Text("gamescope").tag(4)
|
||||
}
|
||||
} header: {
|
||||
Text("Host compositor")
|
||||
} footer: {
|
||||
Text("Which compositor drives the virtual output on the host. A specific "
|
||||
+ "choice is honored only if that backend is available there — "
|
||||
+ "otherwise the host falls back to auto-detection.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
.formStyle(.grouped)
|
||||
.frame(width: 380)
|
||||
|
||||
Reference in New Issue
Block a user