From 5029d50ea8c9a7e231dd35721a14b6bd7524c209 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 10 Nov 2018 16:15:48 -0400 Subject: [PATCH] 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. --- include/SDL_touch.h | 13 +++++ src/core/linux/SDL_evdev.c | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/events/SDL_touch.c | 13 ++++- src/events/SDL_touch_c.h | 3 +- src/video/android/SDL_androidtouch.c | 4 +- src/video/cocoa/SDL_cocoawindow.m | 12 ++++- src/video/emscripten/SDL_emscriptenevents.c | 2 +- src/video/uikit/SDL_uikitview.m | 53 +++++++++++++++++++-- src/video/wayland/SDL_waylandevents.c | 2 +- src/video/wayland/SDL_waylandtouch.c | 2 +- src/video/windows/SDL_windowsevents.c | 6 ++- src/video/winrt/SDL_winrtpointerinput.cpp | 2 +- src/video/x11/SDL_x11xinput2.c | 9 +++- 15 files changed, 109 insertions(+), 15 deletions(-) diff --git a/include/SDL_touch.h b/include/SDL_touch.h index f4075e79a5b5d..926a9e189c511 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; @@ -65,6 +73,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. */ diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c index 5443c21985039..8f22200aed1af 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 73767fbaefa7e..56915f5ab3e06 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 076205ef09204..c95cf708be85b 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 003741644d20c..bed2c499a622b 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 2a4431026e8cd..4070a50fab609 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 5c3e4aaccdd71..37bf055df0165 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 a8e95ccd98f1a..ec2de82f31c4d 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1103,7 +1103,17 @@ - (void)handleTouches:(NSTouchPhase) phase withEvent:(NSEvent *) theEvent 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 14bc24030d45c..d27608a5ae43c 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 caabfac072478..7141f9fd8aa52 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -39,7 +39,9 @@ @implementation SDL_uikitview { SDL_Window *sdlwindow; - SDL_TouchID touchId; + SDL_TouchID directTouchId; + SDL_TouchID indirectTouchId; + UITouch * __weak firstFingerDown; } @@ -68,12 +70,13 @@ - (instancetype)initWithFrame:(CGRect)frame 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 @@ - (void)setSDLWindow:(SDL_Window *)window 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 @@ - (float)pressureForTouch:(UITouch *)touch - (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 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event - (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 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event - (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 0c953a54c203f..5b2cbef44e648 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 1cf37c1a28902..e7d4b77887eb3 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 77d2f7ffca8fe..b8d65d24ab01e 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 bc438f2755185..1ab68144634bb 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 06a8937cf0f58..c2a510e547d76 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);