wayland: Track the serial numbers for implicit grab events and use them when raising windows

Track the serial numbers of key events, mouse button presses, touch down events, tablet tool down events, and tablet button presses, and pass the serial, along with the seat, to the xdg-activation protocol when raising windows to increase the chances of it succeeding.
main
Frank Praznik 2023-03-31 17:02:13 -04:00
parent 6119ac8bb4
commit 1869e1247d
3 changed files with 50 additions and 8 deletions

View File

@ -710,6 +710,10 @@ static void pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_
} }
} }
if (state) {
input->button_press_serial = serial;
}
Wayland_data_device_set_serial(input->data_device, serial); Wayland_data_device_set_serial(input->data_device, serial);
Wayland_primary_selection_device_set_serial(input->primary_selection_device, serial); Wayland_primary_selection_device_set_serial(input->primary_selection_device, serial);
@ -938,6 +942,7 @@ static void touch_handler_down(void *data, struct wl_touch *touch, uint32_t seri
const float y = dbly / window_data->sdlwindow->h; const float y = dbly / window_data->sdlwindow->h;
touch_add(id, x, y, surface); touch_add(id, x, y, surface);
input->touch_down_serial = serial;
SDL_SendTouch(Wayland_GetTouchTimestamp(input, timestamp), (SDL_TouchID)(intptr_t)touch, SDL_SendTouch(Wayland_GetTouchTimestamp(input, timestamp), (SDL_TouchID)(intptr_t)touch,
(SDL_FingerID)id, window_data->sdlwindow, SDL_TRUE, x, y, 1.0f); (SDL_FingerID)id, window_data->sdlwindow, SDL_TRUE, x, y, 1.0f);
@ -1482,6 +1487,8 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
SDL_bool handled_by_ime = SDL_FALSE; SDL_bool handled_by_ime = SDL_FALSE;
const Uint64 timestamp_raw_ns = Wayland_GetKeyboardTimestampRaw(input, time); const Uint64 timestamp_raw_ns = Wayland_GetKeyboardTimestampRaw(input, time);
input->key_serial = serial;
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
has_text = keyboard_input_get_text(text, input, key, SDL_PRESSED, &handled_by_ime); has_text = keyboard_input_get_text(text, input, key, SDL_PRESSED, &handled_by_ime);
} else { } else {
@ -2388,6 +2395,7 @@ static void tablet_tool_handle_down(void *data, struct zwp_tablet_tool_v2 *tool,
struct SDL_WaylandTabletInput *input = data; struct SDL_WaylandTabletInput *input = data;
SDL_WindowData *window = input->tool_focus; SDL_WindowData *window = input->tool_focus;
input->is_down = SDL_TRUE; input->is_down = SDL_TRUE;
input->press_serial = serial;
if (window == NULL) { if (window == NULL) {
/* tablet_tool_handle_proximity_out gets called when moving over the libdecoration csd. /* tablet_tool_handle_proximity_out gets called when moving over the libdecoration csd.
* that sets input->tool_focus (window) to NULL, but handle_{down,up} events are still * that sets input->tool_focus (window) to NULL, but handle_{down,up} events are still
@ -2455,6 +2463,8 @@ static void tablet_tool_handle_button(void *data, struct zwp_tablet_tool_v2 *too
input->is_down = SDL_TRUE; input->is_down = SDL_TRUE;
} }
input->press_serial = serial;
switch (button) { switch (button) {
/* see %{_includedir}/linux/input-event-codes.h */ /* see %{_includedir}/linux/input-event-codes.h */
case 0x14b: /* BTN_STYLUS */ case 0x14b: /* BTN_STYLUS */
@ -3036,4 +3046,21 @@ int Wayland_input_ungrab_keyboard(SDL_Window *window)
return 0; return 0;
} }
Uint32 Wayland_GetLastImplicitGrabSerial(struct SDL_WaylandInput *input)
{
Uint32 serial = input->key_serial;
if (serial < input->button_press_serial) {
serial = input->button_press_serial;
}
if (serial < input->touch_down_serial) {
serial = input->touch_down_serial;
}
if (input->tablet && serial < input->tablet->press_serial) {
serial = input->tablet->press_serial;
}
return serial;
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND */ #endif /* SDL_VIDEO_DRIVER_WAYLAND */

View File

@ -54,6 +54,7 @@ struct SDL_WaylandTabletInput
SDL_WindowData *tool_focus; SDL_WindowData *tool_focus;
uint32_t tool_prox_serial; uint32_t tool_prox_serial;
uint32_t press_serial;
/* Last motion location */ /* Last motion location */
wl_fixed_t sx_w; wl_fixed_t sx_w;
@ -110,6 +111,11 @@ struct SDL_WaylandInput
uint32_t buttons_pressed; uint32_t buttons_pressed;
/* Implicit grab serial events */
Uint32 key_serial;
Uint32 button_press_serial;
Uint32 touch_down_serial;
struct struct
{ {
struct xkb_keymap *keymap; struct xkb_keymap *keymap;
@ -195,4 +201,6 @@ extern void Wayland_input_destroy_tablet(struct SDL_WaylandInput *input);
extern void Wayland_RegisterTimestampListeners(struct SDL_WaylandInput *input); extern void Wayland_RegisterTimestampListeners(struct SDL_WaylandInput *input);
extern Uint32 Wayland_GetLastImplicitGrabSerial(struct SDL_WaylandInput *input);
#endif /* SDL_waylandevents_h_ */ #endif /* SDL_waylandevents_h_ */

View File

@ -1554,7 +1554,7 @@ static void Wayland_activate_window(SDL_VideoData *data, SDL_WindowData *wind,
&activation_listener_xdg, &activation_listener_xdg,
wind); wind);
/* Note that we are not setting the app_id or serial here. /* Note that we are not setting the app_id here.
* *
* Hypothetically we could set the app_id from data->classname, but * Hypothetically we could set the app_id from data->classname, but
* that part of the API is for _external_ programs, not ourselves. * that part of the API is for _external_ programs, not ourselves.
@ -1574,18 +1574,25 @@ static void Wayland_activate_window(SDL_VideoData *data, SDL_WindowData *wind,
void Wayland_RaiseWindow(_THIS, SDL_Window *window) void Wayland_RaiseWindow(_THIS, SDL_Window *window)
{ {
SDL_WindowData *wind = window->driverdata; SDL_WindowData *wind = window->driverdata;
struct SDL_WaylandInput * input = _this->driverdata->input;
struct wl_seat *seat = NULL;
Uint32 serial = 0;
/* FIXME: This Raise event is arbitrary and doesn't come from an event, so /* Pass the seat and last serial from a key event, mouse button press,
* it's actually very likely that this token will be ignored! Maybe add * touch down event, or tablet tool event to the activation token in order
* support for passing serials (and the associated seat) so this can have * to increases the chances of the window being activated, as compositors
* a better chance of actually raising the window. * may require an activation to be in response to an event.
* -flibit
*/ */
if (input) {
seat = input->seat;
serial = Wayland_GetLastImplicitGrabSerial(input);
}
Wayland_activate_window(_this->driverdata, Wayland_activate_window(_this->driverdata,
wind, wind,
wind->surface, wind->surface,
0, serial,
NULL); seat);
} }
int Wayland_FlashWindow(_THIS, SDL_Window *window, SDL_FlashOperation operation) int Wayland_FlashWindow(_THIS, SDL_Window *window, SDL_FlashOperation operation)