Repository: godotengine/godot (language: cpp)

Issue:
Wayland Cursor custom image doesn't update when using Image instead of Texture2D
### Tested versions

- v4.4.beta.gentoo [4ce466d7f]

### System information

Linux Gentoo using Wayland

### Issue description

When using the Wayland DisplayServer you can only update the custom mouse cursor once if you are using Image instead of Texture2D resources and the images have the same hotspot.

The function `Input.set_custom_mouse_cursor` claims that it is okay to use either an Image or a Texture2D as a custom cursor image. The caching code in `DisplayServerWayland::cursor_set_custom_image` checks for cursor reuse using "get_rid()" on the provided resource. Since an Image does not have a RID, any image will always enter the branch `// We have a cached cursor. Nice.`.

Bug is visible since #96647 was fixed, although the underlying bug was already older than that.

### Workarounds
* Use Texture2D instead of image resources - may cause undesired overhead to convert back to image
* Reset the cursor in between - may cause cursor flickering
* Move the hotspot locations to force a cache miss - unwanted extra work to make images suitable with different hotspots

### Steps to reproduce

* Force editor and game to use the Wayland display server
* Make sure the referenced `img1` and `img2` are imported as Image and not as Texture.

```gdscript
Input.set_custom_mouse_cursor(img1, Input.CURSOR_ARROW)
# Correctly shows img1 as the cursor
Input.set_custom_mouse_cursor(img2, Input.CURSOR_ARROW)
# Still shows img1 as the cursor
```

### Minimal reproduction project (MRP)

[wayland-cursor-reproducer.zip](https://github.com/user-attachments/files/18510307/wayland-cursor-reproducer.zip)


Discussion / hints:
Hi, thank you for you report and for the thorough analysis!

> Since an Image does not have a RID

Shoot, I really had no idea. You just saved me from _a lot_ of debugging :D

You see, this `Image` thing is actually relatively new. For a long time the custom cursor method only supported `Texture2D` but then #88970 allowed images and this quirk slipped right through.

I'll fix this ASAP!

Fix patch:
diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp
index 532eaa6bcf49..f9b34ff043bf 100644
--- a/platform/linuxbsd/wayland/display_server_wayland.cpp
+++ b/platform/linuxbsd/wayland/display_server_wayland.cpp
@@ -1033,7 +1033,7 @@ void DisplayServerWayland::cursor_set_custom_image(const Ref<Resource> &p_cursor
 		HashMap<CursorShape, CustomCursor>::Iterator cursor_c = custom_cursors.find(p_shape);
 
 		if (cursor_c) {
-			if (cursor_c->value.rid == p_cursor->get_rid() && cursor_c->value.hotspot == p_hotspot) {
+			if (cursor_c->value.resource == p_cursor && cursor_c->value.hotspot == p_hotspot) {
 				// We have a cached cursor. Nice.
 				wayland_thread.cursor_set_shape(p_shape);
 				return;
@@ -1049,7 +1049,7 @@ void DisplayServerWayland::cursor_set_custom_image(const Ref<Resource> &p_cursor
 
 		CustomCursor &cursor = custom_cursors[p_shape];
 
-		cursor.rid = p_cursor->get_rid();
+		cursor.resource = p_cursor;
 		cursor.hotspot = p_hotspot;
 
 		wayland_thread.cursor_shape_set_custom_image(p_shape, image, p_hotspot);
diff --git a/platform/linuxbsd/wayland/display_server_wayland.h b/platform/linuxbsd/wayland/display_server_wayland.h
index 8c3bac9c7e3b..43a8b01b3208 100644
--- a/platform/linuxbsd/wayland/display_server_wayland.h
+++ b/platform/linuxbsd/wayland/display_server_wayland.h
@@ -101,7 +101,7 @@ class DisplayServerWayland : public DisplayServer {
 	};
 
 	struct CustomCursor {
-		RID rid;
+		Ref<Resource> resource;
 		Point2i hotspot;
 	};
 


Test patch: