From e41576188d17fd09c95777d665f6c4532574f8ac Mon Sep 17 00:00:00 2001 From: Sylvain Becker Date: Thu, 4 Apr 2019 16:51:50 +0200 Subject: [PATCH] Add hint SDL_HINT_MOUSE_TOUCH_EVENTS for mouse events to generate touch events controlling whether mouse events should generate synthetic touch events By default SDL will *not* generate touch events for mouse events --- include/SDL_hints.h | 12 ++++++++++ include/SDL_touch.h | 3 +++ src/events/SDL_mouse.c | 48 +++++++++++++++++++++++++++++++++++++++ src/events/SDL_mouse_c.h | 1 + src/events/SDL_touch.c | 49 ++++++++++++++++++++++------------------ 5 files changed, 91 insertions(+), 22 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index ac605db095742..90d0e8150ab3b 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -315,6 +315,18 @@ extern "C" { */ #define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS" +/** + * \brief A variable controlling whether mouse events should generate synthetic touch events + * + * This variable can be set to the following values: + * "0" - Mouse events will not generate touch events + * "1" - Mouse events will generate touch events + * + * By default SDL will *not* generate touch events for mouse events + */ + +#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS" + /** * \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to true. * diff --git a/include/SDL_touch.h b/include/SDL_touch.h index ae94abf7bbca3..99dbcb8c3fa34 100644 --- a/include/SDL_touch.h +++ b/include/SDL_touch.h @@ -60,6 +60,9 @@ typedef struct SDL_Finger /* Used as the device ID for mouse events simulated with touch input */ #define SDL_TOUCH_MOUSEID ((Uint32)-1) +/* Used as the SDL_TouchID for touch events simulated with mouse input */ +#define SDL_MOUSE_TOUCHID ((Sint64)-1) + /* Function prototypes */ diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 451b451a5cc14..893ecc72bd3cf 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -37,6 +37,9 @@ /* The mouse state */ static SDL_Mouse SDL_mouse; +/* for mapping mouse events to touch */ +static SDL_bool track_mouse_down = SDL_FALSE; + static int SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y); @@ -104,6 +107,21 @@ SDL_TouchMouseEventsChanged(void *userdata, const char *name, const char *oldVal } } +static void SDLCALL +SDL_MouseTouchEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_Mouse *mouse = (SDL_Mouse *)userdata; + + if (hint && (*hint == '1' || SDL_strcasecmp(hint, "true") == 0)) { + + SDL_AddTouch(SDL_MOUSE_TOUCHID, SDL_TOUCH_DEVICE_DIRECT, "mouse_input"); + + mouse->mouse_touch_events = SDL_TRUE; + } else { + mouse->mouse_touch_events = SDL_FALSE; + } +} + /* Public functions */ int SDL_MouseInit(void) @@ -127,6 +145,9 @@ SDL_MouseInit(void) SDL_AddHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS, SDL_TouchMouseEventsChanged, mouse); + SDL_AddHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS, + SDL_MouseTouchEventsChanged, mouse); + mouse->cursor_shown = SDL_TRUE; return (0); @@ -298,6 +319,17 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ int xrel; int yrel; + /* SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events */ + if (mouse->mouse_touch_events) { + if (mouseID != SDL_TOUCH_MOUSEID && !relative && track_mouse_down) { + if (window) { + float fx = (float)x / (float)window->w; + float fy = (float)y / (float)window->h; + SDL_SendTouchMotion(SDL_MOUSE_TOUCHID, 0, fx, fy, 1.0f); + } + } + } + if (mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) { int center_x = 0, center_y = 0; SDL_GetWindowSize(window, ¢er_x, ¢er_y); @@ -443,6 +475,22 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state Uint32 type; Uint32 buttonstate = mouse->buttonstate; + /* SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events */ + if (mouse->mouse_touch_events) { + if (mouseID != SDL_TOUCH_MOUSEID && button == SDL_BUTTON_LEFT) { + if (window) { + float fx = (float)mouse->x / (float)window->w; + float fy = (float)mouse->y / (float)window->h; + if (state == SDL_PRESSED) { + track_mouse_down = SDL_TRUE; + } else { + track_mouse_down = SDL_FALSE; + } + SDL_SendTouch(SDL_MOUSE_TOUCHID, 0, track_mouse_down, fx, fy, 1.0f); + } + } + } + /* Figure out which event to perform */ switch (state) { case SDL_PRESSED: diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index 8994e02a0fb4c..9f88d408a5627 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -93,6 +93,7 @@ typedef struct Uint32 double_click_time; int double_click_radius; SDL_bool touch_mouse_events; + SDL_bool mouse_touch_events; /* Data for double-click tracking */ int num_clickstates; diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c index 1f5810af12e4b..3274cc521eaeb 100644 --- a/src/events/SDL_touch.c +++ b/src/events/SDL_touch.c @@ -249,22 +249,25 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, { SDL_Mouse *mouse = SDL_GetMouse(); if (mouse->touch_mouse_events) { - SDL_Window *window = SDL_GetMouseFocus(); - if (window) { - if (down) { - if (finger_touching == SDL_FALSE) { - int pos_x = (int)(x * (float)window->w); - int pos_y = (int)(y * (float)window->h); - finger_touching = SDL_TRUE; - track_touchid = id; - track_fingerid = fingerid; - SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y); - SDL_SendMouseButton(window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); - } - } else { - if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) { - SDL_SendMouseButton(window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); - finger_touching = SDL_FALSE; + /* FIXME: maybe we should only restrict to a few SDL_TouchDeviceType */ + if (id != SDL_MOUSE_TOUCHID) { + SDL_Window *window = SDL_GetMouseFocus(); + if (window) { + if (down) { + if (finger_touching == SDL_FALSE) { + int pos_x = (int)(x * (float)window->w); + int pos_y = (int)(y * (float)window->h); + finger_touching = SDL_TRUE; + track_touchid = id; + track_fingerid = fingerid; + SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y); + SDL_SendMouseButton(window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); + } + } else { + if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) { + SDL_SendMouseButton(window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); + finger_touching = SDL_FALSE; + } } } } @@ -339,12 +342,14 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, { SDL_Mouse *mouse = SDL_GetMouse(); if (mouse->touch_mouse_events) { - SDL_Window *window = SDL_GetMouseFocus(); - if (window) { - if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) { - int pos_x = (int)(x * (float)window->w); - int pos_y = (int)(y * (float)window->h); - SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y); + if (id != SDL_MOUSE_TOUCHID) { + SDL_Window *window = SDL_GetMouseFocus(); + if (window) { + if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) { + int pos_x = (int)(x * (float)window->w); + int pos_y = (int)(y * (float)window->h); + SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y); + } } } }