Skip to content

X11: keep colour game cursors by implementing the RENDER cursor subset - #784

Merged
maxjivi05 merged 2 commits into
WinNative-Emu:mainfrom
kingokksa:fix/mouse-cursor-display
Oct 11, 2026
Merged

maxjivi05 merged 2 commits into
WinNative-Emu:mainfrom
kingokksa:fix/mouse-cursor-display

Conversation

@kingokksa

@kingokksa kingokksa commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Games that ask for a colour cursor (Kingdom Come Deliverance I and II,
Subnautica, Gothic Remake) got the two-colour core arrow instead. winex11
loads libXcursor, libXcursor probes for the RENDER extension, and with no
RENDER in this server it falls back to the monochrome core cursor, so the
pointer loses its colour depth.

RenderExtension answers the subset libXcursor needs and nothing else:
QueryVersion, QueryPictFormats, CreatePicture, FreePicture, CreateCursor and
CreateAnimCursor. CreatePicture snapshots the pixmap while it is still alive,
because libXcursor frees it before CreateCursor; animated cursors show their
first frame. Any other request gets BadImplementation, and a failure is
reported as an X error instead of dropping the game's connection; after 8
failures the arrow is used for the rest of the session.

CursorManager.createArgbCursor builds the cursor drawable from the ARGB data
and un-premultiplies it, because the cursor texture is drawn with a straight
alpha blend while the Xcursor pixels arrive premultiplied. A fully transparent
cursor stays invisible instead of becoming the arrow, since that is how games
hide the pointer.

The extension is registered only when the session asks for it:
applyColorCursors() enables it for X sessions and BANNER_X11_RENDER=0 turns it
off, and applyColorCursorRegistry() writes ClientSideWithRender=N so winex11's
GDI path does not take the RENDER route into a server that only implements
cursors.

kingokksa and others added 2 commits October 10, 2026 22:17
Games that ask for a colour cursor (Kingdom Come Deliverance I and II,
Subnautica, Gothic Remake) got the two-colour core arrow instead. winex11
loads libXcursor, libXcursor probes for the RENDER extension, and with no
RENDER in this server it falls back to the monochrome core cursor, so the
pointer loses its colour depth.

RenderExtension answers the subset libXcursor needs and nothing else:
QueryVersion, QueryPictFormats, CreatePicture, FreePicture, CreateCursor and
CreateAnimCursor. CreatePicture snapshots the pixmap while it is still alive,
because libXcursor frees it before CreateCursor; animated cursors show their
first frame. Any other request gets BadImplementation, and a failure is
reported as an X error instead of dropping the game's connection; after 8
failures the arrow is used for the rest of the session.

CursorManager.createArgbCursor builds the cursor drawable from the ARGB data
and un-premultiplies it, because the cursor texture is drawn with a straight
alpha blend while the Xcursor pixels arrive premultiplied. A fully transparent
cursor stays invisible instead of becoming the arrow, since that is how games
hide the pointer.

The extension is registered only when the session asks for it:
applyColorCursors() enables it for X sessions and BANNER_X11_RENDER=0 turns it
off, and applyColorCursorRegistry() writes ClientSideWithRender=N so winex11's
GDI path does not take the RENDER route into a server that only implements
cursors.
@maxjivi05
maxjivi05 merged commit 36dffda into WinNative-Emu:main Oct 11, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants