90
90
// Scoped function declarations
91
91
static void Wayland_SeatUpdateKeyboardGrab (SDL_WaylandSeat * seat );
92
92
93
- struct SDL_WaylandTouchPoint
93
+ typedef struct
94
94
{
95
95
SDL_TouchID id ;
96
96
wl_fixed_t fx ;
97
97
wl_fixed_t fy ;
98
98
struct wl_surface * surface ;
99
99
100
100
struct wl_list link ;
101
- };
101
+ } SDL_WaylandTouchPoint ;
102
102
103
103
static void Wayland_SeatAddTouch (SDL_WaylandSeat * seat , SDL_TouchID id , wl_fixed_t fx , wl_fixed_t fy , struct wl_surface * surface )
104
104
{
105
- struct SDL_WaylandTouchPoint * tp = SDL_malloc (sizeof (struct SDL_WaylandTouchPoint ));
105
+ SDL_WaylandTouchPoint * tp = SDL_malloc (sizeof (SDL_WaylandTouchPoint ));
106
106
107
107
SDL_zerop (tp );
108
108
tp -> id = id ;
@@ -113,9 +113,37 @@ static void Wayland_SeatAddTouch(SDL_WaylandSeat *seat, SDL_TouchID id, wl_fixed
113
113
WAYLAND_wl_list_insert (& seat -> touch .points , & tp -> link );
114
114
}
115
115
116
+ static void Wayland_SeatCancelTouch (SDL_WaylandSeat * seat , SDL_WaylandTouchPoint * tp )
117
+ {
118
+ if (tp -> surface ) {
119
+ SDL_WindowData * window_data = (SDL_WindowData * )wl_surface_get_user_data (tp -> surface );
120
+
121
+ if (window_data ) {
122
+ const float x = (float )(wl_fixed_to_double (tp -> fx ) / window_data -> current .logical_width );
123
+ const float y = (float )(wl_fixed_to_double (tp -> fy ) / window_data -> current .logical_height );
124
+
125
+ SDL_SendTouch (0 , (SDL_TouchID )(uintptr_t )seat -> touch .wl_touch ,
126
+ (SDL_FingerID )(tp -> id + 1 ), window_data -> sdlwindow , SDL_EVENT_FINGER_CANCELED , x , y , 0.0f );
127
+
128
+ -- window_data -> active_touch_count ;
129
+
130
+ /* If the window currently has mouse focus and has no currently active keyboards, pointers,
131
+ * or touch events, then consider mouse focus to be lost.
132
+ */
133
+ if (SDL_GetMouseFocus () == window_data -> sdlwindow && !window_data -> keyboard_focus_count &&
134
+ !window_data -> pointer_focus_count && !window_data -> active_touch_count ) {
135
+ SDL_SetMouseFocus (NULL );
136
+ }
137
+ }
138
+ }
139
+
140
+ WAYLAND_wl_list_remove (& tp -> link );
141
+ SDL_free (tp );
142
+ }
143
+
116
144
static void Wayland_SeatUpdateTouch (SDL_WaylandSeat * seat , SDL_TouchID id , wl_fixed_t fx , wl_fixed_t fy , struct wl_surface * * surface )
117
145
{
118
- struct SDL_WaylandTouchPoint * tp ;
146
+ SDL_WaylandTouchPoint * tp ;
119
147
120
148
wl_list_for_each (tp , & seat -> touch .points , link ) {
121
149
if (tp -> id == id ) {
@@ -131,7 +159,7 @@ static void Wayland_SeatUpdateTouch(SDL_WaylandSeat *seat, SDL_TouchID id, wl_fi
131
159
132
160
static void Wayland_SeatRemoveTouch (SDL_WaylandSeat * seat , SDL_TouchID id , wl_fixed_t * fx , wl_fixed_t * fy , struct wl_surface * * surface )
133
161
{
134
- struct SDL_WaylandTouchPoint * tp ;
162
+ SDL_WaylandTouchPoint * tp ;
135
163
136
164
wl_list_for_each (tp , & seat -> touch .points , link ) {
137
165
if (tp -> id == id ) {
@@ -152,23 +180,6 @@ static void Wayland_SeatRemoveTouch(SDL_WaylandSeat *seat, SDL_TouchID id, wl_fi
152
180
}
153
181
}
154
182
155
- static bool Wayland_SurfaceHasActiveTouches (SDL_VideoData * display , struct wl_surface * surface )
156
- {
157
- struct SDL_WaylandTouchPoint * tp ;
158
- SDL_WaylandSeat * seat ;
159
-
160
- // Check all seats for active touches on the surface.
161
- wl_list_for_each (seat , & display -> seat_list , link ) {
162
- wl_list_for_each (tp , & seat -> touch .points , link ) {
163
- if (tp -> surface == surface ) {
164
- return true;
165
- }
166
- }
167
- }
168
-
169
- return false;
170
- }
171
-
172
183
static void Wayland_GetScaledMouseRect (SDL_Window * window , SDL_Rect * scaled_rect )
173
184
{
174
185
SDL_WindowData * window_data = window -> internal ;
@@ -751,7 +762,7 @@ static void pointer_handle_leave(void *data, struct wl_pointer *pointer,
751
762
*/
752
763
SDL_Window * mouse_focus = SDL_GetMouseFocus ();
753
764
const bool had_focus = mouse_focus && window -> sdlwindow == mouse_focus ;
754
- if (!-- window -> pointer_focus_count && had_focus && !Wayland_SurfaceHasActiveTouches ( seat -> display , surface ) ) {
765
+ if (!-- window -> pointer_focus_count && had_focus && !window -> active_touch_count ) {
755
766
SDL_SetMouseFocus (NULL );
756
767
}
757
768
@@ -1243,6 +1254,7 @@ static void touch_handler_down(void *data, struct wl_touch *touch, uint32_t seri
1243
1254
y = (float )wl_fixed_to_double (fy ) / (window_data -> current .logical_height - 1 );
1244
1255
}
1245
1256
1257
+ ++ window_data -> active_touch_count ;
1246
1258
SDL_SetMouseFocus (window_data -> sdlwindow );
1247
1259
1248
1260
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
1269
1281
SDL_SendTouch (Wayland_GetTouchTimestamp (seat , timestamp ), (SDL_TouchID )(uintptr_t )touch ,
1270
1282
(SDL_FingerID )(id + 1 ), window_data -> sdlwindow , SDL_EVENT_FINGER_UP , x , y , 0.0f );
1271
1283
1272
- /* If the window currently has mouse focus, the keyboard focus is another window or NULL, the window has no
1273
- * pointers active on it, and the surface has no active touch events, then consider mouse focus to be lost.
1284
+ -- window_data -> active_touch_count ;
1285
+
1286
+ /* If the window currently has mouse focus and has no currently active keyboards, pointers,
1287
+ * or touch events, then consider mouse focus to be lost.
1274
1288
*/
1275
- if (SDL_GetMouseFocus () == window_data -> sdlwindow && seat -> keyboard . focus != window_data &&
1276
- !window_data -> pointer_focus_count && !Wayland_SurfaceHasActiveTouches ( seat -> display , surface ) ) {
1289
+ if (SDL_GetMouseFocus () == window_data -> sdlwindow && ! window_data -> keyboard_focus_count &&
1290
+ !window_data -> pointer_focus_count && !window_data -> active_touch_count ) {
1277
1291
SDL_SetMouseFocus (NULL );
1278
1292
}
1279
1293
}
@@ -1308,39 +1322,11 @@ static void touch_handler_frame(void *data, struct wl_touch *touch)
1308
1322
static void touch_handler_cancel (void * data , struct wl_touch * touch )
1309
1323
{
1310
1324
SDL_WaylandSeat * seat = (SDL_WaylandSeat * )data ;
1311
- struct SDL_WaylandTouchPoint * tp , * temp ;
1325
+ SDL_WaylandTouchPoint * tp , * temp ;
1312
1326
1327
+ // Need the safe loop variant here as cancelling a touch point removes it from the list.
1313
1328
wl_list_for_each_safe (tp , temp , & seat -> touch .points , link ) {
1314
- bool removed = false;
1315
-
1316
- if (tp -> surface ) {
1317
- SDL_WindowData * window_data = (SDL_WindowData * )wl_surface_get_user_data (tp -> surface );
1318
-
1319
- if (window_data ) {
1320
- const float x = (float )(wl_fixed_to_double (tp -> fx ) / window_data -> current .logical_width );
1321
- const float y = (float )(wl_fixed_to_double (tp -> fy ) / window_data -> current .logical_height );
1322
-
1323
- SDL_SendTouch (0 , (SDL_TouchID )(uintptr_t )touch ,
1324
- (SDL_FingerID )(tp -> id + 1 ), window_data -> sdlwindow , SDL_EVENT_FINGER_CANCELED , x , y , 0.0f );
1325
-
1326
- // Remove the touch from the list before checking for still-active touches on the surface.
1327
- WAYLAND_wl_list_remove (& tp -> link );
1328
- removed = true;
1329
-
1330
- /* If the window currently has mouse focus, the keyboard focus is another window or NULL, the window has no
1331
- * pointers active on it, and the surface has no active touch events, then consider mouse focus to be lost.
1332
- */
1333
- if (SDL_GetMouseFocus () == window_data -> sdlwindow && seat -> keyboard .focus != window_data &&
1334
- !window_data -> pointer_focus_count && !Wayland_SurfaceHasActiveTouches (seat -> display , tp -> surface )) {
1335
- SDL_SetMouseFocus (NULL );
1336
- }
1337
- }
1338
- }
1339
-
1340
- if (!removed ) {
1341
- WAYLAND_wl_list_remove (& tp -> link );
1342
- }
1343
- SDL_free (tp );
1329
+ Wayland_SeatCancelTouch (seat , tp );
1344
1330
}
1345
1331
}
1346
1332
@@ -1924,8 +1910,7 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
1924
1910
/* If the window has mouse focus, has no pointers within it, and no active touches, consider
1925
1911
* mouse focus to be lost.
1926
1912
*/
1927
- if (SDL_GetMouseFocus () == window -> sdlwindow && !window -> pointer_focus_count &&
1928
- !Wayland_SurfaceHasActiveTouches (seat -> display , surface )) {
1913
+ if (SDL_GetMouseFocus () == window -> sdlwindow && !window -> pointer_focus_count && !window -> active_touch_count ) {
1929
1914
SDL_SetMouseFocus (NULL );
1930
1915
}
1931
1916
}
@@ -3416,6 +3401,36 @@ void Wayland_DisplayCreateSeat(SDL_VideoData *display, struct wl_seat *wl_seat,
3416
3401
WAYLAND_wl_display_flush (display -> display );
3417
3402
}
3418
3403
3404
+ void Wayland_DisplayRemoveWindowReferencesFromSeats (SDL_VideoData * display , SDL_WindowData * window )
3405
+ {
3406
+ SDL_WaylandSeat * seat ;
3407
+ wl_list_for_each (seat , & display -> seat_list , link )
3408
+ {
3409
+ if (seat -> keyboard .focus == window ) {
3410
+ keyboard_handle_leave (seat , seat -> keyboard .wl_keyboard , 0 , window -> surface );
3411
+ }
3412
+
3413
+ if (seat -> pointer .focus == window ) {
3414
+ pointer_handle_leave (seat , seat -> pointer .wl_pointer , 0 , window -> surface );
3415
+ }
3416
+
3417
+ // Need the safe loop variant here as cancelling a touch point removes it from the list.
3418
+ SDL_WaylandTouchPoint * tp , * temp ;
3419
+ wl_list_for_each_safe (tp , temp , & seat -> touch .points , link ) {
3420
+ if (tp -> surface == window -> surface ) {
3421
+ Wayland_SeatCancelTouch (seat , tp );
3422
+ }
3423
+ }
3424
+
3425
+ SDL_WaylandPenTool * tool ;
3426
+ wl_list_for_each (tool , & seat -> tablet .tool_list , link ) {
3427
+ if (tool -> tool_focus == window -> sdlwindow ) {
3428
+ tablet_tool_handle_proximity_out (tool , tool -> wltool );
3429
+ }
3430
+ }
3431
+ }
3432
+ }
3433
+
3419
3434
void Wayland_SeatDestroy (SDL_WaylandSeat * seat , bool send_events )
3420
3435
{
3421
3436
if (!seat ) {
0 commit comments