mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-16 17:10:20 +08:00
[fix] prevent iOS relative cursor jumps after movement
This commit is contained in:
@@ -58,6 +58,7 @@ struct RemoteTouchInputView: UIViewRepresentable {
|
||||
let videoSize: CGSize
|
||||
let controlMode: MouseControlMode
|
||||
let remoteCursorPosition: CGPoint?
|
||||
let remoteCursorPositionRevision: UInt64
|
||||
let viewportScale: CGFloat
|
||||
let viewportOffset: CGSize
|
||||
let viewportChanged: (CGFloat, CGSize) -> Void
|
||||
@@ -81,7 +82,8 @@ struct RemoteTouchInputView: UIViewRepresentable {
|
||||
view.onLeftUp = leftUp
|
||||
view.onRightClick = rightClick
|
||||
view.onScroll = scroll
|
||||
view.synchronizeRemoteCursor(remoteCursorPosition)
|
||||
view.synchronizeRemoteCursor(remoteCursorPosition,
|
||||
revision: remoteCursorPositionRevision)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +110,7 @@ final class RemoteTouchSurface: UIView, UIGestureRecognizerDelegate {
|
||||
|
||||
private var relativeCursorPoint: (Float, Float) = (0.5, 0.5)
|
||||
private var lastRemoteCursorPoint: (Float, Float)?
|
||||
private var lastRemoteCursorRevision: UInt64?
|
||||
private var relativePanActive = false
|
||||
private var heldDragPoint: (Float, Float)?
|
||||
private var heldDragLastLocation: CGPoint?
|
||||
@@ -184,7 +187,12 @@ final class RemoteTouchSurface: UIView, UIGestureRecognizerDelegate {
|
||||
viewportOffset = constrainedViewportOffset(offset, scale: nextScale)
|
||||
}
|
||||
|
||||
func synchronizeRemoteCursor(_ position: CGPoint?) {
|
||||
func synchronizeRemoteCursor(_ position: CGPoint?, revision: UInt64) {
|
||||
// SwiftUI refreshes this view for video frames and shape-only feedback
|
||||
// too. Consume each position update once, even when it arrives during
|
||||
// local movement, so a later refresh cannot restore an old coordinate.
|
||||
guard revision != lastRemoteCursorRevision else { return }
|
||||
lastRemoteCursorRevision = revision
|
||||
guard let position else {
|
||||
lastRemoteCursorPoint = nil
|
||||
return
|
||||
@@ -194,7 +202,11 @@ final class RemoteTouchSurface: UIView, UIGestureRecognizerDelegate {
|
||||
Float(min(max(position.y, 0), 1))
|
||||
)
|
||||
lastRemoteCursorPoint = point
|
||||
applyRemoteCursorIfIdle()
|
||||
guard controlMode == .relative,
|
||||
!relativePanActive,
|
||||
heldDragPoint == nil,
|
||||
hoverLastLocation == nil else { return }
|
||||
relativeCursorPoint = point
|
||||
}
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
|
||||
@@ -400,7 +412,6 @@ final class RemoteTouchSurface: UIView, UIGestureRecognizerDelegate {
|
||||
}
|
||||
default:
|
||||
relativePanActive = false
|
||||
applyRemoteCursorIfIdle()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,7 +440,6 @@ final class RemoteTouchSurface: UIView, UIGestureRecognizerDelegate {
|
||||
}
|
||||
heldDragPoint = nil
|
||||
heldDragLastLocation = nil
|
||||
applyRemoteCursorIfIdle()
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -457,14 +467,6 @@ final class RemoteTouchSurface: UIView, UIGestureRecognizerDelegate {
|
||||
return relativeCursorPoint
|
||||
}
|
||||
|
||||
private func applyRemoteCursorIfIdle() {
|
||||
guard controlMode == .relative,
|
||||
!relativePanActive,
|
||||
heldDragPoint == nil,
|
||||
let point = lastRemoteCursorPoint else { return }
|
||||
relativeCursorPoint = point
|
||||
}
|
||||
|
||||
private func normalized(_ point: CGPoint) -> (Float, Float)? {
|
||||
guard let renderRect = renderRect(), renderRect.contains(point) else { return nil }
|
||||
return (Float((point.x - renderRect.minX) / renderRect.width),
|
||||
|
||||
@@ -381,6 +381,7 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
|
||||
@Published private(set) var remoteCursorVisible = true
|
||||
@Published private(set) var remoteCursorShape = 0
|
||||
@Published private(set) var remoteCursorPosition: CGPoint?
|
||||
@Published private(set) var remoteCursorPositionRevision: UInt64 = 0
|
||||
@Published private(set) var remoteCursorVisualOffset = CGPoint.zero
|
||||
@Published private(set) var hasRemoteCursorState = false
|
||||
@Published private(set) var bitrate: UInt = 0
|
||||
@@ -775,6 +776,7 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
|
||||
remoteCursorVisible = true
|
||||
remoteCursorShape = 0
|
||||
remoteCursorPosition = nil
|
||||
remoteCursorPositionRevision &+= 1
|
||||
remoteCursorVisualOffset = .zero
|
||||
hasRemoteCursorState = false
|
||||
remoteCursorSequence = nil
|
||||
@@ -991,6 +993,7 @@ final class RemoteSessionModel: NSObject, ObservableObject, CrossDeskRTCBridgeDe
|
||||
} else {
|
||||
remoteCursorPosition = nil
|
||||
}
|
||||
remoteCursorPositionRevision &+= 1
|
||||
}
|
||||
hasRemoteCursorState = true
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ struct RemoteSessionView: View {
|
||||
videoSize: session.displayGeometrySize,
|
||||
controlMode: session.mouseControlMode,
|
||||
remoteCursorPosition: session.remoteCursorPosition,
|
||||
remoteCursorPositionRevision: session.remoteCursorPositionRevision,
|
||||
viewportScale: viewport.scale,
|
||||
viewportOffset: viewport.offset,
|
||||
viewportChanged: { scale, offset in
|
||||
@@ -161,8 +162,8 @@ struct RemoteSessionView: View {
|
||||
.onChange(of: session.mouseControlMode) { _ in
|
||||
cursorPosition = session.remoteCursorPosition
|
||||
}
|
||||
.onChange(of: session.remoteCursorPosition) { position in
|
||||
guard let position else { return }
|
||||
.onChange(of: session.remoteCursorPositionRevision) { _ in
|
||||
guard let position = session.remoteCursorPosition else { return }
|
||||
cursorPosition = position
|
||||
}
|
||||
.fileImporter(isPresented: $showingFileImporter,
|
||||
|
||||
Reference in New Issue
Block a user