From: Katharine Chui <[email protected]>

Signed-off-by: Katharine Chui [email protected]
---
 include/ui/sdl2.h |  9 +++++
 ui/sdl2.c         | 98 ++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 106 insertions(+), 1 deletion(-)

diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h
index dbe6e3d9739..d965554e185 100644
--- a/include/ui/sdl2.h
+++ b/include/ui/sdl2.h
@@ -26,6 +26,9 @@
 # include "ui/egl-helpers.h"
 #endif
 
+#include "input.h"
+#include "console.h"
+
 struct sdl2_console {
     DisplayGLCtx dgc;
     DisplayChangeListener dcl;
@@ -52,6 +55,12 @@ struct sdl2_console {
     bool y0_top;
     bool scanout_mode;
 #endif
+    struct {
+        bool pressing;
+        SDL_TouchID touch_id;
+        SDL_FingerID finger_id;
+    } fingers[INPUT_EVENT_SLOTS_MAX];
+    struct touch_slot touch_slots[INPUT_EVENT_SLOTS_MAX];
 };
 
 void sdl2_window_create(struct sdl2_console *scon);
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 032dc14bc39..56ec0c5a97e 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -651,6 +651,92 @@ static void handle_windowevent(SDL_Event *ev)
     }
 }
 
+static void handle_touch(SDL_Event *ev){
+    SDL_TouchFingerEvent *finger_ev = (SDL_TouchFingerEvent *)ev;
+    struct sdl2_console *scon = get_scon_from_window(finger_ev->windowID);
+    Error *err = NULL;
+    int num_slot = -1;
+    int type = -1;
+    int width, height;
+    double x, y;
+    int i;
+
+    if (!scon) {
+        return;
+    }
+
+    switch (finger_ev->type) {
+    case SDL_FINGERDOWN:
+        for (i = 0; i < INPUT_EVENT_SLOTS_MAX; i++){
+            if (scon->fingers[i].pressing &&
+                scon->fingers[i].touch_id == finger_ev->touchId &&
+                scon->fingers[i].finger_id == finger_ev->fingerId){
+                // it is possible for sdl2 to send this twice, in that case 
treat it as an update
+                num_slot = i;
+                type = INPUT_MULTI_TOUCH_TYPE_UPDATE;
+                break;
+            }
+        }
+        if (num_slot != -1){
+            break;
+        }
+        for (i = 0; i < INPUT_EVENT_SLOTS_MAX; i++){
+            if (!scon->fingers[i].pressing){
+                scon->fingers[i].pressing = true;
+                scon->fingers[i].touch_id = finger_ev->touchId;
+                scon->fingers[i].finger_id = finger_ev->fingerId;
+                num_slot = i;
+                type = INPUT_MULTI_TOUCH_TYPE_BEGIN;
+                break;
+            }
+        }
+        break;
+    case SDL_FINGERMOTION:
+        for (i = 0; i < INPUT_EVENT_SLOTS_MAX; i++){
+            if (scon->fingers[i].pressing &&
+                scon->fingers[i].touch_id == finger_ev->touchId &&
+                scon->fingers[i].finger_id == finger_ev->fingerId){
+                num_slot = i;
+                type = INPUT_MULTI_TOUCH_TYPE_UPDATE;
+                break;
+            }
+        }
+        break;
+    case SDL_FINGERUP:
+        for (i = 0; i < INPUT_EVENT_SLOTS_MAX; i++){
+            if (scon->fingers[i].pressing &&
+                scon->fingers[i].touch_id == finger_ev->touchId &&
+                scon->fingers[i].finger_id == finger_ev->fingerId){
+                scon->fingers[i].pressing = false;
+                num_slot = i;
+                type = INPUT_MULTI_TOUCH_TYPE_END;
+                break;
+            }
+        }
+        break;
+    }
+
+    if (num_slot == -1){
+        error_setg(&err, "Cannot handle more than %d fingers",
+                   INPUT_EVENT_SLOTS_MAX);
+        warn_report_err(err);
+        return;
+    }
+
+    width = surface_width(scon->surface);
+    height = surface_height(scon->surface);
+    x = finger_ev->x * width;
+    y = finger_ev->y * height;
+
+    console_handle_touch_event(scon->dcl.con, scon->touch_slots,
+                               num_slot, width, height, x, y,
+                               type, &err);
+
+    if (err) {
+        warn_report_err(err);
+    }
+}
+
 void sdl2_poll_events(struct sdl2_console *scon)
 {
     SDL_Event ev1, *ev = &ev1;
@@ -701,6 +787,12 @@ void sdl2_poll_events(struct sdl2_console *scon)
         case SDL_WINDOWEVENT:
             handle_windowevent(ev);
             break;
+        case SDL_FINGERMOTION:
+        case SDL_FINGERDOWN:
+        case SDL_FINGERUP:
+            idle = 0;
+            handle_touch(ev);
+            break;
         default:
             break;
         }
@@ -838,7 +930,7 @@ static void sdl2_display_early_init(DisplayOptions *o)
 static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
 {
     uint8_t data = 0;
-    int i;
+    int i, j;
     SDL_SysWMinfo info;
     SDL_Surface *icon = NULL;
     char *dir;
@@ -920,6 +1012,10 @@ static void sdl2_display_init(DisplayState *ds, 
DisplayOptions *o)
 #endif
         }
 #endif
+
+        for (j = 0; j < INPUT_EVENT_SLOTS_MAX; j++) {
+            sdl2_console[i].touch_slots[j].tracking_id = -1;
+        }
     }
 
 #ifdef CONFIG_SDL_IMAGE
-- 
2.49.1

Reply via email to