Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/winex11.drv/xrandr.c | 304 +++++++++++++++++++++-----------------
1 file changed, 168 insertions(+), 136 deletions(-)
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c
index 67fd2851825..155bd85d811 100644
--- a/dlls/winex11.drv/xrandr.c
+++ b/dlls/winex11.drv/xrandr.c
@@ -83,11 +83,6 @@ MAKE_FUNCPTR(XRRFreeProviderInfo)
#undef MAKE_FUNCPTR
-static struct x11drv_mode_info *dd_modes;
-static SizeID *xrandr10_modes;
-static unsigned int xrandr_mode_count;
-static int xrandr_current_mode = -1;
-
static int load_xrandr(void)
{
int r = 0;
@@ -144,157 +139,187 @@ static int XRandRErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
return 1;
}
-static int xrandr10_get_current_mode(void)
+/* XRandR 1.0 display settings handler */
+static BOOL xrandr10_get_id( const WCHAR *device_name, ULONG_PTR *id )
{
- SizeID size;
- Rotation rot;
- XRRScreenConfiguration *sc;
- short rate;
- unsigned int i;
- int res = -1;
+ WCHAR primary_adapter[CCHDEVICENAME];
- if (xrandr_current_mode != -1)
- return xrandr_current_mode;
+ if (!get_primary_adapter( primary_adapter ))
+ return FALSE;
- sc = pXRRGetScreenInfo (gdi_display, DefaultRootWindow( gdi_display ));
- size = pXRRConfigCurrentConfiguration (sc, &rot);
- rate = pXRRConfigCurrentRate (sc);
- pXRRFreeScreenConfigInfo(sc);
-
- for (i = 0; i < xrandr_mode_count; ++i)
- {
- if (xrandr10_modes[i] == size && dd_modes[i].refresh_rate == rate)
- {
- res = i;
- break;
- }
- }
- if (res == -1)
- {
- ERR("In unknown mode, returning default\n");
- return 0;
- }
-
- xrandr_current_mode = res;
- return res;
+ /* RandR 1.0 only supports changing the primary adapter settings.
+ * For non-primary adapters, an id is still provided but getting
+ * and changing non-primary adapters' settings will be ignored. */
+ *id = !lstrcmpiW( device_name, primary_adapter ) ? 1 : 0;
+ return TRUE;
}
-static LONG xrandr10_set_current_mode( int mode )
+static void add_xrandr10_mode( DEVMODEW *mode, DWORD depth, DWORD width, DWORD height,
+ DWORD frequency, SizeID size_id )
{
- SizeID size;
- Rotation rot;
- Window root;
- XRRScreenConfiguration *sc;
- Status stat;
+ mode->dmSize = sizeof(*mode);
+ mode->dmDriverExtra = sizeof(SizeID);
+ mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH |
+ DM_PELSHEIGHT | DM_DISPLAYFLAGS;
+ if (frequency)
+ {
+ mode->dmFields |= DM_DISPLAYFREQUENCY;
+ mode->dmDisplayFrequency = frequency;
+ }
+ mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
+ mode->dmBitsPerPel = depth;
+ mode->dmPelsWidth = width;
+ mode->dmPelsHeight = height;
+ mode->u2.dmDisplayFlags = 0;
+ memcpy( (BYTE *)mode + sizeof(*mode), &size_id, sizeof(size_id) );
+}
+
+static BOOL xrandr10_get_modes( ULONG_PTR id, DWORD flags, DEVMODEW **new_modes, UINT *new_mode_count )
+{
+ INT size_idx, depth_idx, rate_idx, mode_idx = 0;
+ INT size_count, rate_count, mode_count = 0;
+ DEVMODEW *modes, *mode;
+ XRRScreenSize *sizes;
+ short *rates;
+
+ sizes = pXRRSizes( gdi_display, DefaultScreen( gdi_display ), &size_count );
+ if (size_count <= 0)
+ return FALSE;
+
+ for (size_idx = 0; size_idx < size_count; ++size_idx)
+ {
+ rates = pXRRRates( gdi_display, DefaultScreen( gdi_display ), size_idx, &rate_count );
+ if (rate_count)
+ mode_count += rate_count;
+ else
+ ++mode_count;
+ }
+
+ /* Allocate space for reported modes in three depths, and put an SizeID at the end of DEVMODEW as
+ * driver private data */
+ modes = heap_calloc( mode_count * DEPTH_COUNT, sizeof(*modes) + sizeof(SizeID) );
+ if (!modes)
+ {
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ return FALSE;
+ }
+
+ for (size_idx = 0; size_idx < size_count; ++size_idx)
+ {
+ for (depth_idx = 0; depth_idx < DEPTH_COUNT; ++depth_idx)
+ {
+ rates = pXRRRates( gdi_display, DefaultScreen( gdi_display ), size_idx, &rate_count );
+ if (!rate_count)
+ {
+ mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*mode) + sizeof(SizeID)) * mode_idx++);
+ add_xrandr10_mode( mode, depths[depth_idx], sizes[size_idx].width,
+ sizes[size_idx].height, 0, size_idx );
+ continue;
+ }
+
+ for (rate_idx = 0; rate_idx < rate_count; ++rate_idx)
+ {
+ mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*mode) + sizeof(SizeID)) * mode_idx++);
+ add_xrandr10_mode( mode, depths[depth_idx], sizes[size_idx].width,
+ sizes[size_idx].height, rates[rate_idx], size_idx );
+ }
+ }
+ }
+
+ *new_modes = modes;
+ *new_mode_count = mode_idx;
+ return TRUE;
+}
+
+static void xrandr10_free_modes( DEVMODEW *modes )
+{
+ heap_free( modes );
+}
+
+static BOOL xrandr10_get_current_mode( ULONG_PTR id, DEVMODEW *mode )
+{
+ XRRScreenConfiguration *screen_config;
+ XRRScreenSize *sizes;
+ Rotation rotation;
+ SizeID size_id;
+ INT size_count;
short rate;
- root = DefaultRootWindow( gdi_display );
- sc = pXRRGetScreenInfo (gdi_display, root);
- pXRRConfigCurrentConfiguration (sc, &rot);
- mode = mode % xrandr_mode_count;
+ mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
+ DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION;
+ mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
+ mode->u2.dmDisplayFlags = 0;
+ mode->u1.s2.dmPosition.x = 0;
+ mode->u1.s2.dmPosition.y = 0;
- TRACE("Changing Resolution to %dx%d @%d Hz\n",
- dd_modes[mode].width,
- dd_modes[mode].height,
- dd_modes[mode].refresh_rate);
-
- size = xrandr10_modes[mode];
- rate = dd_modes[mode].refresh_rate;
-
- if (rate)
- stat = pXRRSetScreenConfigAndRate( gdi_display, sc, root, size, rot, rate, CurrentTime );
- else
- stat = pXRRSetScreenConfig( gdi_display, sc, root, size, rot, CurrentTime );
-
- pXRRFreeScreenConfigInfo(sc);
-
- if (stat == RRSetConfigSuccess)
+ if (id != 1)
{
- xrandr_current_mode = mode;
- X11DRV_DisplayDevices_Update( TRUE );
+ FIXME("Non-primary adapters are unsupported.\n");
+ mode->dmBitsPerPel = 0;
+ mode->dmPelsWidth = 0;
+ mode->dmPelsHeight = 0;
+ mode->dmDisplayFrequency = 0;
+ return TRUE;
+ }
+
+ sizes = pXRRSizes( gdi_display, DefaultScreen( gdi_display ), &size_count );
+ if (size_count <= 0)
+ return FALSE;
+
+ screen_config = pXRRGetScreenInfo( gdi_display, DefaultRootWindow( gdi_display ) );
+ size_id = pXRRConfigCurrentConfiguration( screen_config, &rotation );
+ rate = pXRRConfigCurrentRate( screen_config );
+ pXRRFreeScreenConfigInfo( screen_config );
+
+ mode->dmBitsPerPel = screen_bpp;
+ mode->dmPelsWidth = sizes[size_id].width;
+ mode->dmPelsHeight = sizes[size_id].height;
+ mode->dmDisplayFrequency = rate;
+ return TRUE;
+}
+
+static LONG xrandr10_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
+{
+ XRRScreenConfiguration *screen_config;
+ Rotation rotation;
+ SizeID size_id;
+ Window root;
+ Status stat;
+
+ if (id != 1)
+ {
+ FIXME("Non-primary adapters are unsupported.\n");
return DISP_CHANGE_SUCCESSFUL;
}
- ERR("Resolution change not successful -- perhaps display has changed?\n");
- return DISP_CHANGE_FAILED;
-}
-
-static void xrandr10_init_modes(void)
-{
- XRRScreenSize *sizes;
- int sizes_count;
- int i, j, nmodes = 0;
-
- sizes = pXRRSizes( gdi_display, DefaultScreen(gdi_display), &sizes_count );
- if (sizes_count <= 0) return;
-
- TRACE("XRandR: found %d sizes.\n", sizes_count);
- for (i = 0; i < sizes_count; ++i)
+ if (is_detached_mode(mode))
{
- int rates_count;
- short *rates;
-
- rates = pXRRRates( gdi_display, DefaultScreen(gdi_display), i, &rates_count );
- TRACE("- at %d: %dx%d (%d rates):", i, sizes[i].width, sizes[i].height, rates_count);
- if (rates_count)
- {
- nmodes += rates_count;
- for (j = 0; j < rates_count; ++j)
- {
- if (j > 0)
- TRACE(",");
- TRACE(" %d", rates[j]);
- }
- }
- else
- {
- ++nmodes;
- TRACE(" <default>");
- }
- TRACE(" Hz\n");
+ FIXME("Detaching adapters is unsupported.\n");
+ return DISP_CHANGE_SUCCESSFUL;
}
- TRACE("XRandR modes: count=%d\n", nmodes);
+ if (mode->dmFields & DM_BITSPERPEL && mode->dmBitsPerPel != screen_bpp)
+ WARN("Cannot change screen bit depth from %dbits to %dbits!\n", screen_bpp, mode->dmBitsPerPel);
- if (!(xrandr10_modes = HeapAlloc( GetProcessHeap(), 0, sizeof(*xrandr10_modes) * nmodes )))
- {
- ERR("Failed to allocate xrandr mode info array.\n");
- return;
- }
+ root = DefaultRootWindow( gdi_display );
+ screen_config = pXRRGetScreenInfo( gdi_display, root );
+ pXRRConfigCurrentConfiguration( screen_config, &rotation );
- dd_modes = X11DRV_Settings_SetHandlers( "XRandR 1.0",
- xrandr10_get_current_mode,
- xrandr10_set_current_mode,
- nmodes, 1 );
+ assert( mode->dmDriverExtra == sizeof(SizeID) );
+ memcpy( &size_id, (BYTE *)mode + sizeof(*mode), sizeof(size_id) );
- xrandr_mode_count = 0;
- for (i = 0; i < sizes_count; ++i)
- {
- int rates_count;
- short *rates;
+ if (mode->dmFields & DM_DISPLAYFREQUENCY && mode->dmDisplayFrequency)
+ stat = pXRRSetScreenConfigAndRate( gdi_display, screen_config, root, size_id, rotation,
+ mode->dmDisplayFrequency, CurrentTime );
+ else
+ stat = pXRRSetScreenConfig( gdi_display, screen_config, root, size_id, rotation, CurrentTime );
+ pXRRFreeScreenConfigInfo( screen_config );
- rates = pXRRRates( gdi_display, DefaultScreen(gdi_display), i, &rates_count );
+ if (stat != RRSetConfigSuccess)
+ return DISP_CHANGE_FAILED;
- if (rates_count)
- {
- for (j = 0; j < rates_count; ++j)
- {
- X11DRV_Settings_AddOneMode( sizes[i].width, sizes[i].height, 0, rates[j] );
- xrandr10_modes[xrandr_mode_count++] = i;
- }
- }
- else
- {
- X11DRV_Settings_AddOneMode( sizes[i].width, sizes[i].height, 0, 0 );
- xrandr10_modes[xrandr_mode_count++] = i;
- }
- }
-
- X11DRV_Settings_AddDepthModes();
- nmodes = X11DRV_Settings_GetModeCount();
-
- TRACE("Available DD modes: count=%d\n", nmodes);
- TRACE("Enabling XRandR\n");
+ XFlush( gdi_display );
+ return DISP_CHANGE_SUCCESSFUL;
}
#ifdef HAVE_XRRGETPROVIDERRESOURCES
@@ -1432,7 +1457,14 @@ void X11DRV_XRandR_Init(void)
TRACE("Found XRandR %d.%d.\n", major, minor);
- xrandr10_init_modes();
+ settings_handler.name = "XRandR 1.0";
+ settings_handler.priority = 200;
+ settings_handler.get_id = xrandr10_get_id;
+ settings_handler.get_modes = xrandr10_get_modes;
+ settings_handler.free_modes = xrandr10_free_modes;
+ settings_handler.get_current_mode = xrandr10_get_current_mode;
+ settings_handler.set_current_mode = xrandr10_set_current_mode;
+ X11DRV_Settings_SetHandler( &settings_handler );
#ifdef HAVE_XRRGETPROVIDERRESOURCES
if (ret >= 4 && (major > 1 || (major == 1 && minor >= 4)))
--
2.25.1