瀏覽代碼

Implement SDL_GetPenDeviceType() for Android

Susko3 5 月之前
父節點
當前提交
e2bbbdc515

+ 5 - 3
android-project/app/src/main/java/org/libsdl/app/SDLActivity.java

@@ -229,9 +229,11 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
     private static SDLFileDialogState mFileDialogState = null;
     protected static boolean mDispatchingKeyEvent = false;
 
-    protected static SDLGenericMotionListener_API14 getMotionListener() {
+    public static SDLGenericMotionListener_API14 getMotionListener() {
         if (mMotionListener == null) {
-            if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {
+            if (Build.VERSION.SDK_INT >= 29 /* Android 10 (Q) */) {
+                mMotionListener = new SDLGenericMotionListener_API29();
+            } else 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();
@@ -1063,7 +1065,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
     public static native void onNativeTouch(int touchDevId, int pointerFingerId,
                                             int action, float x,
                                             float y, float p);
-    public static native void onNativePen(int penId, int button, int action, float x, float y, float p);
+    public static native void onNativePen(int penId, int device_type, int button, int action, float x, float y, float p);
     public static native void onNativeAccel(float x, float y, float z);
     public static native void onNativeClipboardChanged();
     public static native void onNativeSurfaceCreated();

+ 20 - 1
android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java

@@ -646,6 +646,10 @@ class SDLHapticHandler {
 }
 
 class SDLGenericMotionListener_API14 implements View.OnGenericMotionListener {
+    protected static final int SDL_PEN_DEVICE_TYPE_UNKNOWN = 0;
+    protected static final int SDL_PEN_DEVICE_TYPE_DIRECT = 1;
+    protected static final int SDL_PEN_DEVICE_TYPE_INDIRECT = 2;
+
     // Generic Motion (mouse hover, joystick...) events go here
     @Override
     public boolean onGenericMotion(View v, MotionEvent event) {
@@ -697,7 +701,7 @@ class SDLGenericMotionListener_API14 implements View.OnGenericMotionListener {
                         // BUTTON_STYLUS_PRIMARY is 2^5, so shift by 4, and apply SDL_PEN_INPUT_DOWN/SDL_PEN_INPUT_ERASER_TIP
                         int buttons = (event.getButtonState() >> 4) | (1 << (toolType == MotionEvent.TOOL_TYPE_STYLUS ? 0 : 30));
 
-                        SDLActivity.onNativePen(event.getPointerId(i), buttons, action, x, y, p);
+                        SDLActivity.onNativePen(event.getPointerId(i), getPenDeviceType(event.getDevice()), buttons, action, x, y, p);
                         consumed = true;
                         break;
                 }
@@ -735,6 +739,9 @@ class SDLGenericMotionListener_API14 implements View.OnGenericMotionListener {
         return event.getY(pointerIndex);
     }
 
+    int getPenDeviceType(InputDevice penDevice) {
+        return SDL_PEN_DEVICE_TYPE_UNKNOWN;
+    }
 }
 
 class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API14 {
@@ -856,3 +863,15 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
         return event.getY(pointerIndex);
     }
 }
+
+class SDLGenericMotionListener_API29 extends SDLGenericMotionListener_API26 {
+    @Override
+    int getPenDeviceType(InputDevice penDevice)
+    {
+        if (penDevice == null) {
+            return SDL_PEN_DEVICE_TYPE_UNKNOWN;
+        }
+
+        return penDevice.isExternal() ? SDL_PEN_DEVICE_TYPE_INDIRECT : SDL_PEN_DEVICE_TYPE_DIRECT;
+    }
+}

+ 1 - 1
android-project/app/src/main/java/org/libsdl/app/SDLSurface.java

@@ -281,7 +281,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
                 // 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);
+                SDLActivity.onNativePen(pointerId, SDLActivity.getMotionListener().getPenDeviceType(event.getDevice()), buttonState, action, x, y, p);
             } else { // MotionEvent.TOOL_TYPE_FINGER or MotionEvent.TOOL_TYPE_UNKNOWN
                 pointerId = event.getPointerId(i);
                 x = getNormalizedX(event.getX(i));

+ 27 - 1
include/SDL3/SDL_pen.h

@@ -52,6 +52,7 @@
 #include <SDL3/SDL_mouse.h>
 #include <SDL3/SDL_touch.h>
 
+#include <SDL3/SDL_begin_code.h>
 /* Set up for C function definitions, even when using C++ */
 #ifdef __cplusplus
 extern "C" {
@@ -84,7 +85,6 @@ typedef Uint32 SDL_PenID;
  */
 #define SDL_PEN_TOUCHID ((SDL_TouchID)-2)
 
-
 /**
  * Pen input flags, as reported by various pen events' `pen_state` field.
  *
@@ -127,10 +127,36 @@ typedef enum SDL_PenAxis
     SDL_PEN_AXIS_COUNT       /**< Total known pen axis types in this version of SDL. This number may grow in future releases! */
 } SDL_PenAxis;
 
+/**
+ * An enum that describes the type of a pen device.
+ *
+ * \since This enum is available since SDL 3.4.0.
+ */
+typedef enum SDL_PenDeviceType
+{
+    SDL_PEN_DEVICE_TYPE_INVALID = -1,
+    SDL_PEN_DEVICE_TYPE_UNKNOWN,
+    SDL_PEN_DEVICE_TYPE_DIRECT,
+    SDL_PEN_DEVICE_TYPE_INDIRECT
+} SDL_PenDeviceType;
+
+/**
+ * Get the device type of the given pen.
+ *
+ * \param instance_id the pen instance ID.
+ * \returns the device type of the given pen, or SDL_PEN_DEVICE_TYPE_INVALID on failure; call SDL_GetError() for more information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.4.0.
+ */
+extern SDL_DECLSPEC SDL_PenDeviceType SDLCALL SDL_GetPenDeviceType(SDL_PenID instance_id);
+
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus
 }
 #endif
+#include <SDL3/SDL_close_code.h>
 
 #endif /* SDL_pen_h_ */
 

+ 4 - 4
src/core/android/SDL_android.c

@@ -137,7 +137,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
 
 JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePen)(
     JNIEnv *env, jclass jcls,
-    jint pen_id_in, jint button, jint action, jfloat x, jfloat y, jfloat p);
+    jint pen_id_in, jint device_type, jint button, jint action, jfloat x, jfloat y, jfloat p);
 
 JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeAccel)(
     JNIEnv *env, jclass jcls,
@@ -235,7 +235,7 @@ static JNINativeMethod SDLActivity_tab[] = {
     { "onNativePinchUpdate", "(F)V", SDL_JAVA_INTERFACE(onNativePinchUpdate) },
     { "onNativePinchEnd", "()V", SDL_JAVA_INTERFACE(onNativePinchEnd) },
     { "onNativeMouse", "(IIFFZ)V", SDL_JAVA_INTERFACE(onNativeMouse) },
-    { "onNativePen", "(IIIFFF)V", SDL_JAVA_INTERFACE(onNativePen) },
+    { "onNativePen", "(IIIIFFF)V", SDL_JAVA_INTERFACE(onNativePen) },
     { "onNativeAccel", "(FFF)V", SDL_JAVA_INTERFACE(onNativeAccel) },
     { "onNativeClipboardChanged", "()V", SDL_JAVA_INTERFACE(onNativeClipboardChanged) },
     { "nativeLowMemory", "()V", SDL_JAVA_INTERFACE(nativeLowMemory) },
@@ -1431,11 +1431,11 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
 // Pen
 JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativePen)(
     JNIEnv *env, jclass jcls,
-    jint pen_id_in, jint button, jint action, jfloat x, jfloat y, jfloat p)
+    jint pen_id_in, jint device_type, jint button, jint action, jfloat x, jfloat y, jfloat p)
 {
     SDL_LockMutex(Android_ActivityMutex);
 
-    Android_OnPen(Android_Window, pen_id_in, button, action, x, y, p);
+    Android_OnPen(Android_Window, pen_id_in, device_type, button, action, x, y, p);
 
     SDL_UnlockMutex(Android_ActivityMutex);
 }

+ 1 - 0
src/dynapi/SDL_dynapi.sym

@@ -1265,6 +1265,7 @@ SDL3_0.0.0 {
     SDL_SavePNG_IO;
     SDL_SavePNG;
     SDL_GetSystemPageSize;
+    SDL_GetPenDeviceType;
     # extra symbols go here (don't modify this line)
   local: *;
 };

+ 1 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -1291,3 +1291,4 @@
 #define SDL_SavePNG_IO SDL_SavePNG_IO_REAL
 #define SDL_SavePNG SDL_SavePNG_REAL
 #define SDL_GetSystemPageSize SDL_GetSystemPageSize_REAL
+#define SDL_GetPenDeviceType SDL_GetPenDeviceType_REAL

+ 1 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -1299,3 +1299,4 @@ SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadPNG,(const char *a),(a),return)
 SDL_DYNAPI_PROC(bool,SDL_SavePNG_IO,(SDL_Surface *a,SDL_IOStream *b,bool c),(a,b,c),return)
 SDL_DYNAPI_PROC(bool,SDL_SavePNG,(SDL_Surface *a,const char *b),(a,b),return)
 SDL_DYNAPI_PROC(int,SDL_GetSystemPageSize,(void),(),return)
+SDL_DYNAPI_PROC(SDL_PenDeviceType,SDL_GetPenDeviceType,(SDL_PenID a),(a),return)

+ 9 - 0
src/events/SDL_pen.c

@@ -199,6 +199,15 @@ SDL_PenInputFlags SDL_GetPenStatus(SDL_PenID instance_id, float *axes, int num_a
     return result;
 }
 
+SDL_PenDeviceType SDL_GetPenDeviceType(SDL_PenID instance_id)
+{
+    SDL_LockRWLockForReading(pen_device_rwlock);
+    const SDL_Pen *pen = FindPenByInstanceId(instance_id);
+    const SDL_PenDeviceType result = pen ? pen->info.device_type : SDL_PEN_DEVICE_TYPE_INVALID;
+    SDL_UnlockRWLock(pen_device_rwlock);
+    return result;
+}
+
 SDL_PenCapabilityFlags SDL_GetPenCapabilityFromAxis(SDL_PenAxis axis)
 {
     // the initial capability bits happen to match up, but as

+ 3 - 0
src/events/SDL_pen_c.h

@@ -36,6 +36,8 @@ typedef Uint32 SDL_PenCapabilityFlags;
 #define SDL_PEN_CAPABILITY_TANGENTIAL_PRESSURE (1u << 6)  /**< Provides barrel pressure on SDL_PEN_AXIS_TANGENTIAL_PRESSURE. */
 #define SDL_PEN_CAPABILITY_ERASER    (1u << 7)  /**< Pen also has an eraser tip. */
 
+// Rename before making this public as it clashes with SDL_PenDeviceType.
+// Prior art in Android calls this "tool type".
 typedef enum SDL_PenSubtype
 {
     SDL_PEN_TYPE_UNKNOWN,   /**< Unknown pen device */
@@ -53,6 +55,7 @@ typedef struct SDL_PenInfo
     Uint32 wacom_id;   /**< For Wacom devices: wacom tool type ID, otherwise 0 (useful e.g. with libwacom) */
     int num_buttons; /**< Number of pen buttons (not counting the pen tip), or -1 if unknown. */
     SDL_PenSubtype subtype;  /**< type of pen device */
+    SDL_PenDeviceType device_type;
 } SDL_PenInfo;
 
 // Backend calls this when a new pen device is hotplugged, plus once for each pen already connected at startup.

+ 2 - 1
src/video/android/SDL_androidpen.c

@@ -33,7 +33,7 @@
 #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)
+void Android_OnPen(SDL_Window *window, int pen_id_in, SDL_PenDeviceType device_type, int button, int action, float x, float y, float p)
 {
     if (!window) {
         return;
@@ -50,6 +50,7 @@ void Android_OnPen(SDL_Window *window, int pen_id_in, int button, int action, fl
         peninfo.capabilities = SDL_PEN_CAPABILITY_PRESSURE | SDL_PEN_CAPABILITY_ERASER;
         peninfo.num_buttons = 2;
         peninfo.subtype = SDL_PEN_TYPE_PEN;
+        peninfo.device_type = device_type;
         pen = SDL_AddPenDevice(0, NULL, &peninfo, (void *) (size_t) pen_id_in);
         if (!pen) {
             SDL_Log("error: can't add a pen device %d", pen_id_in);

+ 1 - 1
src/video/android/SDL_androidpen.h

@@ -22,4 +22,4 @@
 
 #include "SDL_androidvideo.h"
 
-extern void Android_OnPen(SDL_Window *window, int pen_id_in, int button, int action, float x, float y, float p);
+extern void Android_OnPen(SDL_Window *window, int pen_id_in, SDL_PenDeviceType device_type, int button, int action, float x, float y, float p);