diff options
Diffstat (limited to 'platform/android/java/lib/src')
6 files changed, 106 insertions, 30 deletions
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java index bc7234e2ad..b465377743 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java @@ -166,8 +166,10 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView @Override public void requestPointerCapture() { - super.requestPointerCapture(); - inputHandler.onPointerCaptureChange(true); + if (canCapturePointer()) { + super.requestPointerCapture(); + inputHandler.onPointerCaptureChange(true); + } } @Override diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java index 02c0d67fff..00243dab2a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java @@ -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(); + } } diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java index 5439f55b25..681e182adb 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java @@ -134,8 +134,10 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV @Override public void requestPointerCapture() { - super.requestPointerCapture(); - mInputHandler.onPointerCaptureChange(true); + if (canCapturePointer()) { + super.requestPointerCapture(); + mInputHandler.onPointerCaptureChange(true); + } } @Override diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt index 7dc5fb6f83..e9bc435689 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.kt @@ -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 @@ -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 } diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java index cedbbfb7c3..317344f2a5 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java @@ -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; @@ -105,6 +110,10 @@ public class GodotInputHandler 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) { godotGestureHandler.onPointerCaptureChange(hasCapture); } @@ -174,6 +183,8 @@ public class GodotInputHandler 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. @@ -198,6 +209,8 @@ public class GodotInputHandler 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; @@ -471,15 +484,27 @@ public class GodotInputHandler 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: diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java index e34c94975b..a94188c405 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java @@ -42,10 +42,12 @@ import android.os.Environment; import android.provider.Settings; import android.util.Log; +import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * This class includes utility functions for Android permissions related operations. @@ -58,6 +60,7 @@ public final class PermissionsUtil { static final int REQUEST_CAMERA_PERMISSION = 2; static final int REQUEST_VIBRATE_PERMISSION = 3; public static final int REQUEST_ALL_PERMISSION_REQ_CODE = 1001; + public static final int REQUEST_SINGLE_PERMISSION_REQ_CODE = 1002; public static final int REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE = 2002; private PermissionsUtil() { @@ -65,31 +68,57 @@ public final class PermissionsUtil { /** * Request a dangerous permission. name must be specified in <a href="https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/res/AndroidManifest.xml">this</a> - * @param name the name of the requested permission. + * @param permissionName the name of the requested permission. * @param activity the caller activity for this method. * @return true/false. "true" if permission was granted otherwise returns "false". */ - public static boolean requestPermission(String name, Activity activity) { + public static boolean requestPermission(String permissionName, Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { // Not necessary, asked on install already return true; } - if (name.equals("RECORD_AUDIO") && ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { - activity.requestPermissions(new String[] { Manifest.permission.RECORD_AUDIO }, REQUEST_RECORD_AUDIO_PERMISSION); - return false; - } + switch (permissionName) { + case "RECORD_AUDIO": + case Manifest.permission.RECORD_AUDIO: + if (ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + activity.requestPermissions(new String[] { Manifest.permission.RECORD_AUDIO }, REQUEST_RECORD_AUDIO_PERMISSION); + return false; + } + return true; - if (name.equals("CAMERA") && ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { - activity.requestPermissions(new String[] { Manifest.permission.CAMERA }, REQUEST_CAMERA_PERMISSION); - return false; - } + case "CAMERA": + case Manifest.permission.CAMERA: + if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { + activity.requestPermissions(new String[] { Manifest.permission.CAMERA }, REQUEST_CAMERA_PERMISSION); + return false; + } + return true; - if (name.equals("VIBRATE") && ContextCompat.checkSelfPermission(activity, Manifest.permission.VIBRATE) != PackageManager.PERMISSION_GRANTED) { - activity.requestPermissions(new String[] { Manifest.permission.VIBRATE }, REQUEST_VIBRATE_PERMISSION); - return false; + case "VIBRATE": + case Manifest.permission.VIBRATE: + if (ContextCompat.checkSelfPermission(activity, Manifest.permission.VIBRATE) != PackageManager.PERMISSION_GRANTED) { + activity.requestPermissions(new String[] { Manifest.permission.VIBRATE }, REQUEST_VIBRATE_PERMISSION); + return false; + } + return true; + + default: + // Check if the given permission is a dangerous permission + try { + PermissionInfo permissionInfo = getPermissionInfo(activity, permissionName); + int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel; + if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, permissionName) != PackageManager.PERMISSION_GRANTED) { + activity.requestPermissions(new String[] { permissionName }, REQUEST_SINGLE_PERMISSION_REQ_CODE); + return false; + } + } catch (PackageManager.NameNotFoundException e) { + // Unknown permission - return false as it can't be granted. + Log.w(TAG, "Unable to identify permission " + permissionName, e); + return false; + } + return true; } - return true; } /** @@ -98,6 +127,16 @@ public final class PermissionsUtil { * @return true/false. "true" if all permissions were granted otherwise returns "false". */ public static boolean requestManifestPermissions(Activity activity) { + return requestManifestPermissions(activity, null); + } + + /** + * Request dangerous permissions which are defined in the Android manifest file from the user. + * @param activity the caller activity for this method. + * @param excludes Set of permissions to exclude from the request + * @return true/false. "true" if all permissions were granted otherwise returns "false". + */ + public static boolean requestManifestPermissions(Activity activity, @Nullable Set<String> excludes) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } @@ -115,6 +154,9 @@ public final class PermissionsUtil { List<String> requestedPermissions = new ArrayList<>(); for (String manifestPermission : manifestPermissions) { + if (excludes != null && excludes.contains(manifestPermission)) { + continue; + } try { if (manifestPermission.equals(Manifest.permission.MANAGE_EXTERNAL_STORAGE)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) { |