diff --git a/gdk/wayland/gdkcursor-wayland.c b/gdk/wayland/gdkcursor-wayland.c index e21fd78093..3cc8d94719 100644 --- a/gdk/wayland/gdkcursor-wayland.c +++ b/gdk/wayland/gdkcursor-wayland.c @@ -169,6 +169,7 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display, { GdkTexture *texture; int desired_scale_factor; + gboolean can_cache = TRUE; desired_scale_factor = (int) ceil (desired_scale); @@ -220,7 +221,7 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display, } else if (gdk_cursor_get_texture (cursor)) { - cairo_surface_t *surface; + cairo_surface_t *surface = NULL; struct wl_buffer *buffer; texture = g_object_ref (gdk_cursor_get_texture (cursor)); @@ -234,7 +235,9 @@ from_texture2: *hotspot_x = gdk_cursor_get_hotspot_x (cursor); *hotspot_y = gdk_cursor_get_hotspot_y (cursor); - surface = g_hash_table_lookup (display->cursor_surface_cache, cursor); + if (can_cache) + surface = g_hash_table_lookup (display->cursor_surface_cache, cursor); + if (surface == NULL) { surface = gdk_wayland_display_create_shm_surface (display, @@ -247,8 +250,12 @@ from_texture2: cairo_image_surface_get_stride (surface)); cairo_surface_mark_dirty (surface); - g_object_weak_ref (G_OBJECT (cursor), gdk_wayland_cursor_remove_from_cache, display); - g_hash_table_insert (display->cursor_surface_cache, cursor, surface); + if (can_cache) + { + g_object_weak_ref (G_OBJECT (cursor), gdk_wayland_cursor_remove_from_cache, display); + + g_hash_table_insert (display->cursor_surface_cache, cursor, surface); + } } cairo_surface_reference (surface); @@ -276,6 +283,8 @@ from_texture2: can_cache = (gdk_paintable_get_flags (paintable) & GDK_PAINTABLE_STATIC_CONTENTS) != 0; + can_cache = (gdk_paintable_get_flags (paintable) & GDK_PAINTABLE_STATIC_CONTENTS) != 0; + goto from_texture2; } diff --git a/gdk/wayland/gdkdevice-wayland-private.h b/gdk/wayland/gdkdevice-wayland-private.h index 28e3d7ecb1..0fdb95afc9 100644 --- a/gdk/wayland/gdkdevice-wayland-private.h +++ b/gdk/wayland/gdkdevice-wayland-private.h @@ -68,6 +68,7 @@ struct _GdkWaylandPointerData { guint cursor_timeout_id; guint cursor_image_index; guint cursor_image_delay; + gulong cursor_invalidated_handler; guint touchpad_event_sequence; double current_output_scale; diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index 0d7257eef1..cd3d94e2cd 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -58,11 +58,12 @@ gdk_wayland_device_set_surface_cursor (GdkDevice *device, { if (!pointer->cursor_is_default) { + gdk_wayland_seat_stop_cursor_animation (seat, pointer); + g_clear_object (&pointer->cursor); pointer->cursor = gdk_cursor_new_from_name ("default", NULL); pointer->cursor_is_default = TRUE; - gdk_wayland_seat_stop_cursor_animation (seat, pointer); gdk_wayland_device_update_surface_cursor (device); } else @@ -72,10 +73,11 @@ gdk_wayland_device_set_surface_cursor (GdkDevice *device, } else { + gdk_wayland_seat_stop_cursor_animation (seat, pointer); + g_set_object (&pointer->cursor, cursor); pointer->cursor_is_default = FALSE; - gdk_wayland_seat_stop_cursor_animation (seat, pointer); gdk_wayland_device_update_surface_cursor (device); } } @@ -332,6 +334,23 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device) wl_surface_commit (pointer->pointer_surface); } + GdkPaintable *paintable = gdk_cursor_get_paintable (pointer->cursor); + + if (paintable) + { + if ((gdk_paintable_get_flags (paintable) & GDK_PAINTABLE_STATIC_CONTENTS) == 0) + { + if (pointer->cursor_invalidated_handler == 0) + { + pointer->cursor_invalidated_handler = + g_signal_connect_swapped (paintable, "invalidate-contents", + G_CALLBACK (gdk_wayland_device_update_surface_cursor), device); + } + } + + return G_SOURCE_REMOVE; + } + next_image_index = _gdk_wayland_cursor_get_next_image_index (GDK_WAYLAND_DISPLAY (seat->display), pointer->cursor, diff --git a/gdk/wayland/gdkseat-wayland.c b/gdk/wayland/gdkseat-wayland.c index c851a23c88..18708c7f1a 100644 --- a/gdk/wayland/gdkseat-wayland.c +++ b/gdk/wayland/gdkseat-wayland.c @@ -117,6 +117,15 @@ gdk_wayland_seat_stop_cursor_animation (GdkWaylandSeat *seat, } pointer->cursor_image_index = 0; + + if (pointer->cursor_invalidated_handler != 0) + { + GdkPaintable *paintable; + + paintable = gdk_cursor_get_paintable (pointer->cursor); + g_signal_handler_disconnect (paintable, pointer->cursor_invalidated_handler); + pointer->cursor_invalidated_handler = 0; + } } GdkWaylandTabletData *