Fixed bug 2485 - [PATCH] Wayland: cursor disappears permanently after window loses mouse focus
authorSam Lantinga <slouken@libsdl.org>
Thu, 17 Apr 2014 20:51:28 -0700
changeset 871146f85bfe9303
parent 8710 403c95143f8a
child 8712 e33b5f7df761
Fixed bug 2485 - [PATCH] Wayland: cursor disappears permanently after window loses mouse focus

Bryan Cain

Using any SDL application with the Wayland backend under Weston, if the application sets a cursor with SDL_SetCursor, the cursor will work until the mouse pointer leaves the window. When the pointer re-enters the window, there will be no cursor displayed at all.

I did some digging, and the reason for this is that SDL attaches the buffer to the cursor surface only once (during cursor creation) and assumes that it will stay attached. This is not how Wayland works, though - once the compositor is done rendering the buffer, it will release it, so it is no longer attached to the surface. When the cursor re-enters the window a second time, SDL sets the cursor to the same surface with no buffer attached, so no cursor is displayed.

This is fixed by the attached patch, which makes SDL attach the buffer to the surface when the cursor is set, not when it is created.
src/video/wayland/SDL_waylandmouse.c
     1.1 --- a/src/video/wayland/SDL_waylandmouse.c	Thu Apr 17 20:21:10 2014 -0700
     1.2 +++ b/src/video/wayland/SDL_waylandmouse.c	Thu Apr 17 20:51:28 2014 -0700
     1.3 @@ -53,6 +53,7 @@
     1.4      struct wl_surface  *surface;
     1.5  
     1.6      int                hot_x, hot_y;
     1.7 +    int                w, h;
     1.8  
     1.9      /* Either a preloaded cursor, or one we created ourselves */
    1.10      struct wl_cursor   *cursor;
    1.11 @@ -182,19 +183,11 @@
    1.12  
    1.13          data->surface = wl_compositor_create_surface(wd->compositor);
    1.14          wl_surface_set_user_data(data->surface, NULL);
    1.15 -        wl_surface_attach(data->surface,
    1.16 -                          data->buffer,
    1.17 -                          0,
    1.18 -                          0);
    1.19 -        wl_surface_damage(data->surface,
    1.20 -                          0,
    1.21 -                          0,
    1.22 -                          surface->w,
    1.23 -                          surface->h);
    1.24 -        wl_surface_commit(data->surface);
    1.25  
    1.26          data->hot_x = hot_x;
    1.27          data->hot_y = hot_y;
    1.28 +        data->w = surface->w;
    1.29 +        data->h = surface->h;
    1.30      }
    1.31  
    1.32      return cursor;
    1.33 @@ -210,24 +203,13 @@
    1.34          Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
    1.35          cursor->driverdata = (void *) data;
    1.36  
    1.37 -        /* The wl_buffer here will be destroyed from wl_cursor_theme_destroy
    1.38 -         * if we are fetching this from a wl_cursor_theme, so don't store a
    1.39 -         * reference to it here */
    1.40 -        data->buffer = NULL;
    1.41 +        data->buffer = WAYLAND_wl_cursor_image_get_buffer(wlcursor->images[0]);
    1.42          data->surface = wl_compositor_create_surface(d->compositor);
    1.43          wl_surface_set_user_data(data->surface, NULL);
    1.44 -        wl_surface_attach(data->surface,
    1.45 -                          WAYLAND_wl_cursor_image_get_buffer(wlcursor->images[0]),
    1.46 -                          0,
    1.47 -                          0);
    1.48 -        wl_surface_damage(data->surface,
    1.49 -                          0,
    1.50 -                          0,
    1.51 -                          wlcursor->images[0]->width,
    1.52 -                          wlcursor->images[0]->height);
    1.53 -        wl_surface_commit(data->surface);
    1.54          data->hot_x = wlcursor->images[0]->hotspot_x;
    1.55          data->hot_y = wlcursor->images[0]->hotspot_y;
    1.56 +        data->w = wlcursor->images[0]->width;
    1.57 +        data->h = wlcursor->images[0]->height;
    1.58          data->cursor= wlcursor;
    1.59      } else {
    1.60          SDL_OutOfMemory ();
    1.61 @@ -315,7 +297,7 @@
    1.62      if (!d)
    1.63          return;
    1.64  
    1.65 -    if (d->buffer)
    1.66 +    if (d->buffer && !d->cursor)
    1.67          wl_buffer_destroy(d->buffer);
    1.68  
    1.69      if (d->surface)
    1.70 @@ -341,6 +323,9 @@
    1.71      {
    1.72          Wayland_CursorData *data = cursor->driverdata;
    1.73  
    1.74 +        wl_surface_attach(data->surface, data->buffer, 0, 0);
    1.75 +        wl_surface_damage(data->surface, 0, 0, data->w, data->h);
    1.76 +        wl_surface_commit(data->surface);
    1.77          wl_pointer_set_cursor (pointer, 0,
    1.78                                 data->surface,
    1.79                                 data->hot_x,