android: Hook jni input properly
This commit is contained in:
parent
5b80dee181
commit
92fb7cc4e4
5 changed files with 105 additions and 91 deletions
|
@ -42,9 +42,17 @@ import static android.Manifest.permission.RECORD_AUDIO;
|
||||||
*/
|
*/
|
||||||
public final class NativeLibrary {
|
public final class NativeLibrary {
|
||||||
/**
|
/**
|
||||||
* Default touchscreen device
|
* Default controller id for each device
|
||||||
*/
|
*/
|
||||||
public static final String TouchScreenDevice = "Touchscreen";
|
public static final int Player1Device = 0;
|
||||||
|
public static final int Player2Device = 1;
|
||||||
|
public static final int Player3Device = 2;
|
||||||
|
public static final int Player4Device = 3;
|
||||||
|
public static final int Player5Device = 4;
|
||||||
|
public static final int Player6Device = 5;
|
||||||
|
public static final int Player7Device = 6;
|
||||||
|
public static final int Player8Device = 7;
|
||||||
|
public static final int ConsoleDevice = 8;
|
||||||
public static WeakReference<EmulationActivity> sEmulationActivity = new WeakReference<>(null);
|
public static WeakReference<EmulationActivity> sEmulationActivity = new WeakReference<>(null);
|
||||||
|
|
||||||
private static boolean alertResult = false;
|
private static boolean alertResult = false;
|
||||||
|
@ -90,36 +98,37 @@ public final class NativeLibrary {
|
||||||
* @param Action Mask identifying which action is happening (button pressed down, or button released).
|
* @param Action Mask identifying which action is happening (button pressed down, or button released).
|
||||||
* @return If we handled the button press.
|
* @return If we handled the button press.
|
||||||
*/
|
*/
|
||||||
public static native boolean onGamePadEvent(String Device, int Button, int Action);
|
public static native boolean onGamePadButtonEvent(int Device, int Button, int Action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles gamepad movement events.
|
* Handles joystick movement events.
|
||||||
*
|
*
|
||||||
* @param Device The device ID of the gamepad.
|
* @param Device The device ID of the gamepad.
|
||||||
* @param Axis The axis ID
|
* @param Axis The axis ID
|
||||||
* @param x_axis The value of the x-axis represented by the given ID.
|
* @param x_axis The value of the x-axis represented by the given ID.
|
||||||
* @param y_axis The value of the y-axis represented by the given ID
|
* @param y_axis The value of the y-axis represented by the given ID.
|
||||||
*/
|
*/
|
||||||
public static native boolean onGamePadMoveEvent(String Device, int Axis, float x_axis, float y_axis);
|
public static native boolean onGamePadJoystickEvent(int Device, int Axis, float x_axis, float y_axis);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles gamepad movement events.
|
* Handles motion events.
|
||||||
*
|
*
|
||||||
* @param Device The device ID of the gamepad.
|
* @param delta_timestamp The finger id corresponding to this event
|
||||||
* @param Axis_id The axis ID
|
* @param gyro_x,gyro_y,gyro_z The value of the accelerometer sensor.
|
||||||
* @param axis_val The value of the axis represented by the given ID.
|
* @param accel_x,accel_y,accel_z The value of the y-axis
|
||||||
*/
|
*/
|
||||||
public static native boolean onGamePadAxisEvent(String Device, int Axis_id, float axis_val);
|
|
||||||
|
public static native boolean onGamePadMotionEvent(int Device, long delta_timestamp, float gyro_x, float gyro_y,
|
||||||
|
float gyro_z, float accel_x, float accel_y, float accel_z);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles touch events.
|
* Handles touch press events.
|
||||||
*
|
*
|
||||||
|
* @param finger_id The finger id corresponding to this event
|
||||||
* @param x_axis The value of the x-axis.
|
* @param x_axis The value of the x-axis.
|
||||||
* @param y_axis The value of the y-axis
|
* @param y_axis The value of the y-axis.
|
||||||
* @param pressed To identify if the touch held down or released.
|
|
||||||
* @return true if the pointer is within the touchscreen
|
|
||||||
*/
|
*/
|
||||||
public static native boolean onTouchEvent(float x_axis, float y_axis, boolean pressed);
|
public static native void onTouchPressed(int finger_id, float x_axis, float y_axis);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles touch movement.
|
* Handles touch movement.
|
||||||
|
@ -127,7 +136,14 @@ public final class NativeLibrary {
|
||||||
* @param x_axis The value of the instantaneous x-axis.
|
* @param x_axis The value of the instantaneous x-axis.
|
||||||
* @param y_axis The value of the instantaneous y-axis.
|
* @param y_axis The value of the instantaneous y-axis.
|
||||||
*/
|
*/
|
||||||
public static native void onTouchMoved(float x_axis, float y_axis);
|
public static native void onTouchMoved(int finger_id, float x_axis, float y_axis);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles touch release events.
|
||||||
|
*
|
||||||
|
* @param finger_id The finger id corresponding to this event
|
||||||
|
*/
|
||||||
|
public static native void onTouchReleased(int finger_id);
|
||||||
|
|
||||||
public static native void ReloadSettings();
|
public static native void ReloadSettings();
|
||||||
|
|
||||||
|
|
|
@ -345,17 +345,17 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
|
||||||
if (!button.updateStatus(event)) {
|
if (!button.updateStatus(event)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), button.getStatus());
|
NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, button.getId(), button.getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (InputOverlayDrawableDpad dpad : overlayDpads) {
|
for (InputOverlayDrawableDpad dpad : overlayDpads) {
|
||||||
if (!dpad.updateStatus(event, EmulationMenuSettings.getDpadSlideEnable())) {
|
if (!dpad.updateStatus(event, EmulationMenuSettings.getDpadSlideEnable())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getUpId(), dpad.getUpStatus());
|
NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, dpad.getUpId(), dpad.getUpStatus());
|
||||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getDownId(), dpad.getDownStatus());
|
NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, dpad.getDownId(), dpad.getDownStatus());
|
||||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getLeftId(), dpad.getLeftStatus());
|
NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, dpad.getLeftId(), dpad.getLeftStatus());
|
||||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getRightId(), dpad.getRightStatus());
|
NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, dpad.getRightId(), dpad.getRightStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (InputOverlayDrawableJoystick joystick : overlayJoysticks) {
|
for (InputOverlayDrawableJoystick joystick : overlayJoysticks) {
|
||||||
|
@ -363,8 +363,8 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int axisID = joystick.getJoystickId();
|
int axisID = joystick.getJoystickId();
|
||||||
NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisID, joystick.getXAxis(), joystick.getYAxis());
|
NativeLibrary.onGamePadJoystickEvent(NativeLibrary.Player1Device, axisID, joystick.getXAxis(), joystick.getYAxis());
|
||||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, joystick.getButtonId(), joystick.getButtonStatus());
|
NativeLibrary.onGamePadButtonEvent(NativeLibrary.Player1Device, joystick.getButtonId(), joystick.getButtonStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mPreferences.getBoolean("isTouchEnabled", true)) {
|
if (!mPreferences.getBoolean("isTouchEnabled", true)) {
|
||||||
|
@ -381,7 +381,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
|
||||||
boolean isActionUp = motion_event == MotionEvent.ACTION_UP || motion_event == MotionEvent.ACTION_POINTER_UP;
|
boolean isActionUp = motion_event == MotionEvent.ACTION_UP || motion_event == MotionEvent.ACTION_POINTER_UP;
|
||||||
|
|
||||||
if (isActionDown && !isTouchInputConsumed(pointerId)) {
|
if (isActionDown && !isTouchInputConsumed(pointerId)) {
|
||||||
NativeLibrary.onTouchEvent(xPosition, yPosition, true);
|
NativeLibrary.onTouchPressed(pointerId, xPosition, yPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isActionMove) {
|
if (isActionMove) {
|
||||||
|
@ -390,12 +390,12 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
|
||||||
if (isTouchInputConsumed(fingerId)) {
|
if (isTouchInputConsumed(fingerId)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
NativeLibrary.onTouchMoved(event.getX(i), event.getY(i));
|
NativeLibrary.onTouchMoved(fingerId, event.getX(i), event.getY(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isActionUp && !isTouchInputConsumed(pointerId)) {
|
if (isActionUp && !isTouchInputConsumed(pointerId)) {
|
||||||
NativeLibrary.onTouchEvent(xPosition, yPosition, false);
|
NativeLibrary.onTouchReleased(pointerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
|
|
|
@ -10,27 +10,35 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||||
render_window = surface;
|
render_window = surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmuWindow_Android::OnTouchEvent(float x, float y, bool pressed) {
|
void EmuWindow_Android::OnTouchPressed(int id, float x, float y) {
|
||||||
if (pressed) {
|
const auto [touch_x,touch_y]=MapToTouchScreen(x,y);
|
||||||
input_subsystem->GetTouchScreen()->TouchPressed(NormalizeX(x), NormalizeY(y), 0);
|
input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
input_subsystem->GetTouchScreen()->ReleaseAllTouch();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::OnTouchMoved(float x, float y) {
|
void EmuWindow_Android::OnTouchMoved(int id, float x, float y) {
|
||||||
input_subsystem->GetTouchScreen()->TouchMoved(NormalizeX(x), NormalizeY(y), 0);
|
const auto [touch_x,touch_y]=MapToTouchScreen(x,y);
|
||||||
|
input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::OnGamepadEvent(int button_id, bool pressed) {
|
void EmuWindow_Android::OnTouchReleased(int id) {
|
||||||
input_subsystem->GetVirtualGamepad()->SetButtonState(0, button_id, pressed);
|
input_subsystem->GetTouchScreen()->TouchReleased(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::OnGamepadMoveEvent(float x, float y) {
|
void EmuWindow_Android::OnGamepadButtonEvent(int player_index, int button_id, bool pressed) {
|
||||||
|
input_subsystem->GetVirtualGamepad()->SetButtonState(player_index, button_id, pressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuWindow_Android::OnGamepadJoystickEvent(int player_index, int stick_id, float x, float y) {
|
||||||
input_subsystem->GetVirtualGamepad()->SetStickPosition(
|
input_subsystem->GetVirtualGamepad()->SetStickPosition(
|
||||||
0, InputCommon::VirtualGamepad::VirtualStick::Left, x, y);
|
player_index, stick_id, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x, float gyro_y,
|
||||||
|
float gyro_z, float accel_x, float accel_y,
|
||||||
|
float accel_z) {
|
||||||
|
// TODO:
|
||||||
|
// input_subsystem->GetVirtualGamepad()->SetMotionState(player_index, delta_timestamp, gyro_x, gyro_y,
|
||||||
|
// gyro_z, accel_x, accel_y, accel_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_,
|
EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_,
|
||||||
|
|
|
@ -19,10 +19,13 @@ public:
|
||||||
~EmuWindow_Android();
|
~EmuWindow_Android();
|
||||||
|
|
||||||
void OnSurfaceChanged(ANativeWindow* surface);
|
void OnSurfaceChanged(ANativeWindow* surface);
|
||||||
bool OnTouchEvent(float x, float y, bool pressed);
|
void OnTouchPressed(int id, float x, float y);
|
||||||
void OnTouchMoved(float x, float y);
|
void OnTouchMoved(int id, float x, float y);
|
||||||
void OnGamepadEvent(int button, bool pressed);
|
void OnTouchReleased(int id);
|
||||||
void OnGamepadMoveEvent(float x, float y);
|
void OnGamepadButtonEvent(int player_index, int button_id, bool pressed);
|
||||||
|
void OnGamepadJoystickEvent(int player_index, int stick_id, float x, float y);
|
||||||
|
void OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x, float gyro_y,
|
||||||
|
float gyro_z, float accel_x, float accel_y, float accel_z);
|
||||||
void OnFrameDisplayed() override {}
|
void OnFrameDisplayed() override {}
|
||||||
|
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override {
|
std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override {
|
||||||
|
@ -33,14 +36,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float NormalizeX(float x) const {
|
|
||||||
return std::clamp(x / window_width, 0.f, 1.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
float NormalizeY(float y) const {
|
|
||||||
return std::clamp(y / window_height, 0.f, 1.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
InputCommon::InputSubsystem* input_subsystem{};
|
InputCommon::InputSubsystem* input_subsystem{};
|
||||||
|
|
||||||
ANativeWindow* render_window{};
|
ANativeWindow* render_window{};
|
||||||
|
|
|
@ -358,60 +358,55 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_IsRunning([[maybe_unused]] JNIEnv
|
||||||
return static_cast<jboolean>(EmulationSession::GetInstance().IsRunning());
|
return static_cast<jboolean>(EmulationSession::GetInstance().IsRunning());
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadEvent([[maybe_unused]] JNIEnv* env,
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadButtonEvent([[maybe_unused]] JNIEnv* env,
|
||||||
[[maybe_unused]] jclass clazz,
|
[[maybe_unused]] jclass clazz,
|
||||||
[[maybe_unused]] jstring j_device,
|
[[maybe_unused]] jint j_device,
|
||||||
jint j_button, jint action) {
|
jint j_button, jint action) {
|
||||||
if (EmulationSession::GetInstance().IsRunning()) {
|
if (EmulationSession::GetInstance().IsRunning()) {
|
||||||
EmulationSession::GetInstance().Window().OnGamepadEvent(j_button, action != 0);
|
EmulationSession::GetInstance().Window().OnGamepadButtonEvent(j_device,j_button, action != 0);
|
||||||
}
|
}
|
||||||
return static_cast<jboolean>(true);
|
return static_cast<jboolean>(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadMoveEvent([[maybe_unused]] JNIEnv* env,
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadJoystickEvent([[maybe_unused]] JNIEnv* env,
|
||||||
[[maybe_unused]] jclass clazz,
|
[[maybe_unused]] jclass clazz,
|
||||||
jstring j_device, jint axis,
|
jint j_device, jint stick_id,
|
||||||
jfloat x, jfloat y) {
|
jfloat x, jfloat y) {
|
||||||
// Clamp joystick movement to supported minimum and maximum.
|
|
||||||
x = std::clamp(x, -1.f, 1.f);
|
|
||||||
y = std::clamp(-y, -1.f, 1.f);
|
|
||||||
|
|
||||||
// Clamp the input to a circle.
|
|
||||||
float r = x * x + y * y;
|
|
||||||
if (r > 1.0f) {
|
|
||||||
r = std::sqrt(r);
|
|
||||||
x /= r;
|
|
||||||
y /= r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EmulationSession::GetInstance().IsRunning()) {
|
if (EmulationSession::GetInstance().IsRunning()) {
|
||||||
EmulationSession::GetInstance().Window().OnGamepadMoveEvent(x, y);
|
EmulationSession::GetInstance().Window().OnGamepadJoystickEvent(j_device,stick_id, x, y);
|
||||||
}
|
}
|
||||||
return static_cast<jboolean>(false);
|
return static_cast<jboolean>(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadAxisEvent([[maybe_unused]] JNIEnv* env,
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadMotionEvent([[maybe_unused]] JNIEnv* env,
|
||||||
[[maybe_unused]] jclass clazz,
|
[[maybe_unused]] jclass clazz, jint j_device,jlong delta_timestamp, jfloat gyro_x, jfloat gyro_y,
|
||||||
jstring j_device, jint axis_id,
|
jfloat gyro_z, jfloat accel_x, jfloat accel_y, jfloat accel_z){
|
||||||
jfloat axis_val) {
|
if (EmulationSession::GetInstance().IsRunning()) {
|
||||||
return {};
|
EmulationSession::GetInstance().Window().OnGamepadMotionEvent(j_device,delta_timestamp, gyro_x, gyro_y,gyro_z,accel_x,accel_y,accel_z);
|
||||||
|
}
|
||||||
|
return static_cast<jboolean>(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchEvent([[maybe_unused]] JNIEnv* env,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchPressed([[maybe_unused]] JNIEnv* env,
|
||||||
[[maybe_unused]] jclass clazz, jfloat x,
|
[[maybe_unused]] jclass clazz, jint id, jfloat x,
|
||||||
jfloat y, jboolean pressed) {
|
jfloat y) {
|
||||||
if (EmulationSession::GetInstance().IsRunning()) {
|
if (EmulationSession::GetInstance().IsRunning()) {
|
||||||
return static_cast<jboolean>(
|
EmulationSession::GetInstance().Window().OnTouchPressed(id, x, y);
|
||||||
EmulationSession::GetInstance().Window().OnTouchEvent(x, y, pressed));
|
|
||||||
}
|
}
|
||||||
return static_cast<jboolean>(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchMoved([[maybe_unused]] JNIEnv* env,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchMoved([[maybe_unused]] JNIEnv* env,
|
||||||
[[maybe_unused]] jclass clazz, jfloat x,
|
[[maybe_unused]] jclass clazz, jint id, jfloat x,
|
||||||
jfloat y) {
|
jfloat y) {
|
||||||
if (EmulationSession::GetInstance().IsRunning()) {
|
if (EmulationSession::GetInstance().IsRunning()) {
|
||||||
EmulationSession::GetInstance().Window().OnTouchMoved(x, y);
|
EmulationSession::GetInstance().Window().OnTouchMoved(id, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchReleased([[maybe_unused]] JNIEnv* env,
|
||||||
|
[[maybe_unused]] jclass clazz, jint id) {
|
||||||
|
if (EmulationSession::GetInstance().IsRunning()) {
|
||||||
|
EmulationSession::GetInstance().Window().OnTouchReleased(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue