wayland: Mark window as MOUSE_CAPTURE while a mouse button is down. Wayland works like SDL's "auto capture" feature already, tracking the mouse globally only while a drag is occuring, and this is the only way to get mouse input outside the window. Setting this flag ourselves lets SDL_CaptureMouse() work in the most common use case without actually implementing CaptureMouse for the backend, including SDL's auto capture feature. Fixes #6010.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 2b547fa..14a2843 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -545,7 +545,7 @@ pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_t serial,
enum wl_pointer_button_state state = state_w;
uint32_t sdl_button;
- if (input->pointer_focus) {
+ if (window) {
switch (button) {
case BTN_LEFT:
sdl_button = SDL_BUTTON_LEFT;
@@ -569,6 +569,23 @@ pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_t serial,
return;
}
+ /* Wayland won't let you "capture" the mouse, but it will
+ automatically track the mouse outside the window if you
+ drag outside of it, until you let go of all buttons (even
+ if you add or remove presses outside the window, as long
+ as any button is still down, the capture remains) */
+ if (state) { /* update our mask of currently-pressed buttons */
+ input->buttons_pressed |= SDL_BUTTON(sdl_button);
+ } else {
+ input->buttons_pressed &= ~(SDL_BUTTON(sdl_button));
+ }
+
+ if (input->buttons_pressed != 0) {
+ window->sdlwindow->flags |= SDL_WINDOW_MOUSE_CAPTURE;
+ } else {
+ window->sdlwindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
+ }
+
Wayland_data_device_set_serial(input->data_device, serial);
SDL_SendMouseButton(window->sdlwindow, 0,
@@ -913,11 +930,17 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
uint32_t serial, struct wl_surface *surface)
{
struct SDL_WaylandInput *input = data;
+ SDL_WindowData *window;
if (!surface || !SDL_WAYLAND_own_surface(surface)) {
return;
}
+ window = wl_surface_get_user_data(surface);
+ if (window) {
+ window->sdlwindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
+ }
+
/* Stop key repeat before clearing keyboard focus */
keyboard_repeat_clear(&input->keyboard_repeat);
diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h
index 59dc0c8..9bcb2c9 100644
--- a/src/video/wayland/SDL_waylandevents_c.h
+++ b/src/video/wayland/SDL_waylandevents_c.h
@@ -88,6 +88,8 @@ struct SDL_WaylandInput {
wl_fixed_t sx_w;
wl_fixed_t sy_w;
+ uint32_t buttons_pressed;
+
double dx_frac;
double dy_frac;