Commit 5029d50ea8c9a7e231dd35721a14b6bd7524c209

Alex Szpakowski 2018-11-10T16:15:48

Add SDL_TouchDeviceType enum and SDL_GetTouchDeviceType(SDL_TouchID id). Touch device types include SDL_TOUCH_DEVICE_DIRECT (a touch screen with window-relative coordinates for touches), SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE (a trackpad-style device with absolute device coordinates), and SDL_TOUCH_DEVICE_INDIRECT_RELATIVE (a trackpad-style device with screen cursor-relative coordinates). Phone screens are an example of a direct device type. Mac trackpads are the indirect-absolute touch device type. The Apple TV remote is an indirect-relative touch device type.

diff --git a/include/SDL_touch.h b/include/SDL_touch.h
index f4075e7..926a9e1 100644
--- a/include/SDL_touch.h
+++ b/include/SDL_touch.h
@@ -41,6 +41,14 @@ extern "C" {
 typedef Sint64 SDL_TouchID;
 typedef Sint64 SDL_FingerID;
 
+typedef enum
+{
+    SDL_TOUCH_DEVICE_INVALID = -1,
+    SDL_TOUCH_DEVICE_DIRECT,            /* touch screen with window-relative coordinates */
+    SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE, /* trackpad with absolute device coordinates */
+    SDL_TOUCH_DEVICE_INDIRECT_RELATIVE, /* trackpad with screen cursor-relative coordinates */
+} SDL_TouchDeviceType;
+
 typedef struct SDL_Finger
 {
     SDL_FingerID id;
@@ -66,6 +74,11 @@ extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(void);
 extern DECLSPEC SDL_TouchID SDLCALL SDL_GetTouchDevice(int index);
 
 /**
+ * \brief Get the type of the given touch device.
+ */
+extern DECLSPEC SDL_TouchDeviceType SDLCALL SDL_GetTouchDeviceType(SDL_TouchID touchID);
+
+/**
  *  \brief Get the number of active fingers for a given touch device.
  */
 extern DECLSPEC int SDLCALL SDL_GetNumTouchFingers(SDL_TouchID touchID);
diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c
index 5443c21..8f22200 100644
--- a/src/core/linux/SDL_evdev.c
+++ b/src/core/linux/SDL_evdev.c
@@ -475,6 +475,7 @@ SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
     }
 
     ret = SDL_AddTouch(item->fd, /* I guess our fd is unique enough */
+        SDL_TOUCH_DEVICE_DIRECT,
         item->touchscreen_data->name);
     if (ret < 0) {
         SDL_free(item->touchscreen_data->slots);
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 73767fb..56915f5 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -712,3 +712,4 @@
 #define SDL_RenderFillRectsF SDL_RenderFillRectsF_REAL
 #define SDL_RenderCopyF SDL_RenderCopyF_REAL
 #define SDL_RenderCopyExF SDL_RenderCopyExF_REAL
+#define SDL_GetTouchDeviceType SDL_GetTouchDeviceType_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 076205e..c95cf70 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -766,3 +766,4 @@ SDL_DYNAPI_PROC(int,SDL_RenderFillRectF,(SDL_Renderer *a, const SDL_FRect *b),(a
 SDL_DYNAPI_PROC(int,SDL_RenderFillRectsF,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_RenderCopyF,(SDL_Renderer *a, SDL_Texture *b, const SDL_Rect *c, const SDL_FRect *d),(a,b,c,d),return)
 SDL_DYNAPI_PROC(int,SDL_RenderCopyExF,(SDL_Renderer *a, SDL_Texture *b, const SDL_Rect *c, const SDL_FRect *d, const double e, const SDL_FPoint *f, const SDL_RendererFlip g),(a,b,c,d,e,f,g),return)
+SDL_DYNAPI_PROC(SDL_TouchDeviceType,SDL_GetTouchDeviceType,(SDL_TouchID a),(a),return)
diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c
index 0037416..bed2c49 100644
--- a/src/events/SDL_touch.c
+++ b/src/events/SDL_touch.c
@@ -86,6 +86,16 @@ SDL_GetTouch(SDL_TouchID id)
     return SDL_touchDevices[index];
 }
 
+SDL_TouchDeviceType
+SDL_GetTouchDeviceType(SDL_TouchID id)
+{
+    SDL_Touch *touch = SDL_GetTouch(id);
+    if (touch) {
+        return touch->type;
+    }
+    return SDL_TOUCH_DEVICE_INVALID;
+}
+
 static int
 SDL_GetFingerIndex(const SDL_Touch * touch, SDL_FingerID fingerid)
 {
@@ -133,7 +143,7 @@ SDL_GetTouchFinger(SDL_TouchID touchID, int index)
 }
 
 int
-SDL_AddTouch(SDL_TouchID touchID, const char *name)
+SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
 {
     SDL_Touch **touchDevices;
     int index;
@@ -163,6 +173,7 @@ SDL_AddTouch(SDL_TouchID touchID, const char *name)
 
     /* we're setting the touch properties */
     SDL_touchDevices[index]->id = touchID;
+    SDL_touchDevices[index]->type = type;
     SDL_touchDevices[index]->num_fingers = 0;
     SDL_touchDevices[index]->max_fingers = 0;
     SDL_touchDevices[index]->fingers = NULL;
diff --git a/src/events/SDL_touch_c.h b/src/events/SDL_touch_c.h
index 2a44310..4070a50 100644
--- a/src/events/SDL_touch_c.h
+++ b/src/events/SDL_touch_c.h
@@ -27,6 +27,7 @@
 typedef struct SDL_Touch
 {
     SDL_TouchID id;
+    SDL_TouchDeviceType type;
     int num_fingers;
     int max_fingers;
     SDL_Finger** fingers;
@@ -37,7 +38,7 @@ typedef struct SDL_Touch
 extern int SDL_TouchInit(void);
 
 /* Add a touch, returning the index of the touch, or -1 if there was an error. */
-extern int SDL_AddTouch(SDL_TouchID id, const char *name);
+extern int SDL_AddTouch(SDL_TouchID id, SDL_TouchDeviceType type, const char *name);
 
 /* Get the touch with a given id */
 extern SDL_Touch *SDL_GetTouch(SDL_TouchID id);
diff --git a/src/video/android/SDL_androidtouch.c b/src/video/android/SDL_androidtouch.c
index 5c3e4aa..37bf055 100644
--- a/src/video/android/SDL_androidtouch.c
+++ b/src/video/android/SDL_androidtouch.c
@@ -72,7 +72,7 @@ void Android_InitTouch(void)
 
     if (0 < number) {
         for (i = 0; i < number; ++i) {
-            SDL_AddTouch((SDL_TouchID) ids[i], ""); /* no error handling */
+            SDL_AddTouch((SDL_TouchID) ids[i], SDL_TOUCH_DEVICE_DIRECT, ""); /* no error handling */
         }
         SDL_free(ids);
     }
@@ -97,7 +97,7 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio
     }
 
     touchDeviceId = (SDL_TouchID)touch_device_id_in;
-    if (SDL_AddTouch(touchDeviceId, "") < 0) {
+    if (SDL_AddTouch(touchDeviceId, SDL_TOUCH_DEVICE_DIRECT, "") < 0) {
         SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__);
     }
 
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index a8e95cc..ec2de82 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -1103,7 +1103,17 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
 
     for (NSTouch *touch in touches) {
         const SDL_TouchID touchId = (SDL_TouchID)(intptr_t)[touch device];
-        if (SDL_AddTouch(touchId, "") < 0) {
+        SDL_TouchDeviceType devtype = SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101202 /* Added in the 10.12.2 SDK. */
+        if ([touch respondsToSelector:@selector(type)]) {
+            if ([touch type] == NSTouchTypeDirect) {
+                devtype = SDL_TOUCH_DEVICE_DIRECT;
+            }
+        }
+#endif
+
+        if (SDL_AddTouch(touchId, devtype, "") < 0) {
             return;
         }
 
diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c
index 14bc240..d27608a 100644
--- a/src/video/emscripten/SDL_emscriptenevents.c
+++ b/src/video/emscripten/SDL_emscriptenevents.c
@@ -428,7 +428,7 @@ Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, vo
     int preventDefault = 0;
 
     SDL_TouchID deviceId = 1;
-    if (SDL_AddTouch(deviceId, "") < 0) {
+    if (SDL_AddTouch(deviceId, SDL_TOUCH_DEVICE_DIRECT, "") < 0) {
          return 0;
     }
 
diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m
index caabfac..7141f9f 100644
--- a/src/video/uikit/SDL_uikitview.m
+++ b/src/video/uikit/SDL_uikitview.m
@@ -39,7 +39,9 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick;
 @implementation SDL_uikitview {
     SDL_Window *sdlwindow;
 
-    SDL_TouchID touchId;
+    SDL_TouchID directTouchId;
+    SDL_TouchID indirectTouchId;
+
     UITouch * __weak firstFingerDown;
 }
 
@@ -68,12 +70,13 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick;
         self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
         self.autoresizesSubviews = YES;
 
+        directTouchId = 1;
+        indirectTouchId = 2;
+
 #if !TARGET_OS_TV
         self.multipleTouchEnabled = YES;
+        SDL_AddTouch(directTouchId, SDL_TOUCH_DEVICE_DIRECT, "");
 #endif
-
-        touchId = 1;
-        SDL_AddTouch(touchId, "");
     }
 
     return self;
@@ -135,6 +138,30 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick;
     sdlwindow = window;
 }
 
+- (SDL_TouchDeviceType)touchTypeForTouch:(UITouch *)touch
+{
+#ifdef __IPHONE_9_0
+    if ([touch respondsToSelector:@selector((type))]) {
+        if (touch.type == UITouchTypeIndirect) {
+            return SDL_TOUCH_DEVICE_INDIRECT_RELATIVE;
+        }
+    }
+#endif
+
+    return SDL_TOUCH_DEVICE_DIRECT;
+}
+
+- (SDL_TouchID)touchIdForType:(SDL_TouchDeviceType)type
+{
+    switch (type) {
+        case SDL_TOUCH_DEVICE_DIRECT:
+        default:
+            return directTouchId;
+        case SDL_TOUCH_DEVICE_INDIRECT_RELATIVE:
+            return indirectTouchId;
+    }
+}
+
 - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize
 {
     CGPoint point = [touch locationInView:self];
@@ -162,8 +189,14 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick;
 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
 {
     for (UITouch *touch in touches) {
+        SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
+        SDL_TouchID touchId = [self touchIdForType:touchType];
         float pressure = [self pressureForTouch:touch];
 
+        if (SDL_AddTouch(touchId, touchType, "") < 0) {
+            continue;
+        }
+
         if (!firstFingerDown) {
             CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
             int clicks = (int) touch.tapCount;
@@ -186,8 +219,14 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick;
 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
 {
     for (UITouch *touch in touches) {
+        SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
+        SDL_TouchID touchId = [self touchIdForType:touchType];
         float pressure = [self pressureForTouch:touch];
 
+        if (SDL_AddTouch(touchId, touchType, "") < 0) {
+            continue;
+        }
+
         if (touch == firstFingerDown) {
             /* send mouse up */
             int clicks = (int) touch.tapCount;
@@ -209,8 +248,14 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick;
 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
 {
     for (UITouch *touch in touches) {
+        SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
+        SDL_TouchID touchId = [self touchIdForType:touchType];
         float pressure = [self pressureForTouch:touch];
 
+        if (SDL_AddTouch(touchId, touchType, "") < 0) {
+            continue;
+        }
+
         if (touch == firstFingerDown) {
             CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
 
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 0c953a5..5b2cbef 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -614,7 +614,7 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
     }
 
     if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) {
-        SDL_AddTouch(1, "wayland_touch");
+        SDL_AddTouch(1, SDL_TOUCH_DEVICE_DIRECT, "wayland_touch");
         input->touch = wl_seat_get_touch(seat);
         wl_touch_set_user_data(input->touch, input);
         wl_touch_add_listener(input->touch, &touch_listener,
diff --git a/src/video/wayland/SDL_waylandtouch.c b/src/video/wayland/SDL_waylandtouch.c
index 1cf37c1..e7d4b77 100644
--- a/src/video/wayland/SDL_waylandtouch.c
+++ b/src/video/wayland/SDL_waylandtouch.c
@@ -89,7 +89,7 @@ touch_handle_touch(void *data,
     */
 
     SDL_TouchID deviceId = 1;
-    if (SDL_AddTouch(deviceId, "qt_touch_extension") < 0) {
+    if (SDL_AddTouch(deviceId, SDL_TOUCH_DEVICE_DIRECT, "qt_touch_extension") < 0) {
          SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__);
     }
 
diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index 77d2f7f..b8d65d2 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -932,7 +932,11 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
                     PTOUCHINPUT input = &inputs[i];
 
                     const SDL_TouchID touchId = (SDL_TouchID)((size_t)input->hSource);
-                    if (SDL_AddTouch(touchId, "") < 0) {
+
+                    /* TODO: Can we use GetRawInputDeviceInfo and HID info to
+                       determine if this is a direct or indirect touch device?
+                     */
+                    if (SDL_AddTouch(touchId, SDL_TOUCH_DEVICE_DIRECT, "") < 0) {
                         continue;
                     }
 
diff --git a/src/video/winrt/SDL_winrtpointerinput.cpp b/src/video/winrt/SDL_winrtpointerinput.cpp
index bc438f2..1ab6814 100644
--- a/src/video/winrt/SDL_winrtpointerinput.cpp
+++ b/src/video/winrt/SDL_winrtpointerinput.cpp
@@ -44,7 +44,7 @@ static unsigned int WINRT_LeftFingerDown = 0;
 void
 WINRT_InitTouch(_THIS)
 {
-    SDL_AddTouch(WINRT_TouchID, "");
+    SDL_AddTouch(WINRT_TouchID, SDL_TOUCH_DEVICE_DIRECT, "");
 }
 
 
diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c
index 06a8937..c2a510e 100644
--- a/src/video/x11/SDL_x11xinput2.c
+++ b/src/video/x11/SDL_x11xinput2.c
@@ -244,6 +244,7 @@ X11_InitXinput2Multitouch(_THIS)
         XIDeviceInfo *dev = &info[i];
         for (j = 0; j < dev->num_classes; j++) {
             SDL_TouchID touchId;
+            SDL_TouchDeviceType touchType;
             XIAnyClassInfo *class = dev->classes[j];
             XITouchClassInfo *t = (XITouchClassInfo*)class;
 
@@ -251,8 +252,14 @@ X11_InitXinput2Multitouch(_THIS)
             if (class->type != XITouchClass)
                 continue;
 
+            if (t->mode == XIDependentTouch) {
+                touchType = SDL_TOUCH_DEVICE_INDIRECT_RELATIVE;
+            } else { /* XIDirectTouch */
+                touchType = SDL_TOUCH_DEVICE_DIRECT;
+            }
+
             touchId = t->sourceid;
-            SDL_AddTouch(touchId, dev->name);
+            SDL_AddTouch(touchId, touchType, dev->name);
         }
     }
     X11_XIFreeDeviceInfo(info);