Add a windowID field to SDL_TouchFingerEvent (bug #4331).

This is unimplemented on some platforms and will cause compile errors when building those platform backends for now.
diff --git a/include/SDL_events.h b/include/SDL_events.h
index 282b9fb..1e1e47e 100644
--- a/include/SDL_events.h
+++ b/include/SDL_events.h
@@ -442,6 +442,7 @@
     float dx;           /**< Normalized in the range -1...1 */
     float dy;           /**< Normalized in the range -1...1 */
     float pressure;     /**< Normalized in the range 0...1 */
+    Uint32 windowID;    /**< The window underneath the finger, if any */
 } SDL_TouchFingerEvent;
 
 
diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c
index ae2c7f3..819c5bf 100644
--- a/src/core/linux/SDL_evdev.c
+++ b/src/core/linux/SDL_evdev.c
@@ -403,16 +403,16 @@
 
                             switch(item->touchscreen_data->slots[j].delta) {
                             case EVDEV_TOUCH_SLOTDELTA_DOWN:
-                                SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_TRUE, norm_x, norm_y, norm_pressure);
+                                SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, /* FIXME: window */, SDL_TRUE, norm_x, norm_y, norm_pressure);
                                 item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
                                 break;
                             case EVDEV_TOUCH_SLOTDELTA_UP:
-                                SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_FALSE, norm_x, norm_y, norm_pressure);
+                                SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, /* FIXME: window */, SDL_FALSE, norm_x, norm_y, norm_pressure);
                                 item->touchscreen_data->slots[j].tracking_id = -1;
                                 item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
                                 break;
                             case EVDEV_TOUCH_SLOTDELTA_MOVE:
-                                SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, norm_x, norm_y, norm_pressure);
+                                SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, /* FIXME: window */, norm_x, norm_y, norm_pressure);
                                 item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
                                 break;
                             default:
diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index 98b7298..646649d 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -339,7 +339,7 @@
             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);
+                SDL_SendTouchMotion(SDL_MOUSE_TOUCHID, 0, window, fx, fy, 1.0f);
             }
         }
     }
@@ -509,7 +509,7 @@
             if (window) {
                 float fx = (float)mouse->x / (float)window->w;
                 float fy = (float)mouse->y / (float)window->h;
-                SDL_SendTouch(SDL_MOUSE_TOUCHID, 0, track_mouse_down, fx, fy, 1.0f);
+                SDL_SendTouch(SDL_MOUSE_TOUCHID, 0, window, track_mouse_down, fx, fy, 1.0f);
             }
         }
     }
diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c
index 150acb8..51f2053 100644
--- a/src/events/SDL_touch.c
+++ b/src/events/SDL_touch.c
@@ -239,7 +239,7 @@
 }
 
 int
-SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
+SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window * window,
               SDL_bool down, float x, float y, float pressure)
 {
     int posted;
@@ -259,16 +259,6 @@
         if (mouse->touch_mouse_events) {
             /* FIXME: maybe we should only restrict to a few SDL_TouchDeviceType */
             if (id != SDL_MOUSE_TOUCHID) {
-                SDL_Window *window = SDL_GetMouseFocus();
-                if (window == NULL) {
-                    /* Mouse focus may have been lost by e.g. the window resizing
-                     * due to device orientation change while the mouse state is
-                     * pressed (because its position is now out of the window).
-                     * SendMouse* will update mouse focus again after that, but
-                     * if those are never called then SDL might think the
-                     * 'mouse' has no focus at all. */
-                    window = SDL_GetKeyboardFocus();
-                }
                 if (window) {
                     if (down) {
                         if (finger_touching == SDL_FALSE) {
@@ -332,6 +322,7 @@
             event.tfinger.dx = 0;
             event.tfinger.dy = 0;
             event.tfinger.pressure = pressure;
+            event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
             posted = (SDL_PushEvent(&event) > 0);
         }
     } else {
@@ -344,7 +335,7 @@
         if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
             SDL_Event event;
             event.tfinger.type = SDL_FINGERUP;
-            event.tfinger.touchId =  id;
+            event.tfinger.touchId = id;
             event.tfinger.fingerId = fingerid;
             /* I don't trust the coordinates passed on fingerUp */
             event.tfinger.x = finger->x;
@@ -352,6 +343,7 @@
             event.tfinger.dx = 0;
             event.tfinger.dy = 0;
             event.tfinger.pressure = pressure;
+            event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
             posted = (SDL_PushEvent(&event) > 0);
         }
 
@@ -361,7 +353,7 @@
 }
 
 int
-SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
+SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window * window,
                     float x, float y, float pressure)
 {
     SDL_Touch *touch;
@@ -382,7 +374,6 @@
     {
         if (mouse->touch_mouse_events) {
             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);
@@ -408,7 +399,7 @@
 
     finger = SDL_GetFinger(touch,fingerid);
     if (!finger) {
-        return SDL_SendTouch(id, fingerid, SDL_TRUE, x, y, pressure);
+        return SDL_SendTouch(id, fingerid, window, SDL_TRUE, x, y, pressure);
     }
 
     xrel = x - finger->x;
@@ -440,6 +431,7 @@
         event.tfinger.dx = xrel;
         event.tfinger.dy = yrel;
         event.tfinger.pressure = pressure;
+        event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
         posted = (SDL_PushEvent(&event) > 0);
     }
     return posted;
diff --git a/src/events/SDL_touch_c.h b/src/events/SDL_touch_c.h
index fe73b93..cbd1e78 100644
--- a/src/events/SDL_touch_c.h
+++ b/src/events/SDL_touch_c.h
@@ -44,11 +44,11 @@
 extern SDL_Touch *SDL_GetTouch(SDL_TouchID id);
 
 /* Send a touch down/up event for a touch */
-extern int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
+extern int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window * window,
                          SDL_bool down, float x, float y, float pressure);
 
 /* Send a touch motion event for a touch */
-extern int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
+extern int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window * window,
                                float x, float y, float pressure);
 
 /* Remove a touch */
diff --git a/src/video/android/SDL_androidtouch.c b/src/video/android/SDL_androidtouch.c
index 1320326..7c86921 100644
--- a/src/video/android/SDL_androidtouch.c
+++ b/src/video/android/SDL_androidtouch.c
@@ -69,16 +69,16 @@
     switch (action) {
         case ACTION_DOWN:
         case ACTION_POINTER_DOWN:
-            SDL_SendTouch(touchDeviceId, fingerId, SDL_TRUE, x, y, p);
+            SDL_SendTouch(touchDeviceId, fingerId, window, SDL_TRUE, x, y, p);
             break;
 
         case ACTION_MOVE:
-            SDL_SendTouchMotion(touchDeviceId, fingerId, x, y, p);
+            SDL_SendTouchMotion(touchDeviceId, fingerId, window, x, y, p);
             break;
 
         case ACTION_UP:
         case ACTION_POINTER_UP:
-            SDL_SendTouch(touchDeviceId, fingerId, SDL_FALSE, x, y, p);
+            SDL_SendTouch(touchDeviceId, fingerId, window, SDL_FALSE, x, y, p);
             break;
 
         default:
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index faee02c..0c8557e 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -1132,7 +1132,13 @@
         DLog("Reset Lost Fingers: %d", numFingers);
         for (--numFingers; numFingers >= 0; --numFingers) {
             SDL_Finger* finger = SDL_GetTouchFinger(touchID, numFingers);
-            SDL_SendTouch(touchID, finger->id, SDL_FALSE, 0, 0, 0);
+            /* trackpad touches have no window. If we really wanted one we could
+             * use the window that has mouse or keyboard focus.
+             * Sending a null window currently also prevents synthetic mouse
+             * events from being generated from touch events.
+             */
+            SDL_Window *window = NULL;
+            SDL_SendTouch(touchID, finger->id, window, SDL_FALSE, 0, 0, 0);
         }
     }
 
@@ -1167,10 +1173,24 @@
         const SDL_TouchID touchId = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[touch device];
         SDL_TouchDeviceType devtype = SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE;
 
+        /* trackpad touches have no window. If we really wanted one we could
+         * use the window that has mouse or keyboard focus.
+         * Sending a null window currently also prevents synthetic mouse events
+         * from being generated from touch events.
+         */
+        SDL_Window *window = NULL;
+
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101202 /* Added in the 10.12.2 SDK. */
         if ([touch respondsToSelector:@selector(type)]) {
+            /* TODO: Before implementing direct touch support here, we need to
+             * figure out whether the OS generates mouse events from them on its
+             * own. If it does, we should prevent SendTouch from generating
+             * synthetic mouse events for these touches itself (while also
+             * sending a window.) It will also need to use normalized window-
+             * relative coordinates via [touch locationInView:].
+             */
             if ([touch type] == NSTouchTypeDirect) {
-                devtype = SDL_TOUCH_DEVICE_DIRECT;
+                return;
             }
         }
 #endif
@@ -1187,14 +1207,14 @@
 
         switch (phase) {
         case NSTouchPhaseBegan:
-            SDL_SendTouch(touchId, fingerId, SDL_TRUE, x, y, 1.0f);
+            SDL_SendTouch(touchId, fingerId, window, SDL_TRUE, x, y, 1.0f);
             break;
         case NSTouchPhaseEnded:
         case NSTouchPhaseCancelled:
-            SDL_SendTouch(touchId, fingerId, SDL_FALSE, x, y, 1.0f);
+            SDL_SendTouch(touchId, fingerId, window, SDL_FALSE, x, y, 1.0f);
             break;
         case NSTouchPhaseMoved:
-            SDL_SendTouchMotion(touchId, fingerId, x, y, 1.0f);
+            SDL_SendTouchMotion(touchId, fingerId, window, x, y, 1.0f);
             break;
         default:
             break;
diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c
index 5fb08a6..64a399b 100644
--- a/src/video/emscripten/SDL_emscriptenevents.c
+++ b/src/video/emscripten/SDL_emscriptenevents.c
@@ -455,16 +455,16 @@
         y = touchEvent->touches[i].targetY / client_h;
 
         if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) {
-            SDL_SendTouch(deviceId, id, SDL_TRUE, x, y, 1.0f);
+            SDL_SendTouch(deviceId, id, window_data->window, SDL_TRUE, x, y, 1.0f);
 
             /* disable browser scrolling/pinch-to-zoom if app handles touch events */
             if (!preventDefault && SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
                 preventDefault = 1;
             }
         } else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) {
-            SDL_SendTouchMotion(deviceId, id, x, y, 1.0f);
+            SDL_SendTouchMotion(deviceId, id, window_data->window, x, y, 1.0f);
         } else {
-            SDL_SendTouch(deviceId, id, SDL_FALSE, x, y, 1.0f);
+            SDL_SendTouch(deviceId, id, window_data->window, SDL_FALSE, x, y, 1.0f);
 
             /* block browser's simulated mousedown/mouseup on touchscreen devices */
             preventDefault = 1;
diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m
index eccd81d..35ec4a7 100644
--- a/src/video/uikit/SDL_uikitview.m
+++ b/src/video/uikit/SDL_uikitview.m
@@ -198,7 +198,7 @@
         /* FIXME, need to send: int clicks = (int) touch.tapCount; ? */
 
         CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
-        SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
+        SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
                       SDL_TRUE, locationInView.x, locationInView.y, pressure);
     }
 }
@@ -217,7 +217,7 @@
         /* FIXME, need to send: int clicks = (int) touch.tapCount; ? */
 
         CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
-        SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch),
+        SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
                       SDL_FALSE, locationInView.x, locationInView.y, pressure);
     }
 }
@@ -239,7 +239,7 @@
         }
 
         CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
-        SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch),
+        SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
                             locationInView.x, locationInView.y, pressure);
     }
 }
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index ec3d9b1..f9397fd 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -129,7 +129,7 @@
 }
 
 static void
-touch_del(SDL_TouchID id, float* x, float* y)
+touch_del(SDL_TouchID id, float* x, float* y, struct wl_surface **surface)
 {
     struct SDL_WaylandTouchPoint* tp = touch_points.head;
 
@@ -137,6 +137,7 @@
         if (tp->id == id) {
             *x = tp->x;
             *y = tp->y;
+            *surface = tp->surface;
 
             if (tp->prev) {
                 tp->prev->next = tp->next;
@@ -407,7 +408,7 @@
 
     touch_add(id, x, y, surface);
 
-    SDL_SendTouch(1, (SDL_FingerID)id, SDL_TRUE, x, y, 1.0f);
+    SDL_SendTouch(1, (SDL_FingerID)id, window_data->sdlwindow, SDL_TRUE, x, y, 1.0f);
 }
 
 static void
@@ -415,9 +416,17 @@
                  unsigned int timestamp, int id)
 {
     float x = 0, y = 0;
+    struct wl_surface *surface = NULL;
+    SDL_Window *window = NULL;
 
-    touch_del(id, &x, &y);
-    SDL_SendTouch(1, (SDL_FingerID)id, SDL_FALSE, x, y, 0.0f);
+    touch_del(id, &x, &y, &surface);
+
+    if (surface) {
+        SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(surface);
+        window = window_data->sdlwindow;
+    }
+
+    SDL_SendTouch(1, (SDL_FingerID)id, window, SDL_FALSE, x, y, 0.0f);
 }
 
 static void
@@ -431,7 +440,7 @@
     const float y = dbly / window_data->sdlwindow->h;
 
     touch_update(id, x, y);
-    SDL_SendTouchMotion(1, (SDL_FingerID)id, x, y, 1.0f);
+    SDL_SendTouchMotion(1, (SDL_FingerID)id, window_data->sdlwindow, x, y, 1.0f);
 }
 
 static void
diff --git a/src/video/wayland/SDL_waylandtouch.c b/src/video/wayland/SDL_waylandtouch.c
index 9c05a54..0750cbb 100644
--- a/src/video/wayland/SDL_waylandtouch.c
+++ b/src/video/wayland/SDL_waylandtouch.c
@@ -96,12 +96,12 @@
     switch (touchState) {
         case QtWaylandTouchPointPressed:
         case QtWaylandTouchPointReleased:
-            SDL_SendTouch(deviceId, (SDL_FingerID)id,
+            SDL_SendTouch(deviceId, (SDL_FingerID)id, /* FIXME: window */,
                     (touchState == QtWaylandTouchPointPressed) ? SDL_TRUE : SDL_FALSE,
                     xf, yf, pressuref);
             break;
         case QtWaylandTouchPointMoved:
-            SDL_SendTouchMotion(deviceId, (SDL_FingerID)id, xf, yf, pressuref);
+            SDL_SendTouchMotion(deviceId, (SDL_FingerID)id, /* FIXME: window */, xf, yf, pressuref);
             break;
         default:
             /* Should not happen */
diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index 2316ee3..49e3fbb 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -985,13 +985,13 @@
                     y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
 
                     if (input->dwFlags & TOUCHEVENTF_DOWN) {
-                        SDL_SendTouch(touchId, input->dwID, SDL_TRUE, x, y, 1.0f);
+                        SDL_SendTouch(touchId, input->dwID, data->window, SDL_TRUE, x, y, 1.0f);
                     }
                     if (input->dwFlags & TOUCHEVENTF_MOVE) {
-                        SDL_SendTouchMotion(touchId, input->dwID, x, y, 1.0f);
+                        SDL_SendTouchMotion(touchId, input->dwID, data->window, x, y, 1.0f);
                     }
                     if (input->dwFlags & TOUCHEVENTF_UP) {
-                        SDL_SendTouch(touchId, input->dwID, SDL_FALSE, x, y, 1.0f);
+                        SDL_SendTouch(touchId, input->dwID, data->window, SDL_FALSE, x, y, 1.0f);
                     }
                 }
             }
diff --git a/src/video/winrt/SDL_winrtpointerinput.cpp b/src/video/winrt/SDL_winrtpointerinput.cpp
index 00f73fe..01b523d 100644
--- a/src/video/winrt/SDL_winrtpointerinput.cpp
+++ b/src/video/winrt/SDL_winrtpointerinput.cpp
@@ -233,6 +233,7 @@
         SDL_SendTouch(
             WINRT_TouchID,
             (SDL_FingerID) pointerPoint->PointerId,
+            window,
             SDL_TRUE,
             normalizedPoint.X,
             normalizedPoint.Y,
@@ -256,6 +257,7 @@
         SDL_SendTouchMotion(
             WINRT_TouchID,
             (SDL_FingerID) pointerPoint->PointerId,
+            window,
             normalizedPoint.X,
             normalizedPoint.Y,
             pointerPoint->Properties->Pressure);
@@ -278,6 +280,7 @@
         SDL_SendTouch(
             WINRT_TouchID,
             (SDL_FingerID) pointerPoint->PointerId,
+            window,
             SDL_FALSE,
             normalizedPoint.X,
             normalizedPoint.Y,
diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c
index 2805bf9..724935b 100644
--- a/src/video/x11/SDL_x11xinput2.c
+++ b/src/video/x11/SDL_x11xinput2.c
@@ -230,7 +230,7 @@
             float x, y;
             SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
             xinput2_normalize_touch_coordinates(window, xev->event_x, xev->event_y, &x, &y);
-            SDL_SendTouch(xev->sourceid,xev->detail, SDL_TRUE, x, y, 1.0);
+            SDL_SendTouch(xev->sourceid,xev->detail, /* FIXME: window */, SDL_TRUE, x, y, 1.0);
             return 1;
             }
             break;
@@ -239,7 +239,7 @@
             float x, y;
             SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
             xinput2_normalize_touch_coordinates(window, xev->event_x, xev->event_y, &x, &y);
-            SDL_SendTouch(xev->sourceid,xev->detail, SDL_FALSE, x, y, 1.0);
+            SDL_SendTouch(xev->sourceid,xev->detail, /* FIXME: window */, SDL_FALSE, x, y, 1.0);
             return 1;
             }
             break;
@@ -248,7 +248,7 @@
             float x, y;
             SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
             xinput2_normalize_touch_coordinates(window, xev->event_x, xev->event_y, &x, &y);
-            SDL_SendTouchMotion(xev->sourceid,xev->detail, x, y, 1.0);
+            SDL_SendTouchMotion(xev->sourceid,xev->detail, /* FIXME: window */, x, y, 1.0);
             return 1;
             }
             break;