- SessionController wraps RoyalVNCKit.VNCConnection via nonisolated delegate adapter that bridges callbacks to @MainActor; Keychain-resolved passwords; reconnect with jittered exponential backoff; NWPathMonitor adaptive-quality hook; framebuffer rendered to CALayer.contents from didUpdateFramebuffer. - Touch + trackpad input modes with floating soft cursor overlay; hardware keyboard via pressesBegan/Ended → X11 keysyms; UIPointerInteraction with hidden cursor for indirect pointers; pinch-to-zoom; Apple Pencil as direct touch; two-finger pan / indirect scroll wheel events. - Bidirectional clipboard sync (per-connection opt-in); multi-monitor screen picker with input remapping; screenshot capture → share sheet; on-disconnect reconnect/close prompt; view-only and curtain-mode persisted. - iPad multi-window via WindowGroup(for: UUID.self) + context-menu open; CloudKit-backed ModelContainer with local fallback; PrivacyInfo.xcprivacy. 10 VNCCore tests + 4 VNCUI tests pass; iPhone and iPad simulator builds clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
30 lines
1.0 KiB
Swift
30 lines
1.0 KiB
Swift
import SwiftUI
|
|
import VNCCore
|
|
|
|
struct TrackpadCursorOverlay: View {
|
|
let normalizedPosition: CGPoint
|
|
let framebufferSize: CGSize
|
|
let isVisible: Bool
|
|
|
|
var body: some View {
|
|
GeometryReader { proxy in
|
|
let mapper = InputMapper()
|
|
if isVisible,
|
|
let displayed = mapper.displayedRect(for: framebufferSize, in: proxy.size),
|
|
displayed.width > 0 && displayed.height > 0 {
|
|
let x = displayed.origin.x + normalizedPosition.x * displayed.width
|
|
let y = displayed.origin.y + normalizedPosition.y * displayed.height
|
|
Image(systemName: "cursorarrow")
|
|
.font(.system(size: 22, weight: .bold))
|
|
.foregroundStyle(.white, .black)
|
|
.shadow(radius: 1)
|
|
.position(x: x, y: y)
|
|
.allowsHitTesting(false)
|
|
.accessibilityHidden(true)
|
|
.transition(.opacity)
|
|
}
|
|
}
|
|
.ignoresSafeArea()
|
|
}
|
|
}
|