|
|
|
|
@@ -90,7 +90,7 @@
|
|
|
|
|
// Scoped function declarations
|
|
|
|
|
static void Wayland_SeatUpdateKeyboardGrab(SDL_WaylandSeat *seat);
|
|
|
|
|
|
|
|
|
|
struct SDL_WaylandTouchPoint
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
SDL_TouchID id;
|
|
|
|
|
wl_fixed_t fx;
|
|
|
|
|
@@ -98,11 +98,11 @@ struct SDL_WaylandTouchPoint
|
|
|
|
|
struct wl_surface *surface;
|
|
|
|
|
|
|
|
|
|
struct wl_list link;
|
|
|
|
|
};
|
|
|
|
|
} SDL_WaylandTouchPoint;
|
|
|
|
|
|
|
|
|
|
static void Wayland_SeatAddTouch(SDL_WaylandSeat *seat, SDL_TouchID id, wl_fixed_t fx, wl_fixed_t fy, struct wl_surface *surface)
|
|
|
|
|
{
|
|
|
|
|
struct SDL_WaylandTouchPoint *tp = SDL_malloc(sizeof(struct SDL_WaylandTouchPoint));
|
|
|
|
|
SDL_WaylandTouchPoint *tp = SDL_malloc(sizeof(SDL_WaylandTouchPoint));
|
|
|
|
|
|
|
|
|
|
SDL_zerop(tp);
|
|
|
|
|
tp->id = id;
|
|
|
|
|
@@ -113,9 +113,37 @@ static void Wayland_SeatAddTouch(SDL_WaylandSeat *seat, SDL_TouchID id, wl_fixed
|
|
|
|
|
WAYLAND_wl_list_insert(&seat->touch.points, &tp->link);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void Wayland_SeatCancelTouch(SDL_WaylandSeat *seat, SDL_WaylandTouchPoint *tp)
|
|
|
|
|
{
|
|
|
|
|
if (tp->surface) {
|
|
|
|
|
SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(tp->surface);
|
|
|
|
|
|
|
|
|
|
if (window_data) {
|
|
|
|
|
const float x = (float)(wl_fixed_to_double(tp->fx) / window_data->current.logical_width);
|
|
|
|
|
const float y = (float)(wl_fixed_to_double(tp->fy) / window_data->current.logical_height);
|
|
|
|
|
|
|
|
|
|
SDL_SendTouch(0, (SDL_TouchID)(uintptr_t)seat->touch.wl_touch,
|
|
|
|
|
(SDL_FingerID)(tp->id + 1), window_data->sdlwindow, SDL_EVENT_FINGER_CANCELED, x, y, 0.0f);
|
|
|
|
|
|
|
|
|
|
--window_data->active_touch_count;
|
|
|
|
|
|
|
|
|
|
/* If the window currently has mouse focus and has no currently active keyboards, pointers,
|
|
|
|
|
* or touch events, then consider mouse focus to be lost.
|
|
|
|
|
*/
|
|
|
|
|
if (SDL_GetMouseFocus() == window_data->sdlwindow && !window_data->keyboard_focus_count &&
|
|
|
|
|
!window_data->pointer_focus_count && !window_data->active_touch_count) {
|
|
|
|
|
SDL_SetMouseFocus(NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WAYLAND_wl_list_remove(&tp->link);
|
|
|
|
|
SDL_free(tp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void Wayland_SeatUpdateTouch(SDL_WaylandSeat *seat, SDL_TouchID id, wl_fixed_t fx, wl_fixed_t fy, struct wl_surface **surface)
|
|
|
|
|
{
|
|
|
|
|
struct SDL_WaylandTouchPoint *tp;
|
|
|
|
|
SDL_WaylandTouchPoint *tp;
|
|
|
|
|
|
|
|
|
|
wl_list_for_each (tp, &seat->touch.points, link) {
|
|
|
|
|
if (tp->id == id) {
|
|
|
|
|
@@ -131,7 +159,7 @@ static void Wayland_SeatUpdateTouch(SDL_WaylandSeat *seat, SDL_TouchID id, wl_fi
|
|
|
|
|
|
|
|
|
|
static void Wayland_SeatRemoveTouch(SDL_WaylandSeat *seat, SDL_TouchID id, wl_fixed_t *fx, wl_fixed_t *fy, struct wl_surface **surface)
|
|
|
|
|
{
|
|
|
|
|
struct SDL_WaylandTouchPoint *tp;
|
|
|
|
|
SDL_WaylandTouchPoint *tp;
|
|
|
|
|
|
|
|
|
|
wl_list_for_each (tp, &seat->touch.points, link) {
|
|
|
|
|
if (tp->id == id) {
|
|
|
|
|
@@ -152,23 +180,6 @@ static void Wayland_SeatRemoveTouch(SDL_WaylandSeat *seat, SDL_TouchID id, wl_fi
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool Wayland_SurfaceHasActiveTouches(SDL_VideoData *display, struct wl_surface *surface)
|
|
|
|
|
{
|
|
|
|
|
struct SDL_WaylandTouchPoint *tp;
|
|
|
|
|
SDL_WaylandSeat *seat;
|
|
|
|
|
|
|
|
|
|
// Check all seats for active touches on the surface.
|
|
|
|
|
wl_list_for_each (seat, &display->seat_list, link) {
|
|
|
|
|
wl_list_for_each (tp, &seat->touch.points, link) {
|
|
|
|
|
if (tp->surface == surface) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void Wayland_GetScaledMouseRect(SDL_Window *window, SDL_Rect *scaled_rect)
|
|
|
|
|
{
|
|
|
|
|
SDL_WindowData *window_data = window->internal;
|
|
|
|
|
@@ -751,7 +762,7 @@ static void pointer_handle_leave(void *data, struct wl_pointer *pointer,
|
|
|
|
|
*/
|
|
|
|
|
SDL_Window *mouse_focus = SDL_GetMouseFocus();
|
|
|
|
|
const bool had_focus = mouse_focus && window->sdlwindow == mouse_focus;
|
|
|
|
|
if (!--window->pointer_focus_count && had_focus && !Wayland_SurfaceHasActiveTouches(seat->display, surface)) {
|
|
|
|
|
if (!--window->pointer_focus_count && had_focus && !window->active_touch_count) {
|
|
|
|
|
SDL_SetMouseFocus(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1243,6 +1254,7 @@ static void touch_handler_down(void *data, struct wl_touch *touch, uint32_t seri
|
|
|
|
|
y = (float)wl_fixed_to_double(fy) / (window_data->current.logical_height - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++window_data->active_touch_count;
|
|
|
|
|
SDL_SetMouseFocus(window_data->sdlwindow);
|
|
|
|
|
|
|
|
|
|
SDL_SendTouch(Wayland_GetTouchTimestamp(seat, timestamp), (SDL_TouchID)(uintptr_t)touch,
|
|
|
|
|
@@ -1269,11 +1281,13 @@ static void touch_handler_up(void *data, struct wl_touch *touch, uint32_t serial
|
|
|
|
|
SDL_SendTouch(Wayland_GetTouchTimestamp(seat, timestamp), (SDL_TouchID)(uintptr_t)touch,
|
|
|
|
|
(SDL_FingerID)(id + 1), window_data->sdlwindow, SDL_EVENT_FINGER_UP, x, y, 0.0f);
|
|
|
|
|
|
|
|
|
|
/* If the window currently has mouse focus, the keyboard focus is another window or NULL, the window has no
|
|
|
|
|
* pointers active on it, and the surface has no active touch events, then consider mouse focus to be lost.
|
|
|
|
|
--window_data->active_touch_count;
|
|
|
|
|
|
|
|
|
|
/* If the window currently has mouse focus and has no currently active keyboards, pointers,
|
|
|
|
|
* or touch events, then consider mouse focus to be lost.
|
|
|
|
|
*/
|
|
|
|
|
if (SDL_GetMouseFocus() == window_data->sdlwindow && seat->keyboard.focus != window_data &&
|
|
|
|
|
!window_data->pointer_focus_count && !Wayland_SurfaceHasActiveTouches(seat->display, surface)) {
|
|
|
|
|
if (SDL_GetMouseFocus() == window_data->sdlwindow && !window_data->keyboard_focus_count &&
|
|
|
|
|
!window_data->pointer_focus_count && !window_data->active_touch_count) {
|
|
|
|
|
SDL_SetMouseFocus(NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -1308,39 +1322,11 @@ static void touch_handler_frame(void *data, struct wl_touch *touch)
|
|
|
|
|
static void touch_handler_cancel(void *data, struct wl_touch *touch)
|
|
|
|
|
{
|
|
|
|
|
SDL_WaylandSeat *seat = (SDL_WaylandSeat *)data;
|
|
|
|
|
struct SDL_WaylandTouchPoint *tp, *temp;
|
|
|
|
|
SDL_WaylandTouchPoint *tp, *temp;
|
|
|
|
|
|
|
|
|
|
// Need the safe loop variant here as cancelling a touch point removes it from the list.
|
|
|
|
|
wl_list_for_each_safe (tp, temp, &seat->touch.points, link) {
|
|
|
|
|
bool removed = false;
|
|
|
|
|
|
|
|
|
|
if (tp->surface) {
|
|
|
|
|
SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(tp->surface);
|
|
|
|
|
|
|
|
|
|
if (window_data) {
|
|
|
|
|
const float x = (float)(wl_fixed_to_double(tp->fx) / window_data->current.logical_width);
|
|
|
|
|
const float y = (float)(wl_fixed_to_double(tp->fy) / window_data->current.logical_height);
|
|
|
|
|
|
|
|
|
|
SDL_SendTouch(0, (SDL_TouchID)(uintptr_t)touch,
|
|
|
|
|
(SDL_FingerID)(tp->id + 1), window_data->sdlwindow, SDL_EVENT_FINGER_CANCELED, x, y, 0.0f);
|
|
|
|
|
|
|
|
|
|
// Remove the touch from the list before checking for still-active touches on the surface.
|
|
|
|
|
WAYLAND_wl_list_remove(&tp->link);
|
|
|
|
|
removed = true;
|
|
|
|
|
|
|
|
|
|
/* If the window currently has mouse focus, the keyboard focus is another window or NULL, the window has no
|
|
|
|
|
* pointers active on it, and the surface has no active touch events, then consider mouse focus to be lost.
|
|
|
|
|
*/
|
|
|
|
|
if (SDL_GetMouseFocus() == window_data->sdlwindow && seat->keyboard.focus != window_data &&
|
|
|
|
|
!window_data->pointer_focus_count && !Wayland_SurfaceHasActiveTouches(seat->display, tp->surface)) {
|
|
|
|
|
SDL_SetMouseFocus(NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!removed) {
|
|
|
|
|
WAYLAND_wl_list_remove(&tp->link);
|
|
|
|
|
}
|
|
|
|
|
SDL_free(tp);
|
|
|
|
|
Wayland_SeatCancelTouch(seat, tp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1924,8 +1910,7 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
|
|
|
|
|
/* If the window has mouse focus, has no pointers within it, and no active touches, consider
|
|
|
|
|
* mouse focus to be lost.
|
|
|
|
|
*/
|
|
|
|
|
if (SDL_GetMouseFocus() == window->sdlwindow && !window->pointer_focus_count &&
|
|
|
|
|
!Wayland_SurfaceHasActiveTouches(seat->display, surface)) {
|
|
|
|
|
if (SDL_GetMouseFocus() == window->sdlwindow && !window->pointer_focus_count && !window->active_touch_count) {
|
|
|
|
|
SDL_SetMouseFocus(NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -3416,6 +3401,36 @@ void Wayland_DisplayCreateSeat(SDL_VideoData *display, struct wl_seat *wl_seat,
|
|
|
|
|
WAYLAND_wl_display_flush(display->display);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Wayland_DisplayRemoveWindowReferencesFromSeats(SDL_VideoData *display, SDL_WindowData *window)
|
|
|
|
|
{
|
|
|
|
|
SDL_WaylandSeat *seat;
|
|
|
|
|
wl_list_for_each (seat, &display->seat_list, link)
|
|
|
|
|
{
|
|
|
|
|
if (seat->keyboard.focus == window) {
|
|
|
|
|
keyboard_handle_leave(seat, seat->keyboard.wl_keyboard, 0, window->surface);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (seat->pointer.focus == window) {
|
|
|
|
|
pointer_handle_leave(seat, seat->pointer.wl_pointer, 0, window->surface);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Need the safe loop variant here as cancelling a touch point removes it from the list.
|
|
|
|
|
SDL_WaylandTouchPoint *tp, *temp;
|
|
|
|
|
wl_list_for_each_safe (tp, temp, &seat->touch.points, link) {
|
|
|
|
|
if (tp->surface == window->surface) {
|
|
|
|
|
Wayland_SeatCancelTouch(seat, tp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SDL_WaylandPenTool *tool;
|
|
|
|
|
wl_list_for_each (tool, &seat->tablet.tool_list, link) {
|
|
|
|
|
if (tool->tool_focus == window->sdlwindow) {
|
|
|
|
|
tablet_tool_handle_proximity_out(tool, tool->wltool);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Wayland_SeatDestroy(SDL_WaylandSeat *seat, bool send_events)
|
|
|
|
|
{
|
|
|
|
|
if (!seat) {
|
|
|
|
|
|