Ported: Improve touchpad and mouse support for the Android editor

- m4gr3d
ccd36e0dbe
This commit is contained in:
Relintai 2023-06-11 13:29:53 +02:00
parent de059c33bc
commit d7499a0868
5 changed files with 60 additions and 15 deletions

View File

@ -138,8 +138,15 @@ public class PandemoniumView extends PandemoniumGLSurfaceView {
@Override
public void onPointerCaptureChange(boolean hasCapture) {
super.onPointerCaptureChange(hasCapture);
inputHandler.onPointerCaptureChange(hasCapture);
if (canCapturePointer()) {
super.onPointerCaptureChange(hasCapture);
inputHandler.onPointerCaptureChange(hasCapture);
}
}
@Keep
private boolean canCapturePointer() {
return inputHandler.canCapturePointer();
}
@Override

View File

@ -227,18 +227,16 @@ internal class PandemoniumGestureHandler : SimpleOnGestureListener(), OnScaleGes
)
dragInProgress = false
}
return true
}
dragInProgress = true
val x = terminusEvent.x
val y = terminusEvent.y
if (terminusEvent.pointerCount >= 2 && panningAndScalingEnabled && !pointerCaptureInProgress) {
PandemoniumLib.pan(x, y, distanceX / 5f, distanceY / 5f)
} else {
} else if (!scaleInProgress) {
PandemoniumInputHandler.handleMotionEvent(terminusEvent)
}
return true
}
@ -246,11 +244,14 @@ internal class PandemoniumGestureHandler : SimpleOnGestureListener(), OnScaleGes
if (!panningAndScalingEnabled || pointerCaptureInProgress) {
return false
}
PandemoniumLib.magnify(
detector.focusX,
detector.focusY,
detector.scaleFactor
)
if (detector.scaleFactor >= 0.8f && detector.scaleFactor != 1f && detector.scaleFactor <= 1.2f) {
PandemoniumLib.magnify(
detector.focusX,
detector.focusY,
detector.scaleFactor
)
}
return true
}

View File

@ -66,6 +66,11 @@ public class PandemoniumInputHandler implements InputManager.InputDeviceListener
private final ScaleGestureDetector scaleGestureDetector;
private final PandemoniumGestureHandler pandemoniumGestureHandler;
/**
* Used to decide whether mouse capture can be enabled.
*/
private int lastSeenToolType = MotionEvent.TOOL_TYPE_UNKNOWN;
public PandemoniumInputHandler(PandemoniumView pandemoniumView) {
final Context context = pandemoniumView.getContext();
this.pandemoniumView = pandemoniumView;
@ -105,6 +110,10 @@ public class PandemoniumInputHandler implements InputManager.InputDeviceListener
return (source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK || (source & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD || (source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD;
}
public boolean canCapturePointer() {
return lastSeenToolType == MotionEvent.TOOL_TYPE_MOUSE;
}
public void onPointerCaptureChange(boolean hasCapture) {
pandemoniumGestureHandler.onPointerCaptureChange(hasCapture);
}
@ -176,6 +185,8 @@ public class PandemoniumInputHandler implements InputManager.InputDeviceListener
}
public boolean onTouchEvent(final MotionEvent event) {
lastSeenToolType = event.getToolType(0);
this.scaleGestureDetector.onTouchEvent(event);
if (this.gestureDetector.onTouchEvent(event)) {
// The gesture detector has handled the event.
@ -200,6 +211,8 @@ public class PandemoniumInputHandler implements InputManager.InputDeviceListener
}
public boolean onGenericMotionEvent(MotionEvent event) {
lastSeenToolType = event.getToolType(0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && gestureDetector.onGenericMotionEvent(event)) {
// The gesture detector has handled the event.
return true;
@ -479,15 +492,27 @@ public class PandemoniumInputHandler implements InputManager.InputDeviceListener
}
static boolean handleMouseEvent(int eventAction, int buttonsMask, float x, float y, float deltaX, float deltaY, boolean doubleClick, boolean sourceMouseRelative) {
// Fix the buttonsMask
switch (eventAction) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// Zero-up the button state
buttonsMask = 0;
break;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (buttonsMask == 0) {
buttonsMask = MotionEvent.BUTTON_PRIMARY;
}
break;
}
// We don't handle ACTION_BUTTON_PRESS and ACTION_BUTTON_RELEASE events as they typically
// follow ACTION_DOWN and ACTION_UP events. As such, handling them would result in duplicate
// stream of events to the engine.
switch (eventAction) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// Zero-up the button state
buttonsMask = 0;
// FALL THROUGH
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_HOVER_ENTER:
case MotionEvent.ACTION_HOVER_EXIT:

View File

@ -47,6 +47,8 @@ PandemoniumJavaViewWrapper::PandemoniumJavaViewWrapper(jobject pandemonium_view)
_request_pointer_capture = env->GetMethodID(_cls, "requestPointerCapture", "()V");
_release_pointer_capture = env->GetMethodID(_cls, "releasePointerCapture", "()V");
}
_can_capture_pointer = env->GetMethodID(_cls, "canCapturePointer", "()Z");
}
bool PandemoniumJavaViewWrapper::can_update_pointer_icon() const {
@ -54,7 +56,16 @@ bool PandemoniumJavaViewWrapper::can_update_pointer_icon() const {
}
bool PandemoniumJavaViewWrapper::can_capture_pointer() const {
return _request_pointer_capture != nullptr && _release_pointer_capture != nullptr;
// We can capture the pointer if the other jni capture method ids are initialized,
// and PandemoniumView#canCapturePointer() returns true.
if (_request_pointer_capture != nullptr && _release_pointer_capture != nullptr && _can_capture_pointer != nullptr) {
JNIEnv *env = get_jni_env();
ERR_FAIL_NULL_V(env, false);
return env->CallBooleanMethod(_godot_view, _can_capture_pointer);
}
return false;
}
void PandemoniumJavaViewWrapper::request_pointer_capture() {

View File

@ -44,6 +44,7 @@ private:
jclass _cls;
jobject _pandemonium_view;
jmethodID _can_capture_pointer = 0;
jmethodID _request_pointer_capture = 0;
jmethodID _release_pointer_capture = 0;