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 a1edff7f40..6067fa74dc 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 @@ -223,7 +223,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh protected static SDLClipboardHandler mClipboardHandler; protected static Hashtable mCursors; protected static int mLastCursorID; - protected static SDLGenericMotionListener_API12 mMotionListener; + protected static SDLGenericMotionListener_API14 mMotionListener; protected static HIDDeviceManager mHIDDeviceManager; // This is what SDL runs in. It invokes SDL_main(), eventually @@ -232,14 +232,14 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh protected static boolean mActivityCreated = false; private static SDLFileDialogState mFileDialogState = null; - protected static SDLGenericMotionListener_API12 getMotionListener() { + protected static SDLGenericMotionListener_API14 getMotionListener() { if (mMotionListener == null) { if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) { mMotionListener = new SDLGenericMotionListener_API26(); } else if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) { mMotionListener = new SDLGenericMotionListener_API24(); } else { - mMotionListener = new SDLGenericMotionListener_API12(); + mMotionListener = new SDLGenericMotionListener_API14(); } } 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 b7faee8997..dc6fb9d12a 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 @@ -662,44 +662,61 @@ class SDLHapticHandler { } } -class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener { +class SDLGenericMotionListener_API14 implements View.OnGenericMotionListener { // Generic Motion (mouse hover, joystick...) events go here @Override public boolean onGenericMotion(View v, MotionEvent event) { + if (event.getSource() == InputDevice.SOURCE_JOYSTICK) + return SDLControllerManager.handleJoystickMotionEvent(event); + float x, y; - int action; + int action = event.getActionMasked(); + int pointerCount = event.getPointerCount(); + boolean consumed = false; - switch ( event.getSource() ) { - case InputDevice.SOURCE_JOYSTICK: - return SDLControllerManager.handleJoystickMotionEvent(event); + for (int i = 0; i < pointerCount; i++) { + int toolType = event.getToolType(i); - case InputDevice.SOURCE_MOUSE: - action = event.getActionMasked(); + if (toolType == MotionEvent.TOOL_TYPE_MOUSE) { switch (action) { case MotionEvent.ACTION_SCROLL: - x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0); - y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0); + x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, i); + y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, i); SDLActivity.onNativeMouse(0, action, x, y, false); - return true; + consumed = true; + break; case MotionEvent.ACTION_HOVER_MOVE: - x = event.getX(0); - y = event.getY(0); + x = getEventX(event, i); + y = getEventY(event, i); - SDLActivity.onNativeMouse(0, action, x, y, false); - return true; + SDLActivity.onNativeMouse(0, action, x, y, checkRelativeEvent(event)); + consumed = true; + break; default: break; } - break; + } else if (toolType == MotionEvent.TOOL_TYPE_STYLUS || toolType == MotionEvent.TOOL_TYPE_ERASER) { + switch (action) { + case MotionEvent.ACTION_HOVER_ENTER: + case MotionEvent.ACTION_HOVER_MOVE: + case MotionEvent.ACTION_HOVER_EXIT: + x = event.getX(i); + y = event.getY(i); + float p = event.getPressure(i); - default: - break; + // BUTTON_STYLUS_PRIMARY is 2^5, so shift by 4 + int buttons = event.getButtonState() >> 4; + + SDLActivity.onNativePen(event.getPointerId(i), buttons, action, x, y, p); + consumed = true; + break; + } + } } - // Event was not managed - return false; + return consumed; } public boolean supportsRelativeMouse() { @@ -714,46 +731,29 @@ class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener { return false; } - public void reclaimRelativeMouseModeIfNeeded() - { + public void reclaimRelativeMouseModeIfNeeded() { } - public float getEventX(MotionEvent event) { - return event.getX(0); + public boolean checkRelativeEvent(MotionEvent event) { + return inRelativeMode(); } - public float getEventY(MotionEvent event) { - return event.getY(0); + public float getEventX(MotionEvent event, int pointerIndex) { + return event.getX(pointerIndex); + } + + public float getEventY(MotionEvent event, int pointerIndex) { + return event.getY(pointerIndex); } } -class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API12 { +class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API14 { // Generic Motion (mouse hover, joystick...) events go here private boolean mRelativeModeEnabled; - @Override - public boolean onGenericMotion(View v, MotionEvent event) { - - // Handle relative mouse mode - if (mRelativeModeEnabled) { - if (event.getSource() == InputDevice.SOURCE_MOUSE) { - int action = event.getActionMasked(); - if (action == MotionEvent.ACTION_HOVER_MOVE) { - float x = event.getAxisValue(MotionEvent.AXIS_RELATIVE_X); - float y = event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y); - SDLActivity.onNativeMouse(0, action, x, y, true); - return true; - } - } - } - - // Event was not managed, call SDLGenericMotionListener_API12 method - return super.onGenericMotion(v, event); - } - @Override public boolean supportsRelativeMouse() { return true; @@ -771,20 +771,20 @@ class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API12 { } @Override - public float getEventX(MotionEvent event) { - if (mRelativeModeEnabled) { - return event.getAxisValue(MotionEvent.AXIS_RELATIVE_X); + public float getEventX(MotionEvent event, int pointerIndex) { + if (mRelativeModeEnabled && event.getToolType(pointerIndex) == MotionEvent.TOOL_TYPE_MOUSE) { + return event.getAxisValue(MotionEvent.AXIS_RELATIVE_X, pointerIndex); } else { - return event.getX(0); + return event.getX(pointerIndex); } } @Override - public float getEventY(MotionEvent event) { - if (mRelativeModeEnabled) { - return event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y); + public float getEventY(MotionEvent event, int pointerIndex) { + if (mRelativeModeEnabled && event.getToolType(pointerIndex) == MotionEvent.TOOL_TYPE_MOUSE) { + return event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y, pointerIndex); } else { - return event.getY(0); + return event.getY(pointerIndex); } } } @@ -793,65 +793,6 @@ 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: - return SDLControllerManager.handleJoystickMotionEvent(event); - - case InputDevice.SOURCE_MOUSE: - // DeX desktop mouse cursor is a separate non-standard input type. - case InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_TOUCHSCREEN: - 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: - 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 (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */); @@ -878,22 +819,26 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 { } @Override - public void reclaimRelativeMouseModeIfNeeded() - { + public void reclaimRelativeMouseModeIfNeeded() { if (mRelativeModeEnabled && !SDLActivity.isDeXMode()) { 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); + public boolean checkRelativeEvent(MotionEvent event) { + return event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE; } @Override - public float getEventY(MotionEvent event) { + public float getEventX(MotionEvent event, int pointerIndex) { // Relative mouse in capture mode will only have relative for X/Y - return event.getY(0); + return event.getX(pointerIndex); + } + + @Override + public float getEventY(MotionEvent event, int pointerIndex) { + // Relative mouse in capture mode will only have relative for X/Y + return event.getY(pointerIndex); } } diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java b/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java index d896f6ce4a..6b5f434662 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLSurface.java @@ -239,93 +239,65 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, int touchDevId = event.getDeviceId(); final int pointerCount = event.getPointerCount(); int action = event.getActionMasked(); - int pointerFingerId; - int i = -1; + int pointerId; + int i = 0; float x,y,p; - // 12290 = Samsung DeX mode desktop mouse - // 12290 = 0x3002 = 0x2002 | 0x1002 = SOURCE_MOUSE | SOURCE_TOUCHSCREEN - // 0x2 = SOURCE_CLASS_POINTER - if (event.getSource() == InputDevice.SOURCE_MOUSE || event.getSource() == (InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_TOUCHSCREEN)) { - int mouseButton = 1; - try { - Object object = event.getClass().getMethod("getButtonState").invoke(event); - if (object != null) { - mouseButton = (Integer) object; + if (action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN) + i = event.getActionIndex(); + + do { + int toolType = event.getToolType(i); + + if (toolType == MotionEvent.TOOL_TYPE_MOUSE) { + int buttonState = event.getButtonState(); + boolean relative = false; + + // We need to check if we're in relative mouse mode and get the axis offset rather than the x/y values + // if we are. We'll leverage our existing mouse motion listener + SDLGenericMotionListener_API14 motionListener = SDLActivity.getMotionListener(); + x = motionListener.getEventX(event, i); + y = motionListener.getEventY(event, i); + relative = motionListener.inRelativeMode(); + + SDLActivity.onNativeMouse(buttonState, action, x, y, relative); + } else if (toolType == MotionEvent.TOOL_TYPE_STYLUS || toolType == MotionEvent.TOOL_TYPE_ERASER) { + pointerId = event.getPointerId(i); + x = event.getX(i); + y = event.getY(i); + p = event.getPressure(i); + if (p > 1.0f) { + // may be larger than 1.0f on some devices + // see the documentation of getPressure(i) + p = 1.0f; } - } catch(Exception ignored) { + + // BUTTON_STYLUS_PRIMARY is 2^5, so shift by 4, and apply SDL_PEN_INPUT_DOWN/SDL_PEN_INPUT_ERASER_TIP + int buttonState = (event.getButtonState() >> 4) | (1 << (toolType == MotionEvent.TOOL_TYPE_STYLUS ? 0 : 30)); + + SDLActivity.onNativePen(pointerId, buttonState, action, x, y, p); + } else if (toolType == MotionEvent.TOOL_TYPE_FINGER) { + pointerId = event.getPointerId(i); + x = getNormalizedX(event.getX(i)); + y = getNormalizedY(event.getY(i)); + p = event.getPressure(i); + if (p > 1.0f) { + // may be larger than 1.0f on some devices + // see the documentation of getPressure(i) + p = 1.0f; + } + + SDLActivity.onNativeTouch(touchDevId, pointerId, + action == MotionEvent.ACTION_CANCEL ? MotionEvent.ACTION_UP : action, x, y, p); } - // We need to check if we're in relative mouse mode and get the axis offset rather than the x/y values - // if we are. We'll leverage our existing mouse motion listener - SDLGenericMotionListener_API12 motionListener = SDLActivity.getMotionListener(); - x = motionListener.getEventX(event); - y = motionListener.getEventY(event); - - SDLActivity.onNativeMouse(mouseButton, action, x, y, motionListener.inRelativeMode()); - } else { - switch(action) { - case MotionEvent.ACTION_MOVE: - for (i = 0; i < pointerCount; i++) { - pointerFingerId = event.getPointerId(i); - x = getNormalizedX(event.getX(i)); - y = getNormalizedY(event.getY(i)); - p = event.getPressure(i); - if (p > 1.0f) { - // may be larger than 1.0f on some devices - // see the documentation of getPressure(i) - p = 1.0f; - } - SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); - } - break; - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_DOWN: - // Primary pointer up/down, the index is always zero - i = 0; - /* fallthrough */ - case MotionEvent.ACTION_POINTER_UP: - case MotionEvent.ACTION_POINTER_DOWN: - // Non primary pointer up/down - if (i == -1) { - i = event.getActionIndex(); - } - - pointerFingerId = event.getPointerId(i); - x = getNormalizedX(event.getX(i)); - y = getNormalizedY(event.getY(i)); - p = event.getPressure(i); - if (p > 1.0f) { - // may be larger than 1.0f on some devices - // see the documentation of getPressure(i) - p = 1.0f; - } - SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); - break; - - case MotionEvent.ACTION_CANCEL: - for (i = 0; i < pointerCount; i++) { - pointerFingerId = event.getPointerId(i); - x = getNormalizedX(event.getX(i)); - y = getNormalizedY(event.getY(i)); - p = event.getPressure(i); - if (p > 1.0f) { - // may be larger than 1.0f on some devices - // see the documentation of getPressure(i) - p = 1.0f; - } - SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p); - } - break; - - default: - break; - } - } + // Non-primary up/down + if (action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN) + break; + } while (++i < pointerCount); return true; - } + } // Sensor events public void enableSensor(int sensortype, boolean enabled) { @@ -395,39 +367,42 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, public boolean onCapturedPointerEvent(MotionEvent event) { int action = event.getActionMasked(); + int pointerCount = event.getPointerCount(); - 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; + for (int i = 0; i < pointerCount; i++) { + float x, y; + switch (action) { + case MotionEvent.ACTION_SCROLL: + x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, i); + y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, i); + 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_HOVER_MOVE: + case MotionEvent.ACTION_MOVE: + x = event.getX(i); + y = event.getY(i); + SDLActivity.onNativeMouse(0, action, x, y, true); + return true; - case MotionEvent.ACTION_BUTTON_PRESS: - case MotionEvent.ACTION_BUTTON_RELEASE: + 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 { /* MotionEvent.ACTION_BUTTON_RELEASE */ - action = MotionEvent.ACTION_UP; - } + // Change our action value to what SDL's code expects. + if (action == MotionEvent.ACTION_BUTTON_PRESS) { + action = MotionEvent.ACTION_DOWN; + } else { /* MotionEvent.ACTION_BUTTON_RELEASE */ + action = MotionEvent.ACTION_UP; + } - x = event.getX(0); - y = event.getY(0); - int button = event.getButtonState(); + x = event.getX(i); + y = event.getY(i); + int button = event.getButtonState(); - SDLActivity.onNativeMouse(button, action, x, y, true); - return true; - } + SDLActivity.onNativeMouse(button, action, x, y, true); + return true; + } + } return false; } diff --git a/src/video/android/SDL_androidpen.c b/src/video/android/SDL_androidpen.c index 65730bd75d..a691b2e146 100644 --- a/src/video/android/SDL_androidpen.c +++ b/src/video/android/SDL_androidpen.c @@ -26,11 +26,12 @@ #include "../../events/SDL_pen_c.h" #include "../../core/android/SDL_android.h" -#define ACTION_DOWN 0 -#define ACTION_UP 1 -#define ACTION_POINTER_DOWN 5 -#define ACTION_POINTER_UP 6 -#define ACTION_HOVER_EXIT 10 +#define ACTION_DOWN 0 +#define ACTION_UP 1 +#define ACTION_CANCEL 3 +#define ACTION_POINTER_DOWN 5 +#define ACTION_POINTER_UP 6 +#define ACTION_HOVER_EXIT 10 void Android_OnPen(SDL_Window *window, int pen_id_in, int button, int action, float x, float y, float p) { @@ -56,11 +57,6 @@ void Android_OnPen(SDL_Window *window, int pen_id_in, int button, int action, fl } } - if (action == ACTION_HOVER_EXIT) { - SDL_RemovePenDevice(0, pen); - return; - } - SDL_SendPenMotion(0, pen, window, x, y); SDL_SendPenAxis(0, pen, window, SDL_PEN_AXIS_PRESSURE, p); // TODO: add more axis @@ -77,7 +73,13 @@ void Android_OnPen(SDL_Window *window, int pen_id_in, int button, int action, fl } // button contains DOWN/ERASER_TIP on DOWN/UP regardless of pressed state, use action to distinguish + // we don't compare tip flags above because MotionEvent.getButtonState doesn't return stylus tip/eraser state. switch (action) { + case ACTION_CANCEL: + case ACTION_HOVER_EXIT: + SDL_RemovePenDevice(0, pen); + break; + case ACTION_DOWN: case ACTION_POINTER_DOWN: SDL_SendPenTouch(0, pen, window, (button & SDL_PEN_INPUT_ERASER_TIP) != 0, true);