Commit 8c5b7af2d2f317c42c5437aa4b4dc7c3f5a06057

Cameron Gutman 2021-02-25T19:30:47

Wayland: Fix mouse pointer hiding on Plasma Wayland Unlike Mutter and Sway, KWin actually checks the serial passed in wl_pointer_set_cursor(). The serial provided is supposed to be the serial of the pointer enter event, but We were always passing 0. This caused KWin to drop our requests to hide the cursor. Thanks to the KDE folks for spotting this in my debug logs. Fixes #3576

diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 0cb1f67..5e17e12 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -61,55 +61,6 @@
 /* Weston uses a ratio of 10 units per scroll tick */
 #define WAYLAND_WHEEL_AXIS_UNIT 10
 
-typedef struct {
-    // repeat_rate in range of [1, 1000]
-    int32_t repeat_rate;
-    int32_t repeat_delay;
-    SDL_bool is_initialized;
-
-    SDL_bool is_key_down;
-    uint32_t next_repeat_ms;
-    uint32_t scancode;
-    char text[8];
-} SDL_WaylandKeyboardRepeat;
-
-struct SDL_WaylandInput {
-    SDL_VideoData *display;
-    struct wl_seat *seat;
-    struct wl_pointer *pointer;
-    struct wl_touch *touch;
-    struct wl_keyboard *keyboard;
-    SDL_WaylandDataDevice *data_device;
-    struct zwp_relative_pointer_v1 *relative_pointer;
-    struct zwp_confined_pointer_v1 *confined_pointer;
-    SDL_Window *confined_pointer_window;
-    SDL_WindowData *pointer_focus;
-    SDL_WindowData *keyboard_focus;
-
-    /* Last motion location */
-    wl_fixed_t sx_w;
-    wl_fixed_t sy_w;
-
-    double dx_frac;
-    double dy_frac;
-
-    struct {
-        struct xkb_keymap *keymap;
-        struct xkb_state *state;
-    } xkb;
-
-    /* information about axis events on current frame */
-    struct {
-        SDL_bool is_x_discrete;
-        float x;
-
-        SDL_bool is_y_discrete;
-        float y;
-    } pointer_curr_axis_info;
-
-    SDL_WaylandKeyboardRepeat keyboard_repeat;
-};
-
 struct SDL_WaylandTouchPoint {
     SDL_TouchID id;
     float x;
@@ -324,6 +275,7 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
 
     if (window) {
         input->pointer_focus = window;
+        input->pointer_enter_serial = serial;
         SDL_SetMouseFocus(window->sdlwindow);
         /* In the case of e.g. a pointer confine warp, we may receive an enter
          * event with no following motion event, but with the new coordinates
diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h
index 74ea24c..8e3fc99 100644
--- a/src/video/wayland/SDL_waylandevents_c.h
+++ b/src/video/wayland/SDL_waylandevents_c.h
@@ -28,7 +28,55 @@
 #include "SDL_waylandwindow.h"
 #include "SDL_waylanddatamanager.h"
 
-struct SDL_WaylandInput;
+typedef struct {
+    // repeat_rate in range of [1, 1000]
+    int32_t repeat_rate;
+    int32_t repeat_delay;
+    SDL_bool is_initialized;
+
+    SDL_bool is_key_down;
+    uint32_t next_repeat_ms;
+    uint32_t scancode;
+    char text[8];
+} SDL_WaylandKeyboardRepeat;
+
+struct SDL_WaylandInput {
+    SDL_VideoData *display;
+    struct wl_seat *seat;
+    struct wl_pointer *pointer;
+    struct wl_touch *touch;
+    struct wl_keyboard *keyboard;
+    SDL_WaylandDataDevice *data_device;
+    struct zwp_relative_pointer_v1 *relative_pointer;
+    struct zwp_confined_pointer_v1 *confined_pointer;
+    SDL_Window *confined_pointer_window;
+    SDL_WindowData *pointer_focus;
+    SDL_WindowData *keyboard_focus;
+    uint32_t pointer_enter_serial;
+
+    /* Last motion location */
+    wl_fixed_t sx_w;
+    wl_fixed_t sy_w;
+
+    double dx_frac;
+    double dy_frac;
+
+    struct {
+        struct xkb_keymap *keymap;
+        struct xkb_state *state;
+    } xkb;
+
+    /* information about axis events on current frame */
+    struct {
+        SDL_bool is_x_discrete;
+        float x;
+
+        SDL_bool is_y_discrete;
+        float y;
+    } pointer_curr_axis_info;
+
+    SDL_WaylandKeyboardRepeat keyboard_repeat;
+};
 
 extern void Wayland_PumpEvents(_THIS);
 
diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c
index ef259b9..bf0ede0 100644
--- a/src/video/wayland/SDL_waylandmouse.c
+++ b/src/video/wayland/SDL_waylandmouse.c
@@ -318,6 +318,7 @@ Wayland_ShowCursor(SDL_Cursor *cursor)
 {
     SDL_VideoDevice *vd = SDL_GetVideoDevice();
     SDL_VideoData *d = vd->driverdata;
+    struct SDL_WaylandInput *input = d->input;
 
     struct wl_pointer *pointer = d->pointer;
 
@@ -328,7 +329,8 @@ Wayland_ShowCursor(SDL_Cursor *cursor)
     {
         Wayland_CursorData *data = cursor->driverdata;
 
-        wl_pointer_set_cursor (pointer, 0,
+        wl_pointer_set_cursor (pointer,
+                               input->pointer_enter_serial,
                                data->surface,
                                data->hot_x,
                                data->hot_y);
@@ -338,7 +340,8 @@ Wayland_ShowCursor(SDL_Cursor *cursor)
     }
     else
     {
-        wl_pointer_set_cursor (pointer, 0,
+        wl_pointer_set_cursor (pointer,
+                               input->pointer_enter_serial,
                                NULL,
                                0,
                                0);