From 2987e03a8608b2a3af3c67a5c0c44307fe0007e9 Mon Sep 17 00:00:00 2001 From: albexk Date: Sun, 24 Nov 2024 21:18:35 +0300 Subject: [PATCH] fix: add the touch emulation method for Android TV --- .../src/org/amnezia/vpn/AmneziaActivity.kt | 48 +++++++++++++++++++ .../platforms/android/android_controller.cpp | 5 ++ client/platforms/android/android_controller.h | 1 + client/ui/controllers/systemController.cpp | 7 +++ client/ui/controllers/systemController.h | 2 + 5 files changed, 63 insertions(+) diff --git a/client/android/src/org/amnezia/vpn/AmneziaActivity.kt b/client/android/src/org/amnezia/vpn/AmneziaActivity.kt index b43a22c5..8d873859 100644 --- a/client/android/src/org/amnezia/vpn/AmneziaActivity.kt +++ b/client/android/src/org/amnezia/vpn/AmneziaActivity.kt @@ -23,9 +23,12 @@ import android.os.Looper import android.os.Message import android.os.Messenger import android.os.ParcelFileDescriptor +import android.os.SystemClock import android.provider.OpenableColumns import android.provider.Settings import android.view.MotionEvent +import android.view.View +import android.view.ViewGroup import android.view.WindowManager.LayoutParams import android.webkit.MimeTypeMap import android.widget.Toast @@ -800,6 +803,50 @@ class AmneziaActivity : QtActivity() { } } + // method to workaround Qt's problem with calling the keyboard on TVs + @Suppress("unused") + fun sendTouch(x: Float, y: Float) { + Log.v(TAG, "Send touch: $x, $y") + blockingCall { + findQtWindow(window.decorView)?.let { + Log.v(TAG, "Send touch to $it") + it.dispatchTouchEvent(createEvent(x, y, SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN)) + it.dispatchTouchEvent(createEvent(x, y, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP)) + } + } + } + + private fun findQtWindow(view: View): View? { + Log.v(TAG, "findQtWindow: process $view") + if (view::class.simpleName == "QtWindow") return view + else if (view is ViewGroup) { + for (i in 0 until view.childCount) { + val result = findQtWindow(view.getChildAt(i)) + if (result != null) return result + } + return null + } else return null + } + + private fun createEvent(x: Float, y: Float, eventTime: Long, action: Int): MotionEvent = + MotionEvent.obtain( + eventTime, + eventTime, + action, + 1, + arrayOf(MotionEvent.PointerProperties().apply { + id = 0 + toolType = MotionEvent.TOOL_TYPE_FINGER + }), + arrayOf(MotionEvent.PointerCoords().apply { + this.x = x + this.y = y + pressure = 1f + size = 1f + }), + 0, 0, 1.0f, 1.0f, 0, 0, 0,0 + ) + // workaround for a bug in Qt that causes the mouse click event not to be handled // also disable right-click, as it causes the application to crash private var lastButtonState = 0 @@ -849,6 +896,7 @@ class AmneziaActivity : QtActivity() { } override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { + Log.v(TAG, "dispatchTouch: $ev") if (ev != null && ev.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) { return handleMouseEvent(ev) { super.dispatchTouchEvent(it) } } diff --git a/client/platforms/android/android_controller.cpp b/client/platforms/android/android_controller.cpp index 6ea8bea5..d9195f87 100644 --- a/client/platforms/android/android_controller.cpp +++ b/client/platforms/android/android_controller.cpp @@ -304,6 +304,11 @@ bool AndroidController::requestAuthentication() return result; } +void AndroidController::sendTouch(float x, float y) +{ + callActivityMethod("sendTouch", "(FF)V", x, y); +} + // Moving log processing to the Android side jclass AndroidController::log; jmethodID AndroidController::logDebug; diff --git a/client/platforms/android/android_controller.h b/client/platforms/android/android_controller.h index c2e082ea..5707771e 100644 --- a/client/platforms/android/android_controller.h +++ b/client/platforms/android/android_controller.h @@ -51,6 +51,7 @@ public: bool isNotificationPermissionGranted(); void requestNotificationPermission(); bool requestAuthentication(); + void sendTouch(float x, float y); static bool initLogging(); static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message); diff --git a/client/ui/controllers/systemController.cpp b/client/ui/controllers/systemController.cpp index 6de66769..3463d5f9 100644 --- a/client/ui/controllers/systemController.cpp +++ b/client/ui/controllers/systemController.cpp @@ -159,3 +159,10 @@ bool SystemController::isAuthenticated() return true; #endif } + +void SystemController::sendTouch(float x, float y) +{ +#ifdef Q_OS_ANDROID + AndroidController::instance()->sendTouch(x, y); +#endif +} diff --git a/client/ui/controllers/systemController.h b/client/ui/controllers/systemController.h index ddc3476a..f80d2fdb 100644 --- a/client/ui/controllers/systemController.h +++ b/client/ui/controllers/systemController.h @@ -22,6 +22,8 @@ public slots: void setQmlRoot(QObject *qmlRoot); bool isAuthenticated(); + void sendTouch(float x, float y); + signals: void fileDialogClosed(const bool isAccepted);