205e5c5a59
apple / swift (push) Successful in 1m20s
android / android (push) Has been cancelled
apple / screenshots (push) Has been cancelled
arch / build-publish (push) Has been cancelled
ci / web (push) Successful in 52s
ci / docs-site (push) Successful in 1m17s
ci / rust (push) Has been cancelled
ci / bench (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Successful in 24s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 12s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 17s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 18s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 18s
docker / deploy-docs (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
release / apple (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
The W7/W8 client refactor (extracting FullscreenController/ApprovalRequest out of ContentView, splitting Settings) landed the DefaultsKeys + scaffolding but dropped the feature WIRING, which was uncommitted WIP shelved in a stash during the 16:28 clipboard/v4 reconcile. Recovered from that stash (+ its untracked-files parent for the whole new ModifierLayout.swift) and re-ported onto the refactored tree: - invertScroll: applied in InputCapture.sendScroll (the one scroll sink) + Settings toggle - modifierLayout (Cmd/Option switch): restored ModifierLayout.swift enum + KeyMaps .applyModifierLayout + InputCapture.emitKey wire-boundary + Settings picker - fullscreen shortcut (Ctrl+Cmd+F): InputCapture ⌃⌘F interception + onToggleFullscreen + StreamView wiring + Stream-menu item (the .punktfunkToggleFullscreen sink + FullscreenController observer already survived on main) - render scale: Settings picker + MatchWindowFollower renderScale/maxDimension application + StreamView/StreamViewIOS plumbing (RenderScale.swift already on main) StreamCommands re-ported by hand (the stash hunk deleted the since-landed clipboard item — kept it, added the fullscreen item alongside). Recovered ModifierLayout + RenderScale tests. swift build green; 15 tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
53 lines
2.8 KiB
Swift
53 lines
2.8 KiB
Swift
// Location-based modifier mapping — which Windows VK each PHYSICAL modifier position forwards to
|
|
// the host. A Mac keyboard's bottom row is `⌃ Control / ⌥ Option / ⌘ Command / space`; a Windows
|
|
// keyboard's is `Ctrl / ⊞ Super / Alt / space`. So the key NEAREST the space bar is Command on a
|
|
// Mac but Alt on Windows, and the next one out is Option on a Mac but the Windows key. A user who
|
|
// grew up on Windows reaches for Alt where the Mac has Command; this setting lets them get that
|
|
// muscle memory back WITHOUT relabelling keycaps — it remaps by physical position, not by a blunt
|
|
// "swap these two VKs" that would also drag Control/Shift or lose the left/right distinction.
|
|
//
|
|
// The model: keep the physical detection (which side, which key) exactly as the OS reports it, and
|
|
// swap only the Alt-vs-Super ROLE between the Option and Command keys, per side. So under `.windows`
|
|
// the ⌘ position emits Alt (VK_L/RMENU) and the ⌥ position emits the Windows key (VK_L/RWIN), while
|
|
// left stays left and right stays right. Control and Shift are in the same place on both keyboards,
|
|
// so they never move. Lives in PunktfunkShared because both the Settings UI (PunktfunkClient) and
|
|
// the wire-boundary remap (`InputCapture.applyModifierLayout`, PunktfunkKit) resolve it.
|
|
|
|
import Foundation
|
|
|
|
/// How the physical ⌥ Option / ⌘ Command keys map to host modifiers. The raw values are stable on
|
|
/// disk — rename the cases freely, never the strings.
|
|
public enum ModifierLayout: String, CaseIterable, Sendable {
|
|
/// Apple positions (default): ⌥ Option → Alt, ⌘ Command → Super/Windows. The current behaviour.
|
|
case mac
|
|
/// Windows positions: the key nearest the space bar (⌘ Command) → Alt, the next one (⌥ Option)
|
|
/// → the Windows/Super key. Side (left/right) is preserved.
|
|
case windows
|
|
|
|
/// User-facing label (Settings picker).
|
|
public var label: String {
|
|
switch self {
|
|
case .mac: return "Mac (⌥ Alt · ⌘ Super)"
|
|
case .windows: return "Windows (⌘ Alt · ⌥ Super)"
|
|
}
|
|
}
|
|
|
|
/// A one-line explanation for the setting's footer.
|
|
public var detail: String {
|
|
switch self {
|
|
case .mac:
|
|
return "The ⌥ Option key sends Alt and the ⌘ Command key sends the Windows key — the Apple layout."
|
|
case .windows:
|
|
return "The key nearest the space bar sends Alt and the next one sends the Windows key, matching a PC keyboard. Client shortcuts (⌘⎋ and friends) still use the physical ⌘ key."
|
|
}
|
|
}
|
|
|
|
/// The persisted layout (default `.mac` when unset).
|
|
public static var current: ModifierLayout {
|
|
guard let raw = UserDefaults.standard.string(forKey: DefaultsKey.modifierLayout) else {
|
|
return .mac
|
|
}
|
|
return ModifierLayout(rawValue: raw) ?? .mac
|
|
}
|
|
}
|