summaryrefslogtreecommitdiff
path: root/Source/Android/app/src/main/java
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2025-05-13 16:55:48 +0200
committerJosJuice <josjuice@gmail.com>2025-06-07 10:20:18 +0200
commit4214cb6eb8828e319b90cfde6604cc36eb236f19 (patch)
tree3f7d4c11764644351864b2e5ee772c295a7fffe8 /Source/Android/app/src/main/java
parent903eafcf6521601c0a2dc882c3d37d0e5a32ccd6 (diff)
Android: Make input state changes observable
Diffstat (limited to 'Source/Android/app/src/main/java')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.kt47
1 files changed, 44 insertions, 3 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.kt
index 3bca59f7b7..d5945f2784 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/ControllerInterface.kt
@@ -6,6 +6,7 @@ import android.content.Context
import android.hardware.input.InputManager
import android.os.Build
import android.os.Handler
+import android.os.Looper
import android.os.VibrationEffect
import android.os.Vibrator
import android.os.VibratorManager
@@ -13,8 +14,11 @@ import android.view.InputDevice
import android.view.KeyEvent
import android.view.MotionEvent
import androidx.annotation.Keep
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
import org.dolphinemu.dolphinemu.DolphinApplication
import org.dolphinemu.dolphinemu.utils.LooperThread
+import java.util.concurrent.atomic.AtomicBoolean
/**
* This class interfaces with the native ControllerInterface,
@@ -24,6 +28,12 @@ object ControllerInterface {
private var inputDeviceListener: InputDeviceListener? = null
private lateinit var looperThread: LooperThread
+ private var inputStateUpdatePending = AtomicBoolean(false)
+ private val inputStateVersion = MutableLiveData(0)
+
+ val inputStateChanged: LiveData<Int>
+ get() = inputStateVersion
+
/**
* Activities which want to pass on inputs to native code
* should call this in their own dispatchKeyEvent method.
@@ -31,7 +41,13 @@ object ControllerInterface {
* @return true if the emulator core seems to be interested in this event.
* false if the event should be passed on to the default dispatchKeyEvent.
*/
- external fun dispatchKeyEvent(event: KeyEvent): Boolean
+ fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ val result = dispatchKeyEventNative(event)
+ onInputStateChanged()
+ return result
+ }
+
+ private external fun dispatchKeyEventNative(event: KeyEvent): Boolean
/**
* Activities which want to pass on inputs to native code
@@ -40,7 +56,13 @@ object ControllerInterface {
* @return true if the emulator core seems to be interested in this event.
* false if the event should be passed on to the default dispatchGenericMotionEvent.
*/
- external fun dispatchGenericMotionEvent(event: MotionEvent): Boolean
+ fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
+ val result = dispatchGenericMotionEventNative(event)
+ onInputStateChanged()
+ return result
+ }
+
+ private external fun dispatchGenericMotionEventNative(event: MotionEvent): Boolean
/**
* [DolphinSensorEventListener] calls this for each axis of a received SensorEvent.
@@ -48,7 +70,13 @@ object ControllerInterface {
* @return true if the emulator core seems to be interested in this event.
* false if the sensor can be suspended to save battery.
*/
- external fun dispatchSensorEvent(
+ fun dispatchSensorEvent(deviceQualifier: String, axisName: String, value: Float): Boolean {
+ val result = dispatchSensorEventNative(deviceQualifier, axisName, value)
+ onInputStateChanged()
+ return result
+ }
+
+ private external fun dispatchSensorEventNative(
deviceQualifier: String,
axisName: String,
value: Float
@@ -76,6 +104,19 @@ object ControllerInterface {
external fun getDevice(deviceString: String): CoreDevice?
+ private fun onInputStateChanged() {
+ // When a single SensorEvent is dispatched, this method is likely to get called many times.
+ // For the sake of performance, let's batch input state updates so that observers only have
+ // to process one update.
+ if (!inputStateUpdatePending.getAndSet(true)) {
+ Handler(Looper.getMainLooper()).post {
+ if (inputStateUpdatePending.getAndSet(false)) {
+ inputStateVersion.value = inputStateVersion.value?.plus(1)
+ }
+ }
+ }
+ }
+
@Keep
@JvmStatic
private fun registerInputDeviceListener() {