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.
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/display.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 2d7b9656103..f111ef222ea 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -53,7 +53,7 @@ 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 CFArrayRef cached_modes; static BOOL modes_has_8bpp, modes_has_16bpp; static int default_mode_bpp; static pthread_mutex_t modes_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -1014,18 +1014,18 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmod
pthread_mutex_lock(&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); + if (cached_modes) CFRelease(cached_modes); + cached_modes = copy_display_modes(displays[0].displayID, (flags & EDS_RAWMODE) != 0); modes_has_8bpp = modes_has_16bpp = FALSE;
- if (modes) + if (cached_modes) { - count = CFArrayGetCount(modes); + count = CFArrayGetCount(cached_modes); for (i = 0; i < count && !(modes_has_8bpp && 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; @@ -1036,15 +1036,15 @@ BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmod }
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) @@ -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;
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 f111ef222ea..dca65c0d761 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 | 49 ++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 10 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index dca65c0d761..a2685da2f6e 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 modes_has_8bpp, modes_has_16bpp; static int default_mode_bpp; static pthread_mutex_t 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,12 +1012,22 @@ 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(&modes_mutex);
- if (mode == 0 || !cached_modes) + if (mode == 0 || !cached_modes || cached_modes_display_id != 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_display_id = display_id; modes_has_8bpp = modes_has_16bpp = FALSE;
if (cached_modes) @@ -1094,13 +1107,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; @@ -1140,28 +1153,44 @@ failed: */ BOOL macdrv_GetCurrentDisplaySettings(LPCWSTR devname, LPDEVMODEW devmode) { + WCHAR primary_adapter[CCHDEVICENAME]; struct macdrv_display *displays = NULL; - int num_displays; + int num_displays, display_idx; CGDisplayModeRef display_mode; + CGDirectDisplayID display_id; + WCHAR *end;
TRACE("%s, %p + %hu\n", debugstr_w(devname), devmode, devmode->dmSize);
init_original_display_mode();
+ if (!get_primary_adapter(primary_adapter)) + return FALSE; + 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); + + if (wcsicmp(primary_adapter, devname)) + FIXME("Non-primary display mode position not implemented.\n");
- /* 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); + 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;
Zhiyi Zhang (@zhiyi) commented about dlls/winemac.drv/display.c:
- if (display_idx >= num_displays)
- {
macdrv_free_displays(displays);
return FALSE;
- }
- display_id = displays[display_idx].displayID;
- display_mode = CGDisplayCopyDisplayMode(display_id);
- if (wcsicmp(primary_adapter, devname))
FIXME("Non-primary display mode position not implemented.\n");
- /* 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;
Position for monitors is at displays[display_idx].frame. I think you can split this patch into two patches. One for enumerating the current mode and the other for available modes.
Zhiyi Zhang (@zhiyi) commented about dlls/winemac.drv/display.c:
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(&modes_mutex);
- if (mode == 0 || !cached_modes)
- if (mode == 0 || !cached_modes || cached_modes_display_id != display_id)
Although it's not handled previously, we should invalidate cached display modes when 'flags' changes as well.
On Sat Aug 27 02:06:21 2022 +0000, Zhiyi Zhang wrote:
Position for monitors is at displays[display_idx].frame. I think you can split this patch into two patches. One for enumerating the current mode and the other for available modes.
I haven't checked. But can the displays from macdrv_get_displays() be detached? If it can, you should handle it as well. For example, when a Mac laptop is connected to an external monitor and the lid is closed.