Commit 7c5f3cf3cb8b4b270dba815857564605a358ed5a

Sam Lantinga 2018-06-05T14:08:39

Added improved mouse pointer capture under API 26. (Thanks Rachel!)

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 e505533..c62a514 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 class SDLActivity extends Activity {
 
     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 class SDLActivity extends Activity {
         SDLActivity.mHasFocus = hasFocus;
         if (hasFocus) {
            mNextNativeState = NativeState.RESUMED;
+           SDLActivity.getMotionListener().reclaimRelativeMouseModeIfNeeded();
         } else {
            mNextNativeState = NativeState.PAUSED;
         }
@@ -635,7 +639,6 @@ public class SDLActivity extends Activity {
         }
     }
 
-
     /**
      * This method is called by SDL using JNI.
      */
@@ -736,6 +739,12 @@ public class SDLActivity extends Activity {
         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 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
             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 c2d394c..f97dd20 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 @@ class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener {
         return false;
     }
 
+    public void reclaimRelativeMouseModeIfNeeded()
+    {
+
+    }
+
     public float getEventX(MotionEvent event) {
         return event.getX(0);
     }
@@ -633,19 +638,23 @@ class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API12 {
         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 @@ class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API12 {
         }
     }
 
+    @Override
     public float getEventY(MotionEvent event) {
         if (mRelativeModeEnabled) {
             return event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y);
@@ -665,3 +675,163 @@ class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API12 {
     }
 }
 
+
+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;
+    }
+}
+