diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 770a8d47c6..28293c2913 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -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_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; touch_add(id, x, y, surface); + input->touch_down_serial = serial; SDL_SendTouch(Wayland_GetTouchTimestamp(input, timestamp), (SDL_TouchID)(intptr_t)touch, (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; const Uint64 timestamp_raw_ns = Wayland_GetKeyboardTimestampRaw(input, time); + input->key_serial = serial; + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { has_text = keyboard_input_get_text(text, input, key, SDL_PRESSED, &handled_by_ime); } else { @@ -2388,6 +2395,7 @@ static void tablet_tool_handle_down(void *data, struct zwp_tablet_tool_v2 *tool, struct SDL_WaylandTabletInput *input = data; SDL_WindowData *window = input->tool_focus; input->is_down = SDL_TRUE; + input->press_serial = serial; if (window == NULL) { /* 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 @@ -2455,6 +2463,8 @@ static void tablet_tool_handle_button(void *data, struct zwp_tablet_tool_v2 *too input->is_down = SDL_TRUE; } + input->press_serial = serial; + switch (button) { /* see %{_includedir}/linux/input-event-codes.h */ case 0x14b: /* BTN_STYLUS */ @@ -3036,4 +3046,21 @@ int Wayland_input_ungrab_keyboard(SDL_Window *window) 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 */ diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h index f1d0c52241..6e8afda890 100644 --- a/src/video/wayland/SDL_waylandevents_c.h +++ b/src/video/wayland/SDL_waylandevents_c.h @@ -54,6 +54,7 @@ struct SDL_WaylandTabletInput SDL_WindowData *tool_focus; uint32_t tool_prox_serial; + uint32_t press_serial; /* Last motion location */ wl_fixed_t sx_w; @@ -110,6 +111,11 @@ struct SDL_WaylandInput uint32_t buttons_pressed; + /* Implicit grab serial events */ + Uint32 key_serial; + Uint32 button_press_serial; + Uint32 touch_down_serial; + struct { 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 Uint32 Wayland_GetLastImplicitGrabSerial(struct SDL_WaylandInput *input); + #endif /* SDL_waylandevents_h_ */ diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index fec053c2c0..0e7da693a6 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -1554,7 +1554,7 @@ static void Wayland_activate_window(SDL_VideoData *data, SDL_WindowData *wind, &activation_listener_xdg, 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 * 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) { 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 - * it's actually very likely that this token will be ignored! Maybe add - * support for passing serials (and the associated seat) so this can have - * a better chance of actually raising the window. - * -flibit + /* Pass the seat and last serial from a key event, mouse button press, + * touch down event, or tablet tool event to the activation token in order + * to increases the chances of the window being activated, as compositors + * may require an activation to be in response to an event. */ + if (input) { + seat = input->seat; + serial = Wayland_GetLastImplicitGrabSerial(input); + } + Wayland_activate_window(_this->driverdata, wind, wind->surface, - 0, - NULL); + serial, + seat); } int Wayland_FlashWindow(_THIS, SDL_Window *window, SDL_FlashOperation operation)