diff --git a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt index 23dcddc78..59d172005 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt @@ -97,42 +97,82 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex return onTouchWhileEditing(event) } - var hasActiveButtons = false val pointerIndex = event.actionIndex val pointerId = event.getPointerId(pointerIndex) + + val xPosition = event.getX(pointerIndex).toInt() + val yPosition = event.getY(pointerIndex).toInt() + val motionEvent = event.action and MotionEvent.ACTION_MASK + val isActionDown = + motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN + val isActionMove = motionEvent == MotionEvent.ACTION_MOVE + val isActionUp = + motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP + + var hasActiveButtons = false + var isAnyButtonSliding = false for (button in overlayButtons) { if (button.trackId == pointerId) { hasActiveButtons = true - break + } + if (button.isButtonSliding) { + if (isActionUp) { + // A touch event ended, so tell any buttons tracking sliding to stop + button.isButtonSliding = false + } else { + isAnyButtonSliding = true + } } } var hasActiveDpad = false - if (!hasActiveButtons) { - for (dpad in overlayDpads) { - if (dpad.trackId == pointerId) { - hasActiveDpad = true - break - } + for (dpad in overlayDpads) { + if (dpad.trackId == pointerId) { + hasActiveDpad = true + break } } var hasActiveJoystick = false - if(!hasActiveButtons && !hasActiveDpad){ - for (joystick in overlayJoysticks) { - if (joystick.trackId == pointerId) { - hasActiveJoystick = true - break - } + for (joystick in overlayJoysticks) { + if (joystick.trackId == pointerId) { + hasActiveJoystick = true + break } } var shouldUpdateView = false + + if (!preferences.getBoolean("isTouchEnabled", true)) { + return true + } + + if (isActionMove) { + var noneConsumed = true + for (i in 0 until event.pointerCount) { + val fingerId = event.getPointerId(i) + if (isTouchInputConsumed(fingerId)) { + noneConsumed = false + continue + } + NativeLibrary.onTouchMoved(xPosition.toFloat(), yPosition.toFloat()) + } + + if (noneConsumed && !isAnyButtonSliding) { + return true + } + } + if (isActionUp && !isTouchInputConsumed(pointerId)) { + NativeLibrary.onTouchEvent(0f, 0f, false) + } + + var anyStateChanged = false if(!hasActiveDpad && !hasActiveJoystick) { for (button in overlayButtons) { val stateChanged = button.updateStatus(event, hasActiveButtons, this) if (!stateChanged) { continue } + anyStateChanged = true if (button.id == NativeLibrary.ButtonType.BUTTON_SWAP && button.status == NativeLibrary.ButtonState.PRESSED) { swapScreen() @@ -162,6 +202,7 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex if (!stateChanged) { continue } + anyStateChanged = true NativeLibrary.onGamePadEvent( NativeLibrary.TouchScreenDevice, @@ -188,56 +229,32 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex } } - if(!hasActiveDpad && !hasActiveButtons) { - for (joystick in overlayJoysticks) { - val stateChanged = joystick.updateStatus(event, hasActiveJoystick, this) - if (!stateChanged) { - continue - } - - val axisID = joystick.joystickId - NativeLibrary.onGamePadMoveEvent( - NativeLibrary.TouchScreenDevice, - axisID, - joystick.xAxis, - joystick.yAxis - ) - - shouldUpdateView = true + for (joystick in overlayJoysticks) { + val stateChanged = joystick.updateStatus(event, true, this) + if (!stateChanged) { + continue } + anyStateChanged = true + + val axisID = joystick.joystickId + NativeLibrary.onGamePadMoveEvent( + NativeLibrary.TouchScreenDevice, + axisID, + joystick.xAxis, + joystick.yAxis + ) + + shouldUpdateView = true } if (shouldUpdateView) { invalidate() } - if (!preferences.getBoolean("isTouchEnabled", true)) { - return true - } - - val xPosition = event.getX(pointerIndex).toInt() - val yPosition = event.getY(pointerIndex).toInt() - val motionEvent = event.action and MotionEvent.ACTION_MASK - val isActionDown = - motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN - val isActionMove = motionEvent == MotionEvent.ACTION_MOVE - val isActionUp = - motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP - if (isActionDown && !isTouchInputConsumed(pointerId)) { + if (!anyStateChanged && isActionDown && !isTouchInputConsumed(pointerId)) { NativeLibrary.onTouchEvent(xPosition.toFloat(), yPosition.toFloat(), true) } - if (isActionMove) { - for (i in 0 until event.pointerCount) { - val fingerId = event.getPointerId(i) - if (isTouchInputConsumed(fingerId)) { - continue - } - NativeLibrary.onTouchMoved(xPosition.toFloat(), yPosition.toFloat()) - } - } - if (isActionUp && !isTouchInputConsumed(pointerId)) { - NativeLibrary.onTouchEvent(0f, 0f, false) - } + return true } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableButton.kt b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableButton.kt index 0e9b0185d..ffb0b6b41 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableButton.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableButton.kt @@ -44,6 +44,7 @@ class InputOverlayDrawableButton( val opacity: Int ) { var trackId: Int + var isButtonSliding: Boolean private var isMotionFirstButton = false // mark the first activated button with the current motion @@ -61,6 +62,7 @@ class InputOverlayDrawableButton( this.defaultStateBitmap = BitmapDrawable(res, defaultStateBitmap) this.pressedStateBitmap = BitmapDrawable(res, pressedStateBitmap) trackId = -1 + isButtonSliding = false width = this.defaultStateBitmap.intrinsicWidth height = this.defaultStateBitmap.intrinsicHeight } @@ -92,7 +94,7 @@ class InputOverlayDrawableButton( if (trackId != pointerId) { return false } - buttonUp(overlay) + buttonUp(overlay, false) return true } @@ -109,7 +111,7 @@ class InputOverlayDrawableButton( if (buttonSliding == ButtonSlidingMode.Alternative.int && isMotionFirstButton) { return false } - buttonUp(overlay) + buttonUp(overlay, true) return true } else { // button was not yet pressed @@ -132,10 +134,11 @@ class InputOverlayDrawableButton( overlay.hapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) } - private fun buttonUp(overlay: InputOverlay) { + private fun buttonUp(overlay: InputOverlay, _isButtonSliding: Boolean) { pressedState = false isMotionFirstButton = false trackId = -1 + isButtonSliding = _isButtonSliding overlay.hapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE) }