Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/user32/tests/monitor.c | 36 +---
dlls/winex11.drv/settings.c | 382 +++++++++++++++++++++++++++++++-----
dlls/winex11.drv/xrandr.c | 7 +-
3 files changed, 337 insertions(+), 88 deletions(-)
diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c
index 005627f28b0..0d32dbfeef9 100644
--- a/dlls/user32/tests/monitor.c
+++ b/dlls/user32/tests/monitor.c
@@ -283,29 +283,9 @@ struct device_info
DEVMODEA original_mode;
};
-static BOOL get_primary_adapter(CHAR *name)
-{
- DISPLAY_DEVICEA dd;
- DWORD i;
-
- dd.cb = sizeof(dd);
- for (i = 0; EnumDisplayDevicesA(NULL, i, &dd, 0); ++i)
- {
- if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
- {
- lstrcpyA(name, dd.DeviceName);
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
#define expect_dm(a, b, c) _expect_dm(__LINE__, a, b, c)
static void _expect_dm(INT line, DEVMODEA expected, const CHAR *device, DWORD test)
{
- CHAR primary_adapter[CCHDEVICENAME];
- BOOL is_primary;
DEVMODEA dm;
BOOL ret;
@@ -315,33 +295,23 @@ static void _expect_dm(INT line, DEVMODEA expected, const CHAR *device, DWORD te
ret = EnumDisplaySettingsA(device, ENUM_CURRENT_SETTINGS, &dm);
ok_(__FILE__, line)(ret, "Device %s test %d EnumDisplaySettingsA failed, error %#x\n", device, test, GetLastError());
- ok(get_primary_adapter(primary_adapter), "Failed to get primary adapter name.\n");
- is_primary = !lstrcmpA(primary_adapter, device);
-
ok_(__FILE__, line)((dm.dmFields & expected.dmFields) == expected.dmFields,
"Device %s test %d expect dmFields to contain %#x, got %#x\n", device, test, expected.dmFields, dm.dmFields);
/* Wine doesn't support changing color depth yet */
todo_wine_if(expected.dmBitsPerPel != 32 && expected.dmBitsPerPel != 24)
ok_(__FILE__, line)(dm.dmBitsPerPel == expected.dmBitsPerPel, "Device %s test %d expect dmBitsPerPel %d, got %d\n",
device, test, expected.dmBitsPerPel, dm.dmBitsPerPel);
- /* Wine currently reports primary monitor settings for non-primary monitors */
- todo_wine_if(!is_primary && dm.dmPelsWidth != expected.dmPelsWidth)
ok_(__FILE__, line)(dm.dmPelsWidth == expected.dmPelsWidth, "Device %s test %d expect dmPelsWidth %d, got %d\n",
device, test, expected.dmPelsWidth, dm.dmPelsWidth);
- todo_wine_if(!is_primary && dm.dmPelsHeight != expected.dmPelsHeight)
ok_(__FILE__, line)(dm.dmPelsHeight == expected.dmPelsHeight, "Device %s test %d expect dmPelsHeight %d, got %d\n",
device, test, expected.dmPelsHeight, dm.dmPelsHeight);
- todo_wine_if(!is_primary && dm.dmPosition.x != expected.dmPosition.x)
ok_(__FILE__, line)(dm.dmPosition.x == expected.dmPosition.x, "Device %s test %d expect dmPosition.x %d, got %d\n",
device, test, expected.dmPosition.x, dm.dmPosition.x);
- todo_wine_if(!is_primary && dm.dmPosition.y != expected.dmPosition.y)
ok_(__FILE__, line)(dm.dmPosition.y == expected.dmPosition.y, "Device %s test %d expect dmPosition.y %d, got %d\n",
device, test, expected.dmPosition.y, dm.dmPosition.y);
- todo_wine_if(!is_primary && dm.dmDisplayFrequency != expected.dmDisplayFrequency)
ok_(__FILE__, line)(dm.dmDisplayFrequency == expected.dmDisplayFrequency,
"Device %s test %d expect dmDisplayFrequency %d, got %d\n", device, test, expected.dmDisplayFrequency,
dm.dmDisplayFrequency);
- todo_wine_if(!is_primary && dm.dmDisplayOrientation != expected.dmDisplayOrientation)
ok_(__FILE__, line)(dm.dmDisplayOrientation == expected.dmDisplayOrientation,
"Device %s test %d expect dmDisplayOrientation %d, got %d\n", device, test, expected.dmDisplayOrientation,
dm.dmDisplayOrientation);
@@ -778,7 +748,7 @@ static void test_ChangeDisplaySettingsEx(void)
if (res)
{
/* The secondary adapter should be to the right of the primary adapter */
- todo_wine ok(dm2.dmPosition.x == dm.dmPosition.x + dm.dmPelsWidth,
+ ok(dm2.dmPosition.x == dm.dmPosition.x + dm.dmPelsWidth,
"Expected dm2.dmPosition.x %d, got %d.\n", dm.dmPosition.x + dm.dmPelsWidth,
dm2.dmPosition.x);
ok(dm2.dmPosition.y == dm.dmPosition.y, "Expected dm2.dmPosition.y %d, got %d.\n",
@@ -795,7 +765,7 @@ static void test_ChangeDisplaySettingsEx(void)
dm2.dmSize = sizeof(dm2);
res = EnumDisplaySettingsA(devices[1].name, ENUM_CURRENT_SETTINGS, &dm2);
ok(res, "EnumDisplaySettingsA %s failed, error %#x\n", devices[1].name, GetLastError());
- todo_wine ok((dm2.dmPosition.x == dm.dmPosition.x - dm2.dmPelsWidth),
+ ok(dm2.dmPosition.x == dm.dmPosition.x - dm2.dmPelsWidth,
"Expected dmPosition.x %d, got %d.\n", dm.dmPosition.x - dm2.dmPelsWidth,
dm2.dmPosition.x);
@@ -889,7 +859,7 @@ static void test_ChangeDisplaySettingsEx(void)
dm2.dmSize = sizeof(dm2);
res = EnumDisplaySettingsA(devices[1].name, ENUM_CURRENT_SETTINGS, &dm2);
ok(res, "EnumDisplaySettingsA %s failed, error %#x\n", devices[1].name, GetLastError());
- todo_wine ok(dm2.dmPosition.x == dm.dmPelsWidth, "Expect dmPosition.x %d, got %d\n",
+ ok(dm2.dmPosition.x == dm.dmPelsWidth, "Expect dmPosition.x %d, got %d\n",
dm.dmPelsWidth, dm2.dmPosition.x);
}
else
diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c
index 02495756179..56f55e78b42 100644
--- a/dlls/winex11.drv/settings.c
+++ b/dlls/winex11.drv/settings.c
@@ -36,6 +36,15 @@
WINE_DEFAULT_DEBUG_CHANNEL(x11settings);
+struct x11drv_display_setting
+{
+ ULONG_PTR id;
+ BOOL placed;
+ RECT new_rect;
+ RECT desired_rect;
+ DEVMODEW desired_mode;
+};
+
static struct x11drv_mode_info *dd_modes = NULL;
static unsigned int dd_mode_count = 0;
static unsigned int dd_max_modes = 0;
@@ -534,6 +543,305 @@ static DEVMODEW *get_full_mode(ULONG_PTR id, const DEVMODEW *dev_mode)
return full_mode;
}
+static LONG get_display_settings(struct x11drv_display_setting **new_displays,
+ INT *new_display_count, const WCHAR *dev_name, DEVMODEW *dev_mode)
+{
+ struct x11drv_display_setting *displays;
+ DEVMODEW registry_mode, current_mode;
+ INT display_idx, display_count = 0;
+ DISPLAY_DEVICEW display_device;
+ LONG ret = DISP_CHANGE_FAILED;
+
+ display_device.cb = sizeof(display_device);
+ for (display_idx = 0; EnumDisplayDevicesW(NULL, display_idx, &display_device, 0); ++display_idx)
+ ++display_count;
+
+ displays = heap_calloc(display_count, sizeof(*displays));
+ if (!displays)
+ goto done;
+
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (!EnumDisplayDevicesW(NULL, display_idx, &display_device, 0))
+ goto done;
+
+ if (!handler.get_id(display_device.DeviceName, &displays[display_idx].id))
+ {
+ ret = DISP_CHANGE_BADPARAM;
+ goto done;
+ }
+
+ if (!dev_mode)
+ {
+ registry_mode.dmSize = sizeof(registry_mode);
+ if (!EnumDisplaySettingsExW(display_device.DeviceName, ENUM_REGISTRY_SETTINGS, ®istry_mode, 0))
+ goto done;
+
+ displays[display_idx].desired_mode = registry_mode;
+ }
+ else if (!lstrcmpiW(dev_name, display_device.DeviceName))
+ {
+ displays[display_idx].desired_mode = *dev_mode;
+ if (!(dev_mode->dmFields & DM_POSITION))
+ {
+ current_mode.dmSize = sizeof(current_mode);
+ if (!EnumDisplaySettingsExW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, ¤t_mode, 0))
+ goto done;
+
+ displays[display_idx].desired_mode.dmFields |= DM_POSITION;
+ displays[display_idx].desired_mode.u1.s2.dmPosition = current_mode.u1.s2.dmPosition;
+ }
+ }
+ else
+ {
+ current_mode.dmSize = sizeof(current_mode);
+ if (!EnumDisplaySettingsExW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, ¤t_mode, 0))
+ goto done;
+
+ displays[display_idx].desired_mode = current_mode;
+ }
+
+ SetRect(&displays[display_idx].desired_rect,
+ displays[display_idx].desired_mode.u1.s2.dmPosition.x,
+ displays[display_idx].desired_mode.u1.s2.dmPosition.y,
+ displays[display_idx].desired_mode.u1.s2.dmPosition.x + displays[display_idx].desired_mode.dmPelsWidth,
+ displays[display_idx].desired_mode.u1.s2.dmPosition.y + displays[display_idx].desired_mode.dmPelsHeight);
+ lstrcpyW(displays[display_idx].desired_mode.dmDeviceName, display_device.DeviceName);
+ }
+
+ *new_displays = displays;
+ *new_display_count = display_count;
+ return DISP_CHANGE_SUCCESSFUL;
+
+done:
+ heap_free(displays);
+ return ret;
+}
+
+static INT offset_length(POINT offset)
+{
+ return offset.x * offset.x + offset.y * offset.y;
+}
+
+/* Check if a rect overlaps with placed display rects */
+static BOOL overlap_placed_displays(const RECT *rect, const struct x11drv_display_setting *displays, INT display_count)
+{
+ INT display_idx;
+ RECT intersect;
+
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (displays[display_idx].placed &&
+ IntersectRect(&intersect, &displays[display_idx].new_rect, rect))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Get the offset with minimum length to place a display next to the placed displays with no spacing and overlaps */
+static POINT get_placement_offset(const struct x11drv_display_setting *displays, INT display_count, INT placing_idx)
+{
+ POINT points[8], left_top, offset, min_offset = {0, 0};
+ INT display_idx, point_idx, point_count, vertex_idx;
+ BOOL has_placed = FALSE, first = TRUE;
+ INT width, height;
+ RECT rect;
+
+ /* If the display to be placed is detached, no offset is needed to place it */
+ if (IsRectEmpty(&displays[placing_idx].desired_rect))
+ return min_offset;
+
+ /* If there is no placed and attached display, place this display as it is */
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (displays[display_idx].placed && !IsRectEmpty(&displays[display_idx].new_rect))
+ {
+ has_placed = TRUE;
+ break;
+ }
+ }
+
+ if (!has_placed)
+ return min_offset;
+
+ /* Try to place this display with each of its four vertices at every vertex of the placed
+ * displays and see which combination has the minimum offset length */
+ width = displays[placing_idx].desired_rect.right - displays[placing_idx].desired_rect.left;
+ height = displays[placing_idx].desired_rect.bottom - displays[placing_idx].desired_rect.top;
+
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (!displays[display_idx].placed || IsRectEmpty(&displays[display_idx].new_rect))
+ continue;
+
+ /* Get four vertices of the placed display rectangle */
+ points[0].x = displays[display_idx].new_rect.left;
+ points[0].y = displays[display_idx].new_rect.top;
+ points[1].x = displays[display_idx].new_rect.left;
+ points[1].y = displays[display_idx].new_rect.bottom;
+ points[2].x = displays[display_idx].new_rect.right;
+ points[2].y = displays[display_idx].new_rect.top;
+ points[3].x = displays[display_idx].new_rect.right;
+ points[3].y = displays[display_idx].new_rect.bottom;
+ point_count = 4;
+
+ /* Intersected points when moving the display to be placed horizontally */
+ if (displays[placing_idx].desired_rect.bottom >= displays[display_idx].new_rect.top &&
+ displays[placing_idx].desired_rect.top <= displays[display_idx].new_rect.bottom)
+ {
+ points[point_count].x = displays[display_idx].new_rect.left;
+ points[point_count++].y = displays[placing_idx].desired_rect.top;
+ points[point_count].x = displays[display_idx].new_rect.right;
+ points[point_count++].y = displays[placing_idx].desired_rect.top;
+ }
+ /* Intersected points when moving the display to be placed vertically */
+ if (displays[placing_idx].desired_rect.left <= displays[display_idx].new_rect.right &&
+ displays[placing_idx].desired_rect.right >= displays[display_idx].new_rect.left)
+ {
+ points[point_count].x = displays[placing_idx].desired_rect.left;
+ points[point_count++].y = displays[display_idx].new_rect.top;
+ points[point_count].x = displays[placing_idx].desired_rect.left;
+ points[point_count++].y = displays[display_idx].new_rect.bottom;
+ }
+
+ /* Try moving each vertex of the display rectangle to each points */
+ for (point_idx = 0; point_idx < point_count; ++point_idx)
+ {
+ for (vertex_idx = 0; vertex_idx < 4; ++vertex_idx)
+ {
+ switch (vertex_idx)
+ {
+ /* Move the bottom right vertex to the point */
+ case 0:
+ left_top.x = points[point_idx].x - width;
+ left_top.y = points[point_idx].y - height;
+ break;
+ /* Move the bottom left vertex to the point */
+ case 1:
+ left_top.x = points[point_idx].x;
+ left_top.y = points[point_idx].y - height;
+ break;
+ /* Move the top right vertex to the point */
+ case 2:
+ left_top.x = points[point_idx].x - width;
+ left_top.y = points[point_idx].y;
+ break;
+ /* Move the top left vertex to the point */
+ case 3:
+ left_top.x = points[point_idx].x;
+ left_top.y = points[point_idx].y;
+ break;
+ }
+
+ offset.x = left_top.x - displays[placing_idx].desired_rect.left;
+ offset.y = left_top.y - displays[placing_idx].desired_rect.top;
+ rect = displays[placing_idx].desired_rect;
+ OffsetRect(&rect, offset.x, offset.y);
+ if (!overlap_placed_displays(&rect, displays, display_count))
+ {
+ if (first)
+ {
+ min_offset = offset;
+ first = FALSE;
+ continue;
+ }
+
+ if (offset_length(offset) < offset_length(min_offset))
+ min_offset = offset;
+ }
+ }
+ }
+ }
+
+ return min_offset;
+}
+
+static void place_all_displays(struct x11drv_display_setting *displays, INT display_count)
+{
+ INT left_most = INT_MAX, top_most = INT_MAX;
+ INT placing_idx, display_idx;
+ POINT min_offset, offset;
+
+ /* Place all displays with no extra space between them and no overlapping */
+ while (1)
+ {
+ /* Place the unplaced display with the minimum offset length first */
+ placing_idx = -1;
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (displays[display_idx].placed)
+ continue;
+
+ offset = get_placement_offset(displays, display_count, display_idx);
+ if (placing_idx == -1 || offset_length(offset) < offset_length(min_offset))
+ {
+ min_offset = offset;
+ placing_idx = display_idx;
+ }
+ }
+
+ /* If all displays are placed */
+ if (placing_idx == -1)
+ break;
+
+ displays[placing_idx].new_rect = displays[placing_idx].desired_rect;
+ OffsetRect(&displays[placing_idx].new_rect, min_offset.x, min_offset.y);
+ displays[placing_idx].placed = TRUE;
+ }
+
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ displays[display_idx].desired_mode.u1.s2.dmPosition.x = displays[display_idx].new_rect.left;
+ displays[display_idx].desired_mode.u1.s2.dmPosition.y = displays[display_idx].new_rect.top;
+ left_most = min(left_most, displays[display_idx].new_rect.left);
+ top_most = min(top_most, displays[display_idx].new_rect.top);
+ }
+
+ /* Convert virtual screen coordinates to root coordinates */
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ displays[display_idx].desired_mode.u1.s2.dmPosition.x -= left_most;
+ displays[display_idx].desired_mode.u1.s2.dmPosition.y -= top_most;
+ }
+}
+
+static LONG apply_display_settings(struct x11drv_display_setting *displays, INT display_count)
+{
+ DEVMODEW *full_mode;
+ INT display_idx;
+ LONG ret;
+
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
+ {
+ if (is_detached_mode(&displays[display_idx].desired_mode))
+ {
+ FIXME("Detaching %s is currently unsupported.\n",
+ wine_dbgstr_w(displays[display_idx].desired_mode.dmDeviceName));
+ continue;
+ }
+
+ full_mode = get_full_mode(displays[display_idx].id, &displays[display_idx].desired_mode);
+ if (!full_mode)
+ return DISP_CHANGE_BADMODE;
+
+ full_mode->dmFields |= DM_POSITION;
+ full_mode->u1.s2.dmPosition = displays[display_idx].desired_mode.u1.s2.dmPosition;
+ TRACE("handler:%s changing %s to position:(%d,%d) resolution:%ux%u frequency:%uHz "
+ "depth:%ubits orientation:%#x.\n", handler.name,
+ wine_dbgstr_w(displays[display_idx].desired_mode.dmDeviceName),
+ full_mode->u1.s2.dmPosition.x, full_mode->u1.s2.dmPosition.y, full_mode->dmPelsWidth,
+ full_mode->dmPelsHeight, full_mode->dmDisplayFrequency, full_mode->dmBitsPerPel,
+ full_mode->u1.s2.dmDisplayOrientation);
+
+ ret = handler.set_current_mode(displays[display_idx].id, full_mode);
+ heap_free(full_mode);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return ret;
+ }
+
+ return DISP_CHANGE_SUCCESSFUL;
+}
+
/***********************************************************************
* ChangeDisplaySettingsEx (X11DRV.@)
*
@@ -541,10 +849,11 @@ static DEVMODEW *get_full_mode(ULONG_PTR id, const DEVMODEW *dev_mode)
LONG CDECL X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode,
HWND hwnd, DWORD flags, LPVOID lpvoid )
{
+ struct x11drv_display_setting *displays;
WCHAR primary_adapter[CCHDEVICENAME];
char bpp_buffer[16], freq_buffer[18];
- DEVMODEW default_mode, *full_mode;
- ULONG_PTR id;
+ INT display_idx, display_count;
+ DEVMODEW default_mode;
LONG ret;
DWORD i;
@@ -552,70 +861,39 @@ LONG CDECL X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode,
if (!handler.name)
goto old_interface;
- if (!get_primary_adapter(primary_adapter))
- return DISP_CHANGE_FAILED;
+ ret = get_display_settings(&displays, &display_count, devname, devmode);
+ if (ret != DISP_CHANGE_SUCCESSFUL)
+ return ret;
- if (!devname && !devmode)
+ if (flags & CDS_UPDATEREGISTRY && devname && devmode)
{
- default_mode.dmSize = sizeof(default_mode);
- if (!EnumDisplaySettingsExW(primary_adapter, ENUM_REGISTRY_SETTINGS, &default_mode, 0))
+ for (display_idx = 0; display_idx < display_count; ++display_idx)
{
- ERR("Default mode not found for %s!\n", wine_dbgstr_w(primary_adapter));
- return DISP_CHANGE_BADMODE;
+ if (!lstrcmpiW(displays[display_idx].desired_mode.dmDeviceName, devname))
+ {
+ if (!write_registry_settings(devname, &displays[display_idx].desired_mode))
+ {
+ ERR("Failed to write %s display settings to registry.\n", wine_dbgstr_w(devname));
+ heap_free(displays);
+ return DISP_CHANGE_NOTUPDATED;
+ }
+ break;
+ }
}
-
- devname = primary_adapter;
- devmode = &default_mode;
- }
-
- if (!handler.get_id(devname, &id))
- {
- ERR("Failed to get %s device id.\n", wine_dbgstr_w(devname));
- return DISP_CHANGE_BADPARAM;
- }
-
- if (is_detached_mode(devmode))
- {
- FIXME("Detaching adapters is currently unsupported.\n");
- return DISP_CHANGE_SUCCESSFUL;
- }
-
- if (!(full_mode = get_full_mode(id, devmode)))
- {
- ERR("Failed to find a valid mode.\n");
- return DISP_CHANGE_BADMODE;
- }
-
- if (flags & CDS_UPDATEREGISTRY && !write_registry_settings(devname, full_mode))
- {
- ERR("Failed to write %s display settings to registry.\n", wine_dbgstr_w(devname));
- heap_free(full_mode);
- return DISP_CHANGE_NOTUPDATED;
- }
-
- if (lstrcmpiW(primary_adapter, devname))
- {
- FIXME("Changing non-primary adapter %s settings is currently unsupported.\n",
- wine_dbgstr_w(devname));
- heap_free(full_mode);
- return DISP_CHANGE_SUCCESSFUL;
}
if (flags & (CDS_TEST | CDS_NORESET))
{
- heap_free(full_mode);
+ heap_free(displays);
return DISP_CHANGE_SUCCESSFUL;
}
- TRACE("handler:%s device:%s position:(%d,%d) resolution:%ux%u frequency:%uHz depth:%ubits "
- "orientation:%#x.\n", handler.name, wine_dbgstr_w(devname), full_mode->u1.s2.dmPosition.x,
- full_mode->u1.s2.dmPosition.y, full_mode->dmPelsWidth, full_mode->dmPelsHeight,
- full_mode->dmDisplayFrequency, full_mode->dmBitsPerPel, full_mode->u1.s2.dmDisplayOrientation);
+ place_all_displays(displays, display_count);
- ret = handler.set_current_mode(id, full_mode);
+ ret = apply_display_settings(displays, display_count);
if (ret == DISP_CHANGE_SUCCESSFUL)
X11DRV_DisplayDevices_Update(TRUE);
- heap_free(full_mode);
+ heap_free(displays);
return ret;
old_interface:
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c
index d111b960fa6..4fbb2e540dc 100644
--- a/dlls/winex11.drv/xrandr.c
+++ b/dlls/winex11.drv/xrandr.c
@@ -1367,12 +1367,13 @@ static LONG xrandr14_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
goto done;
get_screen_size( screen_resources, &screen_width, &screen_height );
- screen_width = max( screen_width, crtc_info->x + mode->dmPelsWidth );
- screen_height = max( screen_height, crtc_info->y + mode->dmPelsHeight );
+ screen_width = max( screen_width, mode->u1.s2.dmPosition.x + mode->dmPelsWidth );
+ screen_height = max( screen_height, mode->u1.s2.dmPosition.y + mode->dmPelsHeight );
set_screen_size( screen_width, screen_height );
status = pXRRSetCrtcConfig( gdi_display, screen_resources, crtc, CurrentTime,
- crtc_info->x, crtc_info->y, rrmode, rotation, outputs, output_count );
+ mode->u1.s2.dmPosition.x, mode->u1.s2.dmPosition.y, rrmode,
+ rotation, outputs, output_count );
if (status == RRSetConfigSuccess)
ret = DISP_CHANGE_SUCCESSFUL;
--
2.25.1