Wine applications crash in VNC/headless environments due to invalid all-zero monitor coordinates.
The root cause is: - Environment Issue: VNC systems report all displays as RR_Disconnected - Faulty Fallback: Wine incorrectly reverts to legacy XRandR 1.0 API when no "connected" displays are detected - API Incompatibility: Modern XRandR 1.6 doesn't support Wine's XRandR 1.0 implementation, causing XRRSizes() to return empty display modes - Uninitialized Data: This leaves critical display fields (dmPelsWidth/Height) at initialization value 0
-- v3: winex11: handle fallback display modes when XRandR fails
From: Wei Xie xiewei@uniontech.com
Wine applications crash in VNC/headless environments due to invalid all-zero monitor coordinates.
The root cause is: Environment Issue: VNC systems report all displays as RR_Disconnected Faulty Fallback: Wine incorrectly reverts to legacy XRandR 1.0 API when no "connected" displays are detected API Incompatibility: Modern XRandR 1.6 doesn't support Wine's XRandR 1.0 implementation, causing XRRSizes() to return empty display modes Uninitialized Data: This leaves critical display fields (dmPelsWidth/Height) at initialization value 0 --- server/window.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/server/window.c b/server/window.c index c59b8646118..8d75482940d 100644 --- a/server/window.c +++ b/server/window.c @@ -315,6 +315,8 @@ static void map_point_raw_to_virt( struct desktop *desktop, int *x, int *y ) width_from = monitor->raw.right - monitor->raw.left; height_from = monitor->raw.bottom - monitor->raw.top;
+ if (width_from == 0 || height_from == 0) return; + *x = *x * 2 - (monitor->raw.left * 2 + width_from); *x = (*x * width_to * 2 + width_from) / (width_from * 2); *x = (*x + monitor->virt.left * 2 + width_to) / 2;
From: Wei Xie xiewei@uniontech.com
1. Added fallback logic to use default display dimensions when XRandR fails to provide screen sizes 2. Implemented default mode creation with standard 60Hz refresh rate 3. Added proper error handling for memory allocation failures 4. Maintains compatibility with systems where XRandR extension is not available
The reason for the problem is that in scenes where the monitor is not connected, xrandr does not get connected display --- dlls/winex11.drv/xrandr.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index 979cbc8645f..13d07805f5e 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -267,8 +267,35 @@ static BOOL xrandr10_get_modes( x11drv_settings_id id, DWORD flags, DEVMODEW **n short *rates;
sizes = pXRRSizes( gdi_display, DefaultScreen( gdi_display ), &size_count ); + /* If screen size is not obtained, try using default screen size */ if (size_count <= 0) + { + INT width = DisplayWidth(gdi_display, DefaultScreen(gdi_display)); + INT height = DisplayHeight(gdi_display, DefaultScreen(gdi_display)); + + if (width > 0 && height > 0) + { + /* Use default screen size to create a mode */ + mode_count = 1; + modes = calloc(mode_count * DEPTH_COUNT, sizeof(*modes) + sizeof(SizeID)); + if (!modes) + { + RtlSetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + for (depth_idx = 0, mode = modes; depth_idx < DEPTH_COUNT; ++depth_idx) + { + add_xrandr10_mode(mode, depths[depth_idx], width, height, 0, 0, full); + mode = NEXT_DEVMODEW(mode); + } + + *new_modes = modes; + *new_mode_count = mode_count * DEPTH_COUNT; + return TRUE; + } return FALSE; + }
for (size_idx = 0; size_idx < size_count; ++size_idx) { @@ -350,7 +377,13 @@ static BOOL xrandr10_get_current_mode( x11drv_settings_id id, DEVMODEW *mode )
sizes = pXRRSizes( gdi_display, DefaultScreen( gdi_display ), &size_count ); if (size_count <= 0) - return FALSE; + { + mode->dmBitsPerPel = screen_bpp; + mode->dmPelsWidth = DisplayWidth(gdi_display, DefaultScreen(gdi_display)); + mode->dmPelsHeight = DisplayHeight(gdi_display, DefaultScreen(gdi_display)); + mode->dmDisplayFrequency = 60; + return TRUE; + }
screen_config = pXRRGetScreenInfo( gdi_display, DefaultRootWindow( gdi_display ) ); size_id = pXRRConfigCurrentConfiguration( screen_config, &rotation );
VNC systems report all displays as RR_Disconnected
It seems that this should be fixed on the VNC side instead of being worked around in Wine.
And could you upload an `xrandr --verbose` log?
``` Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 16384 x 16384 HDMI-0 disconnected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 0mm x 0mm DVI-0 disconnected (normal left inverted right x axis y axis) VGA-0 disconnected (normal left inverted right x axis y axis) 1920x1080 (0x54) 148.500MHz +HSync +VSync h: width 1920 start 2008 end 2052 total 2200 skew 0 clock 67.50KHz v: height 1080 start 1084 end 1089 total 1125 clock 60.00Hz ```
This problem not only occurs when using VNC, but also when using other remote tools or virtual machines. This will also occur if the monitor is not connected to the direct ssh connection, which will cause the Wine to be unable to run through ssh on a device without the monitor.
So `XRROutputInfo->connection == RR_Disconnected` but `XRROutputInfo->crtc` is valid? Maybe we can loosen the condition check. Does the attached patch fix your issue?[0001-winex11.drv-Don-t-check-XRandR-output-connection.txt](/uploads/bfbe21e1ef0ebfe5585f2c5e67069e33/0001-winex11.drv-Don-t-check-XRandR-output-connection.txt)
This patch validation is normal, but may affect the logic of fallingback to xrandr version 1.0. I have no environment to verify the situation where fallback to version 1.0, and it is not clear whether such modification will cause this scenario to run abnormally.
On Fri Jun 6 04:04:10 2025 +0000, Wei Xie wrote:
This patch validation is normal, but may affect the logic of fallingback to xrandr version 1.0. I have no environment to verify the situation where fallback to version 1.0, and it is not clear whether such modification will cause this scenario to run abnormally.
If XRandR 1.4 works, I see no reason for it to fall back to XRandR 1.0. To test XRandR 1.0, you can comment out the code after `#ifdef HAVE_XRRGETPROVIDERRESOURCES` in X11DRV_XRandR_Init().

I'm looking at the code comments of the is_broken_driver function that require fallback to version 1.0.
On Fri Jun 6 06:38:26 2025 +0000, Wei Xie wrote:
 I'm looking at the code comments of the is_broken_driver function that require fallback to version 1.0.
is_broken_driver() will return TRUE when only the native mode is available on the Nvidia driver with XRandR 1.4. Removing the RR_Connected check shouldn't affect it.