diff --git a/include/SDL_events.h b/include/SDL_events.h index 282b9fb76..1e1e47ebe 100644 --- a/include/SDL_events.h +++ b/include/SDL_events.h @@ -442,6 +442,7 @@ typedef struct SDL_TouchFingerEvent 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 ae2c7f324..819c5bf9d 100644 --- a/src/core/linux/SDL_evdev.c +++ b/src/core/linux/SDL_evdev.c @@ -403,16 +403,16 @@ SDL_EVDEV_Poll(void) 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 98b7298ed..646649d99 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -339,7 +339,7 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ 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 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state 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 150acb822..51f2053a8 100644 --- a/src/events/SDL_touch.c +++ b/src/events/SDL_touch.c @@ -239,7 +239,7 @@ SDL_DelFinger(SDL_Touch* touch, SDL_FingerID fingerid) } 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 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, 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 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, 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 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, 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 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, 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 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, } 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 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, { 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 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, 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 @@ SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, 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 fe73b93f2..cbd1e78b9 100644 --- a/src/events/SDL_touch_c.h +++ b/src/events/SDL_touch_c.h @@ -44,11 +44,11 @@ extern int SDL_AddTouch(SDL_TouchID id, SDL_TouchDeviceType type, const char *na 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 132032696..7c86921a7 100644 --- a/src/video/android/SDL_androidtouch.c +++ b/src/video/android/SDL_androidtouch.c @@ -69,16 +69,16 @@ void Android_OnTouch(SDL_Window *window, int touch_device_id_in, int pointer_fin 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 faee02cfc..0c8557e3d 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -1132,7 +1132,13 @@ SetWindowStyle(SDL_Window * window, NSUInteger style) 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 @@ SetWindowStyle(SDL_Window * window, NSUInteger style) 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 @@ SetWindowStyle(SDL_Window * window, NSUInteger style) 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 5fb08a61b..64a399bde 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -455,16 +455,16 @@ Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, vo 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 eccd81d96..35ec4a7a7 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -198,7 +198,7 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick; /* 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 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick; /* 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 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick; } 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 ec3d9b125..f9397fd01 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -129,7 +129,7 @@ touch_update(SDL_TouchID id, float x, float y) } 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 @@ touch_del(SDL_TouchID id, float* x, float* y) 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_handler_down(void *data, struct wl_touch *touch, unsigned int serial, 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 @@ touch_handler_up(void *data, struct wl_touch *touch, unsigned int serial, 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 @@ touch_handler_motion(void *data, struct wl_touch *touch, unsigned int timestamp, 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 9c05a540b..0750cbb9d 100644 --- a/src/video/wayland/SDL_waylandtouch.c +++ b/src/video/wayland/SDL_waylandtouch.c @@ -96,12 +96,12 @@ touch_handle_touch(void *data, 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 2316ee3c2..49e3fbbf7 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -985,13 +985,13 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 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 00f73fefb..01b523de2 100644 --- a/src/video/winrt/SDL_winrtpointerinput.cpp +++ b/src/video/winrt/SDL_winrtpointerinput.cpp @@ -233,6 +233,7 @@ void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::Po SDL_SendTouch( WINRT_TouchID, (SDL_FingerID) pointerPoint->PointerId, + window, SDL_TRUE, normalizedPoint.X, normalizedPoint.Y, @@ -256,6 +257,7 @@ WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPo SDL_SendTouchMotion( WINRT_TouchID, (SDL_FingerID) pointerPoint->PointerId, + window, normalizedPoint.X, normalizedPoint.Y, pointerPoint->Properties->Pressure); @@ -278,6 +280,7 @@ void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::P 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 2805bf90d..724935b86 100644 --- a/src/video/x11/SDL_x11xinput2.c +++ b/src/video/x11/SDL_x11xinput2.c @@ -230,7 +230,7 @@ X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie) 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 @@ X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie) 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 @@ X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie) 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;