Update the gdi_device_manager API to enable drivers to set the current mode (along with the registry mode if not already set) in UpdateDisplayDevices.
This changes also allows us to remove the driver code that manually changes the registry settings.
-- v4: wineandroid.drv: Set the current mode using gdi_device_manager. winemac.drv: Set the current mode using gdi_device_manager. winemac.drv: Extract function to get the current mode. winewayland.drv: Set the current mode using gdi_device_manager. winex11.drv: Set the current mode using gdi_device_manager. win32u: Support setting the current mode using gdi_device_manager. debug.h: Add debugstr_devmodew() helper.
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Signed-off-by: Alexandros Frantzis alexandros.frantzis@collabora.com --- dlls/win32u/sysparams.c | 5 +-- include/wine/debug.h | 68 +++++++++++++++++++++++++++++++++++++ programs/explorer/desktop.c | 6 ++-- 3 files changed, 71 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 60b12321953..0b553f447b6 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2699,10 +2699,7 @@ BOOL WINAPI NtUserEnumDisplaySettings( UNICODE_STRING *device, DWORD index, DEVM adapter_release( adapter );
if (!ret) WARN( "Failed to query %s display settings.\n", debugstr_us(device) ); - else TRACE( "position %dx%d, resolution %ux%u, frequency %u, depth %u, orientation %#x.\n", - (int)devmode->dmPosition.x, (int)devmode->dmPosition.y, (int)devmode->dmPelsWidth, - (int)devmode->dmPelsHeight, (int)devmode->dmDisplayFrequency, - (int)devmode->dmBitsPerPel, (int)devmode->dmDisplayOrientation ); + else TRACE( "%s.\n", debugstr_devmodew( devmode ) ); return ret; }
diff --git a/include/wine/debug.h b/include/wine/debug.h index c20924818dd..9fb215392f2 100644 --- a/include/wine/debug.h +++ b/include/wine/debug.h @@ -459,6 +459,70 @@ static inline const char *wine_dbgstr_variant( const VARIANT *v )
#endif /* defined(__oaidl_h__) && defined(V_VT) */
+#if defined(_WINGDI_) && !defined(NOGDI) + +#if defined(NONAMELESSUNION) +#define __WINE_DUMMY_U(i) u##i. +#else +#define __WINE_DUMMY_U(i) +#endif + +#if defined(NONAMELESSSTRUCT) +#define __WINE_DUMMY_S(i) s##i. +#else +#define __WINE_DUMMY_S(i) +#endif + +static inline const char *wine_dbgstr_devmodew( const DEVMODEW *devmode ) +{ + char rotation[32] = {0}; + char position[32] = {0}; + const char *fixed_output = ""; + const char *interlaced = ""; + + if (!devmode) return "(null)"; + + if (devmode->dmFields & DM_DISPLAYORIENTATION) + { + snprintf( rotation, sizeof(rotation), " rotated %u degrees", + (unsigned int)devmode->__WINE_DUMMY_U(1)__WINE_DUMMY_S(2)dmDisplayOrientation * 90 ); + } + + if (devmode->dmFields & DM_DISPLAYFIXEDOUTPUT) + { + switch (devmode->__WINE_DUMMY_U(1)__WINE_DUMMY_S(2)dmDisplayFixedOutput) + { + case DMDFO_DEFAULT: fixed_output = ""; break; + case DMDFO_CENTER: fixed_output = " centered"; break; + case DMDFO_STRETCH: fixed_output = " stretched"; break; + default: fixed_output = " (invalid fixed output mode)"; + } + } + + if ((devmode->dmFields & DM_DISPLAYFLAGS) && + (devmode->__WINE_DUMMY_U(2)dmDisplayFlags & DM_INTERLACED)) + interlaced = " interlaced"; + + if (devmode->dmFields & DM_POSITION) + { + snprintf( position, sizeof(position), " at (%d,%d)", + (int)devmode->__WINE_DUMMY_U(1)__WINE_DUMMY_S(2)dmPosition.x, + (int)devmode->__WINE_DUMMY_U(1)__WINE_DUMMY_S(2)dmPosition.y ); + } + + return wine_dbg_sprintf( "%ux%u %ubits %uHz%s%s%s%s", + (unsigned int)devmode->dmPelsWidth, + (unsigned int)devmode->dmPelsHeight, + (unsigned int)devmode->dmBitsPerPel, + (unsigned int)devmode->dmDisplayFrequency, + rotation, fixed_output, interlaced, position ); +} + +#undef __WINE_DUMMY_U +#undef __WINE_DUMMY_S + +#endif /* defined(_WINGDI_) && !defined(NOGDI) */ + #ifndef WINE_TRACE #define WINE_TRACE __WINE_DPRINTF(_TRACE,__wine_dbch___default) #define WINE_TRACE_(ch) __WINE_DPRINTF(_TRACE,&__wine_dbch_##ch) @@ -503,6 +567,10 @@ static inline const char *debugstr_vt( VARTYPE vt ) { return wine_dbgstr_vt( vt static inline const char *debugstr_variant( const VARIANT *v ) { return wine_dbgstr_variant( v ); } #endif
+#if defined(_WINGDI_) && !defined(NOGDI) +static inline const char *debugstr_devmodew( const DEVMODEW *dm ) { return wine_dbgstr_devmodew( dm ); } +#endif + #define TRACE WINE_TRACE #define TRACE_(ch) WINE_TRACE_(ch) #define TRACE_ON(ch) WINE_TRACE_ON(ch) diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c index 81eb0d1d01b..ef6a3e453fe 100644 --- a/programs/explorer/desktop.c +++ b/programs/explorer/desktop.c @@ -984,10 +984,8 @@ static void initialize_display_settings(void) continue; }
- WINE_TRACE( "Device %s current display mode %lux%lu %luBits %luHz at %ld,%ld.\n", - wine_dbgstr_w( ddW.DeviceName ), dmW.dmPelsWidth, dmW.dmPelsHeight, - dmW.dmBitsPerPel, dmW.dmDisplayFrequency, dmW.u1.s2.dmPosition.x, - dmW.u1.s2.dmPosition.y ); + WINE_TRACE( "Device %s current display mode %s.\n", + wine_dbgstr_w( ddW.DeviceName ), wine_dbgstr_devmodew( &dmW ) );
if (ChangeDisplaySettingsExW( ddW.DeviceName, &dmW, 0, CDS_GLOBAL | CDS_NORESET | CDS_UPDATEREGISTRY, 0 ))
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Update the gdi_device_manager API to enable drivers to set the current mode (along with the registry mode if not already set) in UpdateDisplayDevices.
Signed-off-by: Alexandros Frantzis alexandros.frantzis@collabora.com --- dlls/win32u/sysparams.c | 49 +++++++++++++++++++++++++++++++--- dlls/wineandroid.drv/init.c | 2 +- dlls/winemac.drv/display.c | 2 +- dlls/winewayland.drv/display.c | 2 +- dlls/winex11.drv/display.c | 2 +- include/wine/gdi_driver.h | 2 +- 6 files changed, 50 insertions(+), 9 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 0b553f447b6..317bbd10a7d 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1482,9 +1482,10 @@ static void add_monitor( const struct gdi_monitor *monitor, void *param ) if (hkey) NtClose( hkey ); }
-static void add_mode( const DEVMODEW *mode, void *param ) +static void add_mode( const DEVMODEW *mode, BOOL current, void *param ) { struct device_manager_ctx *ctx = param; + DEVMODEW nopos_mode;
if (!ctx->adapter_count) { @@ -1496,10 +1497,21 @@ static void add_mode( const DEVMODEW *mode, void *param ) add_adapter( &default_adapter, ctx ); }
- if (write_adapter_mode( ctx->adapter_key, ctx->mode_count, mode )) + nopos_mode = *mode; + nopos_mode.dmPosition.x = 0; + nopos_mode.dmPosition.y = 0; + nopos_mode.dmFields &= ~DM_POSITION; + + if (write_adapter_mode( ctx->adapter_key, ctx->mode_count, &nopos_mode )) { ctx->mode_count++; set_reg_value( ctx->adapter_key, mode_countW, REG_DWORD, &ctx->mode_count, sizeof(ctx->mode_count) ); + if (current) + { + if (!read_adapter_mode( ctx->adapter_key, ENUM_REGISTRY_SETTINGS, &nopos_mode )) + write_adapter_mode( ctx->adapter_key, ENUM_REGISTRY_SETTINGS, mode ); + write_adapter_mode( ctx->adapter_key, ENUM_CURRENT_SETTINGS, mode ); + } } }
@@ -1626,6 +1638,32 @@ static BOOL update_display_cache_from_registry(void) return ret; }
+static BOOL is_same_devmode( const DEVMODEW *a, const DEVMODEW *b ) +{ + static const DWORD fields = DM_DISPLAYORIENTATION | DM_DISPLAYFIXEDOUTPUT | + DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | + DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; + + if ((a->dmFields & fields) != (b->dmFields & fields)) return FALSE; + + if ((a->dmFields & DM_DISPLAYORIENTATION) && a->dmDisplayOrientation != b->dmDisplayOrientation) + return FALSE; + if ((a->dmFields & DM_DISPLAYFIXEDOUTPUT) && a->dmDisplayFixedOutput != b->dmDisplayFixedOutput) + return FALSE; + if ((a->dmFields & DM_BITSPERPEL) && a->dmBitsPerPel != b->dmBitsPerPel) + return FALSE; + if ((a->dmFields & DM_PELSWIDTH) && a->dmPelsWidth != b->dmPelsWidth) + return FALSE; + if ((a->dmFields & DM_PELSHEIGHT) && a->dmPelsHeight != b->dmPelsHeight) + return FALSE; + if ((a->dmFields & DM_DISPLAYFLAGS) && a->dmDisplayFlags != b->dmDisplayFlags) + return FALSE; + if ((a->dmFields & DM_DISPLAYFREQUENCY) && a->dmDisplayFrequency != b->dmDisplayFrequency) + return FALSE; + + return TRUE; +} + static BOOL update_display_cache( BOOL force ) { HWINSTA winstation = NtUserGetProcessWindowStation(); @@ -1682,7 +1720,6 @@ static BOOL update_display_cache( BOOL force ) { mode = modes[2]; mode.dmFields |= DM_POSITION; - write_adapter_mode( ctx.adapter_key, ENUM_CURRENT_SETTINGS, &mode ); } monitor.rc_monitor.right = mode.dmPelsWidth; monitor.rc_monitor.bottom = mode.dmPelsHeight; @@ -1690,7 +1727,11 @@ static BOOL update_display_cache( BOOL force ) monitor.rc_work.bottom = mode.dmPelsHeight;
add_monitor( &monitor, &ctx ); - for (i = 0; i < ARRAY_SIZE(modes); ++i) add_mode( modes + i, &ctx ); + for (i = 0; i < ARRAY_SIZE(modes); ++i) + { + if (is_same_devmode( modes + i, &mode )) add_mode( &mode, TRUE, &ctx ); + else add_mode( modes + i, FALSE, &ctx ); + } } release_display_manager_ctx( &ctx );
diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index 074aa6c6257..0ba8a0b3ebb 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -295,7 +295,7 @@ BOOL ANDROID_UpdateDisplayDevices( const struct gdi_device_manager *device_manag device_manager->add_gpu( &gpu, param ); device_manager->add_adapter( &adapter, param ); device_manager->add_monitor( &gdi_monitor, param ); - device_manager->add_mode( &mode, param ); + device_manager->add_mode( &mode, FALSE, param ); force_display_devices_refresh = FALSE; }
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 6a798994e47..438e2bb5390 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -1205,7 +1205,7 @@ BOOL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manage (int)mode->dmBitsPerPel, (int)mode->dmDisplayFrequency, mode->dmDisplayFixedOutput == DMDFO_STRETCH ? "" : "un", mode->dmDisplayFlags & DM_INTERLACED ? "" : "non-"); - device_manager->add_mode( mode, param ); + device_manager->add_mode( mode, FALSE, param ); }
free(modes); diff --git a/dlls/winewayland.drv/display.c b/dlls/winewayland.drv/display.c index e72b26a9da0..1d86b2fd4e3 100644 --- a/dlls/winewayland.drv/display.c +++ b/dlls/winewayland.drv/display.c @@ -126,7 +126,7 @@ static void wayland_add_device_modes(const struct gdi_device_manager *device_man { DEVMODEW mode; populate_devmode(output_mode, &mode); - device_manager->add_mode(&mode, param); + device_manager->add_mode(&mode, FALSE, param); } }
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 78de6a6f88b..e675194b9fd 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -599,7 +599,7 @@ BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage for (mode = modes; mode_count; mode_count--) { TRACE( "mode: %p\n", mode ); - device_manager->add_mode( mode, param ); + device_manager->add_mode( mode, FALSE, param ); mode = (DEVMODEW *)((char *)mode + sizeof(*modes) + modes[0].dmDriverExtra); }
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index c492252d4ab..0eb24fd4424 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -266,7 +266,7 @@ struct gdi_device_manager void (*add_gpu)( const struct gdi_gpu *gpu, void *param ); void (*add_adapter)( const struct gdi_adapter *adapter, void *param ); void (*add_monitor)( const struct gdi_monitor *monitor, void *param ); - void (*add_mode)( const DEVMODEW *mode, void *param ); + void (*add_mode)( const DEVMODEW *mode, BOOL current, void *param ); };
#define WINE_DM_UNSUPPORTED 0x80000000
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Since setting the current mode also sets the registry settings (if not previously set), we also remove the code that manually changes the registry settings.
Signed-off-by: Alexandros Frantzis alexandros.frantzis@collabora.com --- dlls/winex11.drv/display.c | 76 +++++++++++++++++++------------------- dlls/winex11.drv/x11drv.h | 1 - dlls/winex11.drv/xrandr.c | 1 - 3 files changed, 39 insertions(+), 39 deletions(-)
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index e675194b9fd..ab7a12a981a 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -156,41 +156,6 @@ void X11DRV_Settings_Init(void) X11DRV_Settings_SetHandler(&nores_handler); }
-/* Initialize registry display settings when new display devices are added */ -void init_registry_display_settings(void) -{ - DEVMODEW dm = {.dmSize = sizeof(dm)}; - DISPLAY_DEVICEW dd = {sizeof(dd)}; - UNICODE_STRING device_name; - DWORD i = 0; - int ret; - - while (!NtUserEnumDisplayDevices( NULL, i++, &dd, 0 )) - { - RtlInitUnicodeString( &device_name, dd.DeviceName ); - - /* Skip if the device already has registry display settings */ - if (NtUserEnumDisplaySettings( &device_name, ENUM_REGISTRY_SETTINGS, &dm, 0 )) - continue; - - if (!NtUserEnumDisplaySettings( &device_name, ENUM_CURRENT_SETTINGS, &dm, 0 )) - { - ERR("Failed to query current display settings for %s.\n", wine_dbgstr_w(dd.DeviceName)); - continue; - } - - TRACE("Device %s current display mode %ux%u %ubits %uHz at %d,%d.\n", - wine_dbgstr_w(dd.DeviceName), (int)dm.dmPelsWidth, (int)dm.dmPelsHeight, - (int)dm.dmBitsPerPel, (int)dm.dmDisplayFrequency, (int)dm.dmPosition.x, (int)dm.dmPosition.y); - - ret = NtUserChangeDisplaySettings( &device_name, &dm, NULL, - CDS_GLOBAL | CDS_NORESET | CDS_UPDATEREGISTRY, NULL ); - if (ret != DISP_CHANGE_SUCCESSFUL) - ERR("Failed to save registry display settings for %s, returned %d.\n", - wine_dbgstr_w(dd.DeviceName), ret); - } -} - static void set_display_depth(ULONG_PTR display_id, DWORD depth) { struct x11drv_display_depth *display_depth; @@ -551,6 +516,32 @@ BOOL X11DRV_DisplayDevices_SupportEventHandlers(void)
static BOOL force_display_devices_refresh;
+static BOOL is_same_devmode( const DEVMODEW *a, const DEVMODEW *b ) +{ + static const DWORD fields = DM_DISPLAYORIENTATION | DM_DISPLAYFIXEDOUTPUT | + DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | + DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; + + if ((a->dmFields & fields) != (b->dmFields & fields)) return FALSE; + + if ((a->dmFields & DM_DISPLAYORIENTATION) && a->dmDisplayOrientation != b->dmDisplayOrientation) + return FALSE; + if ((a->dmFields & DM_DISPLAYFIXEDOUTPUT) && a->dmDisplayFixedOutput != b->dmDisplayFixedOutput) + return FALSE; + if ((a->dmFields & DM_BITSPERPEL) && a->dmBitsPerPel != b->dmBitsPerPel) + return FALSE; + if ((a->dmFields & DM_PELSWIDTH) && a->dmPelsWidth != b->dmPelsWidth) + return FALSE; + if ((a->dmFields & DM_PELSHEIGHT) && a->dmPelsHeight != b->dmPelsHeight) + return FALSE; + if ((a->dmFields & DM_DISPLAYFLAGS) && a->dmDisplayFlags != b->dmDisplayFlags) + return FALSE; + if ((a->dmFields & DM_DISPLAYFREQUENCY) && a->dmDisplayFrequency != b->dmDisplayFrequency) + return FALSE; + + return TRUE; +} + BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manager, BOOL force, void *param ) { struct x11drv_display_device_handler *handler; @@ -582,6 +573,8 @@ BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage
for (adapter = 0; adapter < adapter_count; adapter++) { + DEVMODEW current_mode = {.dmSize = sizeof(current_mode)}; + device_manager->add_adapter( &adapters[adapter], param );
if (!handler->get_monitors(adapters[adapter].id, &monitors, &monitor_count)) break; @@ -593,13 +586,22 @@ BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manage
handler->free_monitors(monitors, monitor_count);
+ settings_handler.get_current_mode( adapters[adapter].id, ¤t_mode ); if (!settings_handler.get_modes( adapters[adapter].id, EDS_ROTATEDMODE, &modes, &mode_count )) continue;
for (mode = modes; mode_count; mode_count--) { - TRACE( "mode: %p\n", mode ); - device_manager->add_mode( mode, FALSE, param ); + if (is_same_devmode( mode, ¤t_mode )) + { + TRACE("current mode: %s\n", debugstr_devmodew( ¤t_mode )); + device_manager->add_mode( ¤t_mode, TRUE, param ); + } + else + { + TRACE("mode: %s\n", debugstr_devmodew( mode )); + device_manager->add_mode( mode, FALSE, param ); + } mode = (DEVMODEW *)((char *)mode + sizeof(*modes) + modes[0].dmDriverExtra); }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index a41eac928ad..893099489e3 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -758,7 +758,6 @@ extern void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *han
extern void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) DECLSPEC_HIDDEN; extern void X11DRV_resize_desktop(void) DECLSPEC_HIDDEN; -extern void init_registry_display_settings(void) DECLSPEC_HIDDEN; extern BOOL is_virtual_desktop(void) DECLSPEC_HIDDEN; extern BOOL is_desktop_fullscreen(void) DECLSPEC_HIDDEN; extern BOOL is_detached_mode(const DEVMODEW *) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index 7c32e683c5d..3731ca6b4d0 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -1188,7 +1188,6 @@ static BOOL xrandr14_device_change_handler( HWND hwnd, XEvent *event ) if (hwnd == NtUserGetDesktopWindow() && NtUserGetWindowThread( hwnd, NULL ) == GetCurrentThreadId()) { X11DRV_DisplayDevices_Init( TRUE ); - init_registry_display_settings(); X11DRV_resize_desktop(); } /* Update xinerama monitors for xinerama_get_fullscreen_monitors() */
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Signed-off-by: Alexandros Frantzis alexandros.frantzis@collabora.com --- dlls/winewayland.drv/display.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/winewayland.drv/display.c b/dlls/winewayland.drv/display.c index 1d86b2fd4e3..bd99441170e 100644 --- a/dlls/winewayland.drv/display.c +++ b/dlls/winewayland.drv/display.c @@ -124,9 +124,11 @@ static void wayland_add_device_modes(const struct gdi_device_manager *device_man
RB_FOR_EACH_ENTRY(output_mode, &output->modes, struct wayland_output_mode, entry) { - DEVMODEW mode; + DEVMODEW mode = {.dmSize = sizeof(mode)}; + BOOL mode_is_current = output_mode == output->current_mode; populate_devmode(output_mode, &mode); - device_manager->add_mode(&mode, FALSE, param); + if (mode_is_current) mode.dmFields |= DM_POSITION; + device_manager->add_mode(&mode, mode_is_current, param); } }
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Signed-off-by: Alexandros Frantzis alexandros.frantzis@collabora.com --- dlls/winemac.drv/display.c | 50 +++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 22 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 438e2bb5390..b93ebaaa5e7 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -864,6 +864,33 @@ static DEVMODEW *display_get_modes(CGDirectDisplayID display_id, int *modes_coun return devmodes; }
+static void display_get_current_mode(struct macdrv_display *display, DEVMODEW *devmode) +{ + CGDisplayModeRef display_mode; + CGDirectDisplayID display_id; + + display_id = display->displayID; + display_mode = CGDisplayCopyDisplayMode(display_id); + + devmode->dmPosition.x = CGRectGetMinX(display->frame); + devmode->dmPosition.y = CGRectGetMinY(display->frame); + devmode->dmFields |= DM_POSITION; + + display_mode_to_devmode(display_id, display_mode, devmode); + if (retina_enabled) + { + struct display_mode_descriptor *desc = create_original_display_mode_descriptor(display_id); + if (display_mode_matches_descriptor(display_mode, desc)) + { + devmode->dmPelsWidth *= 2; + devmode->dmPelsHeight *= 2; + } + free_display_mode_descriptor(desc); + } + + CFRelease(display_mode); +} + /*********************************************************************** * GetCurrentDisplaySettings (MACDRV.@) * @@ -872,8 +899,6 @@ BOOL macdrv_GetCurrentDisplaySettings(LPCWSTR devname, BOOL is_primary, LPDEVMOD { struct macdrv_display *displays = NULL; int num_displays, display_idx; - CGDisplayModeRef display_mode; - CGDirectDisplayID display_id; WCHAR *end;
TRACE("%s, %u, %p + %hu\n", debugstr_w(devname), is_primary, devmode, devmode->dmSize); @@ -890,26 +915,7 @@ BOOL macdrv_GetCurrentDisplaySettings(LPCWSTR devname, BOOL is_primary, LPDEVMOD return FALSE; }
- display_id = displays[display_idx].displayID; - display_mode = CGDisplayCopyDisplayMode(display_id); - - devmode->dmPosition.x = CGRectGetMinX(displays[display_idx].frame); - devmode->dmPosition.y = CGRectGetMinY(displays[display_idx].frame); - devmode->dmFields |= DM_POSITION; - - display_mode_to_devmode(display_id, display_mode, devmode); - if (retina_enabled) - { - struct display_mode_descriptor *desc = create_original_display_mode_descriptor(display_id); - if (display_mode_matches_descriptor(display_mode, desc)) - { - devmode->dmPelsWidth *= 2; - devmode->dmPelsHeight *= 2; - } - free_display_mode_descriptor(desc); - } - - CFRelease(display_mode); + display_get_current_mode(&displays[display_idx], devmode); macdrv_free_displays(displays);
TRACE("current mode -- %dx%d-%dx%dx%dbpp @%d Hz",
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Since setting the current mode also sets the registry settings (if not already set), we also remove the code that manually changes the registry settings.
Signed-off-by: Alexandros Frantzis <alexandros.frantzis@collabora.com --- dlls/winemac.drv/display.c | 105 +++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 46 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index b93ebaaa5e7..9f42ab0b7d4 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -1076,45 +1076,6 @@ done: return (err == kCGErrorSuccess); }
-/*********************************************************************** - * init_registry_display_settings - * - * Initialize registry display settings when new display devices are added. - */ -static void init_registry_display_settings(void) -{ - DEVMODEW dm = {.dmSize = sizeof(dm)}; - DISPLAY_DEVICEW dd = {sizeof(dd)}; - UNICODE_STRING str; - DWORD i = 0; - int ret; - - while (!NtUserEnumDisplayDevices(NULL, i++, &dd, 0)) - { - RtlInitUnicodeString(&str, dd.DeviceName); - - /* Skip if the device already has registry display settings */ - if (NtUserEnumDisplaySettings(&str, ENUM_REGISTRY_SETTINGS, &dm, 0)) - continue; - - if (!NtUserEnumDisplaySettings(&str, ENUM_CURRENT_SETTINGS, &dm, 0)) - { - ERR("Failed to query current display settings for %s.\n", wine_dbgstr_w(dd.DeviceName)); - continue; - } - - TRACE("Device %s current display mode %ux%u %ubits %uHz at %d,%d.\n", - wine_dbgstr_w(dd.DeviceName), (unsigned int)dm.dmPelsWidth, (unsigned int)dm.dmPelsHeight, - (unsigned int)dm.dmBitsPerPel, (unsigned int)dm.dmDisplayFrequency, (int)dm.dmPosition.x, (int)dm.dmPosition.y); - - ret = NtUserChangeDisplaySettings(&str, &dm, NULL, - CDS_GLOBAL | CDS_NORESET | CDS_UPDATEREGISTRY, NULL); - if (ret != DISP_CHANGE_SUCCESSFUL) - ERR("Failed to save registry display settings for %s, returned %d.\n", - wine_dbgstr_w(dd.DeviceName), ret); - } -} - /*********************************************************************** * macdrv_displays_changed * @@ -1133,25 +1094,57 @@ void macdrv_displays_changed(const macdrv_event *event) NtUserGetWindowThread(hwnd, NULL) == GetCurrentThreadId()) { macdrv_init_display_devices(TRUE); - init_registry_display_settings(); macdrv_resize_desktop(); } }
static BOOL force_display_devices_refresh;
+static BOOL is_same_devmode( const DEVMODEW *a, const DEVMODEW *b ) +{ + static const DWORD fields = DM_DISPLAYORIENTATION | DM_DISPLAYFIXEDOUTPUT | + DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | + DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY; + + if ((a->dmFields & fields) != (b->dmFields & fields)) return FALSE; + + if ((a->dmFields & DM_DISPLAYORIENTATION) && a->dmDisplayOrientation != b->dmDisplayOrientation) + return FALSE; + if ((a->dmFields & DM_DISPLAYFIXEDOUTPUT) && a->dmDisplayFixedOutput != b->dmDisplayFixedOutput) + return FALSE; + if ((a->dmFields & DM_BITSPERPEL) && a->dmBitsPerPel != b->dmBitsPerPel) + return FALSE; + if ((a->dmFields & DM_PELSWIDTH) && a->dmPelsWidth != b->dmPelsWidth) + return FALSE; + if ((a->dmFields & DM_PELSHEIGHT) && a->dmPelsHeight != b->dmPelsHeight) + return FALSE; + if ((a->dmFields & DM_DISPLAYFLAGS) && a->dmDisplayFlags != b->dmDisplayFlags) + return FALSE; + if ((a->dmFields & DM_DISPLAYFREQUENCY) && a->dmDisplayFrequency != b->dmDisplayFrequency) + return FALSE; + + return TRUE; +} + BOOL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manager, BOOL force, void *param ) { struct macdrv_adapter *adapters, *adapter; struct macdrv_monitor *monitors, *monitor; struct macdrv_gpu *gpus, *gpu; - INT gpu_count, adapter_count, monitor_count, mode_count; + struct macdrv_display *displays, *display; + INT gpu_count, adapter_count, monitor_count, mode_count, display_count; DEVMODEW *mode, *modes; DWORD len;
if (!force && !force_display_devices_refresh) return TRUE; force_display_devices_refresh = FALSE;
+ if (macdrv_get_displays(&displays, &display_count)) + { + displays = NULL; + display_count = 0; + } + /* Initialize GPUs */ if (macdrv_get_gpus(&gpus, &gpu_count)) { @@ -1179,6 +1172,7 @@ BOOL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manage
for (adapter = adapters; adapter < adapters + adapter_count; adapter++) { + DEVMODEW current_mode = { .dmSize = sizeof(current_mode) }; struct gdi_adapter gdi_adapter = { .id = adapter->id, @@ -1201,17 +1195,35 @@ BOOL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manage device_manager->add_monitor( &gdi_monitor, param ); }
+ /* Get the current mode */ + if (displays) + { + for (display = displays; display < displays + display_count; display++) + { + if (display->displayID == adapter->id) + { + display_get_current_mode(display, ¤t_mode); + break; + } + } + } + if (!(modes = display_get_modes(adapter->id, &mode_count))) break; TRACE("adapter: %#x, mode count: %d\n", adapter->id, mode_count);
/* Initialize modes */ for (mode = modes; mode < modes + mode_count; mode++) { - TRACE("mode: %dx%dx%dbpp @%d Hz, %sstretched %sinterlaced\n", (int)mode->dmPelsWidth, (int)mode->dmPelsHeight, - (int)mode->dmBitsPerPel, (int)mode->dmDisplayFrequency, - mode->dmDisplayFixedOutput == DMDFO_STRETCH ? "" : "un", - mode->dmDisplayFlags & DM_INTERLACED ? "" : "non-"); - device_manager->add_mode( mode, FALSE, param ); + if (is_same_devmode(mode, ¤t_mode)) + { + TRACE("current mode: %s\n", debugstr_devmodew(¤t_mode)); + device_manager->add_mode( ¤t_mode, TRUE, param ); + } + else + { + TRACE("mode: %s\n", debugstr_devmodew(mode)); + device_manager->add_mode( mode, FALSE, param ); + } }
free(modes); @@ -1222,6 +1234,7 @@ BOOL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manage }
macdrv_free_gpus(gpus); + macdrv_free_displays(displays); return TRUE; }
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Signed-off-by: Alexandros Frantzis alexandros.frantzis@collabora.com --- dlls/wineandroid.drv/init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index 0ba8a0b3ebb..f2423d96407 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -289,13 +289,14 @@ BOOL ANDROID_UpdateDisplayDevices( const struct gdi_device_manager *device_manag }; const DEVMODEW mode = { - .dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, + .dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | + DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION, .dmBitsPerPel = screen_bpp, .dmPelsWidth = screen_width, .dmPelsHeight = screen_height, .dmDisplayFrequency = 60, }; device_manager->add_gpu( &gpu, param ); device_manager->add_adapter( &adapter, param ); device_manager->add_monitor( &gdi_monitor, param ); - device_manager->add_mode( &mode, FALSE, param ); + device_manager->add_mode( &mode, TRUE, param ); force_display_devices_refresh = FALSE; }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=131461
Your paranoid android.
=== debian11 (build log) ===
../wine/include/wine/debug.h:488:40: error: ���DEVMODEW��� has no member named ���u1��� ../wine/include/wine/debug.h:493:24: error: ���DEVMODEW��� has no member named ���u1��� ../wine/include/wine/debug.h:503:17: error: ���DEVMODEW��� has no member named ���u2��� ../wine/include/wine/debug.h:509:30: error: ���DEVMODEW��� has no member named ���u1��� ../wine/include/wine/debug.h:510:30: error: ���DEVMODEW��� has no member named ���u1��� Task: The win32 Wine build failed
=== debian11b (build log) ===
../wine/include/wine/debug.h:488:40: error: ���DEVMODEW��� has no member named ���u1��� ../wine/include/wine/debug.h:493:24: error: ���DEVMODEW��� has no member named ���u1��� ../wine/include/wine/debug.h:503:17: error: ���DEVMODEW��� has no member named ���u2��� ../wine/include/wine/debug.h:509:30: error: ���DEVMODEW��� has no member named ���u1��� ../wine/include/wine/debug.h:510:30: error: ���DEVMODEW��� has no member named ���u1��� Task: The wow64 Wine build failed
Eh, you went the hard way. I didn't want to suggest putting the helper in the global header, it's unlikely to be accepted. Instead just put a TU-local helper and copy it around where you'd need it.
On Tue Apr 4 13:15:44 2023 +0000, Rémi Bernon wrote:
Eh, you went the hard way. I didn't want to suggest putting the helper in the global header, it's unlikely to be accepted. Instead just put a TU-local helper and copy it around where you'd need it.
... which would let you adjust it as needed if some modules don't use specific fields, or don't use nameless unions.
Also, fwiw if you don't have to rebase please don't, it makes the Gitlab comparison feature very useless.
Rémi Bernon (@rbernon) commented about dlls/winex11.drv/display.c:
handler->free_monitors(monitors, monitor_count);
settings_handler.get_current_mode( adapters[adapter].id, ¤t_mode ); if (!settings_handler.get_modes( adapters[adapter].id, EDS_ROTATEDMODE, &modes, &mode_count )) continue; for (mode = modes; mode_count; mode_count--) {
TRACE( "mode: %p\n", mode );
device_manager->add_mode( mode, FALSE, param );
if (is_same_devmode( mode, ¤t_mode ))
{
TRACE("current mode: %s\n", debugstr_devmodew( ¤t_mode ));
Please keep space style consistent.
On Tue Apr 4 13:19:38 2023 +0000, Rémi Bernon wrote:
Please keep space style consistent.
I'll admit sometimes it's challenging to guess what's the right style and the most important consistency level/scope, since many files (including this one) contain a mix of styles, even a few lines apart. In this particular case, I went with macro call (no spaces, like all other TRACE calls in the file) vs function call (mostly spaces) split, causing an inter-line inconsistency (which I guess what your comment is mainly about?). I am happy to use any preferred style, I just wish it was easier to guess what that style is.
So is the preferred way to use a with-spaces style for `TRACE()` (even though all other TRACE calls in the file use a no-space style)?
On Tue Apr 4 13:15:43 2023 +0000, Rémi Bernon wrote:
... which would let you adjust it as needed if some modules don't use specific fields, or don't use nameless unions. Also, fwiw if you don't have to rebase please don't, it makes the Gitlab comparison feature very useless.
Ack on both fronts.
On Tue Apr 4 13:09:00 2023 +0000, Alexandros Frantzis wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/2568/diffs?diff_id=40581&start_sha=759cc1237d0e1c85ba903af6df0e43ca6bdf8545#d1968e8c429ee8f293c300a3b265157c4161beb0_1178_1211)
I have moved the `macdrv_get_displays()` outside the loop. I changed the behavior (compared to the last version) to (try) to populate the modes even when there are no macdrv_displays, since I am not certain about the expected mac semantics in terms of displays, adapters, modes etc (but I can reinstate if someone more familiar with this code can verify that this is the right thing to do).
On Tue Apr 4 13:08:59 2023 +0000, Alexandros Frantzis wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/2568/diffs?diff_id=40581&start_sha=759cc1237d0e1c85ba903af6df0e43ca6bdf8545#281cd1a9b246cf9b867f5ef76600365651a8aacf_577_595)
Done.
On Tue Apr 4 13:08:59 2023 +0000, Alexandros Frantzis wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/2568/diffs?diff_id=40581&start_sha=759cc1237d0e1c85ba903af6df0e43ca6bdf8545#281cd1a9b246cf9b867f5ef76600365651a8aacf_572_595)
I will change to TU-local function as suggested in the other comment (although it's kind of a shame to not have a single debug function for this available to all core and driver components).
On Tue Apr 4 13:08:58 2023 +0000, Alexandros Frantzis wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/2568/diffs?diff_id=40581&start_sha=759cc1237d0e1c85ba903af6df0e43ca6bdf8545#85770a8b187bd82db4dbb9a2b8a5f34616049d0f_1705_1730)
Done.
On Tue Apr 4 14:18:19 2023 +0000, Alexandros Frantzis wrote:
I'll admit sometimes it's challenging to guess what's the right style and the most important consistency level/scope, since many files (including this one) contain a mix of styles, even a few lines apart. In this particular case, I went with macro call (no spaces, like all other TRACE calls in the file) vs function call (mostly spaces) split, causing an inter-line inconsistency (which I guess what your comment is mainly about?). I am happy to use any preferred style, I just wish it was easier to guess what that style is. So is the preferred way to use a with-spaces style for `TRACE()` (even though all other TRACE calls in the file use a no-space style)?
I think it's fine to assume it's either always spaces in paren for all calls, or never. There's some variations in some places I'm not even sure why.
In general trying to keep what was there is probably the best course, especially if the code was changed recentely. Then, try to keep consistent within a function, then within the file and then the module.
In `winex11` case it's a mixed bag, but I believe the module's maintainer prefers the style with more spacing, and I think the module already has a fair amount of this, so we should try to move towards more of it.
On Tue Apr 4 14:22:55 2023 +0000, Rémi Bernon wrote:
I think it's fine to assume it's either always spaces in paren for all calls, or never. There's some variations in some places I'm not even sure why. In general trying to keep what was there is probably the best course, especially if the code was changed recentely. Then, try to keep consistent within a function, then within the file and then the module. In `winex11` case it's a mixed bag, but I believe the module's maintainer prefers the style with more spacing, and I think the module already has a fair amount of this, so we should try to move towards more of it.
Thanks!