|
@@ -148,6 +148,19 @@ static void touch_del(SDL_TouchID id, wl_fixed_t *fx, wl_fixed_t *fy, struct wl_
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static SDL_bool Wayland_SurfaceHasActiveTouches(struct wl_surface *surface)
|
|
|
+{
|
|
|
+ struct SDL_WaylandTouchPoint *tp;
|
|
|
+
|
|
|
+ wl_list_for_each (tp, &touch_points, link) {
|
|
|
+ if (tp->surface == surface) {
|
|
|
+ return SDL_TRUE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return SDL_FALSE;
|
|
|
+}
|
|
|
+
|
|
|
static Uint64 Wayland_GetEventTimestamp(Uint64 nsTimestamp)
|
|
|
{
|
|
|
static Uint64 last;
|
|
@@ -581,7 +594,13 @@ static void pointer_handle_leave(void *data, struct wl_pointer *pointer,
|
|
|
SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, 0), wind->sdlwindow, 0, SDL_RELEASED, SDL_BUTTON_X2);
|
|
|
}
|
|
|
|
|
|
- SDL_SetMouseFocus(NULL);
|
|
|
+
|
|
|
+ /* A pointer leave event may be emitted if the compositor hides the pointer in response to receiving a touch event.
|
|
|
+ * Don't relinquish focus if the surface has active touches, as the compositor is just transitioning from mouse to touch mode.
|
|
|
+ */
|
|
|
+ if (!Wayland_SurfaceHasActiveTouches(surface)) {
|
|
|
+ SDL_SetMouseFocus(NULL);
|
|
|
+ }
|
|
|
input->pointer_focus = NULL;
|
|
|
}
|
|
|
}
|
|
@@ -984,6 +1003,8 @@ static void touch_handler_down(void *data, struct wl_touch *touch, uint32_t seri
|
|
|
y = wl_fixed_to_double(fy) / (window_data->wl_window_height - 1);
|
|
|
}
|
|
|
|
|
|
+ SDL_SetMouseFocus(window_data->sdlwindow);
|
|
|
+
|
|
|
SDL_SendTouch(Wayland_GetTouchTimestamp(input, timestamp), (SDL_TouchID)(intptr_t)touch,
|
|
|
(SDL_FingerID)id, window_data->sdlwindow, SDL_TRUE, x, y, 1.0f);
|
|
|
}
|
|
@@ -1007,6 +1028,14 @@ static void touch_handler_up(void *data, struct wl_touch *touch, uint32_t serial
|
|
|
|
|
|
SDL_SendTouch(Wayland_GetTouchTimestamp(input, timestamp), (SDL_TouchID)(intptr_t)touch,
|
|
|
(SDL_FingerID)id, window_data->sdlwindow, SDL_FALSE, x, y, 0.0f);
|
|
|
+
|
|
|
+ /* If the seat lacks pointer focus, the seat's keyboard focus is another window or NULL, this window curently
|
|
|
+ * has mouse focus, and the surface has no active touch events, consider mouse focus to be lost.
|
|
|
+ */
|
|
|
+ if (!input->pointer_focus && input->keyboard_focus != window_data &&
|
|
|
+ SDL_GetMouseFocus() == window_data->sdlwindow && !Wayland_SurfaceHasActiveTouches(surface)) {
|
|
|
+ SDL_SetMouseFocus(NULL);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -1447,15 +1476,18 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
|
|
|
uint32_t serial, struct wl_surface *surface)
|
|
|
{
|
|
|
struct SDL_WaylandInput *input = data;
|
|
|
- SDL_WindowData *window;
|
|
|
+ SDL_WindowData *wind;
|
|
|
+ SDL_Window *window = NULL;
|
|
|
|
|
|
if (!surface || !SDL_WAYLAND_own_surface(surface)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- window = wl_surface_get_user_data(surface);
|
|
|
- if (window) {
|
|
|
- window->sdlwindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
|
|
|
+ wind = wl_surface_get_user_data(surface);
|
|
|
+ if (wind) {
|
|
|
+ wind->keyboard_device = NULL;
|
|
|
+ window = wind->sdlwindow;
|
|
|
+ window->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
|
|
|
}
|
|
|
|
|
|
/* Stop key repeat before clearing keyboard focus */
|
|
@@ -1463,6 +1495,7 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
|
|
|
|
|
|
/* This will release any keys still pressed */
|
|
|
SDL_SetKeyboardFocus(NULL);
|
|
|
+ input->keyboard_focus = NULL;
|
|
|
|
|
|
/* Clear the pressed modifiers. */
|
|
|
input->pressed_modifiers = SDL_KMOD_NONE;
|
|
@@ -1472,6 +1505,13 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
|
|
|
SDL_IME_SetFocus(SDL_FALSE);
|
|
|
}
|
|
|
#endif
|
|
|
+
|
|
|
+ /* If the surface had a pointer leave event while still having active touch events, it retained mouse focus.
|
|
|
+ * Clear it now if all touch events are raised.
|
|
|
+ */
|
|
|
+ if (!input->pointer_focus && SDL_GetMouseFocus() == window && !Wayland_SurfaceHasActiveTouches(surface)) {
|
|
|
+ SDL_SetMouseFocus(NULL);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static SDL_bool keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key, Uint8 state, SDL_bool *handled_by_ime)
|
|
@@ -1651,7 +1691,6 @@ static void seat_handle_capabilities(void *data, struct wl_seat *seat,
|
|
|
}
|
|
|
|
|
|
if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) {
|
|
|
- WAYLAND_wl_list_init(&touch_points);
|
|
|
input->touch = wl_seat_get_touch(seat);
|
|
|
SDL_AddTouch((SDL_TouchID)(intptr_t)input->touch, SDL_TOUCH_DEVICE_DIRECT, "wayland_touch");
|
|
|
wl_touch_set_user_data(input->touch, input);
|
|
@@ -2955,6 +2994,8 @@ void Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ WAYLAND_wl_list_init(&touch_points);
|
|
|
+
|
|
|
input->display = d;
|
|
|
input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, SDL_min(SDL_WL_SEAT_VERSION, version));
|
|
|
input->sx_w = wl_fixed_from_int(0);
|