From 7c5f3cf3cb8b4b270dba815857564605a358ed5a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 5 Jun 2018 14:08:39 -0700 Subject: [PATCH] Added improved mouse pointer capture under API 26. (Thanks Rachel!) --- .../main/java/org/libsdl/app/SDLActivity.java | 15 +- .../org/libsdl/app/SDLControllerManager.java | 170 ++++++++++++++++++ 2 files changed, 184 insertions(+), 1 deletion(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index e505533da8c62..c62a514ed7968 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -87,6 +87,9 @@ public enum NativeState { protected static SDLGenericMotionListener_API12 getMotionListener() { if (mMotionListener == null) { + if (Build.VERSION.SDK_INT >= 26) { + mMotionListener = new SDLGenericMotionListener_API26(); + } else if (Build.VERSION.SDK_INT >= 24) { mMotionListener = new SDLGenericMotionListener_API24(); } else { @@ -301,6 +304,7 @@ public void onWindowFocusChanged(boolean hasFocus) { SDLActivity.mHasFocus = hasFocus; if (hasFocus) { mNextNativeState = NativeState.RESUMED; + SDLActivity.getMotionListener().reclaimRelativeMouseModeIfNeeded(); } else { mNextNativeState = NativeState.PAUSED; } @@ -635,7 +639,6 @@ public void setOrientationBis(int w, int h, boolean resizable, String hint) } } - /** * This method is called by SDL using JNI. */ @@ -736,6 +739,12 @@ public static boolean getManifestEnvironmentVariables() { return false; } + // This method is called by SDLControllerManager's API 26 Generic Motion Handler. + public static View getContentView() + { + return mSingleton.mLayout; + } + static class ShowTextInputTask implements Runnable { /* * This is used to regulate the pan&scan method to have some offset from @@ -1270,6 +1279,10 @@ public SDLSurface(Context context) { setOnGenericMotionListener(SDLActivity.getMotionListener()); } + if (Build.VERSION.SDK_INT >= 26) { + setOnCapturedPointerListener(new SDLCapturedPointerListener_API26()); + } + // Some arbitrary defaults to avoid a potential division by zero mWidth = 1.0f; mHeight = 1.0f; diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java b/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java index c2d394cd9d217..f97dd20f4e494 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java @@ -569,6 +569,11 @@ public boolean setRelativeMouseEnabled(boolean enabled) { return false; } + public void reclaimRelativeMouseModeIfNeeded() + { + + } + public float getEventX(MotionEvent event) { return event.getX(0); } @@ -633,19 +638,23 @@ public boolean onGenericMotion(View v, MotionEvent event) { return false; } + @Override public boolean supportsRelativeMouse() { return true; } + @Override public boolean inRelativeMode() { return mRelativeModeEnabled; } + @Override public boolean setRelativeMouseEnabled(boolean enabled) { mRelativeModeEnabled = enabled; return true; } + @Override public float getEventX(MotionEvent event) { if (mRelativeModeEnabled) { return event.getAxisValue(MotionEvent.AXIS_RELATIVE_X); @@ -655,6 +664,7 @@ public float getEventX(MotionEvent event) { } } + @Override public float getEventY(MotionEvent event) { if (mRelativeModeEnabled) { return event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y); @@ -665,3 +675,163 @@ public float getEventY(MotionEvent event) { } } + +class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 { + // Generic Motion (mouse hover, joystick...) events go here + private boolean mRelativeModeEnabled; + + @Override + public boolean onGenericMotion(View v, MotionEvent event) { + float x, y; + int action; + + switch ( event.getSource() ) { + case InputDevice.SOURCE_JOYSTICK: + case InputDevice.SOURCE_GAMEPAD: + case InputDevice.SOURCE_DPAD: + return SDLControllerManager.handleJoystickMotionEvent(event); + + case InputDevice.SOURCE_MOUSE: + if (!SDLActivity.mSeparateMouseAndTouch) { + break; + } + + action = event.getActionMasked(); + switch (action) { + case MotionEvent.ACTION_SCROLL: + x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0); + y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0); + SDLActivity.onNativeMouse(0, action, x, y, false); + return true; + + case MotionEvent.ACTION_HOVER_MOVE: + x = event.getX(0); + y = event.getY(0); + SDLActivity.onNativeMouse(0, action, x, y, false); + return true; + + default: + break; + } + break; + + case InputDevice.SOURCE_MOUSE_RELATIVE: + if (!SDLActivity.mSeparateMouseAndTouch) { + break; + } + action = event.getActionMasked(); + switch (action) { + case MotionEvent.ACTION_SCROLL: + x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0); + y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0); + SDLActivity.onNativeMouse(0, action, x, y, false); + return true; + + case MotionEvent.ACTION_HOVER_MOVE: + x = event.getX(0); + y = event.getY(0); + SDLActivity.onNativeMouse(0, action, x, y, true); + return true; + + default: + break; + } + break; + + default: + break; + } + + // Event was not managed + return false; + } + + @Override + public boolean supportsRelativeMouse() { + return true; + } + + @Override + public boolean inRelativeMode() { + return mRelativeModeEnabled; + } + + @Override + public boolean setRelativeMouseEnabled(boolean enabled) { + if (enabled) { + SDLActivity.getContentView().requestPointerCapture(); + } + else { + SDLActivity.getContentView().releasePointerCapture(); + } + mRelativeModeEnabled = enabled; + return true; + } + + @Override + public void reclaimRelativeMouseModeIfNeeded() + { + if (mRelativeModeEnabled) { + SDLActivity.getContentView().requestPointerCapture(); + } + } + + @Override + public float getEventX(MotionEvent event) { + // Relative mouse in capture mode will only have relative for X/Y + return event.getX(0); + } + + @Override + public float getEventY(MotionEvent event) { + // Relative mouse in capture mode will only have relative for X/Y + return event.getY(0); + } +} + +class SDLCapturedPointerListener_API26 implements View.OnCapturedPointerListener +{ + @Override + public boolean onCapturedPointer(View view, MotionEvent event) + { + int action = event.getActionMasked(); + + float x, y; + switch (action) { + case MotionEvent.ACTION_SCROLL: + x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0); + y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0); + SDLActivity.onNativeMouse(0, action, x, y, false); + return true; + + case MotionEvent.ACTION_HOVER_MOVE: + case MotionEvent.ACTION_MOVE: + x = event.getX(0); + y = event.getY(0); + SDLActivity.onNativeMouse(0, action, x, y, true); + return true; + + case MotionEvent.ACTION_BUTTON_PRESS: + case MotionEvent.ACTION_BUTTON_RELEASE: + + // Change our action value to what SDL's code expects. + if (action == MotionEvent.ACTION_BUTTON_PRESS) { + action = MotionEvent.ACTION_DOWN; + } + else if (action == MotionEvent.ACTION_BUTTON_RELEASE) { + action = MotionEvent.ACTION_UP; + } + + x = event.getX(0); + y = event.getY(0); + int button = event.getButtonState(); + + SDLActivity.onNativeMouse(button, action, x, y, true); + return true; + + } + + return false; + } +} +