wayland: Set the mouse state before calling the hit test callback

Update the mouse state before entering the hit test, in case the global state is queried, or the system menu opened, while in the client hit testing callback.
This commit is contained in:
Frank Praznik
2025-01-18 11:59:51 -05:00
parent cd0db8d35e
commit 42e0fb10f8
3 changed files with 13 additions and 14 deletions

View File

@@ -597,6 +597,7 @@ static void pointer_handle_leave(void *data, struct wl_pointer *pointer,
// Clear the capture flag and raise all buttons
wind->sdlwindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
input->buttons_pressed = 0;
SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, 0), wind->sdlwindow, input->pointer_id, SDL_BUTTON_LEFT, false);
SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, 0), wind->sdlwindow, input->pointer_id, SDL_BUTTON_RIGHT, false);
SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, 0), wind->sdlwindow, input->pointer_id, SDL_BUTTON_MIDDLE, false);
@@ -604,7 +605,6 @@ static void pointer_handle_leave(void *data, struct wl_pointer *pointer,
SDL_SendMouseButton(Wayland_GetPointerTimestamp(input, 0), wind->sdlwindow, input->pointer_id, SDL_BUTTON_X2, false);
}
/* 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.
*/
@@ -728,6 +728,13 @@ static void pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_
SDL_VideoData *viddata = window->waylandData;
bool ignore_click = false;
if (state) {
Wayland_UpdateImplicitGrabSerial(input, serial);
input->buttons_pressed |= SDL_BUTTON_MASK(sdl_button);
} else {
input->buttons_pressed &= ~(SDL_BUTTON_MASK(sdl_button));
}
if (sdl_button == SDL_BUTTON_LEFT &&
ProcessHitTest(input->pointer_focus, input->seat, input->sx_w, input->sy_w, serial)) {
return; // don't pass this event on to app.
@@ -747,14 +754,9 @@ static void pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_
* 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).
*
* The mouse is not captured in relative mode.
*/
if (state) { // update our mask of currently-pressed buttons
input->buttons_pressed |= SDL_BUTTON_MASK(sdl_button);
} else {
input->buttons_pressed &= ~(SDL_BUTTON_MASK(sdl_button));
}
// Don't modify the capture flag in relative mode.
if (!viddata->relative_mouse_mode) {
if (input->buttons_pressed != 0) {
window->sdlwindow->flags |= SDL_WINDOW_MOUSE_CAPTURE;
@@ -763,10 +765,6 @@ static void pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_
}
}
if (state) {
Wayland_UpdateImplicitGrabSerial(input, serial);
}
if (!ignore_click) {
SDL_SendMouseButton(timestamp, window->sdlwindow, input->pointer_id, sdl_button, down);
}

View File

@@ -94,7 +94,7 @@ struct SDL_WaylandInput
wl_fixed_t sx_w;
wl_fixed_t sy_w;
uint32_t buttons_pressed;
SDL_MouseButtonFlags buttons_pressed;
// The serial of the last implicit grab event for window activation and selection data.
Uint32 last_implicit_grab_serial;

View File

@@ -892,9 +892,10 @@ static SDL_MouseButtonFlags SDLCALL Wayland_GetGlobalMouseState(float *x, float
SDL_MouseButtonFlags result = 0;
if (focus) {
SDL_VideoData *viddata = SDL_GetVideoDevice()->internal;
int off_x, off_y;
result = SDL_GetMouseState(x, y);
result = viddata->input->buttons_pressed;
SDL_RelativeToGlobalForWindow(focus, focus->x, focus->y, &off_x, &off_y);
*x += off_x;
*y += off_y;