Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve touchpad and mouse support for the Android editor #77498

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,10 @@ public void onPointerCaptureChange(boolean hasCapture) {

@Override
public void requestPointerCapture() {
super.requestPointerCapture();
inputHandler.onPointerCaptureChange(true);
if (canCapturePointer()) {
super.requestPointerCapture();
inputHandler.onPointerCaptureChange(true);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,8 @@ public interface GodotRenderView {
void configurePointerIcon(int pointerType, String imagePath, float hotSpotX, float hotSpotY);

void setPointerIcon(int pointerType);

default boolean canCapturePointer() {
return getInputHandler().canCapturePointer();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,10 @@ public boolean onCapturedPointerEvent(MotionEvent event) {

@Override
public void requestPointerCapture() {
super.requestPointerCapture();
mInputHandler.onPointerCaptureChange(true);
if (canCapturePointer()) {
super.requestPointerCapture();
mInputHandler.onPointerCaptureChange(true);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,16 +227,14 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
)
dragInProgress = false
}
return true
}

dragInProgress = true

val x = terminusEvent.x
val y = terminusEvent.y
if (terminusEvent.pointerCount >= 2 && panningAndScalingEnabled && !pointerCaptureInProgress) {
GodotLib.pan(x, y, distanceX / 5f, distanceY / 5f)
} else {
} else if (!scaleInProgress){
dragInProgress = true
GodotInputHandler.handleMotionEvent(terminusEvent)
}
return true
Expand All @@ -246,11 +244,14 @@ internal class GodotGestureHandler : SimpleOnGestureListener(), OnScaleGestureLi
if (!panningAndScalingEnabled || pointerCaptureInProgress) {
return false
}
GodotLib.magnify(
detector.focusX,
detector.focusY,
detector.scaleFactor
)

if (detector.scaleFactor >= 0.8f && detector.scaleFactor != 1f && detector.scaleFactor <= 1.2f) {
GodotLib.magnify(
detector.focusX,
detector.focusY,
detector.scaleFactor
)
}
return true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public class GodotInputHandler implements InputManager.InputDeviceListener {
private final ScaleGestureDetector scaleGestureDetector;
private final GodotGestureHandler godotGestureHandler;

/**
* Used to decide whether mouse capture can be enabled.
*/
private int lastSeenToolType = MotionEvent.TOOL_TYPE_UNKNOWN;

public GodotInputHandler(GodotRenderView godotView) {
final Context context = godotView.getView().getContext();
mRenderView = godotView;
Expand Down Expand Up @@ -105,6 +110,10 @@ private boolean isKeyEventGameDevice(int source) {
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) {
godotGestureHandler.onPointerCaptureChange(hasCapture);
}
Expand Down Expand Up @@ -174,6 +183,8 @@ public boolean onKeyDown(final int keyCode, KeyEvent event) {
}

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.
Expand All @@ -198,6 +209,8 @@ public boolean onTouchEvent(final MotionEvent event) {
}

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;
Expand Down Expand Up @@ -471,15 +484,27 @@ static boolean handleMouseEvent(int eventAction, int buttonsMask, float x, float
}

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:
Expand Down
13 changes: 12 additions & 1 deletion platform/android/java_godot_view_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,25 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_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 GodotJavaViewWrapper::can_update_pointer_icon() const {
return _configure_pointer_icon != nullptr && _set_pointer_icon != nullptr;
}

bool GodotJavaViewWrapper::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 GodotView#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 GodotJavaViewWrapper::request_pointer_capture() {
Expand Down
1 change: 1 addition & 0 deletions platform/android/java_godot_view_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class GodotJavaViewWrapper {

jobject _godot_view;

jmethodID _can_capture_pointer = 0;
jmethodID _request_pointer_capture = 0;
jmethodID _release_pointer_capture = 0;

Expand Down