From c6b28ea6f168870acb4d89d3b9ad631d5cedfb4e Mon Sep 17 00:00:00 2001 From: Gaurav Ujjwal Date: Fri, 18 Mar 2022 16:48:56 +0530 Subject: [PATCH] Implement 'pan-with-cursor' for relative action mode --- .../java/com/gaurav/avnc/ui/vnc/Dispatcher.kt | 1 + .../java/com/gaurav/avnc/ui/vnc/FrameState.kt | 18 +++++++++++++++ .../com/gaurav/avnc/viewmodel/VncViewModel.kt | 6 +++++ .../java/com/gaurav/avnc/ui/FrameStateTest.kt | 23 +++++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/app/src/main/java/com/gaurav/avnc/ui/vnc/Dispatcher.kt b/app/src/main/java/com/gaurav/avnc/ui/vnc/Dispatcher.kt index a92b513..609521f 100644 --- a/app/src/main/java/com/gaurav/avnc/ui/vnc/Dispatcher.kt +++ b/app/src/main/java/com/gaurav/avnc/ui/vnc/Dispatcher.kt @@ -266,6 +266,7 @@ class Dispatcher(private val activity: VncActivity) { y = y.coerceIn(0f, viewModel.frameState.fbHeight - 1) } doButtonDown(PointerButton.None, pointerPosition) + viewModel.showFbPoint(pointerPosition) } override fun doDrag(p: PointF, dx: Float, dy: Float) { diff --git a/app/src/main/java/com/gaurav/avnc/ui/vnc/FrameState.kt b/app/src/main/java/com/gaurav/avnc/ui/vnc/FrameState.kt index 5b59a91..c215747 100644 --- a/app/src/main/java/com/gaurav/avnc/ui/vnc/FrameState.kt +++ b/app/src/main/java/com/gaurav/avnc/ui/vnc/FrameState.kt @@ -194,6 +194,24 @@ class FrameState(private val minZoomScale: Float = 0.5F, private val maxZoomScal return null } + /** + * Makes sure that framebuffer point [fbX],[fbY] is visible. + * If point is outside of visible area, frame is panned to make the it visible. + */ + fun showFbPoint(fbX: Float, fbY: Float) { + val vpX = fbX * scale + frameX + val vpY = fbY * scale + frameY + var dx = 0f + var dy = 0f + + if (vpX < 0) dx = -vpX + if (vpX >= vpWidth) dx = vpWidth - vpX - 1 + if (vpY < 0) dy = -vpY + if (vpY >= vpHeight) dy = vpHeight - vpY - 1 + + pan(dx, dy) + } + private fun calculateBaseScale() { if (fbHeight == 0F || fbWidth == 0F || windowHeight == 0F) return //Not enough info yet diff --git a/app/src/main/java/com/gaurav/avnc/viewmodel/VncViewModel.kt b/app/src/main/java/com/gaurav/avnc/viewmodel/VncViewModel.kt index 89f5262..7328369 100644 --- a/app/src/main/java/com/gaurav/avnc/viewmodel/VncViewModel.kt +++ b/app/src/main/java/com/gaurav/avnc/viewmodel/VncViewModel.kt @@ -9,6 +9,7 @@ package com.gaurav.avnc.viewmodel import android.app.Application +import android.graphics.PointF import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope @@ -277,6 +278,11 @@ class VncViewModel(app: Application) : BaseViewModel(app), VncClient.Observer { frameViewRef.get()?.requestRender() } + fun showFbPoint(fbPoint: PointF) { + frameState.showFbPoint(fbPoint.x, fbPoint.y) + frameViewRef.get()?.requestRender() + } + /************************************************************************** * Clipboard Sync **************************************************************************/ diff --git a/app/src/test/java/com/gaurav/avnc/ui/FrameStateTest.kt b/app/src/test/java/com/gaurav/avnc/ui/FrameStateTest.kt index 294b6ca..cc63bd4 100644 --- a/app/src/test/java/com/gaurav/avnc/ui/FrameStateTest.kt +++ b/app/src/test/java/com/gaurav/avnc/ui/FrameStateTest.kt @@ -156,4 +156,27 @@ class FrameStateTest { assertEquals(-100f, state.frameX) //Right side of frame and Viewport are aligned assertEquals(-100f, state.frameY) //Bottom side of frame and Viewport are aligned } + + @Test + fun showFbPointTest() { + val state = FrameState() + state.setViewportSize(50f, 50f) + state.setFramebufferSize(100f, 100f) + + state.showFbPoint(49f, 49f) + assertEquals(0f, state.frameX) + assertEquals(0f, state.frameY) + + state.showFbPoint(50f, 50f) + assertEquals(-1f, state.frameX) + assertEquals(-1f, state.frameY) + + state.showFbPoint(0f, 0f) + assertEquals(0f, state.frameX) + assertEquals(0f, state.frameY) + + state.showFbPoint(99f, 99f) + assertEquals(-50f, state.frameX) + assertEquals(-50f, state.frameY) + } } \ No newline at end of file