Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/user32/tests/monitor.c | 11 +++------ dlls/winex11.drv/settings.c | 48 +++++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 26 deletions(-)
diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c index 7cd41145ea1..9a7efb8e9b4 100644 --- a/dlls/user32/tests/monitor.c +++ b/dlls/user32/tests/monitor.c @@ -749,8 +749,8 @@ static void test_ChangeDisplaySettingsEx(void) "Expected dmPelsWidth %u, got %u.\n", dm3.dmPelsWidth, dm.dmPelsWidth); ok(dm.dmPelsHeight == dm3.dmPelsHeight || broken(dm.dmPelsHeight == dm2.dmPelsHeight), /* Win10 */ "Expected dmPelsHeight %u, got %u.\n", dm3.dmPelsHeight, dm.dmPelsHeight); - todo_wine ok(dm.dmBitsPerPel, "Expected dmBitsPerPel not zero.\n"); - todo_wine ok(dm.dmDisplayFrequency, "Expected dmDisplayFrequency not zero.\n"); + ok(dm.dmBitsPerPel, "Expected dmBitsPerPel not zero.\n"); + ok(dm.dmDisplayFrequency, "Expected dmDisplayFrequency not zero.\n"); } else { @@ -758,12 +758,7 @@ static void test_ChangeDisplaySettingsEx(void) }
res = ChangeDisplaySettingsExA(devices[device].name, NULL, NULL, 0, NULL); - todo_wine ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned %d.\n", devices[device].name, res); - if (res != DISP_CHANGE_SUCCESSFUL) - { - skip("ChangeDisplaySettingsExA %s returned %d.\n", devices[device].name, res); - continue; - } + ok(res == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExA %s returned %d.\n", devices[device].name, res); flush_events();
res = EnumDisplaySettingsA(devices[device].name, ENUM_REGISTRY_SETTINGS, &dm); diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c index c4929e9b584..7827ede6560 100644 --- a/dlls/winex11.drv/settings.c +++ b/dlls/winex11.drv/settings.c @@ -456,12 +456,15 @@ BOOL is_detached_mode(const DEVMODEW *mode) }
/* Get the full display mode with all the necessary fields set. - * Return NULL on failure. Caller should free the returned mode. */ -static DEVMODEW *get_full_mode(ULONG_PTR id, const DEVMODEW *dev_mode) + * Return NULL on failure. Caller should call free_full_mode() to free the returned mode. */ +static DEVMODEW *get_full_mode(ULONG_PTR id, DEVMODEW *dev_mode) { DEVMODEW *modes, *full_mode, *found_mode = NULL; UINT mode_count, mode_idx;
+ if (is_detached_mode(dev_mode)) + return dev_mode; + if (!handler.get_modes(id, 0, &modes, &mode_count)) return NULL;
@@ -500,9 +503,18 @@ static DEVMODEW *get_full_mode(ULONG_PTR id, const DEVMODEW *dev_mode)
memcpy(full_mode, found_mode, sizeof(*found_mode) + found_mode->dmDriverExtra); handler.free_modes(modes); + + full_mode->dmFields |= DM_POSITION; + full_mode->u1.s2.dmPosition = dev_mode->u1.s2.dmPosition; return full_mode; }
+static void free_full_mode(DEVMODEW *mode) +{ + if (!is_detached_mode(mode)) + heap_free(mode); +} + static LONG get_display_settings(struct x11drv_display_setting **new_displays, INT *new_display_count, const WCHAR *dev_name, DEVMODEW *dev_mode) { @@ -781,19 +793,9 @@ static LONG apply_display_settings(struct x11drv_display_setting *displays, INT if ((attached_mode && !do_attach) || (!attached_mode && do_attach)) continue;
- if (attached_mode) - { - 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; - } - else - { - full_mode = &displays[display_idx].desired_mode; - } + full_mode = get_full_mode(displays[display_idx].id, &displays[display_idx].desired_mode); + if (!full_mode) + return DISP_CHANGE_BADMODE;
TRACE("handler:%s changing %s to position:(%d,%d) resolution:%ux%u frequency:%uHz " "depth:%ubits orientation:%#x.\n", handler.name, @@ -803,8 +805,7 @@ static LONG apply_display_settings(struct x11drv_display_setting *displays, INT full_mode->u1.s2.dmDisplayOrientation);
ret = handler.set_current_mode(displays[display_idx].id, full_mode); - if (attached_mode) - heap_free(full_mode); + free_full_mode(full_mode); if (ret != DISP_CHANGE_SUCCESSFUL) return ret; } @@ -834,6 +835,7 @@ LONG CDECL X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, { struct x11drv_display_setting *displays; INT display_idx, display_count; + DEVMODEW *full_mode; LONG ret;
ret = get_display_settings(&displays, &display_count, devname, devmode); @@ -846,12 +848,22 @@ LONG CDECL X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, { if (!lstrcmpiW(displays[display_idx].desired_mode.dmDeviceName, devname)) { - if (!write_registry_settings(devname, &displays[display_idx].desired_mode)) + full_mode = get_full_mode(displays[display_idx].id, &displays[display_idx].desired_mode); + if (!full_mode) + { + heap_free(displays); + return DISP_CHANGE_BADMODE; + } + + if (!write_registry_settings(devname, full_mode)) { ERR("Failed to write %s display settings to registry.\n", wine_dbgstr_w(devname)); + free_full_mode(full_mode); heap_free(displays); return DISP_CHANGE_NOTUPDATED; } + + free_full_mode(full_mode); break; } }