In preparation for nulldrv display modes support.
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/display.c | 161 +++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 77 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 1350ffcede9..d40acc20f7f 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -716,85 +716,14 @@ static BOOL is_detached_mode(const DEVMODEW *mode) mode->dmPelsHeight == 0; }
-/*********************************************************************** - * ChangeDisplaySettingsEx (MACDRV.@) - * - */ -LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, - HWND hwnd, DWORD flags, LPVOID lpvoid) +static CGDisplayModeRef find_best_display_mode(DEVMODEW *devmode, CFArrayRef display_modes, int bpp, struct display_mode_descriptor* desc) { - WCHAR primary_adapter[CCHDEVICENAME]; - LONG ret = DISP_CHANGE_BADMODE; - DEVMODEW default_mode; - int bpp; - struct macdrv_display *displays; - int num_displays; - CFArrayRef display_modes; - struct display_mode_descriptor* desc; CFIndex count, i, best; CGDisplayModeRef best_display_mode; uint32_t best_io_flags; - BOOL best_is_original; - - TRACE("%s %p %p 0x%08x %p\n", debugstr_w(devname), devmode, hwnd, flags, lpvoid); - - init_original_display_mode(); - - if (!get_primary_adapter(primary_adapter)) - return DISP_CHANGE_FAILED; - - if (!devname && !devmode) - { - UNICODE_STRING str; - memset(&default_mode, 0, sizeof(default_mode)); - default_mode.dmSize = sizeof(default_mode); - RtlInitUnicodeString(&str, primary_adapter); - if (!NtUserEnumDisplaySettings(&str, ENUM_REGISTRY_SETTINGS, &default_mode, 0)) - { - ERR("Default mode not found for %s!\n", wine_dbgstr_w(primary_adapter)); - return DISP_CHANGE_BADMODE; - } - - devname = primary_adapter; - devmode = &default_mode; - } - - if (is_detached_mode(devmode)) - { - FIXME("Detaching adapters is currently unsupported.\n"); - return DISP_CHANGE_SUCCESSFUL; - } - - if (macdrv_get_displays(&displays, &num_displays)) - return DISP_CHANGE_FAILED; - - display_modes = copy_display_modes(displays[0].displayID, FALSE); - if (!display_modes) - { - macdrv_free_displays(displays); - return DISP_CHANGE_FAILED; - } - - pthread_mutex_lock(&modes_mutex); - bpp = get_default_bpp(); - pthread_mutex_unlock(&modes_mutex); - if ((devmode->dmFields & DM_BITSPERPEL) && devmode->dmBitsPerPel != bpp) - TRACE("using default %d bpp instead of caller's request %d bpp\n", bpp, devmode->dmBitsPerPel); - - TRACE("looking for %dx%dx%dbpp @%d Hz", - (devmode->dmFields & DM_PELSWIDTH ? devmode->dmPelsWidth : 0), - (devmode->dmFields & DM_PELSHEIGHT ? devmode->dmPelsHeight : 0), - bpp, - (devmode->dmFields & DM_DISPLAYFREQUENCY ? devmode->dmDisplayFrequency : 0)); - if (devmode->dmFields & DM_DISPLAYFIXEDOUTPUT) - TRACE(" %sstretched", devmode->dmDisplayFixedOutput == DMDFO_STRETCH ? "" : "un"); - if (devmode->dmFields & DM_DISPLAYFLAGS) - TRACE(" %sinterlaced", devmode->dmDisplayFlags & DM_INTERLACED ? "" : "non-"); - TRACE("\n"); - - desc = create_original_display_mode_descriptor(displays[0].displayID);
best_display_mode = NULL; + count = CFArrayGetCount(display_modes); for (i = 0; i < count; i++) { @@ -866,14 +795,92 @@ better: best_display_mode = display_mode; best = i; best_io_flags = io_flags; - best_is_original = is_original; }
if (best_display_mode) - { - /* we have a valid mode */ TRACE("Requested display settings match mode %ld\n", best);
+ return best_display_mode; +} + +/*********************************************************************** + * ChangeDisplaySettingsEx (MACDRV.@) + * + */ +LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, + HWND hwnd, DWORD flags, LPVOID lpvoid) +{ + WCHAR primary_adapter[CCHDEVICENAME]; + LONG ret = DISP_CHANGE_BADMODE; + DEVMODEW default_mode; + int bpp; + struct macdrv_display *displays; + int num_displays; + CFArrayRef display_modes; + struct display_mode_descriptor* desc; + CGDisplayModeRef best_display_mode; + + TRACE("%s %p %p 0x%08x %p\n", debugstr_w(devname), devmode, hwnd, flags, lpvoid); + + init_original_display_mode(); + + if (!get_primary_adapter(primary_adapter)) + return DISP_CHANGE_FAILED; + + if (!devname && !devmode) + { + UNICODE_STRING str; + memset(&default_mode, 0, sizeof(default_mode)); + default_mode.dmSize = sizeof(default_mode); + RtlInitUnicodeString(&str, primary_adapter); + if (!NtUserEnumDisplaySettings(&str, ENUM_REGISTRY_SETTINGS, &default_mode, 0)) + { + ERR("Default mode not found for %s!\n", wine_dbgstr_w(primary_adapter)); + return DISP_CHANGE_BADMODE; + } + + devname = primary_adapter; + devmode = &default_mode; + } + + if (is_detached_mode(devmode)) + { + FIXME("Detaching adapters is currently unsupported.\n"); + return DISP_CHANGE_SUCCESSFUL; + } + + if (macdrv_get_displays(&displays, &num_displays)) + return DISP_CHANGE_FAILED; + + display_modes = copy_display_modes(displays[0].displayID, FALSE); + if (!display_modes) + { + macdrv_free_displays(displays); + return DISP_CHANGE_FAILED; + } + + pthread_mutex_lock(&modes_mutex); + bpp = get_default_bpp(); + pthread_mutex_unlock(&modes_mutex); + if ((devmode->dmFields & DM_BITSPERPEL) && devmode->dmBitsPerPel != bpp) + TRACE("using default %d bpp instead of caller's request %d bpp\n", bpp, devmode->dmBitsPerPel); + + TRACE("looking for %dx%dx%dbpp @%d Hz", + (devmode->dmFields & DM_PELSWIDTH ? devmode->dmPelsWidth : 0), + (devmode->dmFields & DM_PELSHEIGHT ? devmode->dmPelsHeight : 0), + bpp, + (devmode->dmFields & DM_DISPLAYFREQUENCY ? devmode->dmDisplayFrequency : 0)); + if (devmode->dmFields & DM_DISPLAYFIXEDOUTPUT) + TRACE(" %sstretched", devmode->dmDisplayFixedOutput == DMDFO_STRETCH ? "" : "un"); + if (devmode->dmFields & DM_DISPLAYFLAGS) + TRACE(" %sinterlaced", devmode->dmDisplayFlags & DM_INTERLACED ? "" : "non-"); + TRACE("\n"); + + desc = create_original_display_mode_descriptor(displays[0].displayID); + best_display_mode = find_best_display_mode(devmode, display_modes, bpp, desc); + + if (best_display_mode) + { if (flags & (CDS_TEST | CDS_NORESET)) ret = DISP_CHANGE_SUCCESSFUL; else if (wcsicmp(primary_adapter, devname)) { @@ -888,7 +895,7 @@ better:
macdrv_init_display_devices(TRUE);
- if (best_is_original && retina_enabled) + if (retina_enabled && display_mode_matches_descriptor(best_display_mode, desc)) { width *= 2; height *= 2;
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 0a453f937c3..7806f2f51a7 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -448,8 +448,11 @@ static BOOL write_adapter_mode( HKEY adapter_key, DWORD index, const DEVMODEW *m set_mode_field( flagsW, dmDisplayFlags, DM_DISPLAYFLAGS ); set_mode_field( orientationW, dmDisplayOrientation, DM_DISPLAYORIENTATION ); set_mode_field( fixed_outputW, dmDisplayFixedOutput, DM_DISPLAYFIXEDOUTPUT ); - set_mode_field( x_panningW, dmPosition.x, DM_POSITION ); - set_mode_field( y_panningW, dmPosition.y, DM_POSITION ); + if (index == ENUM_CURRENT_SETTINGS || index == ENUM_REGISTRY_SETTINGS) + { + set_mode_field( x_panningW, dmPosition.x, DM_POSITION ); + set_mode_field( y_panningW, dmPosition.y, DM_POSITION ); + } ret = set_reg_value( hkey, driver_extraW, REG_BINARY, mode + 1, mode->dmDriverExtra );
#undef set_mode_field @@ -487,8 +490,11 @@ static BOOL read_adapter_mode( HKEY adapter_key, DWORD index, DEVMODEW *mode ) query_mode_field( y_resolutionW, dmPelsHeight, DM_PELSHEIGHT ); query_mode_field( v_refreshW, dmDisplayFrequency, DM_DISPLAYFREQUENCY ); query_mode_field( flagsW, dmDisplayFlags, DM_DISPLAYFLAGS ); - query_mode_field( x_panningW, dmPosition.x, DM_POSITION ); - query_mode_field( y_panningW, dmPosition.y, DM_POSITION ); + if (index == ENUM_CURRENT_SETTINGS || index == ENUM_REGISTRY_SETTINGS) + { + query_mode_field( x_panningW, dmPosition.x, DM_POSITION ); + query_mode_field( y_panningW, dmPosition.y, DM_POSITION ); + } query_mode_field( orientationW, dmDisplayOrientation, DM_DISPLAYORIENTATION ); query_mode_field( fixed_outputW, dmDisplayFixedOutput, 0 );
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/win32u/driver.c | 12 +++ dlls/win32u/sysparams.c | 3 +- dlls/wineandroid.drv/init.c | 26 +++++- dlls/winemac.drv/display.c | 181 ++++++++++++++++++++++-------------- dlls/winemac.drv/gdi.c | 1 + dlls/winemac.drv/macdrv.h | 1 + dlls/winex11.drv/display.c | 33 ++++--- dlls/winex11.drv/init.c | 1 + dlls/winex11.drv/x11drv.h | 1 + include/wine/gdi_driver.h | 1 + 10 files changed, 176 insertions(+), 84 deletions(-)
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 3d29453c2bf..8f23872bb20 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -759,6 +759,11 @@ static LONG nulldrv_ChangeDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode, HWND return DISP_CHANGE_FAILED; }
+static BOOL nulldrv_CurrentDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode ) +{ + return FALSE; +} + static BOOL nulldrv_EnumDisplaySettingsEx( LPCWSTR name, DWORD num, LPDEVMODEW mode, DWORD flags ) { return FALSE; @@ -1072,6 +1077,11 @@ static LONG loaderdrv_ChangeDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode, HW return load_driver()->pChangeDisplaySettingsEx( name, mode, hwnd, flags, lparam ); }
+static BOOL loaderdrv_CurrentDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode ) +{ + return load_driver()->pCurrentDisplaySettingsEx( name, mode ); +} + static BOOL loaderdrv_EnumDisplaySettingsEx( LPCWSTR name, DWORD num, LPDEVMODEW mode, DWORD flags ) { return load_driver()->pEnumDisplaySettingsEx( name, num, mode, flags ); @@ -1178,6 +1188,7 @@ static const struct user_driver_funcs lazy_load_driver = loaderdrv_UpdateClipboard, /* display modes */ loaderdrv_ChangeDisplaySettingsEx, + loaderdrv_CurrentDisplaySettingsEx, loaderdrv_EnumDisplaySettingsEx, loaderdrv_UpdateDisplayDevices, /* windowing functions */ @@ -1253,6 +1264,7 @@ void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version SET_USER_FUNC(ClipboardWindowProc); SET_USER_FUNC(UpdateClipboard); SET_USER_FUNC(ChangeDisplaySettingsEx); + SET_USER_FUNC(CurrentDisplaySettingsEx); SET_USER_FUNC(EnumDisplaySettingsEx); SET_USER_FUNC(UpdateDisplayDevices); SET_USER_FUNC(CreateDesktopWindow); diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 7806f2f51a7..9a6804ee182 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2155,7 +2155,8 @@ BOOL WINAPI NtUserEnumDisplaySettings( UNICODE_STRING *device, DWORD index, DEVM memset( &devmode->dmDriverExtra, 0, devmode->dmSize - offsetof(DEVMODEW, dmDriverExtra) );
if (index == ENUM_REGISTRY_SETTINGS) ret = read_registry_settings( adapter_path, devmode ); - else ret = user_driver->pEnumDisplaySettingsEx( device_name, index, devmode, flags ); + else if (index != ENUM_CURRENT_SETTINGS) ret = user_driver->pEnumDisplaySettingsEx( device_name, index, devmode, flags ); + else ret = user_driver->pCurrentDisplaySettingsEx( device_name, devmode );
if (!ret) WARN( "Failed to query %s display settings.\n", debugstr_w(device_name) ); else TRACE( "position %dx%d, resolution %ux%u, frequency %u, depth %u, orientation %#x.\n", diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index 04328346852..8e0fd629c96 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -304,6 +304,30 @@ BOOL ANDROID_UpdateDisplayDevices( const struct gdi_device_manager *device_manag }
+/*********************************************************************** + * ANDROID_CurrentDisplaySettingsEx + */ +BOOL ANDROID_CurrentDisplaySettingsEx( LPCWSTR name, LPDEVMODEW devmode ) +{ + devmode->u2.dmDisplayFlags = 0; + devmode->dmDisplayFrequency = 0; + devmode->u1.s2.dmPosition.x = 0; + devmode->u1.s2.dmPosition.y = 0; + devmode->u1.s2.dmDisplayOrientation = 0; + devmode->u1.s2.dmDisplayFixedOutput = 0; + + devmode->dmPelsWidth = screen_width; + devmode->dmPelsHeight = screen_height; + devmode->dmBitsPerPel = screen_bpp; + devmode->dmDisplayFrequency = 60; + devmode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; + TRACE( "current mode -- %dx%d %d bpp @%d Hz\n", + devmode->dmPelsWidth, devmode->dmPelsHeight, + devmode->dmBitsPerPel, devmode->dmDisplayFrequency ); + return TRUE; +} + + /*********************************************************************** * ANDROID_EnumDisplaySettingsEx */ @@ -316,7 +340,6 @@ BOOL ANDROID_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, D devmode->u1.s2.dmDisplayOrientation = 0; devmode->u1.s2.dmDisplayFixedOutput = 0;
- if (n == ENUM_CURRENT_SETTINGS) n = 0; if (n == 0) { devmode->dmPelsWidth = screen_width; @@ -356,6 +379,7 @@ static const struct user_driver_funcs android_drv_funcs = .pVkKeyScanEx = ANDROID_VkKeyScanEx, .pSetCursor = ANDROID_SetCursor, .pChangeDisplaySettingsEx = ANDROID_ChangeDisplaySettingsEx, + .pCurrentDisplaySettingsEx = ANDROID_CurrentDisplaySettingsEx, .pEnumDisplaySettingsEx = ANDROID_EnumDisplaySettingsEx, .pUpdateDisplayDevices = ANDROID_UpdateDisplayDevices, .pCreateWindow = ANDROID_CreateWindow, diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index d40acc20f7f..d5ba799473a 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -992,6 +992,59 @@ static DEVMODEW *display_get_modes(CGDirectDisplayID display_id, int *modes_coun return devmodes; }
+/*********************************************************************** + * CurrentDisplaySettingsEx (MACDRV.@) + * + */ +BOOL macdrv_CurrentDisplaySettingsEx(LPCWSTR devname, DEVMODEW *devmode) +{ + struct macdrv_display *displays = NULL; + int num_displays; + CGDisplayModeRef display_mode; + + TRACE("%s, %p + %hu\n", debugstr_w(devname), devmode, devmode->dmSize); + + init_original_display_mode(); + + if (macdrv_get_displays(&displays, &num_displays)) + return FALSE; + + display_mode = CGDisplayCopyDisplayMode(displays[0].displayID); + + /* We currently only report modes for the primary display, so it's at (0, 0). */ + devmode->dmPosition.x = 0; + devmode->dmPosition.y = 0; + devmode->dmFields |= DM_POSITION; + + display_mode_to_devmode(displays[0].displayID, display_mode, devmode); + if (retina_enabled) + { + struct display_mode_descriptor* desc = create_original_display_mode_descriptor(displays[0].displayID); + if (display_mode_matches_descriptor(display_mode, desc)) + { + devmode->dmPelsWidth *= 2; + devmode->dmPelsHeight *= 2; + } + free_display_mode_descriptor(desc); + } + + CFRelease(display_mode); + macdrv_free_displays(displays); + + TRACE("mode %d -- %dx%dx%dbpp @%d Hz", mode, + devmode->dmPelsWidth, devmode->dmPelsHeight, devmode->dmBitsPerPel, + devmode->dmDisplayFrequency); + if (devmode->dmDisplayOrientation) + TRACE(" rotated %u degrees", devmode->dmDisplayOrientation * 90); + if (devmode->dmDisplayFixedOutput == DMDFO_STRETCH) + TRACE(" stretched"); + if (devmode->dmDisplayFlags & DM_INTERLACED) + TRACE(" interlaced"); + TRACE("\n"); + + return TRUE; +} + /*********************************************************************** * EnumDisplaySettingsEx (MACDRV.@) * @@ -1003,6 +1056,7 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, DEVMODEW *devmode CGDisplayModeRef display_mode; int display_mode_bpp; BOOL synthesized = FALSE; + DWORD count, i;
TRACE("%s, %u, %p + %hu, %08x\n", debugstr_w(devname), mode, devmode, devmode->dmSize, flags);
@@ -1011,99 +1065,88 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, DEVMODEW *devmode if (macdrv_get_displays(&displays, &num_displays)) goto failed;
- if (mode == ENUM_CURRENT_SETTINGS) - { - TRACE("mode %d (current) -- getting current mode\n", mode); - display_mode = CGDisplayCopyDisplayMode(displays[0].displayID); - display_mode_bpp = display_mode_bits_per_pixel(display_mode); - } - else - { - DWORD count, i; + pthread_mutex_lock(&modes_mutex);
- pthread_mutex_lock(&modes_mutex); + if (mode == 0 || !modes) + { + if (modes) CFRelease(modes); + modes = copy_display_modes(displays[0].displayID, (flags & EDS_RAWMODE) != 0); + modes_has_8bpp = modes_has_16bpp = FALSE;
- if (mode == 0 || !modes) + if (modes) { - if (modes) CFRelease(modes); - modes = copy_display_modes(displays[0].displayID, (flags & EDS_RAWMODE) != 0); - modes_has_8bpp = modes_has_16bpp = FALSE; - - if (modes) + count = CFArrayGetCount(modes); + for (i = 0; i < count && !(modes_has_8bpp && modes_has_16bpp); i++) { - count = CFArrayGetCount(modes); - for (i = 0; i < count && !(modes_has_8bpp && modes_has_16bpp); i++) - { - CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); - int bpp = display_mode_bits_per_pixel(mode); - if (bpp == 8) - modes_has_8bpp = TRUE; - else if (bpp == 16) - modes_has_16bpp = TRUE; - } + CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); + int bpp = display_mode_bits_per_pixel(mode); + if (bpp == 8) + modes_has_8bpp = TRUE; + else if (bpp == 16) + modes_has_16bpp = TRUE; } } + }
- display_mode = NULL; - if (modes) + display_mode = NULL; + if (modes) + { + int default_bpp; + DWORD seen_modes = 0; + + count = CFArrayGetCount(modes); + for (i = 0; i < count; i++) { - int default_bpp; - DWORD seen_modes = 0; + CGDisplayModeRef candidate = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i);
- count = CFArrayGetCount(modes); - for (i = 0; i < count; i++) + seen_modes++; + if (seen_modes > mode) { - CGDisplayModeRef candidate = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); - - seen_modes++; - if (seen_modes > mode) - { - display_mode = (CGDisplayModeRef)CFRetain(candidate); - display_mode_bpp = display_mode_bits_per_pixel(display_mode); - break; - } + display_mode = (CGDisplayModeRef)CFRetain(candidate); + display_mode_bpp = display_mode_bits_per_pixel(display_mode); + break; } + }
- default_bpp = get_default_bpp(); + default_bpp = get_default_bpp();
- /* If all the real modes are exhausted, synthesize lower bpp modes. */ - if (!display_mode && (!modes_has_16bpp || !modes_has_8bpp)) + /* If all the real modes are exhausted, synthesize lower bpp modes. */ + if (!display_mode && (!modes_has_16bpp || !modes_has_8bpp)) + { + /* We want to synthesize higher depths first. */ + int synth_bpps[] = { modes_has_16bpp ? 0 : 16, modes_has_8bpp ? 0 : 8 }; + size_t synth_bpp_idx; + for (synth_bpp_idx = 0; synth_bpp_idx < 2; synth_bpp_idx++) { - /* We want to synthesize higher depths first. */ - int synth_bpps[] = { modes_has_16bpp ? 0 : 16, modes_has_8bpp ? 0 : 8 }; - size_t synth_bpp_idx; - for (synth_bpp_idx = 0; synth_bpp_idx < 2; synth_bpp_idx++) + int synth_bpp = synth_bpps[synth_bpp_idx]; + if (synth_bpp == 0) + continue; + + for (i = 0; i < count; i++) { - int synth_bpp = synth_bpps[synth_bpp_idx]; - if (synth_bpp == 0) + CGDisplayModeRef candidate = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); + /* We only synthesize modes from those having the default bpp. */ + if (display_mode_bits_per_pixel(candidate) != default_bpp) continue;
- for (i = 0; i < count; i++) + seen_modes++; + if (seen_modes > mode) { - CGDisplayModeRef candidate = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); - /* We only synthesize modes from those having the default bpp. */ - if (display_mode_bits_per_pixel(candidate) != default_bpp) - continue; - - seen_modes++; - if (seen_modes > mode) - { - display_mode = (CGDisplayModeRef)CFRetain(candidate); - display_mode_bpp = synth_bpp; - synthesized = TRUE; - break; - } - } - - if (display_mode) + display_mode = (CGDisplayModeRef)CFRetain(candidate); + display_mode_bpp = synth_bpp; + synthesized = TRUE; break; + } } + + if (display_mode) + break; } } - - pthread_mutex_unlock(&modes_mutex); }
+ pthread_mutex_unlock(&modes_mutex); + if (!display_mode) goto failed;
diff --git a/dlls/winemac.drv/gdi.c b/dlls/winemac.drv/gdi.c index 7114835677b..c4668c1fb7d 100644 --- a/dlls/winemac.drv/gdi.c +++ b/dlls/winemac.drv/gdi.c @@ -275,6 +275,7 @@ static const struct user_driver_funcs macdrv_funcs = .pDesktopWindowProc = macdrv_DesktopWindowProc, .pDestroyCursorIcon = macdrv_DestroyCursorIcon, .pDestroyWindow = macdrv_DestroyWindow, + .pCurrentDisplaySettingsEx = macdrv_CurrentDisplaySettingsEx, .pEnumDisplaySettingsEx = macdrv_EnumDisplaySettingsEx, .pUpdateDisplayDevices = macdrv_UpdateDisplayDevices, .pGetCursorPos = macdrv_GetCursorPos, diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 7cb1665a8fc..280bb529a77 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -125,6 +125,7 @@ extern BOOL macdrv_ActivateKeyboardLayout(HKL hkl, UINT flags) DECLSPEC_HIDDEN; extern void macdrv_Beep(void) DECLSPEC_HIDDEN; extern LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, HWND hwnd, DWORD flags, LPVOID lpvoid) DECLSPEC_HIDDEN; +extern BOOL macdrv_CurrentDisplaySettingsEx(LPCWSTR name, LPDEVMODEW devmode) DECLSPEC_HIDDEN; extern BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmode, DWORD flags) DECLSPEC_HIDDEN; extern LRESULT macdrv_ClipboardWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 0af9ceeac08..e44a5c05794 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -316,6 +316,26 @@ static DWORD get_display_depth(ULONG_PTR display_id) return screen_bpp; }
+/*********************************************************************** + * CurrentDisplaySettingsEx (X11DRV.@) + * + */ +BOOL X11DRV_CurrentDisplaySettingsEx( LPCWSTR name, LPDEVMODEW devmode ) +{ + DEVMODEW mode; + ULONG_PTR id; + + if (!settings_handler.get_id( name, &id ) || !settings_handler.get_current_mode( id, &mode )) + { + ERR("Failed to get %s current display settings.\n", wine_dbgstr_w(name)); + return FALSE; + } + + memcpy( &devmode->dmFields, &mode.dmFields, devmode->dmSize - offsetof(DEVMODEW, dmFields) ); + if (!is_detached_mode( devmode )) devmode->dmBitsPerPel = get_display_depth( id ); + return TRUE; +} + /*********************************************************************** * EnumDisplaySettingsEx (X11DRV.@) * @@ -326,19 +346,6 @@ BOOL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DW UINT mode_count; ULONG_PTR id;
- if (n == ENUM_CURRENT_SETTINGS) - { - if (!settings_handler.get_id( name, &id ) || !settings_handler.get_current_mode( id, &mode )) - { - ERR("Failed to get %s current display settings.\n", wine_dbgstr_w(name)); - return FALSE; - } - - memcpy( &devmode->dmFields, &mode.dmFields, devmode->dmSize - offsetof(DEVMODEW, dmFields) ); - if (!is_detached_mode( devmode )) devmode->dmBitsPerPel = get_display_depth( id ); - return TRUE; - } - pthread_mutex_lock( &settings_mutex ); if (n == 0 || wcsicmp(cached_device_name, name) || cached_flags != flags) { diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 7c5a1acd7b6..22c911c879d 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -404,6 +404,7 @@ static const struct user_driver_funcs x11drv_funcs = .pSetCursorPos = X11DRV_SetCursorPos, .pClipCursor = X11DRV_ClipCursor, .pChangeDisplaySettingsEx = X11DRV_ChangeDisplaySettingsEx, + .pCurrentDisplaySettingsEx = X11DRV_CurrentDisplaySettingsEx, .pEnumDisplaySettingsEx = X11DRV_EnumDisplaySettingsEx, .pUpdateDisplayDevices = X11DRV_UpdateDisplayDevices, .pCreateDesktopWindow = X11DRV_CreateDesktopWindow, diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index b8997455324..6aa9b82e8cf 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -215,6 +215,7 @@ extern BOOL X11DRV_GetCursorPos( LPPOINT pos ) DECLSPEC_HIDDEN; extern BOOL X11DRV_ClipCursor( LPCRECT clip ) DECLSPEC_HIDDEN; extern LONG X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, HWND hwnd, DWORD flags, LPVOID lpvoid ) DECLSPEC_HIDDEN; +extern BOOL X11DRV_CurrentDisplaySettingsEx( LPCWSTR name, LPDEVMODEW devmode ) DECLSPEC_HIDDEN; extern BOOL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DWORD flags ) DECLSPEC_HIDDEN; extern BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manager, diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 58b6aa9f0b8..8ac3be3bfb8 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -296,6 +296,7 @@ struct user_driver_funcs void (*pUpdateClipboard)(void); /* display modes */ LONG (*pChangeDisplaySettingsEx)(LPCWSTR,LPDEVMODEW,HWND,DWORD,LPVOID); + BOOL (*pCurrentDisplaySettingsEx)(LPCWSTR,LPDEVMODEW); BOOL (*pEnumDisplaySettingsEx)(LPCWSTR,DWORD,LPDEVMODEW,DWORD); BOOL (*pUpdateDisplayDevices)(const struct gdi_device_manager *,BOOL,void*); /* windowing functions */
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/wineandroid.drv/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index 8e0fd629c96..d48834b8817 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -320,7 +320,7 @@ BOOL ANDROID_CurrentDisplaySettingsEx( LPCWSTR name, LPDEVMODEW devmode ) devmode->dmPelsHeight = screen_height; devmode->dmBitsPerPel = screen_bpp; devmode->dmDisplayFrequency = 60; - devmode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; + devmode->dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; TRACE( "current mode -- %dx%d %d bpp @%d Hz\n", devmode->dmPelsWidth, devmode->dmPelsHeight, devmode->dmBitsPerPel, devmode->dmDisplayFrequency ); @@ -346,7 +346,7 @@ BOOL ANDROID_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, D devmode->dmPelsHeight = screen_height; devmode->dmBitsPerPel = screen_bpp; devmode->dmDisplayFrequency = 60; - devmode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; + devmode->dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; TRACE( "mode %d -- %dx%d %d bpp @%d Hz\n", n, devmode->dmPelsWidth, devmode->dmPelsHeight, devmode->dmBitsPerPel, devmode->dmDisplayFrequency );
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 55 +++++++++++++++++++++++++++++++++----- dlls/winemac.drv/display.c | 3 +-- dlls/winex11.drv/display.c | 30 +-------------------- 3 files changed, 51 insertions(+), 37 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 9a6804ee182..b8650fec126 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2037,8 +2037,37 @@ static BOOL is_detached_mode( const DEVMODEW *mode ) mode->dmPelsHeight == 0; }
-static DEVMODEW *validate_display_settings( DEVMODEW *default_mode, DEVMODEW *current_mode, DEVMODEW *devmode ) +static DEVMODEW *find_display_mode( DEVMODEW *modes, DEVMODEW *devmode ) { + DEVMODEW *mode; + + if (is_detached_mode( devmode )) return devmode; + + for (mode = modes; mode && mode->dmSize; mode = NEXT_DEVMODEW(mode)) + { + if ((devmode->dmFields & DM_BITSPERPEL) && devmode->dmBitsPerPel && devmode->dmBitsPerPel != mode->dmBitsPerPel) + continue; + if ((devmode->dmFields & DM_PELSWIDTH) && devmode->dmPelsWidth != mode->dmPelsWidth) + continue; + if ((devmode->dmFields & DM_PELSHEIGHT) && devmode->dmPelsHeight != mode->dmPelsHeight) + continue; + if ((devmode->dmFields & DM_DISPLAYFREQUENCY) && devmode->dmDisplayFrequency && mode->dmDisplayFrequency && + devmode->dmDisplayFrequency != 1 && devmode->dmDisplayFrequency != mode->dmDisplayFrequency) + continue; + if ((devmode->dmFields & DM_DISPLAYORIENTATION) && devmode->dmDisplayOrientation != mode->dmDisplayOrientation) + continue; + + return mode; + } + + return NULL; +} + +static DEVMODEW *validate_display_settings( DEVMODEW *modes, DEVMODEW *default_mode, + DEVMODEW *current_mode, DEVMODEW *devmode ) +{ + DEVMODEW *mode; + if (devmode) { trace_devmode( devmode ); @@ -2072,7 +2101,16 @@ static DEVMODEW *validate_display_settings( DEVMODEW *default_mode, DEVMODEW *cu if (!devmode->dmPelsHeight) devmode->dmPelsHeight = current_mode->dmPelsHeight; }
- return devmode; + if (is_detached_mode( devmode )) return devmode; + + if ((mode = find_display_mode( modes, devmode ))) + { + mode->dmFields |= DM_POSITION; + mode->dmPosition = devmode->dmPosition; + return mode; + } + + return NULL; }
/*********************************************************************** @@ -2081,10 +2119,11 @@ static DEVMODEW *validate_display_settings( DEVMODEW *default_mode, DEVMODEW *cu LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devmode, HWND hwnd, DWORD flags, void *lparam ) { - DEVMODEW default_mode = {.dmSize = sizeof(DEVMODEW)}, current_mode = {.dmSize = sizeof(DEVMODEW)}; + DEVMODEW *modes, default_mode = {.dmSize = sizeof(DEVMODEW)}, current_mode = {.dmSize = sizeof(DEVMODEW)}; WCHAR device_name[CCHDEVICENAME], adapter_path[MAX_PATH]; LONG ret = DISP_CHANGE_SUCCESSFUL; struct adapter *adapter; + SIZE_T size;
TRACE( "%s %p %p %#x %p\n", debugstr_us(devname), devmode, hwnd, flags, lparam ); TRACE( "flags=%s\n", _CDS_flags(flags) ); @@ -2102,9 +2141,13 @@ LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devm { lstrcpyW( device_name, adapter->dev.device_name ); lstrcpyW( adapter_path, adapter->config_key ); + size = sizeof(DEVMODEW) + adapter->modes[0].dmDriverExtra; + /* allocate an extra mode to make iteration easier */ + modes = calloc( adapter->mode_count + 1, size ); + if (modes) memcpy( modes, adapter->modes, adapter->mode_count * size ); } unlock_display_devices(); - if (!adapter) + if (!adapter || !modes) { WARN( "Invalid device name %s.\n", debugstr_us(devname) ); return DISP_CHANGE_BADPARAM; @@ -2113,11 +2156,11 @@ LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devm if (!read_registry_settings( adapter_path, &default_mode )) default_mode.dmSize = 0; if (!NtUserEnumDisplaySettings( devname, ENUM_CURRENT_SETTINGS, ¤t_mode, 0 )) current_mode.dmSize = 0;
- if (!(devmode = validate_display_settings( &default_mode, ¤t_mode, devmode ))) ret = DISP_CHANGE_BADMODE; - else if (user_driver->pChangeDisplaySettingsEx( device_name, devmode, hwnd, flags | CDS_TEST, lparam )) ret = DISP_CHANGE_BADMODE; + if (!(devmode = validate_display_settings( modes, &default_mode, ¤t_mode, devmode ))) ret = DISP_CHANGE_BADMODE; else if ((flags & CDS_UPDATEREGISTRY) && !write_registry_settings( adapter_path, devmode )) ret = DISP_CHANGE_NOTUPDATED; else if (flags & (CDS_TEST | CDS_NORESET)) ret = DISP_CHANGE_SUCCESSFUL; else ret = user_driver->pChangeDisplaySettingsEx( device_name, devmode, hwnd, flags, lparam ); + free( modes );
if (ret) ERR( "Changing %s display settings returned %d.\n", debugstr_us(devname), ret ); return ret; diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index d5ba799473a..de362c676a7 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -881,8 +881,7 @@ LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode,
if (best_display_mode) { - if (flags & (CDS_TEST | CDS_NORESET)) ret = DISP_CHANGE_SUCCESSFUL; - else if (wcsicmp(primary_adapter, devname)) + if (wcsicmp(primary_adapter, devname)) { FIXME("Changing non-primary adapter settings is currently unsupported.\n"); ret = DISP_CHANGE_SUCCESSFUL; diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index e44a5c05794..f9d455d8d5e 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -784,41 +784,13 @@ static BOOL all_detached_settings(const DEVMODEW *displays) LONG X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, HWND hwnd, DWORD flags, LPVOID lpvoid ) { - DEVMODEW *displays, *mode, *full_mode; + DEVMODEW *displays; LONG ret;
ret = get_display_settings( &displays, devname, devmode ); if (ret != DISP_CHANGE_SUCCESSFUL) return ret;
- if (flags & CDS_UPDATEREGISTRY && devname && devmode) - { - for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) - { - ULONG_PTR *id = (ULONG_PTR *)(mode + 1); - - if (!wcsicmp(mode->dmDeviceName, devname)) - { - full_mode = get_full_mode(*id, mode); - if (!full_mode) - { - free(displays); - return DISP_CHANGE_BADMODE; - } - - memcpy( &devmode->dmFields, &full_mode->dmFields, devmode->dmSize - offsetof(DEVMODEW, dmFields) ); - free_full_mode(full_mode); - break; - } - } - } - - if (flags & (CDS_TEST | CDS_NORESET)) - { - free(displays); - return DISP_CHANGE_SUCCESSFUL; - } - if (all_detached_settings( displays )) { WARN("Detaching all displays is not permitted.\n");
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 4 +++- dlls/winex11.drv/display.c | 10 ---------- 2 files changed, 3 insertions(+), 11 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index b8650fec126..3017d02ecaa 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2106,7 +2106,9 @@ static DEVMODEW *validate_display_settings( DEVMODEW *modes, DEVMODEW *default_m if ((mode = find_display_mode( modes, devmode ))) { mode->dmFields |= DM_POSITION; - mode->dmPosition = devmode->dmPosition; + if (devmode->dmFields & DM_POSITION) mode->dmPosition = devmode->dmPosition; + else mode->dmPosition = current_mode->dmPosition; + return mode; }
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index f9d455d8d5e..35065e7cd54 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -498,16 +498,6 @@ static LONG get_display_settings(DEVMODEW **new_displays, const WCHAR *dev_name, else if (!wcsicmp(dev_name, display_device.DeviceName)) { *mode = *dev_mode; - if (!(dev_mode->dmFields & DM_POSITION)) - { - memset(¤t_mode, 0, sizeof(current_mode)); - current_mode.dmSize = sizeof(current_mode); - if (!NtUserEnumDisplaySettings( &device_name, ENUM_CURRENT_SETTINGS, ¤t_mode, 0 )) - goto done; - - mode->dmFields |= DM_POSITION; - mode->dmPosition = current_mode.dmPosition; - } } else {
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/win32u/driver.c | 8 +- dlls/win32u/sysparams.c | 288 +++++++++++++++++++++++++- dlls/wineandroid.drv/init.c | 5 +- dlls/winemac.drv/display.c | 80 +++----- dlls/winemac.drv/macdrv.h | 3 +- dlls/winex11.drv/display.c | 391 ++---------------------------------- dlls/winex11.drv/x11drv.h | 3 +- include/wine/gdi_driver.h | 2 +- 8 files changed, 332 insertions(+), 448 deletions(-)
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 8f23872bb20..347e57d8f1d 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -753,7 +753,7 @@ static void nulldrv_UpdateClipboard(void) { }
-static LONG nulldrv_ChangeDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode, HWND hwnd, +static LONG nulldrv_ChangeDisplaySettingsEx( const DEVMODEW *modes, HWND hwnd, DWORD flags, LPVOID lparam ) { return DISP_CHANGE_FAILED; @@ -1071,10 +1071,10 @@ static SHORT loaderdrv_VkKeyScanEx( WCHAR ch, HKL layout ) return load_driver()->pVkKeyScanEx( ch, layout ); }
-static LONG loaderdrv_ChangeDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode, HWND hwnd, - DWORD flags, LPVOID lparam ) +static LONG loaderdrv_ChangeDisplaySettingsEx( const DEVMODEW *modes, HWND hwnd, + DWORD flags, LPVOID lparam ) { - return load_driver()->pChangeDisplaySettingsEx( name, mode, hwnd, flags, lparam ); + return load_driver()->pChangeDisplaySettingsEx( modes, hwnd, flags, lparam ); }
static BOOL loaderdrv_CurrentDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode ) diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 3017d02ecaa..7fbdea7e418 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -602,8 +602,8 @@ static BOOL read_display_adapter_settings( unsigned int index, struct adapter *i if (query_reg_value( hkey, driver_extraW, value, sizeof(buffer) ) && value->Type == REG_DWORD) driver_extra = *(const DWORD *)value->Data;
- /* Modes */ - if ((info->modes = calloc( info->mode_count, sizeof(DEVMODEW) + driver_extra ))) + /* Modes, allocate an extra mode for easier iteration */ + if ((info->modes = calloc( info->mode_count + 1, sizeof(DEVMODEW) + driver_extra ))) { for (i = 0, mode = info->modes; i < info->mode_count; i++) { @@ -2108,13 +2108,285 @@ static DEVMODEW *validate_display_settings( DEVMODEW *modes, DEVMODEW *default_m mode->dmFields |= DM_POSITION; if (devmode->dmFields & DM_POSITION) mode->dmPosition = devmode->dmPosition; else mode->dmPosition = current_mode->dmPosition; + }
- return mode; + return mode; +} + +static DEVMODEW *get_display_settings( const WCHAR *devname, const DEVMODEW *fullmode ) +{ + DEVMODEW *mode, *full, *displays; + DISPLAY_DEVICEW display_device; + struct adapter *adapter; + UINT size = 0; + BOOL ret; + + if (!lock_display_devices()) return NULL; + + LIST_FOR_EACH_ENTRY(adapter, &adapters, struct adapter, entry) + { + if (!adapter->mode_count) continue; + size += sizeof(DEVMODEW) + adapter->modes[0].dmDriverExtra; }
+ /* allocate an extra mode for easier iteration */ + if (!(displays = calloc( 1, size + sizeof(DEVMODEW) ))) goto done; + mode = displays; + + LIST_FOR_EACH_ENTRY(adapter, &adapters, struct adapter, entry) + { + if (!adapter->mode_count) continue; + + mode->dmSize = sizeof(DEVMODEW); + if (devname) + { + if (!wcsicmp( devname, adapter->dev.device_name )) + memcpy( mode, fullmode, mode->dmSize + fullmode->dmDriverExtra ); + else + { + if (!(ret = user_driver->pCurrentDisplaySettingsEx( adapter->dev.device_name, mode ))) goto done; + if (!(full = find_display_mode( adapter->modes, mode ))) goto done; + mode->dmDriverExtra = full->dmDriverExtra; + memcpy( mode + 1, full + 1, full->dmDriverExtra ); + } + } + else if (!(ret = read_registry_settings( adapter->config_key, mode ))) goto done; + + lstrcpyW( mode->dmDeviceName, display_device.DeviceName ); + mode = NEXT_DEVMODEW(mode); + } + + unlock_display_devices(); + return displays; + +done: + unlock_display_devices(); + free( displays ); return NULL; }
+static INT offset_length( POINT offset ) +{ + return offset.x * offset.x + offset.y * offset.y; +} + +static void set_rect_from_devmode( RECT *rect, const DEVMODEW *mode ) +{ + SetRect( rect, mode->dmPosition.x, mode->dmPosition.y, mode->dmPosition.x + mode->dmPelsWidth, + mode->dmPosition.y + mode->dmPelsHeight ); +} + +/* Check if a rect overlaps with placed display rects */ +static BOOL overlap_placed_displays( const RECT *rect, const DEVMODEW *displays ) +{ + const DEVMODEW *mode; + RECT intersect; + + for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) + { + set_rect_from_devmode( &intersect, mode ); + if ((mode->dmFields & DM_POSITION) && intersect_rect( &intersect, &intersect, 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 DEVMODEW *displays, const DEVMODEW *placing ) +{ + POINT points[8], left_top, offset, min_offset = {0, 0}; + INT point_idx, point_count, vertex_idx; + BOOL has_placed = FALSE, first = TRUE; + RECT desired_rect, rect; + const DEVMODEW *mode; + INT width, height; + + set_rect_from_devmode( &desired_rect, placing ); + + /* If the display to be placed is detached, no offset is needed to place it */ + if (IsRectEmpty( &desired_rect )) return min_offset; + + /* If there is no placed and attached display, place this display as it is */ + for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) + { + set_rect_from_devmode( &rect, mode ); + if ((mode->dmFields & DM_POSITION) && !IsRectEmpty( &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 = desired_rect.right - desired_rect.left; + height = desired_rect.bottom - desired_rect.top; + + for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) + { + set_rect_from_devmode( &rect, mode ); + if (!(mode->dmFields & DM_POSITION) || IsRectEmpty( &rect )) continue; + + /* Get four vertices of the placed display rectangle */ + points[0].x = rect.left; + points[0].y = rect.top; + points[1].x = rect.left; + points[1].y = rect.bottom; + points[2].x = rect.right; + points[2].y = rect.top; + points[3].x = rect.right; + points[3].y = rect.bottom; + point_count = 4; + + /* Intersected points when moving the display to be placed horizontally */ + if (desired_rect.bottom >= rect.top && desired_rect.top <= rect.bottom) + { + points[point_count].x = rect.left; + points[point_count++].y = desired_rect.top; + points[point_count].x = rect.right; + points[point_count++].y = desired_rect.top; + } + /* Intersected points when moving the display to be placed vertically */ + if (desired_rect.left <= rect.right && desired_rect.right >= rect.left) + { + points[point_count].x = desired_rect.left; + points[point_count++].y = rect.top; + points[point_count].x = desired_rect.left; + points[point_count++].y = 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 - desired_rect.left; + offset.y = left_top.y - desired_rect.top; + rect = desired_rect; + OffsetRect( &rect, offset.x, offset.y ); + if (!overlap_placed_displays( &rect, displays )) + { + 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( DEVMODEW *displays ) +{ + INT left_most = INT_MAX, top_most = INT_MAX; + POINT min_offset, offset; + DEVMODEW *mode, *placing; + + for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) + mode->dmFields &= ~DM_POSITION; + + /* 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 = NULL; + for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) + { + if (mode->dmFields & DM_POSITION) continue; + + offset = get_placement_offset( displays, mode ); + if (!placing || offset_length( offset ) < offset_length( min_offset )) + { + min_offset = offset; + placing = mode; + } + } + + /* If all displays are placed */ + if (!placing) break; + + placing->dmPosition.x += min_offset.x; + placing->dmPosition.y += min_offset.y; + placing->dmFields |= DM_POSITION; + + left_most = min( left_most, placing->dmPosition.x ); + top_most = min( top_most, placing->dmPosition.y ); + } + + /* Convert virtual screen coordinates to root coordinates */ + for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) + { + mode->dmPosition.x -= left_most; + mode->dmPosition.y -= top_most; + } +} + +static BOOL all_detached_settings( const DEVMODEW *displays ) +{ + const DEVMODEW *mode; + + for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) + if (!is_detached_mode( mode )) return FALSE; + + return TRUE; +} + +static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *fullmode, + HWND hwnd, DWORD flags, void *lparam ) +{ + DEVMODEW *displays; + LONG ret; + + displays = get_display_settings( devname, fullmode ); + if (!displays) return DISP_CHANGE_FAILED; + + if (all_detached_settings( displays )) + { + WARN( "Detaching all modes is not permitted.\n" ); + free( displays ); + return DISP_CHANGE_SUCCESSFUL; + } + + place_all_displays( displays ); + + ret = user_driver->pChangeDisplaySettingsEx( displays, hwnd, flags, lparam ); + + free( displays ); + return ret; +} + /*********************************************************************** * NtUserChangeDisplaySettings (win32u.@) */ @@ -2130,13 +2402,7 @@ LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devm TRACE( "%s %p %p %#x %p\n", debugstr_us(devname), devmode, hwnd, flags, lparam ); TRACE( "flags=%s\n", _CDS_flags(flags) );
- if ((!devname || !devname->Length) && !devmode) - { - ret = user_driver->pChangeDisplaySettingsEx( NULL, NULL, hwnd, flags, lparam ); - if (ret != DISP_CHANGE_SUCCESSFUL) - ERR( "Restoring all displays to their registry settings returned %d.\n", ret ); - return ret; - } + if ((!devname || !devname->Length) && !devmode) return apply_display_settings( NULL, NULL, hwnd, flags, lparam );
if (!lock_display_devices()) return DISP_CHANGE_FAILED; if ((adapter = find_adapter( devname ))) @@ -2161,7 +2427,7 @@ LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devm if (!(devmode = validate_display_settings( modes, &default_mode, ¤t_mode, devmode ))) ret = DISP_CHANGE_BADMODE; else if ((flags & CDS_UPDATEREGISTRY) && !write_registry_settings( adapter_path, devmode )) ret = DISP_CHANGE_NOTUPDATED; else if (flags & (CDS_TEST | CDS_NORESET)) ret = DISP_CHANGE_SUCCESSFUL; - else ret = user_driver->pChangeDisplaySettingsEx( device_name, devmode, hwnd, flags, lparam ); + else ret = apply_display_settings( device_name, devmode, hwnd, flags, lparam ); free( modes );
if (ret) ERR( "Changing %s display settings returned %d.\n", debugstr_us(devname), ret ); diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index d48834b8817..a40efafb49c 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -262,10 +262,9 @@ static BOOL CDECL ANDROID_DeleteDC( PHYSDEV dev ) /*********************************************************************** * ANDROID_ChangeDisplaySettingsEx */ -LONG ANDROID_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, - HWND hwnd, DWORD flags, LPVOID lpvoid ) +LONG ANDROID_ChangeDisplaySettingsEx( const DEVMODEW *modes, HWND hwnd, DWORD flags, LPVOID lpvoid ) { - FIXME( "(%s,%p,%p,0x%08x,%p)\n", debugstr_w( devname ), devmode, hwnd, flags, lpvoid ); + FIXME( "(%p,%p,0x%08x,%p)\n", modes, hwnd, flags, lpvoid ); return DISP_CHANGE_SUCCESSFUL; }
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index de362c676a7..11b1e2eb9c4 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -807,8 +807,7 @@ better: * ChangeDisplaySettingsEx (MACDRV.@) * */ -LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, - HWND hwnd, DWORD flags, LPVOID lpvoid) +LONG macdrv_ChangeDisplaySettingsEx(const DEVMODEW *modes, HWND hwnd, DWORD flags, LPVOID lpvoid) { WCHAR primary_adapter[CCHDEVICENAME]; LONG ret = DISP_CHANGE_BADMODE; @@ -820,35 +819,13 @@ LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, struct display_mode_descriptor* desc; CGDisplayModeRef best_display_mode;
- TRACE("%s %p %p 0x%08x %p\n", debugstr_w(devname), devmode, hwnd, flags, lpvoid); + TRACE("%p %p 0x%08x %p\n", modes, hwnd, flags, lpvoid);
init_original_display_mode();
if (!get_primary_adapter(primary_adapter)) return DISP_CHANGE_FAILED;
- if (!devname && !devmode) - { - UNICODE_STRING str; - memset(&default_mode, 0, sizeof(default_mode)); - default_mode.dmSize = sizeof(default_mode); - RtlInitUnicodeString(&str, primary_adapter); - if (!NtUserEnumDisplaySettings(&str, ENUM_REGISTRY_SETTINGS, &default_mode, 0)) - { - ERR("Default mode not found for %s!\n", wine_dbgstr_w(primary_adapter)); - return DISP_CHANGE_BADMODE; - } - - devname = primary_adapter; - devmode = &default_mode; - } - - if (is_detached_mode(devmode)) - { - FIXME("Detaching adapters is currently unsupported.\n"); - return DISP_CHANGE_SUCCESSFUL; - } - if (macdrv_get_displays(&displays, &num_displays)) return DISP_CHANGE_FAILED;
@@ -862,29 +839,41 @@ LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, pthread_mutex_lock(&modes_mutex); bpp = get_default_bpp(); pthread_mutex_unlock(&modes_mutex); - if ((devmode->dmFields & DM_BITSPERPEL) && devmode->dmBitsPerPel != bpp) - TRACE("using default %d bpp instead of caller's request %d bpp\n", bpp, devmode->dmBitsPerPel); - - TRACE("looking for %dx%dx%dbpp @%d Hz", - (devmode->dmFields & DM_PELSWIDTH ? devmode->dmPelsWidth : 0), - (devmode->dmFields & DM_PELSHEIGHT ? devmode->dmPelsHeight : 0), - bpp, - (devmode->dmFields & DM_DISPLAYFREQUENCY ? devmode->dmDisplayFrequency : 0)); - if (devmode->dmFields & DM_DISPLAYFIXEDOUTPUT) - TRACE(" %sstretched", devmode->dmDisplayFixedOutput == DMDFO_STRETCH ? "" : "un"); - if (devmode->dmFields & DM_DISPLAYFLAGS) - TRACE(" %sinterlaced", devmode->dmDisplayFlags & DM_INTERLACED ? "" : "non-"); - TRACE("\n");
desc = create_original_display_mode_descriptor(displays[0].displayID); - best_display_mode = find_best_display_mode(devmode, display_modes, bpp, desc);
- if (best_display_mode) + for (mode = modes; mode->dmSize && !ret; mode = NEXT_DEVMODEW(mode)) { - if (wcsicmp(primary_adapter, devname)) + if (wcsicmp(primary_adapter, mode->dmDeviceName)) { FIXME("Changing non-primary adapter settings is currently unsupported.\n"); - ret = DISP_CHANGE_SUCCESSFUL; + continue; + } + if (is_detached_mode(devmode)) + { + FIXME("Detaching adapters is currently unsupported.\n"); + continue; + } + + if ((mode->dmFields & DM_BITSPERPEL) && mode->dmBitsPerPel != bpp) + TRACE("using default %d bpp instead of caller's request %d bpp\n", bpp, mode->dmBitsPerPel); + + TRACE("looking for %dx%dx%dbpp @%d Hz", + (mode->dmFields & DM_PELSWIDTH ? mode->dmPelsWidth : 0), + (mode->dmFields & DM_PELSHEIGHT ? mode->dmPelsHeight : 0), + bpp, + (mode->dmFields & DM_DISPLAYFREQUENCY ? mode->dmDisplayFrequency : 0)); + if (mode->dmFields & DM_DISPLAYFIXEDOUTPUT) + TRACE(" %sstretched", mode->dmDisplayFixedOutput == DMDFO_STRETCH ? "" : "un"); + if (mode->dmFields & DM_DISPLAYFLAGS) + TRACE(" %sinterlaced", mode->dmDisplayFlags & DM_INTERLACED ? "" : "non-"); + TRACE("\n"); + + if (!(best_display_mode = find_best_display_mode(mode, display_modes, bpp, desc))) + { + ERR("No matching mode found %ux%ux%d @%u!\n", mode->dmPelsWidth, mode->dmPelsHeight, + bpp, mode->dmDisplayFrequency); + ret = DISP_CHANGE_BADMODE; } else if (macdrv_set_display_mode(&displays[0], best_display_mode)) { @@ -902,7 +891,6 @@ LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode,
send_message(NtUserGetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp, MAKELPARAM(width, height)); - ret = DISP_CHANGE_SUCCESSFUL; } else { @@ -910,12 +898,6 @@ LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, ret = DISP_CHANGE_FAILED; } } - else - { - /* no valid modes found */ - ERR("No matching mode found %ux%ux%d @%u!\n", devmode->dmPelsWidth, devmode->dmPelsHeight, - bpp, devmode->dmDisplayFrequency); - }
free_display_mode_descriptor(desc); CFRelease(display_modes); diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 280bb529a77..13cb58fdf0e 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -123,8 +123,7 @@ static inline struct macdrv_thread_data *macdrv_thread_data(void)
extern BOOL macdrv_ActivateKeyboardLayout(HKL hkl, UINT flags) DECLSPEC_HIDDEN; extern void macdrv_Beep(void) DECLSPEC_HIDDEN; -extern LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, - HWND hwnd, DWORD flags, LPVOID lpvoid) DECLSPEC_HIDDEN; +extern LONG macdrv_ChangeDisplaySettingsEx(const DEVMODEW *modes, HWND hwnd, DWORD flags, LPVOID lpvoid) DECLSPEC_HIDDEN; extern BOOL macdrv_CurrentDisplaySettingsEx(LPCWSTR name, LPDEVMODEW devmode) DECLSPEC_HIDDEN; extern BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmode, DWORD flags) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 35065e7cd54..399863800fc 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -390,413 +390,52 @@ BOOL is_detached_mode(const DEVMODEW *mode) mode->dmPelsHeight == 0; }
-/* Get the full display mode with all the necessary fields set. - * 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) +static LONG apply_display_settings(const DEVMODEW *displays, BOOL do_attach) { - DEVMODEW *modes, *full_mode, *found_mode = NULL; - UINT mode_count, mode_idx; - - if (is_detached_mode(dev_mode)) - return dev_mode; - - if (!settings_handler.get_modes(id, EDS_ROTATEDMODE, &modes, &mode_count)) - return NULL; - - qsort(modes, mode_count, sizeof(*modes) + modes[0].dmDriverExtra, mode_compare); - for (mode_idx = 0; mode_idx < mode_count; ++mode_idx) - { - found_mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*modes) + modes[0].dmDriverExtra) * mode_idx); - - if (dev_mode->dmFields & DM_BITSPERPEL && - dev_mode->dmBitsPerPel && - found_mode->dmBitsPerPel != dev_mode->dmBitsPerPel) - continue; - if (dev_mode->dmFields & DM_PELSWIDTH && found_mode->dmPelsWidth != dev_mode->dmPelsWidth) - continue; - if (dev_mode->dmFields & DM_PELSHEIGHT && found_mode->dmPelsHeight != dev_mode->dmPelsHeight) - continue; - if (dev_mode->dmFields & DM_DISPLAYFREQUENCY && - dev_mode->dmDisplayFrequency && - found_mode->dmDisplayFrequency && - dev_mode->dmDisplayFrequency != 1 && - dev_mode->dmDisplayFrequency != found_mode->dmDisplayFrequency) - continue; - if (dev_mode->dmFields & DM_DISPLAYORIENTATION && - found_mode->dmDisplayOrientation != dev_mode->dmDisplayOrientation) - continue; - - break; - } - - if (!found_mode || mode_idx == mode_count) - { - settings_handler.free_modes(modes); - return NULL; - } - - if (!(full_mode = malloc(sizeof(*found_mode) + found_mode->dmDriverExtra))) - { - settings_handler.free_modes(modes); - return NULL; - } - - memcpy(full_mode, found_mode, sizeof(*found_mode) + found_mode->dmDriverExtra); - settings_handler.free_modes(modes); - - full_mode->dmFields |= DM_POSITION; - full_mode->dmPosition = dev_mode->dmPosition; - return full_mode; -} - -static void free_full_mode(DEVMODEW *mode) -{ - if (!is_detached_mode(mode)) - free(mode); -} - -static LONG get_display_settings(DEVMODEW **new_displays, const WCHAR *dev_name, DEVMODEW *dev_mode) -{ - DEVMODEW registry_mode, current_mode, *mode, *displays; - INT display_idx, display_count = 0; - DISPLAY_DEVICEW display_device; - LONG ret = DISP_CHANGE_FAILED; - UNICODE_STRING device_name; - - display_device.cb = sizeof(display_device); - for (display_idx = 0; !NtUserEnumDisplayDevices( NULL, display_idx, &display_device, 0 ); ++display_idx) - ++display_count; - - /* use driver extra data to store an ULONG_PTR adapter id after each mode, - * and allocate an extra mode to make iteration easier */ - if (!(displays = calloc(display_count + 1, sizeof(DEVMODEW) + sizeof(ULONG_PTR)))) goto done; - mode = displays; - - for (display_idx = 0; display_idx < display_count; ++display_idx) - { - ULONG_PTR *id = (ULONG_PTR *)(mode + 1); - - if (NtUserEnumDisplayDevices( NULL, display_idx, &display_device, 0 )) - goto done; - - if (!settings_handler.get_id(display_device.DeviceName, id)) - { - ret = DISP_CHANGE_BADPARAM; - goto done; - } - - RtlInitUnicodeString( &device_name, display_device.DeviceName ); - - if (!dev_mode) - { - memset(®istry_mode, 0, sizeof(registry_mode)); - registry_mode.dmSize = sizeof(registry_mode); - if (!NtUserEnumDisplaySettings( &device_name, ENUM_REGISTRY_SETTINGS, ®istry_mode, 0 )) - goto done; - *mode = registry_mode; - } - else if (!wcsicmp(dev_name, display_device.DeviceName)) - { - *mode = *dev_mode; - } - else - { - memset(¤t_mode, 0, sizeof(current_mode)); - current_mode.dmSize = sizeof(current_mode); - if (!NtUserEnumDisplaySettings( &device_name, ENUM_CURRENT_SETTINGS, ¤t_mode, 0 )) - goto done; - *mode = current_mode; - } - - mode->dmSize = sizeof(DEVMODEW); - lstrcpyW(mode->dmDeviceName, display_device.DeviceName); - mode->dmDriverExtra = sizeof(ULONG_PTR); - mode = NEXT_DEVMODEW(mode); - } - - *new_displays = displays; - return DISP_CHANGE_SUCCESSFUL; - -done: - free(displays); - return ret; -} - -static INT offset_length(POINT offset) -{ - return offset.x * offset.x + offset.y * offset.y; -} - -static void set_rect_from_devmode(RECT *rect, const DEVMODEW *mode) -{ - SetRect(rect, mode->dmPosition.x, mode->dmPosition.y, mode->dmPosition.x + mode->dmPelsWidth, mode->dmPosition.y + mode->dmPelsHeight); -} - -/* Check if a rect overlaps with placed display rects */ -static BOOL overlap_placed_displays(const RECT *rect, const DEVMODEW *displays) -{ - const DEVMODEW *mode; - RECT intersect; - - for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) - { - set_rect_from_devmode(&intersect, mode); - if ((mode->dmFields & DM_POSITION) && intersect_rect(&intersect, &intersect, 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 DEVMODEW *displays, const DEVMODEW *placing) -{ - POINT points[8], left_top, offset, min_offset = {0, 0}; - INT point_idx, point_count, vertex_idx; - BOOL has_placed = FALSE, first = TRUE; - RECT desired_rect, rect; const DEVMODEW *mode; - INT width, height; - - set_rect_from_devmode(&desired_rect, placing); - - /* If the display to be placed is detached, no offset is needed to place it */ - if (IsRectEmpty(&desired_rect)) - return min_offset; - - /* If there is no placed and attached display, place this display as it is */ - for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) - { - set_rect_from_devmode(&rect, mode); - if ((mode->dmFields & DM_POSITION) && !IsRectEmpty(&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 = desired_rect.right - desired_rect.left; - height = desired_rect.bottom - desired_rect.top; - - for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) - { - set_rect_from_devmode(&rect, mode); - if (!(mode->dmFields & DM_POSITION) || IsRectEmpty(&rect)) - continue; - - /* Get four vertices of the placed display rectangle */ - points[0].x = rect.left; - points[0].y = rect.top; - points[1].x = rect.left; - points[1].y = rect.bottom; - points[2].x = rect.right; - points[2].y = rect.top; - points[3].x = rect.right; - points[3].y = rect.bottom; - point_count = 4; - - /* Intersected points when moving the display to be placed horizontally */ - if (desired_rect.bottom >= rect.top && - desired_rect.top <= rect.bottom) - { - points[point_count].x = rect.left; - points[point_count++].y = desired_rect.top; - points[point_count].x = rect.right; - points[point_count++].y = desired_rect.top; - } - /* Intersected points when moving the display to be placed vertically */ - if (desired_rect.left <= rect.right && - desired_rect.right >= rect.left) - { - points[point_count].x = desired_rect.left; - points[point_count++].y = rect.top; - points[point_count].x = desired_rect.left; - points[point_count++].y = 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 - desired_rect.left; - offset.y = left_top.y - desired_rect.top; - rect = desired_rect; - OffsetRect(&rect, offset.x, offset.y); - if (!overlap_placed_displays(&rect, displays)) - { - 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(DEVMODEW *displays) -{ - INT left_most = INT_MAX, top_most = INT_MAX; - POINT min_offset, offset; - DEVMODEW *mode, *placing; - - for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) - mode->dmFields &= ~DM_POSITION; - - /* 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 = NULL; - for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) - { - if (mode->dmFields & DM_POSITION) - continue; - - offset = get_placement_offset(displays, mode); - if (!placing || offset_length(offset) < offset_length(min_offset)) - { - min_offset = offset; - placing = mode; - } - } - - /* If all displays are placed */ - if (!placing) - break; - - placing->dmPosition.x += min_offset.x; - placing->dmPosition.y += min_offset.y; - placing->dmFields |= DM_POSITION; - - left_most = min(left_most, placing->dmPosition.x); - top_most = min(top_most, placing->dmPosition.y); - } - - /* Convert virtual screen coordinates to root coordinates */ - for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) - { - mode->dmPosition.x -= left_most; - mode->dmPosition.y -= top_most; - } -} - -static LONG apply_display_settings(DEVMODEW *displays, BOOL do_attach) -{ - DEVMODEW *full_mode; BOOL attached_mode; - DEVMODEW *mode; LONG ret;
for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) { - ULONG_PTR *id = (ULONG_PTR *)(mode + 1); + ULONG_PTR id; + + if (!settings_handler.get_id(mode->dmDeviceName, &id)) + return DISP_CHANGE_BADPARAM;
attached_mode = !is_detached_mode(mode); if ((attached_mode && !do_attach) || (!attached_mode && do_attach)) continue;
- full_mode = get_full_mode(*id, 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", settings_handler.name, wine_dbgstr_w(mode->dmDeviceName), - full_mode->dmPosition.x, full_mode->dmPosition.y, full_mode->dmPelsWidth, - full_mode->dmPelsHeight, full_mode->dmDisplayFrequency, full_mode->dmBitsPerPel, - full_mode->dmDisplayOrientation); - - ret = settings_handler.set_current_mode(*id, full_mode); - if (attached_mode && ret == DISP_CHANGE_SUCCESSFUL) - set_display_depth(*id, full_mode->dmBitsPerPel); - free_full_mode(full_mode); - if (ret != DISP_CHANGE_SUCCESSFUL) - return ret; - } + mode->dmPosition.x, mode->dmPosition.y, mode->dmPelsWidth, + mode->dmPelsHeight, mode->dmDisplayFrequency, mode->dmBitsPerPel, + mode->dmDisplayOrientation);
- return DISP_CHANGE_SUCCESSFUL; -} - -static BOOL all_detached_settings(const DEVMODEW *displays) -{ - const DEVMODEW *mode; - - for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) - { - if (!is_detached_mode(mode)) - return FALSE; + if ((ret = settings_handler.set_current_mode(id, mode))) return ret; + if (attached_mode) set_display_depth(id, mode->dmBitsPerPel); }
- return TRUE; + return DISP_CHANGE_SUCCESSFUL; }
/*********************************************************************** * ChangeDisplaySettingsEx (X11DRV.@) * */ -LONG X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, - HWND hwnd, DWORD flags, LPVOID lpvoid ) +LONG X11DRV_ChangeDisplaySettingsEx( const DEVMODEW *modes, HWND hwnd, DWORD flags, LPVOID lpvoid ) { - DEVMODEW *displays; LONG ret;
- ret = get_display_settings( &displays, devname, devmode ); - if (ret != DISP_CHANGE_SUCCESSFUL) - return ret; - - if (all_detached_settings( displays )) - { - WARN("Detaching all displays is not permitted.\n"); - free(displays); - return DISP_CHANGE_SUCCESSFUL; - } - - place_all_displays( displays ); - /* Detach displays first to free up CRTCs */ - ret = apply_display_settings( displays, FALSE ); + ret = apply_display_settings( modes, FALSE ); if (ret == DISP_CHANGE_SUCCESSFUL) - ret = apply_display_settings( displays, TRUE ); + ret = apply_display_settings( modes, TRUE ); if (ret == DISP_CHANGE_SUCCESSFUL) X11DRV_DisplayDevices_Update(TRUE); - free(displays); + return ret; }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 6aa9b82e8cf..23d508120c8 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -213,8 +213,7 @@ extern void X11DRV_SetCursor( HCURSOR handle ) DECLSPEC_HIDDEN; extern BOOL X11DRV_SetCursorPos( INT x, INT y ) DECLSPEC_HIDDEN; extern BOOL X11DRV_GetCursorPos( LPPOINT pos ) DECLSPEC_HIDDEN; extern BOOL X11DRV_ClipCursor( LPCRECT clip ) DECLSPEC_HIDDEN; -extern LONG X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, - HWND hwnd, DWORD flags, LPVOID lpvoid ) DECLSPEC_HIDDEN; +extern LONG X11DRV_ChangeDisplaySettingsEx( const DEVMODEW *modes, HWND hwnd, DWORD flags, LPVOID lpvoid ) DECLSPEC_HIDDEN; extern BOOL X11DRV_CurrentDisplaySettingsEx( LPCWSTR name, LPDEVMODEW devmode ) DECLSPEC_HIDDEN; extern BOOL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmode, DWORD flags ) DECLSPEC_HIDDEN; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 8ac3be3bfb8..dad15eb0070 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -295,7 +295,7 @@ struct user_driver_funcs LRESULT (*pClipboardWindowProc)(HWND,UINT,WPARAM,LPARAM); void (*pUpdateClipboard)(void); /* display modes */ - LONG (*pChangeDisplaySettingsEx)(LPCWSTR,LPDEVMODEW,HWND,DWORD,LPVOID); + LONG (*pChangeDisplaySettingsEx)(const DEVMODEW *,HWND,DWORD,LPVOID); BOOL (*pCurrentDisplaySettingsEx)(LPCWSTR,LPDEVMODEW); BOOL (*pEnumDisplaySettingsEx)(LPCWSTR,DWORD,LPDEVMODEW,DWORD); BOOL (*pUpdateDisplayDevices)(const struct gdi_device_manager *,BOOL,void*);
Zhiyi Zhang (@zhiyi) commented about dlls/winemac.drv/display.c:
mode->dmPelsHeight == 0;
}
-/***********************************************************************
ChangeDisplaySettingsEx (MACDRV.@)
- */
-LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode,
HWND hwnd, DWORD flags, LPVOID lpvoid)
+static CGDisplayModeRef find_best_display_mode(DEVMODEW *devmode, CFArrayRef display_modes, int bpp, struct display_mode_descriptor* desc)
Style nitpick. While there're some cases * are aligned with the type, most of the time they're aligned with variable names in the this file.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/driver.c:
return DISP_CHANGE_FAILED;
}
+static BOOL nulldrv_CurrentDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode )
It's a bit weird that the function name still uses Ex. I prefer GetCurrentDisplaySettings().
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
memset( &devmode->dmDriverExtra, 0, devmode->dmSize - offsetof(DEVMODEW, dmDriverExtra) ); if (index == ENUM_REGISTRY_SETTINGS) ret = read_registry_settings( adapter_path, devmode );
- else ret = user_driver->pEnumDisplaySettingsEx( device_name, index, devmode, flags );
- else if (index != ENUM_CURRENT_SETTINGS) ret = user_driver->pEnumDisplaySettingsEx( device_name, index, devmode, flags );
No really an issue. But moving the getting the current display settings part right after getting registry settings seems more natural to me. So index == ENUM_CURRENT_SETTINGS here and then do EnumDisplaySettingsEx() in the else branch.
Zhiyi Zhang (@zhiyi) commented about dlls/wineandroid.drv/init.c:
}
+/***********************************************************************
ANDROID_CurrentDisplaySettingsEx
- */
+BOOL ANDROID_CurrentDisplaySettingsEx( LPCWSTR name, LPDEVMODEW devmode ) +{
- devmode->u2.dmDisplayFlags = 0;
- devmode->dmDisplayFrequency = 0;
- devmode->u1.s2.dmPosition.x = 0;
- devmode->u1.s2.dmPosition.y = 0;
- devmode->u1.s2.dmDisplayOrientation = 0;
- devmode->u1.s2.dmDisplayFixedOutput = 0;
Let's remove this empty line.
Zhiyi Zhang (@zhiyi) commented about dlls/wineandroid.drv/init.c:
}
+/***********************************************************************
ANDROID_CurrentDisplaySettingsEx
- */
+BOOL ANDROID_CurrentDisplaySettingsEx( LPCWSTR name, LPDEVMODEW devmode ) +{
- devmode->u2.dmDisplayFlags = 0;
- devmode->dmDisplayFrequency = 0;
dmDisplayFrequency is set twice in this function.
Zhiyi Zhang (@zhiyi) commented about dlls/wineandroid.drv/init.c:
devmode->u1.s2.dmDisplayOrientation = 0; devmode->u1.s2.dmDisplayFixedOutput = 0;
While you're at it. Let's put settings these fields to be inside the if (n == 0) branch or return early if n != 0. This can be a separate patch.
Zhiyi Zhang (@zhiyi) commented about dlls/winemac.drv/display.c:
- init_original_display_mode();
- if (macdrv_get_displays(&displays, &num_displays))
return FALSE;
- display_mode = CGDisplayCopyDisplayMode(displays[0].displayID);
- /* We currently only report modes for the primary display, so it's at (0, 0). */
- devmode->dmPosition.x = 0;
- devmode->dmPosition.y = 0;
- devmode->dmFields |= DM_POSITION;
- display_mode_to_devmode(displays[0].displayID, display_mode, devmode);
- if (retina_enabled)
- {
struct display_mode_descriptor* desc = create_original_display_mode_descriptor(displays[0].displayID);
* to the right.
Zhiyi Zhang (@zhiyi) commented about dlls/wineandroid.drv/init.c:
devmode->dmPelsHeight = screen_height; devmode->dmBitsPerPel = screen_bpp; devmode->dmDisplayFrequency = 60;
- devmode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY;
- devmode->dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY;
You missed DM_POSITION.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
devmode = default_mode; } if ((devmode->dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != (DM_PELSWIDTH | DM_PELSHEIGHT)) { WARN( "devmode doesn't specify the resolution: %#x\n", devmode->dmFields ); return NULL; } if (!is_detached_mode( devmode ) && (!devmode->dmPelsWidth || !devmode->dmPelsHeight))
While you're at it. I think getting the current mode can be deferred until it's really needed. So only when (!devmode->dmPelsWidth || !devmode->dmPelsHeight || !(devmode->dmFields & DM_POSITION)) then call NtUserEnumDisplaySettings( devname, ENUM_CURRENT_SETTINGS, ¤t_mode, 0 ). This saves some calls.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
if (!devmode->dmPelsHeight) devmode->dmPelsHeight = current_mode->dmPelsHeight; }
- return devmode;
- if (is_detached_mode( devmode )) return devmode;
So now validate_display_settings() no longer just do validations. Maybe it's better to change its name to get_full_mode()?
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
if (!devmode->dmPelsHeight) devmode->dmPelsHeight = current_mode->dmPelsHeight; }
- return devmode;
- if (is_detached_mode( devmode )) return devmode;
- if ((mode = find_display_mode( modes, devmode )))
- {
mode->dmFields |= DM_POSITION;
This patch is assuming devmode has a valid position, which it might not and should use the current position in that case. You should check for (devmode->dmFields & DM_POSITION) before copying the position. Basically, part of your next patch should be done in this patch.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
if (!devmode->dmPelsHeight) devmode->dmPelsHeight = current_mode->dmPelsHeight; }
- return devmode;
- if (is_detached_mode( devmode )) return devmode;
- if ((mode = find_display_mode( modes, devmode )))
- {
mode->dmFields |= DM_POSITION;
mode->dmPosition = devmode->dmPosition;
return mode;
You can remove this line and return mode directly at the end. I see you already do this in 7/7. So might as well do it here to reduce the diff later.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
if (!adapter->mode_count) continue;
size += sizeof(DEVMODEW) + adapter->modes[0].dmDriverExtra;
}
/* allocate an extra mode for easier iteration */
if (!(displays = calloc( 1, size + sizeof(DEVMODEW) ))) goto done;
mode = displays;
LIST_FOR_EACH_ENTRY(adapter, &adapters, struct adapter, entry)
{
if (!adapter->mode_count) continue;
mode->dmSize = sizeof(DEVMODEW);
if (devname)
{
if (!wcsicmp( devname, adapter->dev.device_name ))
I don't remember if it's from the D3D code. I think curly braces should be added when any of the branches contain more than one line.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
if (!adapter->mode_count) continue;
mode->dmSize = sizeof(DEVMODEW);
if (devname)
{
if (!wcsicmp( devname, adapter->dev.device_name ))
memcpy( mode, fullmode, mode->dmSize + fullmode->dmDriverExtra );
else
{
if (!(ret = user_driver->pCurrentDisplaySettingsEx( adapter->dev.device_name, mode ))) goto done;
if (!(full = find_display_mode( adapter->modes, mode ))) goto done;
mode->dmDriverExtra = full->dmDriverExtra;
memcpy( mode + 1, full + 1, full->dmDriverExtra );
}
}
else if (!(ret = read_registry_settings( adapter->config_key, mode ))) goto done;
You removed the get_full_mode() code in winex11.drv's apply_display_settings(). This means you lost the dmDriverExtra for modes read from the registry. You still need to call find_display_mode() for modes from the registry.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
placing = mode;
}
}
/* If all displays are placed */
if (!placing) break;
placing->dmPosition.x += min_offset.x;
placing->dmPosition.y += min_offset.y;
placing->dmFields |= DM_POSITION;
left_most = min( left_most, placing->dmPosition.x );
top_most = min( top_most, placing->dmPosition.y );
- }
- /* Convert virtual screen coordinates to root coordinates */
This is probably not appropriate to be here. Root coordinates are X11 concepts. win32u should not be aware of this. So let's do the conversion in winex11.drv instead.
Zhiyi Zhang (@zhiyi) commented about dlls/winemac.drv/display.c:
send_message(NtUserGetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp, MAKELPARAM(width, height));
ret = DISP_CHANGE_SUCCESSFUL;
Why are you removing this? How can ret be DISP_CHANGE_SUCCESSFUL?
On Thu Aug 4 07:42:25 2022 +0000, Zhiyi Zhang wrote:
No really an issue. But moving the getting the current display settings part right after getting registry settings seems more natural to me. So index == ENUM_CURRENT_SETTINGS here and then do EnumDisplaySettingsEx() in the else branch.
Yes, but this way makes it easier to later add a case with `index != ENUM_CURRENT_SETTINGS && (flags & EDS_ROTATEDMODE)` which would also skip the `CurrentDisplaySettings` call like this:
```diff if (index == ENUM_REGISTRY_SETTINGS) ret = read_registry_settings( adapter_path, devmode ); - else if (index != ENUM_CURRENT_SETTINGS) ret = user_driver->pEnumDisplaySettingsEx( device_name, index, devmode, flags ); + /* if EDS_ROTATEDMODE is not specified, enumerate modes with the same display orientation as current */ + else if (index != ENUM_CURRENT_SETTINGS && (flags & EDS_ROTATEDMODE)) ret = TRUE; else ret = user_driver->pCurrentDisplaySettings( device_name, devmode );
+ if (ret && index != ENUM_REGISTRY_SETTINGS && index != ENUM_CURRENT_SETTINGS) + { + for (ret = FALSE, mode = modes; mode && mode->dmSize && !ret; mode = NEXT_DEVMODEW(mode)) + { + if (!(flags & EDS_ROTATEDMODE) && mode->dmDisplayOrientation != devmode->dmDisplayOrientation) continue; + if (index--) continue; + memcpy( &devmode->dmFields, &mode->dmFields, devmode->dmSize - FIELD_OFFSET(DEVMODEW, dmFields) ); + ret = TRUE; + } + } + free( modes ); + ```
On Thu Aug 4 07:47:43 2022 +0000, Zhiyi Zhang wrote:
I don't remember if it's from the D3D code. I think curly braces should be added when any of the branches contain more than one line.
Yeah I don't think user32 / win32u uses that style. Unbraced or one-line if / else are very common and it saves precious vertical space.
On Thu Aug 4 07:47:53 2022 +0000, Zhiyi Zhang wrote:
You removed the get_full_mode() code in winex11.drv's apply_display_settings(). This means you lost the dmDriverExtra for modes read from the registry. You still need to call find_display_mode() for modes from the registry.
As `validate_display_settings` gets a full mode pointer from the adapter mode list copy, it then writes the full display settings to the registry.
There's a mistake here where mode doesn't have `dmDriverExtra` set, so indeed `read_registry_settings` doesn't read it back, but it could.
I'm not completely sure that it should though, as only the available mode list is refreshed when display devices are updated, and the `ENUM_REGISTRY_SETTINGS` index would then have a stale driver extra data after an update.
I guess it's better to always lookup a full mode again here.
On Thu Aug 4 07:48:43 2022 +0000, Zhiyi Zhang wrote:
Why are you removing this? How can ret be DISP_CHANGE_SUCCESSFUL?
Eh, the loop is checking !ret, so I was expecting it to be initialized to 0. It's apparently not the case, so yes there's an issue.