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.
This commit is contained in:
Ryan C. Gordon 2022-08-06 09:19:52 -04:00
parent e2452ede66
commit f600364b8a
No known key found for this signature in database
GPG Key ID: FA148B892AB48044
2 changed files with 26 additions and 1 deletions

View File

@ -545,7 +545,7 @@ pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_t serial,
enum wl_pointer_button_state state = state_w; enum wl_pointer_button_state state = state_w;
uint32_t sdl_button; uint32_t sdl_button;
if (input->pointer_focus) { if (window) {
switch (button) { switch (button) {
case BTN_LEFT: case BTN_LEFT:
sdl_button = SDL_BUTTON_LEFT; sdl_button = SDL_BUTTON_LEFT;
@ -569,6 +569,23 @@ pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_t serial,
return; 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); Wayland_data_device_set_serial(input->data_device, serial);
SDL_SendMouseButton(window->sdlwindow, 0, 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) uint32_t serial, struct wl_surface *surface)
{ {
struct SDL_WaylandInput *input = data; struct SDL_WaylandInput *input = data;
SDL_WindowData *window;
if (!surface || !SDL_WAYLAND_own_surface(surface)) { if (!surface || !SDL_WAYLAND_own_surface(surface)) {
return; return;
} }
window = wl_surface_get_user_data(surface);
if (window) {
window->sdlwindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
}
/* Stop key repeat before clearing keyboard focus */ /* Stop key repeat before clearing keyboard focus */
keyboard_repeat_clear(&input->keyboard_repeat); keyboard_repeat_clear(&input->keyboard_repeat);

View File

@ -88,6 +88,8 @@ struct SDL_WaylandInput {
wl_fixed_t sx_w; wl_fixed_t sx_w;
wl_fixed_t sy_w; wl_fixed_t sy_w;
uint32_t buttons_pressed;
double dx_frac; double dx_frac;
double dy_frac; double dy_frac;