From ddd9b70af3018af815358514e16dc8fa21d93312 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Wed, 26 Feb 2020 21:28:38 +0200 Subject: [PATCH] SDL: capture mouse input on Android O, so notification bar won't pop up every time mouse cursor hits top of screen --- project/java/MainActivity.java | 97 +++------------ project/java/Video.java | 112 ++++++++++++++++-- .../xserver-debian/AndroidAppSettings.cfg | 2 +- .../src/video/android/SDL_androidinput.c | 6 +- 4 files changed, 125 insertions(+), 92 deletions(-) diff --git a/project/java/MainActivity.java b/project/java/MainActivity.java index b77d518d8..f7b3d1b82 100644 --- a/project/java/MainActivity.java +++ b/project/java/MainActivity.java @@ -453,14 +453,13 @@ public class MainActivity extends Activity { _videoLayout.addView(mGLView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); } - mGLView.setFocusableInTouchMode(true); - mGLView.setFocusable(true); - mGLView.requestFocus(); - if (Globals.HideSystemMousePointer && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) + mGLView.captureMouse(true); + if( Globals.HideSystemMousePointer && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N ) { mGLView.setPointerIcon(android.view.PointerIcon.getSystemIcon(this, android.view.PointerIcon.TYPE_NULL)); } + if( _ad.getView() != null ) { _videoLayout.addView(_ad.getView()); @@ -553,9 +552,13 @@ public class MainActivity extends Activity super.onWindowFocusChanged(hasFocus); Log.i("SDL", "libSDL: onWindowFocusChanged: " + hasFocus + " - sending onPause/onResume"); if (hasFocus == false) + { onPause(); + } else + { onResume(); + } } public boolean isPaused() @@ -618,6 +621,7 @@ public class MainActivity extends Activity { public void run() { + mGLView.captureMouse(false); if (keyboard == 0) { _inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); @@ -798,6 +802,7 @@ public class MainActivity extends Activity _inputManager.hideSoftInputFromWindow(mGLView.getWindowToken(), 0); DimSystemStatusBar.get().dim(_videoLayout); //DimSystemStatusBar.get().dim(mGLView); + mGLView.captureMouse(true); } }); } @@ -809,6 +814,7 @@ public class MainActivity extends Activity if(Globals.CompatibilityHacksTextInputEmulatesHwKeyboard) { showScreenKeyboardWithoutTextInputField(Globals.TextInputKeyboard); + mGLView.captureMouse(false); return; } if(_screenKeyboard != null) @@ -882,6 +888,7 @@ public class MainActivity extends Activity screenKeyboard.setInputType(InputType.TYPE_CLASS_TEXT); screenKeyboard.setFocusableInTouchMode(true); screenKeyboard.setFocusable(true); + mGLView.captureMouse(false); //_inputManager.showSoftInput(screenKeyboard, InputMethodManager.SHOW_IMPLICIT); //getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); // Hack to try to force on-screen keyboard @@ -910,7 +917,10 @@ public class MainActivity extends Activity public void hideScreenKeyboard() { if( keyboardWithoutTextInputShown ) + { showScreenKeyboardWithoutTextInputField(Globals.TextInputKeyboard); + mGLView.captureMouse(true); + } if(_screenKeyboard == null || ! (_screenKeyboard instanceof EditText)) return; @@ -927,9 +937,7 @@ public class MainActivity extends Activity _inputManager.hideSoftInputFromWindow(_screenKeyboard.getWindowToken(), 0); _videoLayout.removeView(_screenKeyboard); _screenKeyboard = null; - mGLView.setFocusableInTouchMode(true); - mGLView.setFocusable(true); - mGLView.requestFocus(); + mGLView.captureMouse(true); DimSystemStatusBar.get().dim(_videoLayout); _videoLayout.postDelayed( new Runnable() @@ -945,7 +953,7 @@ public class MainActivity extends Activity { return _screenKeyboard != null; }; - + public void setScreenKeyboardHintMessage(String s) { _screenKeyboardHintMessage = s; @@ -1051,79 +1059,6 @@ public class MainActivity extends Activity } } - /* - @Override - public boolean onKeyDown(int keyCode, final KeyEvent event) - { - if( keyCode == KeyEvent.KEYCODE_BACK ) - { - if( (event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE ) - { - // Stupid Samsung and stupid Acer remaps right mouse button to BACK key - DemoGLSurfaceView.nativeMouseButtonsPressed(2, 1); - return true; - } - else if( keyboardWithoutTextInputShown ) - { - return true; - } - } - if( _screenKeyboard != null && _screenKeyboard.onKeyDown(keyCode, event) ) - return true; - - if( mGLView != null ) - { - if( mGLView.nativeKey( keyCode, 1, event.getUnicodeChar() ) == 0 ) - return super.onKeyDown(keyCode, event); - } - else - if( keyListener != null ) - { - keyListener.onKeyEvent(keyCode); - } - else - if( _btn != null ) - return _btn.onKeyDown(keyCode, event); - return true; - } - - @Override - public boolean onKeyUp(int keyCode, final KeyEvent event) - { - if( keyCode == KeyEvent.KEYCODE_BACK ) - { - if( (event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE ) - { - // Stupid Samsung and stupid Acer remaps right mouse button to BACK key - DemoGLSurfaceView.nativeMouseButtonsPressed(2, 0); - return true; - } - else if( keyboardWithoutTextInputShown ) - { - showScreenKeyboardWithoutTextInputField(0); // Hide keyboard - return true; - } - } - if( _screenKeyboard != null && _screenKeyboard.onKeyUp(keyCode, event) ) - return true; - - if( mGLView != null ) - { - if( mGLView.nativeKey( keyCode, 0, event.getUnicodeChar() ) == 0 ) - return super.onKeyUp(keyCode, event); - if( keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU ) - { - DimSystemStatusBar.get().dim(_videoLayout); - //DimSystemStatusBar.get().dim(mGLView); - } - } - else - if( _btn != null ) - return _btn.onKeyUp(keyCode, event); - return true; - } - */ - //private Configuration oldConfig = null; @Override public void onConfigurationChanged(Configuration newConfig) diff --git a/project/java/Video.java b/project/java/Video.java index 7c0eaf91b..8c27ec4c1 100644 --- a/project/java/Video.java +++ b/project/java/Video.java @@ -108,6 +108,10 @@ abstract class DifferentTouchInput public abstract void processGenericEvent(final MotionEvent event); public static int ExternalMouseDetected = Mouse.MOUSE_HW_INPUT_FINGER; + public static int buttonState = 0; + + public static float capturedMouseX = 0; + public static float capturedMouseY = 0; public static DifferentTouchInput touchInput = getInstance(); @@ -319,6 +323,12 @@ abstract class DifferentTouchInput int hwMouseEvent = ((event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE || Globals.ForceHardwareMouse) ? Mouse.MOUSE_HW_INPUT_MOUSE : ((event.getSource() & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS) ? Mouse.MOUSE_HW_INPUT_STYLUS : Mouse.MOUSE_HW_INPUT_FINGER; + if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ) + { + if( (event.getSource() & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE ) + hwMouseEvent = Mouse.MOUSE_HW_INPUT_MOUSE; + } + if( ExternalMouseDetected != hwMouseEvent ) { ExternalMouseDetected = hwMouseEvent; @@ -366,7 +376,6 @@ abstract class DifferentTouchInput { private static final IcsTouchInput sInstance = new IcsTouchInput(); } - private int buttonState = 0; public void process(final MotionEvent event) { //Log.i("SDL", "Got motion event, type " + (int)(event.getAction()) + " X " + (int)event.getX() + " Y " + (int)event.getY() + " buttons " + buttonState + " source " + event.getSource()); @@ -1045,9 +1054,18 @@ class DemoGLSurfaceView extends GLSurfaceView_SDL { @Override public boolean onKeyDown(int keyCode, final KeyEvent event) { + //Log.v("SDL", "DemoGLSurfaceView::onKeyDown(): keyCode " + keyCode + " event.getSource() " + event.getSource()); if( keyCode == KeyEvent.KEYCODE_BACK ) { + boolean mouseInput = false; if( (event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE ) + mouseInput = true; + if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ) + { + if( (event.getSource() & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE ) + mouseInput = true; + } + if( mouseInput ) { // Stupid Samsung and stupid Acer remaps right mouse button to BACK key nativeMouseButtonsPressed(2, 1); @@ -1070,7 +1088,15 @@ class DemoGLSurfaceView extends GLSurfaceView_SDL { { if( keyCode == KeyEvent.KEYCODE_BACK ) { + boolean mouseInput = false; if( (event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE ) + mouseInput = true; + if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ) + { + if( (event.getSource() & InputDevice.SOURCE_MOUSE_RELATIVE) == InputDevice.SOURCE_MOUSE_RELATIVE ) + mouseInput = true; + } + if( mouseInput ) { // Stupid Samsung and stupid Acer remaps right mouse button to BACK key nativeMouseButtonsPressed(2, 0); @@ -1097,8 +1123,8 @@ class DemoGLSurfaceView extends GLSurfaceView_SDL { { if( event.getCharacters() != null ) { - // International text input - for(int i = 0; i < event.getCharacters().length(); i++ ) + // Non-English text input + for( int i = 0; i < event.getCharacters().length(); i++ ) { nativeKey( event.getKeyCode(), 1, event.getCharacters().codePointAt(i), 0 ); nativeKey( event.getKeyCode(), 0, event.getCharacters().codePointAt(i), 0 ); @@ -1110,13 +1136,14 @@ class DemoGLSurfaceView extends GLSurfaceView_SDL { @Override public boolean onTouchEvent(final MotionEvent event) { - if (mParent.keyboardWithoutTextInputShown && mParent._screenKeyboard != null && - mParent._screenKeyboard.getY() <= event.getY()) { + if( mParent.keyboardWithoutTextInputShown && mParent._screenKeyboard != null && + mParent._screenKeyboard.getY() <= event.getY() ) + { event.offsetLocation(-mParent._screenKeyboard.getX(), -mParent._screenKeyboard.getY()); mParent._screenKeyboard.onTouchEvent(event); return true; } - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) + if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH ) { if (getX() != 0) event.offsetLocation(-getX(), -getY()); @@ -1139,7 +1166,42 @@ class DemoGLSurfaceView extends GLSurfaceView_SDL { } return true; } - + + @Override + public boolean onCapturedPointerEvent (final MotionEvent event) + { + DifferentTouchInput.capturedMouseX += event.getX(); + DifferentTouchInput.capturedMouseY += event.getY(); + if (DifferentTouchInput.capturedMouseX < 0) + DifferentTouchInput.capturedMouseX = 0; + if (DifferentTouchInput.capturedMouseY < 0) + DifferentTouchInput.capturedMouseY = 0; + if (DifferentTouchInput.capturedMouseX >= this.getWidth()) + DifferentTouchInput.capturedMouseX = this.getWidth() - 1; + if (DifferentTouchInput.capturedMouseY >= this.getHeight()) + DifferentTouchInput.capturedMouseY = this.getHeight() - 1; + + //Log.v("SDL", "DemoGLSurfaceView::onCapturedPointerEvent(): X " + DifferentTouchInput.capturedMouseX + " Y " + DifferentTouchInput.capturedMouseY + + // " W " + this.getWidth() + " H " + this.getHeight() + " getX " + event.getX() + " getY " + event.getY() + + // " RelX " + event.getAxisValue(MotionEvent.AXIS_RELATIVE_X) + " RelY " + event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y) ); + + event.setLocation(DifferentTouchInput.capturedMouseX, DifferentTouchInput.capturedMouseY); + event.setAction(MotionEvent.ACTION_HOVER_MOVE); + + //Log.v("SDL", "DemoGLSurfaceView::onCapturedPointerEvent(): XY " + event.getX() + " " + event.getY() + " action " + event.getAction()); + + return this.onTouchEvent(event); + } + + @Override + public void onPointerCaptureChange (boolean hasCapture) + { + Log.v("SDL", "DemoGLSurfaceView::onPointerCaptureChange(): " + hasCapture); + super.onPointerCaptureChange(hasCapture); + DifferentTouchInput.capturedMouseX = this.getWidth() / 2; + DifferentTouchInput.capturedMouseY = this.getHeight() / 2; + } + public void limitEventRate(final MotionEvent event) { // Wait a bit, and try to synchronize to app framerate, or event thread will eat all CPU and we'll lose FPS @@ -1193,8 +1255,44 @@ class DemoGLSurfaceView extends GLSurfaceView_SDL { mRenderer.nativeGlContextRecreated(); if( mRenderer.accelerometer != null && mRenderer.accelerometer.openedBySDL ) // For some reason it crashes here often - are we getting this event before initialization? mRenderer.accelerometer.start(); + captureMouse(true); }; + public void captureMouse(boolean capture) + { + if( capture ) + { + setFocusableInTouchMode(true); + setFocusable(true); + requestFocus(); + if( Globals.HideSystemMousePointer && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ) + { + postDelayed( new Runnable() + { + public void run() + { + Log.v("SDL", "captureMouse::requestPointerCapture() delayed"); + requestPointerCapture(); + } + }, 50 ); + } + } + else + { + if( Globals.HideSystemMousePointer && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ) + { + postDelayed( new Runnable() + { + public void run() + { + Log.v("SDL", "captureMouse::releasePointerCapture()"); + releasePointerCapture(); + } + }, 50 ); + } + } + } + DemoRenderer mRenderer; MainActivity mParent; diff --git a/project/jni/application/xserver-debian/AndroidAppSettings.cfg b/project/jni/application/xserver-debian/AndroidAppSettings.cfg index 859b13fe4..4944fa706 100644 --- a/project/jni/application/xserver-debian/AndroidAppSettings.cfg +++ b/project/jni/application/xserver-debian/AndroidAppSettings.cfg @@ -169,7 +169,7 @@ AppUsesGyroscope=n AppUsesOrientationSensor= # Use gyroscope to move mouse cursor (y) or (n), it eats battery, and can be disabled in settings, do not use with AppUsesGyroscope setting -MoveMouseWithGyroscope=y +MoveMouseWithGyroscope=n # Application uses multitouch (y) or (n), multitouch events are passed as SDL_JOYBALLMOTION events for the joystick 0 AppUsesMultitouch=y diff --git a/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c b/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c index d59a976ef..7088a58d6 100644 --- a/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c +++ b/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c @@ -478,7 +478,7 @@ static void ProcessMouseRelativeMovement( jint *xx, jint *yy, int action ) { int x = *xx, y = *yy; - if( !relativeMovement ) + if( !relativeMovement || hardwareMouseDetected ) return; if( action == MOUSE_DOWN ) @@ -863,9 +863,9 @@ JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeMotionEvent) ( JNIEnv* env, jobject t if( ProcessTouchscreenKeyboard( x, y, action, pointerId ) ) return; - + AssignNewTouchPointers( action, pointerId ); - + AdjustTouchScreenCalibration( &x, &y ); ProcessMultitouchGesture( x, y, action, pointerId );