summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Narr the Reg2023-02-13 13:46:51 -0600
committerGravatar bunnei2023-06-03 00:05:30 -0700
commit92fb7cc4e4c0f3cf18c8aa748fb5ae31eef562d9 (patch)
treeaa0c3141ba1122ff500bcef0cd92f47454da6728
parentandroid: cleanup touch update loop (diff)
downloadyuzu-92fb7cc4e4c0f3cf18c8aa748fb5ae31eef562d9.tar.gz
yuzu-92fb7cc4e4c0f3cf18c8aa748fb5ae31eef562d9.tar.xz
yuzu-92fb7cc4e4c0f3cf18c8aa748fb5ae31eef562d9.zip
android: Hook jni input properly
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java52
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.java20
-rw-r--r--src/android/app/src/main/jni/emu_window/emu_window.cpp36
-rw-r--r--src/android/app/src/main/jni/emu_window/emu_window.h19
-rw-r--r--src/android/app/src/main/jni/native.cpp67
5 files changed, 104 insertions, 90 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java
index 2ab3a834a..a0f6c1f7b 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java
@@ -42,9 +42,17 @@ import static android.Manifest.permission.RECORD_AUDIO;
42 */ 42 */
43public final class NativeLibrary { 43public final class NativeLibrary {
44 /** 44 /**
45 * Default touchscreen device 45 * Default controller id for each device
46 */ 46 */
47 public static final String TouchScreenDevice = "Touchscreen"; 47 public static final int Player1Device = 0;
48 public static final int Player2Device = 1;
49 public static final int Player3Device = 2;
50 public static final int Player4Device = 3;
51 public static final int Player5Device = 4;
52 public static final int Player6Device = 5;
53 public static final int Player7Device = 6;
54 public static final int Player8Device = 7;
55 public static final int ConsoleDevice = 8;
48 public static WeakReference<EmulationActivity> sEmulationActivity = new WeakReference<>(null); 56 public static WeakReference<EmulationActivity> sEmulationActivity = new WeakReference<>(null);
49 57
50 private static boolean alertResult = false; 58 private static boolean alertResult = false;
@@ -90,36 +98,37 @@ public final class NativeLibrary {
90 * @param Action Mask identifying which action is happening (button pressed down, or button released). 98 * @param Action Mask identifying which action is happening (button pressed down, or button released).
91 * @return If we handled the button press. 99 * @return If we handled the button press.
92 */ 100 */
93 public static native boolean onGamePadEvent(String Device, int Button, int Action); 101 public static native boolean onGamePadButtonEvent(int Device, int Button, int Action);
94 102
95 /** 103 /**
96 * Handles gamepad movement events. 104 * Handles joystick movement events.
97 * 105 *
98 * @param Device The device ID of the gamepad. 106 * @param Device The device ID of the gamepad.
99 * @param Axis The axis ID 107 * @param Axis The axis ID
100 * @param x_axis The value of the x-axis represented by the given ID. 108 * @param x_axis The value of the x-axis represented by the given ID.
101 * @param y_axis The value of the y-axis represented by the given ID 109 * @param y_axis The value of the y-axis represented by the given ID.
102 */ 110 */
103 public static native boolean onGamePadMoveEvent(String Device, int Axis, float x_axis, float y_axis); 111 public static native boolean onGamePadJoystickEvent(int Device, int Axis, float x_axis, float y_axis);
104 112
105 /** 113 /**
106 * Handles gamepad movement events. 114 * Handles motion events.
107 * 115 *
108 * @param Device The device ID of the gamepad. 116 * @param delta_timestamp The finger id corresponding to this event
109 * @param Axis_id The axis ID 117 * @param gyro_x,gyro_y,gyro_z The value of the accelerometer sensor.
110 * @param axis_val The value of the axis represented by the given ID. 118 * @param accel_x,accel_y,accel_z The value of the y-axis
111 */ 119 */
112 public static native boolean onGamePadAxisEvent(String Device, int Axis_id, float axis_val); 120
121 public static native boolean onGamePadMotionEvent(int Device, long delta_timestamp, float gyro_x, float gyro_y,
122 float gyro_z, float accel_x, float accel_y, float accel_z);
113 123
114 /** 124 /**
115 * Handles touch events. 125 * Handles touch press events.
116 * 126 *
117 * @param x_axis The value of the x-axis. 127 * @param finger_id The finger id corresponding to this event
118 * @param y_axis The value of the y-axis 128 * @param x_axis The value of the x-axis.
119 * @param pressed To identify if the touch held down or released. 129 * @param y_axis The value of the y-axis.
120 * @return true if the pointer is within the touchscreen
121 */ 130 */
122 public static native boolean onTouchEvent(float x_axis, float y_axis, boolean pressed); 131 public static native void onTouchPressed(int finger_id, float x_axis, float y_axis);
123 132
124 /** 133 /**
125 * Handles touch movement. 134 * Handles touch movement.
@@ -127,7 +136,14 @@ public final class NativeLibrary {
127 * @param x_axis The value of the instantaneous x-axis. 136 * @param x_axis The value of the instantaneous x-axis.
128 * @param y_axis The value of the instantaneous y-axis. 137 * @param y_axis The value of the instantaneous y-axis.
129 */ 138 */
130 public static native void onTouchMoved(float x_axis, float y_axis); 139 public static native void onTouchMoved(int finger_id, float x_axis, float y_axis);
140
141 /**
142 * Handles touch release events.
143 *
144 * @param finger_id The finger id corresponding to this event
145 */
146 public static native void onTouchReleased(int finger_id);
131 147
132 public static native void ReloadSettings(); 148 public static native void ReloadSettings();
133 149
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.java
index 50c95d1de..e6e91aea1 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.java
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.java
@@ -345,17 +345,17 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
345 if (!button.updateStatus(event)) { 345 if (!button.updateStatus(event)) {
346 continue; 346 continue;
347 } 347 }
348 NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), button.getStatus()); 348 NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, button.getId(), button.getStatus());
349 } 349 }
350 350
351 for (InputOverlayDrawableDpad dpad : overlayDpads) { 351 for (InputOverlayDrawableDpad dpad : overlayDpads) {
352 if (!dpad.updateStatus(event, EmulationMenuSettings.getDpadSlideEnable())) { 352 if (!dpad.updateStatus(event, EmulationMenuSettings.getDpadSlideEnable())) {
353 continue; 353 continue;
354 } 354 }
355 NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getUpId(), dpad.getUpStatus()); 355 NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, dpad.getUpId(), dpad.getUpStatus());
356 NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getDownId(), dpad.getDownStatus()); 356 NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, dpad.getDownId(), dpad.getDownStatus());
357 NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getLeftId(), dpad.getLeftStatus()); 357 NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, dpad.getLeftId(), dpad.getLeftStatus());
358 NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getRightId(), dpad.getRightStatus()); 358 NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, dpad.getRightId(), dpad.getRightStatus());
359 } 359 }
360 360
361 for (InputOverlayDrawableJoystick joystick : overlayJoysticks) { 361 for (InputOverlayDrawableJoystick joystick : overlayJoysticks) {
@@ -363,8 +363,8 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
363 continue; 363 continue;
364 } 364 }
365 int axisID = joystick.getJoystickId(); 365 int axisID = joystick.getJoystickId();
366 NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisID, joystick.getXAxis(), joystick.getYAxis()); 366 NativeLibrary.onGamePadJoystickEvent(NativeLibrary.Player1Device, axisID, joystick.getXAxis(), joystick.getYAxis());
367 NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, joystick.getButtonId(), joystick.getButtonStatus()); 367 NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, joystick.getButtonId(), joystick.getButtonStatus());
368 } 368 }
369 369
370 if (!mPreferences.getBoolean("isTouchEnabled", true)) { 370 if (!mPreferences.getBoolean("isTouchEnabled", true)) {
@@ -381,7 +381,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
381 boolean isActionUp = motion_event == MotionEvent.ACTION_UP || motion_event == MotionEvent.ACTION_POINTER_UP; 381 boolean isActionUp = motion_event == MotionEvent.ACTION_UP || motion_event == MotionEvent.ACTION_POINTER_UP;
382 382
383 if (isActionDown && !isTouchInputConsumed(pointerId)) { 383 if (isActionDown && !isTouchInputConsumed(pointerId)) {
384 NativeLibrary.onTouchEvent(xPosition, yPosition, true); 384 NativeLibrary.onTouchPressed(pointerId, xPosition, yPosition);
385 } 385 }
386 386
387 if (isActionMove) { 387 if (isActionMove) {
@@ -390,12 +390,12 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
390 if (isTouchInputConsumed(fingerId)) { 390 if (isTouchInputConsumed(fingerId)) {
391 continue; 391 continue;
392 } 392 }
393 NativeLibrary.onTouchMoved(event.getX(i), event.getY(i)); 393 NativeLibrary.onTouchMoved(fingerId, event.getX(i), event.getY(i));
394 } 394 }
395 } 395 }
396 396
397 if (isActionUp && !isTouchInputConsumed(pointerId)) { 397 if (isActionUp && !isTouchInputConsumed(pointerId)) {
398 NativeLibrary.onTouchEvent(xPosition, yPosition, false); 398 NativeLibrary.onTouchReleased(pointerId);
399 } 399 }
400 400
401 invalidate(); 401 invalidate();
diff --git a/src/android/app/src/main/jni/emu_window/emu_window.cpp b/src/android/app/src/main/jni/emu_window/emu_window.cpp
index cef296037..0f6514a61 100644
--- a/src/android/app/src/main/jni/emu_window/emu_window.cpp
+++ b/src/android/app/src/main/jni/emu_window/emu_window.cpp
@@ -10,32 +10,40 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
10 render_window = surface; 10 render_window = surface;
11} 11}
12 12
13bool EmuWindow_Android::OnTouchEvent(float x, float y, bool pressed) { 13void EmuWindow_Android::OnTouchPressed(int id, float x, float y) {
14 if (pressed) { 14 const auto [touch_x,touch_y]=MapToTouchScreen(x,y);
15 input_subsystem->GetTouchScreen()->TouchPressed(NormalizeX(x), NormalizeY(y), 0); 15 input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id);
16 return true; 16}
17 }
18 17
19 input_subsystem->GetTouchScreen()->ReleaseAllTouch(); 18void EmuWindow_Android::OnTouchMoved(int id, float x, float y) {
20 return true; 19 const auto [touch_x,touch_y]=MapToTouchScreen(x,y);
20 input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id);
21} 21}
22 22
23void EmuWindow_Android::OnTouchMoved(float x, float y) { 23void EmuWindow_Android::OnTouchReleased(int id) {
24 input_subsystem->GetTouchScreen()->TouchMoved(NormalizeX(x), NormalizeY(y), 0); 24 input_subsystem->GetTouchScreen()->TouchReleased(id);
25} 25}
26 26
27void EmuWindow_Android::OnGamepadEvent(int button_id, bool pressed) { 27void EmuWindow_Android::OnGamepadButtonEvent(int player_index, int button_id, bool pressed) {
28 input_subsystem->GetVirtualGamepad()->SetButtonState(0, button_id, pressed); 28 input_subsystem->GetVirtualGamepad()->SetButtonState(player_index, button_id, pressed);
29} 29}
30 30
31void EmuWindow_Android::OnGamepadMoveEvent(float x, float y) { 31void EmuWindow_Android::OnGamepadJoystickEvent(int player_index, int stick_id, float x, float y) {
32 input_subsystem->GetVirtualGamepad()->SetStickPosition( 32 input_subsystem->GetVirtualGamepad()->SetStickPosition(
33 0, InputCommon::VirtualGamepad::VirtualStick::Left, x, y); 33 player_index, stick_id, x, y);
34}
35
36void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x, float gyro_y,
37 float gyro_z, float accel_x, float accel_y,
38 float accel_z) {
39 // TODO:
40 // input_subsystem->GetVirtualGamepad()->SetMotionState(player_index, delta_timestamp, gyro_x, gyro_y,
41 // gyro_z, accel_x, accel_y, accel_z);
34} 42}
35 43
36EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_, 44EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_,
37 ANativeWindow* surface_) 45 ANativeWindow* surface_)
38 : input_subsystem{input_subsystem_} { 46 : input_subsystem{input_subsystem_} {
39 LOG_INFO(Frontend, "initializing"); 47 LOG_INFO(Frontend, "initializing");
40 48
41 if (!surface_) { 49 if (!surface_) {
diff --git a/src/android/app/src/main/jni/emu_window/emu_window.h b/src/android/app/src/main/jni/emu_window/emu_window.h
index 4af51c517..544924caa 100644
--- a/src/android/app/src/main/jni/emu_window/emu_window.h
+++ b/src/android/app/src/main/jni/emu_window/emu_window.h
@@ -19,10 +19,13 @@ public:
19 ~EmuWindow_Android(); 19 ~EmuWindow_Android();
20 20
21 void OnSurfaceChanged(ANativeWindow* surface); 21 void OnSurfaceChanged(ANativeWindow* surface);
22 bool OnTouchEvent(float x, float y, bool pressed); 22 void OnTouchPressed(int id, float x, float y);
23 void OnTouchMoved(float x, float y); 23 void OnTouchMoved(int id, float x, float y);
24 void OnGamepadEvent(int button, bool pressed); 24 void OnTouchReleased(int id);
25 void OnGamepadMoveEvent(float x, float y); 25 void OnGamepadButtonEvent(int player_index, int button_id, bool pressed);
26 void OnGamepadJoystickEvent(int player_index, int stick_id, float x, float y);
27 void OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x, float gyro_y,
28 float gyro_z, float accel_x, float accel_y, float accel_z);
26 void OnFrameDisplayed() override {} 29 void OnFrameDisplayed() override {}
27 30
28 std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override { 31 std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override {
@@ -33,14 +36,6 @@ public:
33 }; 36 };
34 37
35private: 38private:
36 float NormalizeX(float x) const {
37 return std::clamp(x / window_width, 0.f, 1.f);
38 }
39
40 float NormalizeY(float y) const {
41 return std::clamp(y / window_height, 0.f, 1.f);
42 }
43
44 InputCommon::InputSubsystem* input_subsystem{}; 39 InputCommon::InputSubsystem* input_subsystem{};
45 40
46 ANativeWindow* render_window{}; 41 ANativeWindow* render_window{};
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 2bd908308..0a2a65721 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -358,60 +358,55 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_IsRunning([[maybe_unused]] JNIEnv
358 return static_cast<jboolean>(EmulationSession::GetInstance().IsRunning()); 358 return static_cast<jboolean>(EmulationSession::GetInstance().IsRunning());
359} 359}
360 360
361jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadEvent([[maybe_unused]] JNIEnv* env, 361jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadButtonEvent([[maybe_unused]] JNIEnv* env,
362 [[maybe_unused]] jclass clazz, 362 [[maybe_unused]] jclass clazz,
363 [[maybe_unused]] jstring j_device, 363 [[maybe_unused]] jint j_device,
364 jint j_button, jint action) { 364 jint j_button, jint action) {
365 if (EmulationSession::GetInstance().IsRunning()) { 365 if (EmulationSession::GetInstance().IsRunning()) {
366 EmulationSession::GetInstance().Window().OnGamepadEvent(j_button, action != 0); 366 EmulationSession::GetInstance().Window().OnGamepadButtonEvent(j_device,j_button, action != 0);
367 } 367 }
368 return static_cast<jboolean>(true); 368 return static_cast<jboolean>(true);
369} 369}
370 370
371jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadMoveEvent([[maybe_unused]] JNIEnv* env, 371jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadJoystickEvent([[maybe_unused]] JNIEnv* env,
372 [[maybe_unused]] jclass clazz, 372 [[maybe_unused]] jclass clazz,
373 jstring j_device, jint axis, 373 jint j_device, jint stick_id,
374 jfloat x, jfloat y) { 374 jfloat x, jfloat y) {
375 // Clamp joystick movement to supported minimum and maximum.
376 x = std::clamp(x, -1.f, 1.f);
377 y = std::clamp(-y, -1.f, 1.f);
378
379 // Clamp the input to a circle.
380 float r = x * x + y * y;
381 if (r > 1.0f) {
382 r = std::sqrt(r);
383 x /= r;
384 y /= r;
385 }
386
387 if (EmulationSession::GetInstance().IsRunning()) { 375 if (EmulationSession::GetInstance().IsRunning()) {
388 EmulationSession::GetInstance().Window().OnGamepadMoveEvent(x, y); 376 EmulationSession::GetInstance().Window().OnGamepadJoystickEvent(j_device,stick_id, x, y);
389 } 377 }
390 return static_cast<jboolean>(false); 378 return static_cast<jboolean>(true);
391} 379}
392 380
393jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadAxisEvent([[maybe_unused]] JNIEnv* env, 381jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadMotionEvent([[maybe_unused]] JNIEnv* env,
394 [[maybe_unused]] jclass clazz, 382 [[maybe_unused]] jclass clazz, jint j_device,jlong delta_timestamp, jfloat gyro_x, jfloat gyro_y,
395 jstring j_device, jint axis_id, 383 jfloat gyro_z, jfloat accel_x, jfloat accel_y, jfloat accel_z){
396 jfloat axis_val) { 384 if (EmulationSession::GetInstance().IsRunning()) {
397 return {}; 385 EmulationSession::GetInstance().Window().OnGamepadMotionEvent(j_device,delta_timestamp, gyro_x, gyro_y,gyro_z,accel_x,accel_y,accel_z);
386 }
387 return static_cast<jboolean>(true);
398} 388}
399 389
400jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchEvent([[maybe_unused]] JNIEnv* env, 390void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchPressed([[maybe_unused]] JNIEnv* env,
401 [[maybe_unused]] jclass clazz, jfloat x, 391 [[maybe_unused]] jclass clazz, jint id, jfloat x,
402 jfloat y, jboolean pressed) { 392 jfloat y) {
403 if (EmulationSession::GetInstance().IsRunning()) { 393 if (EmulationSession::GetInstance().IsRunning()) {
404 return static_cast<jboolean>( 394 EmulationSession::GetInstance().Window().OnTouchPressed(id, x, y);
405 EmulationSession::GetInstance().Window().OnTouchEvent(x, y, pressed));
406 } 395 }
407 return static_cast<jboolean>(false);
408} 396}
409 397
410void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchMoved([[maybe_unused]] JNIEnv* env, 398void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchMoved([[maybe_unused]] JNIEnv* env,
411 [[maybe_unused]] jclass clazz, jfloat x, 399 [[maybe_unused]] jclass clazz, jint id, jfloat x,
412 jfloat y) { 400 jfloat y) {
413 if (EmulationSession::GetInstance().IsRunning()) { 401 if (EmulationSession::GetInstance().IsRunning()) {
414 EmulationSession::GetInstance().Window().OnTouchMoved(x, y); 402 EmulationSession::GetInstance().Window().OnTouchMoved(id, x, y);
403 }
404}
405
406void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchReleased([[maybe_unused]] JNIEnv* env,
407 [[maybe_unused]] jclass clazz, jint id) {
408 if (EmulationSession::GetInstance().IsRunning()) {
409 EmulationSession::GetInstance().Window().OnTouchReleased(id);
415 } 410 }
416} 411}
417 412