From 972e655a9bc48574844c10eb8d77a6d0bdeec13d Mon Sep 17 00:00:00 2001 From: SSimco <37044560+SSimco@users.noreply.github.com> Date: Sat, 31 Aug 2024 11:22:27 +0300 Subject: [PATCH] Send touch events to Input manager --- src/android/app/src/main/cpp/EmulationState.h | 21 ++++++++++ src/android/app/src/main/cpp/native-lib.cpp | 20 +++++++++- .../java/info/cemu/Cemu/NativeLibrary.java | 6 +++ .../Cemu/emulation/EmulationFragment.java | 40 ++++++++++++++++++- .../cemu/Cemu/inputoverlay/DPadInput.java | 3 +- .../inputoverlay/InputOverlaySurfaceView.java | 2 +- 6 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/android/app/src/main/cpp/EmulationState.h b/src/android/app/src/main/cpp/EmulationState.h index e22ef77f..86e25934 100644 --- a/src/android/app/src/main/cpp/EmulationState.h +++ b/src/android/app/src/main/cpp/EmulationState.h @@ -35,6 +35,15 @@ class EmulationState m_graphicPacks[reinterpret_cast(graphicPack.get())] = graphicPack; } } + void onTouchEvent(sint32 x, sint32 y, bool isPad, std::optional status = {}) + { + auto& instance = InputManager::instance(); + auto& touchInfo = isPad ? instance.m_pad_mouse : instance.m_main_mouse; + std::scoped_lock lock(touchInfo.m_mutex); + touchInfo.position = {x, y}; + if (status.has_value()) + touchInfo.left_down = touchInfo.left_down_toggle = status.value(); + } public: void initializeEmulation() @@ -306,4 +315,16 @@ class EmulationState } g_config.Save(); } + void onTouchMove(sint32 x, sint32 y, bool isPad) + { + onTouchEvent(x, y, isPad); + } + void onTouchUp(sint32 x, sint32 y, bool isPad) + { + onTouchEvent(x, y, isPad, false); + } + void onTouchDown(sint32 x, sint32 y, bool isPad) + { + onTouchEvent(x, y, isPad, true); + } }; \ No newline at end of file diff --git a/src/android/app/src/main/cpp/native-lib.cpp b/src/android/app/src/main/cpp/native-lib.cpp index 01d4f9e9..401ff7d4 100644 --- a/src/android/app/src/main/cpp/native-lib.cpp +++ b/src/android/app/src/main/cpp/native-lib.cpp @@ -516,4 +516,22 @@ Java_info_cemu_Cemu_NativeLibrary_setOverlayDebugEnabled([[maybe_unused]] JNIEnv { g_config.data().overlay.debug = enabled; g_config.Save(); -} \ No newline at end of file +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_NativeLibrary_onTouchDown([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isPad) +{ + s_emulationState.onTouchDown(x, y, isPad); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_NativeLibrary_onTouchUp([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isPad) +{ + s_emulationState.onTouchUp(x, y, isPad); +} + +extern "C" JNIEXPORT void JNICALL +Java_info_cemu_Cemu_NativeLibrary_onTouchMove([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz, jint x, jint y, jboolean isPad) +{ + s_emulationState.onTouchMove(x, y, isPad); +} diff --git a/src/android/app/src/main/java/info/cemu/Cemu/NativeLibrary.java b/src/android/app/src/main/java/info/cemu/Cemu/NativeLibrary.java index 93e74088..e87e1058 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/NativeLibrary.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/NativeLibrary.java @@ -375,4 +375,10 @@ public class NativeLibrary { public static native boolean isOverlayDebugEnabled(); public static native void setOverlayDebugEnabled(boolean enabled); + + public static native void onTouchDown(int x, int y, boolean isPad); + + public static native void onTouchMove(int x, int y, boolean isPad); + + public static native void onTouchUp(int x, int y, boolean isPad); } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/emulation/EmulationFragment.java b/src/android/app/src/main/java/info/cemu/Cemu/emulation/EmulationFragment.java index 31e636f2..f8c9bfdb 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/emulation/EmulationFragment.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/emulation/EmulationFragment.java @@ -1,8 +1,9 @@ package info.cemu.Cemu.emulation; -import android.content.Context; +import android.annotation.SuppressLint; import android.os.Bundle; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; @@ -19,6 +20,7 @@ import info.cemu.Cemu.inputoverlay.InputOverlaySettingsProvider; import info.cemu.Cemu.inputoverlay.InputOverlaySurfaceView; import info.cemu.Cemu.NativeLibrary; +@SuppressLint("ClickableViewAccessibility") public class EmulationFragment extends Fragment implements SurfaceHolder.Callback { private final long gameTitleId; private boolean isGameRunning; @@ -38,6 +40,41 @@ public class EmulationFragment extends Fragment implements SurfaceHolder.Callbac overlaySettings = inputOverlaySettingsProvider.getOverlaySettings(); } + static private class OnSurfaceTouchListener implements View.OnTouchListener { + int currentPointerId = -1; + final boolean isPad; + + public OnSurfaceTouchListener(boolean isPad) { + this.isPad = isPad; + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + int pointerIndex = event.getActionIndex(); + int pointerId = event.getPointerId(pointerIndex); + if (currentPointerId != -1 && pointerId != currentPointerId) { + return false; + } + int x = (int) event.getX(pointerIndex); + int y = (int) event.getY(pointerIndex); + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> { + NativeLibrary.onTouchDown(x, y, isPad); + return true; + } + case MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> { + NativeLibrary.onTouchUp(x, y, isPad); + return true; + } + case MotionEvent.ACTION_MOVE -> { + NativeLibrary.onTouchMove(x, y, isPad); + return true; + } + } + return false; + } + } + @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { FragmentEmulationBinding binding = FragmentEmulationBinding.inflate(inflater, container, false); @@ -73,6 +110,7 @@ public class EmulationFragment extends Fragment implements SurfaceHolder.Callbac } SurfaceView mainCanvas = binding.mainCanvas; mainCanvas.getHolder().addCallback(this); + mainCanvas.setOnTouchListener(new OnSurfaceTouchListener(false)); return binding.getRoot(); } diff --git a/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/DPadInput.java b/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/DPadInput.java index 56cb56a6..a3fc8c15 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/DPadInput.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/DPadInput.java @@ -224,7 +224,8 @@ public class DPadInput extends Input { int pointerId = event.getPointerId(pointerIndex); if (isInside(x, y)) { currentPointerId = pointerId; - nextState = DpadState.NONE; + double angle = Math.atan2(y - centreY, x - centreX); + nextState = getStateByAngle(angle); } } case MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> { diff --git a/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySurfaceView.java b/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySurfaceView.java index c6b61d58..97232a1d 100644 --- a/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySurfaceView.java +++ b/src/android/app/src/main/java/info/cemu/Cemu/inputoverlay/InputOverlaySurfaceView.java @@ -564,6 +564,6 @@ public class InputOverlaySurfaceView extends SurfaceView implements View.OnTouch invalidate(); } - return true; + return touchEventProcessed; } }