In preparation for with https://gitlab.winehq.org/wine/wine/-/merge_requests/576. I think support for changing non-primary display modes in winemac will be easier /after/ the display placement logic is moved to win32u. I also don't really know how to handle the display position on macOS.
-- v3: winemac.drv: Support enumerating non-primary adapters display modes. winemac.drv: Support getting non-primary adapter current display mode. winemac.drv: Invalidate mode cache when enum flags changes. winemac.drv: Remove unnecessary macdrv_EnumDisplaySettingsEx declaration. winemac.drv: Rename display modes cache variables.
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/display.c | 58 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 2d7b9656103..76a9d67be20 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -53,10 +53,10 @@ static const WCHAR initial_mode_keyW[] = {'I','n','i','t','i','a','l',' ','D','i ' ','M','o','d','e'}; static const WCHAR pixelencodingW[] = {'P','i','x','e','l','E','n','c','o','d','i','n','g',0};
-static CFArrayRef modes; -static BOOL modes_has_8bpp, modes_has_16bpp; -static int default_mode_bpp; -static pthread_mutex_t modes_mutex = PTHREAD_MUTEX_INITIALIZER; +static CFArrayRef cached_modes; +static BOOL cached_modes_has_8bpp, cached_modes_has_16bpp; +static int cached_default_mode_bpp; +static pthread_mutex_t cached_modes_mutex = PTHREAD_MUTEX_INITIALIZER;
static BOOL inited_original_display_mode;
@@ -397,20 +397,20 @@ static int get_default_bpp(void) { int ret;
- if (!default_mode_bpp) + if (!cached_default_mode_bpp) { CGDisplayModeRef mode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay); if (mode) { - default_mode_bpp = display_mode_bits_per_pixel(mode); + cached_default_mode_bpp = display_mode_bits_per_pixel(mode); CFRelease(mode); }
- if (!default_mode_bpp) - default_mode_bpp = 32; + if (!cached_default_mode_bpp) + cached_default_mode_bpp = 32; }
- ret = default_mode_bpp; + ret = cached_default_mode_bpp;
TRACE(" -> %d\n", ret); return ret; @@ -859,9 +859,9 @@ LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, return DISP_CHANGE_FAILED; }
- pthread_mutex_lock(&modes_mutex); + pthread_mutex_lock(&cached_modes_mutex); bpp = get_default_bpp(); - pthread_mutex_unlock(&modes_mutex); + pthread_mutex_unlock(&cached_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);
@@ -1012,39 +1012,39 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmod if (macdrv_get_displays(&displays, &num_displays)) goto failed;
- pthread_mutex_lock(&modes_mutex); + pthread_mutex_lock(&cached_modes_mutex);
- if (mode == 0 || !modes) + if (mode == 0 || !cached_modes) { - if (modes) CFRelease(modes); - modes = copy_display_modes(displays[0].displayID, (flags & EDS_RAWMODE) != 0); - modes_has_8bpp = modes_has_16bpp = FALSE; + if (cached_modes) CFRelease(cached_modes); + cached_modes = copy_display_modes(displays[0].displayID, (flags & EDS_RAWMODE) != 0); + cached_modes_has_8bpp = cached_modes_has_16bpp = FALSE;
- if (modes) + if (cached_modes) { - count = CFArrayGetCount(modes); - for (i = 0; i < count && !(modes_has_8bpp && modes_has_16bpp); i++) + count = CFArrayGetCount(cached_modes); + for (i = 0; i < count && !(cached_modes_has_8bpp && cached_modes_has_16bpp); i++) { - CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); + CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(cached_modes, i); int bpp = display_mode_bits_per_pixel(mode); if (bpp == 8) - modes_has_8bpp = TRUE; + cached_modes_has_8bpp = TRUE; else if (bpp == 16) - modes_has_16bpp = TRUE; + cached_modes_has_16bpp = TRUE; } } }
display_mode = NULL; - if (modes) + if (cached_modes) { int default_bpp; DWORD seen_modes = 0;
- count = CFArrayGetCount(modes); + count = CFArrayGetCount(cached_modes); for (i = 0; i < count; i++) { - CGDisplayModeRef candidate = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); + CGDisplayModeRef candidate = (CGDisplayModeRef)CFArrayGetValueAtIndex(cached_modes, i);
seen_modes++; if (seen_modes > mode) @@ -1058,10 +1058,10 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmod 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 (!display_mode && (!cached_modes_has_16bpp || !cached_modes_has_8bpp)) { /* We want to synthesize higher depths first. */ - int synth_bpps[] = { modes_has_16bpp ? 0 : 16, modes_has_8bpp ? 0 : 8 }; + int synth_bpps[] = { cached_modes_has_16bpp ? 0 : 16, cached_modes_has_8bpp ? 0 : 8 }; size_t synth_bpp_idx; for (synth_bpp_idx = 0; synth_bpp_idx < 2; synth_bpp_idx++) { @@ -1071,7 +1071,7 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmod
for (i = 0; i < count; i++) { - CGDisplayModeRef candidate = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); + CGDisplayModeRef candidate = (CGDisplayModeRef)CFArrayGetValueAtIndex(cached_modes, i); /* We only synthesize modes from those having the default bpp. */ if (display_mode_bits_per_pixel(candidate) != default_bpp) continue; @@ -1092,7 +1092,7 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmod } }
- pthread_mutex_unlock(&modes_mutex); + pthread_mutex_unlock(&cached_modes_mutex);
if (!display_mode) goto failed;
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/display.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 76a9d67be20..69348bc9f39 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -46,9 +46,6 @@ struct display_mode_descriptor CFStringRef pixel_encoding; };
- -BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmode, DWORD flags); - static const WCHAR initial_mode_keyW[] = {'I','n','i','t','i','a','l',' ','D','i','s','p','l','a','y', ' ','M','o','d','e'}; static const WCHAR pixelencodingW[] = {'P','i','x','e','l','E','n','c','o','d','i','n','g',0};
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/display.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 69348bc9f39..2034c8b21b4 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -51,7 +51,7 @@ static const WCHAR initial_mode_keyW[] = {'I','n','i','t','i','a','l',' ','D','i static const WCHAR pixelencodingW[] = {'P','i','x','e','l','E','n','c','o','d','i','n','g',0};
static CFArrayRef cached_modes; -static BOOL cached_modes_has_8bpp, cached_modes_has_16bpp; +static BOOL cached_modes_has_8bpp, cached_modes_has_16bpp, cached_modes_flags; static int cached_default_mode_bpp; static pthread_mutex_t cached_modes_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -1011,11 +1011,12 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmod
pthread_mutex_lock(&cached_modes_mutex);
- if (mode == 0 || !cached_modes) + if (mode == 0 || !cached_modes || flags != cached_modes_flags) { if (cached_modes) CFRelease(cached_modes); cached_modes = copy_display_modes(displays[0].displayID, (flags & EDS_RAWMODE) != 0); cached_modes_has_8bpp = cached_modes_has_16bpp = FALSE; + cached_modes_flags = flags;
if (cached_modes) {
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/display.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 2034c8b21b4..f7536fb714f 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -1142,8 +1142,10 @@ failed: BOOL macdrv_GetCurrentDisplaySettings(LPCWSTR devname, LPDEVMODEW devmode) { struct macdrv_display *displays = NULL; - int num_displays; + int i, num_displays, display_idx; CGDisplayModeRef display_mode; + CGDirectDisplayID display_id; + WCHAR *end;
TRACE("%s, %p + %hu\n", debugstr_w(devname), devmode, devmode->dmSize);
@@ -1152,17 +1154,24 @@ BOOL macdrv_GetCurrentDisplaySettings(LPCWSTR devname, LPDEVMODEW devmode) if (macdrv_get_displays(&displays, &num_displays)) return FALSE;
- display_mode = CGDisplayCopyDisplayMode(displays[0].displayID); + display_idx = wcstol(devname + 11, &end, 10) - 1; + if (display_idx >= num_displays) + { + macdrv_free_displays(displays); + return FALSE; + } + + display_id = displays[display_idx].displayID; + display_mode = CGDisplayCopyDisplayMode(display_id);
- /* We currently only report modes for the primary display, so it's at (0, 0). */ - devmode->dmPosition.x = 0; - devmode->dmPosition.y = 0; + devmode->dmPosition.x = CGRectGetMinX(displays[display_idx].frame); + devmode->dmPosition.y = CGRectGetMinY(displays[display_idx].frame); devmode->dmFields |= DM_POSITION;
- display_mode_to_devmode(displays[0].displayID, display_mode, devmode); + display_mode_to_devmode(display_id, display_mode, devmode); if (retina_enabled) { - struct display_mode_descriptor *desc = create_original_display_mode_descriptor(displays[0].displayID); + struct display_mode_descriptor *desc = create_original_display_mode_descriptor(display_id); if (display_mode_matches_descriptor(display_mode, desc)) { devmode->dmPelsWidth *= 2; @@ -1174,7 +1183,8 @@ BOOL macdrv_GetCurrentDisplaySettings(LPCWSTR devname, LPDEVMODEW devmode) CFRelease(display_mode); macdrv_free_displays(displays);
- TRACE("current mode -- %dx%dx%dbpp @%d Hz", + TRACE("current mode -- %dx%d-%dx%dx%dbpp @%d Hz", + devmode->dmPosition.x, devmode->dmPosition.y, devmode->dmPelsWidth, devmode->dmPelsHeight, devmode->dmBitsPerPel, devmode->dmDisplayFrequency); if (devmode->dmDisplayOrientation)
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/display.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index f7536fb714f..3fc97733e18 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -51,6 +51,7 @@ static const WCHAR initial_mode_keyW[] = {'I','n','i','t','i','a','l',' ','D','i static const WCHAR pixelencodingW[] = {'P','i','x','e','l','E','n','c','o','d','i','n','g',0};
static CFArrayRef cached_modes; +static CGDirectDisplayID cached_modes_display_id; static BOOL cached_modes_has_8bpp, cached_modes_has_16bpp, cached_modes_flags; static int cached_default_mode_bpp; static pthread_mutex_t cached_modes_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -998,9 +999,11 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmod struct macdrv_display *displays = NULL; int num_displays; CGDisplayModeRef display_mode; - int display_mode_bpp; + int display_mode_bpp, display_idx; BOOL synthesized = FALSE; + CGDirectDisplayID display_id; DWORD count, i; + WCHAR *end;
TRACE("%s, %u, %p + %hu, %08x\n", debugstr_w(devname), mode, devmode, devmode->dmSize, flags);
@@ -1009,13 +1012,23 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmod if (macdrv_get_displays(&displays, &num_displays)) goto failed;
+ display_idx = wcstol(devname + 11, &end, 10) - 1; + if (display_idx >= num_displays) + { + macdrv_free_displays(displays); + return FALSE; + } + + display_id = displays[display_idx].displayID; + pthread_mutex_lock(&cached_modes_mutex);
- if (mode == 0 || !cached_modes || flags != cached_modes_flags) + if (mode == 0 || !cached_modes || flags != cached_modes_flags || display_id != cached_modes_display_id) { if (cached_modes) CFRelease(cached_modes); - cached_modes = copy_display_modes(displays[0].displayID, (flags & EDS_RAWMODE) != 0); + cached_modes = copy_display_modes(display_id, (flags & EDS_RAWMODE) != 0); cached_modes_has_8bpp = cached_modes_has_16bpp = FALSE; + cached_modes_display_id = display_id; cached_modes_flags = flags;
if (cached_modes) @@ -1095,13 +1108,13 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmod if (!display_mode) goto failed;
- display_mode_to_devmode(displays[0].displayID, display_mode, devmode); + display_mode_to_devmode(display_id, display_mode, devmode); devmode->dmBitsPerPel = display_mode_bpp; if (devmode->dmBitsPerPel) devmode->dmFields |= DM_BITSPERPEL; if (retina_enabled) { - struct display_mode_descriptor* desc = create_original_display_mode_descriptor(displays[0].displayID); + struct display_mode_descriptor* desc = create_original_display_mode_descriptor(display_id); if (display_mode_matches_descriptor(display_mode, desc)) { devmode->dmPelsWidth *= 2;
On Mon Aug 29 13:05:01 2022 +0000, R��mi Bernon wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/720/diffs?diff_id=9027&start_sha=8fcbe5b5ec9852994ef5b1f440da107f99320c06#d1968e8c429ee8f293c300a3b265157c4161beb0_1190_1180)
Thanks, I removed the position fixup code, looks like it's unnecessary then.
Zhiyi Zhang (@zhiyi) commented about dlls/winemac.drv/display.c:
BOOL macdrv_GetCurrentDisplaySettings(LPCWSTR devname, LPDEVMODEW devmode) { struct macdrv_display *displays = NULL;
- int num_displays;
- int i, num_displays, display_idx;
i is unused.
Also this commit makes the console spam "002c:err:system:NtUserChangeDisplaySettings Changing L"\\.\DISPLAY2" display settings returned -2. 002c:err:display:init_registry_display_settings Failed to save registry display settings for L"\\.\DISPLAY2", returned -2.", even after patch 5/5. This is caused by macdrv_ChangeDisplaySettingsEx() still using the primary monitor available mode list even for secondary monitors. You can move the non-primary monitor check earlier and return fake success to avoid this for now.