You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Win32] Retrieving handle for cursor leads to non-disposed resource error #2355
Describe the bug
When retrieving a handle for a cursor that does not yet exist (because it is required for a different zoom), a non-disposed resource error is printed in case the non-disposed resource tracker is enabled.
This is caused by the Cursor#win32_getHandle() method creating a cursor instance just to extract the handle out of it. So it's actually intended that the cursor is not disposed, as that would also dispose the handle, but the implementation itself is strange as it should not be necessary to create such a dummy cursor at all:
When taking a look at the issue, it should also be considered that for the hotspotX/hotspotY values no scaling is considered, i.e., for every zoomed version of the cursor the same hotspot coordinates are used even though the image data is at different scales. That seems to be wrong.
To Reproduce
The error can be produced with the following simple snippet executed on a Windows machine with a primary monitor zoom <= 150%:
Note that the System.gc() call is just there to ensure that the dummy cursor is cleaned up by GC, which yields the error, and the Thread.sleep() ensures that the JVM has sufficient time to print the error (as otherwise it may stop before the printing is finished).
Expected behavior
No non-disposed resource should be created and tracked when retrieving cursor handles. Actually I would not expect a dummy cursor to be created just for the sake of getting a handle at all.
Environment:
Select the platform(s) on which the behavior is seen:
All OS
Windows
Linux
macOS
Additional OS info (e.g. OS version, Linux Desktop, etc)
Any Windows version
Workaround (or) Additional context
The error can just be ignored, there is no negative effect. It's just an irrelevant error that indicates a design flaw.
Currently, when retrieving a handle for a specific zoom level via win32_getHandle, a new Cursor resource is internally created just to obtain the native handle. This leads to two major issues:
The temporary resource is never disposed, causing resource leaks.
We cannot safely return a handle from a previously disposedCursor instance.
Proposed Solution
To fix this, the Cursor class should be refactored to manage zoom-level-specific handles more robustly and safely. The following changes are needed:
Extract OS Handle Creation Logic
Move the logic responsible for creating native OS handles out of the constructors and into a separate method. This allows win32_getHandle to lazily create and cache handles on demand.
Always Initialize Default Zoom Handle
Upon creation of a new Cursor, always initialize and store the handle for the default zoom level (100) immediately. This ensures that the cursor is usable right after construction.
Remove handle Field
Eliminate the dedicated handle field from the class. All handle accesses should go through the zoomLevelToHandle map, which now acts as the single source of truth for all zoom levels.
Update All Related Methods
Refactor all methods that previously relied on the handle field to instead use zoomLevelToHandle. This includes:
hashCode()
equals(Object obj)
isDisposed()
destroy()
Benefits
Eliminates resource leaks by ensuring that all handles are properly tracked and owned by the cursor instance.
Enables safe, lazy creation of per-zoom handles when needed.
Ensures default usability by initializing the zoom=100 handle at construction time.
Simplifies and centralizes handle management logic for better maintainability.
Activity
ShahzaibIbrahim commentedon Jul 30, 2025
Problem
Currently, when retrieving a handle for a specific zoom level via
win32_getHandle, a newCursorresource is internally created just to obtain the native handle. This leads to two major issues:Cursorinstance.Proposed Solution
To fix this, the
Cursorclass should be refactored to manage zoom-level-specific handles more robustly and safely. The following changes are needed:Extract OS Handle Creation Logic
Move the logic responsible for creating native OS handles out of the constructors and into a separate method. This allows
win32_getHandleto lazily create and cache handles on demand.Always Initialize Default Zoom Handle
Upon creation of a new
Cursor, always initialize and store the handle for the default zoom level (100) immediately. This ensures that the cursor is usable right after construction.Remove
handleFieldEliminate the dedicated
handlefield from the class. All handle accesses should go through thezoomLevelToHandlemap, which now acts as the single source of truth for all zoom levels.Update All Related Methods
Refactor all methods that previously relied on the
handlefield to instead usezoomLevelToHandle. This includes:hashCode()equals(Object obj)isDisposed()destroy()Benefits
Refactor Cursor handle to support per-zoom handles
Refactor Cursor handle to support per-zoom handles