For winewayland display modes emulation, instead of https://gitlab.winehq.org/wine/wine/-/merge_requests/5057. Also this could be a move toward implementing some kind of fshack upstream.
(Also includes !5679, I'll rebase it when it is merged).
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index e7262cd33f6..d25ac89f130 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1718,23 +1718,29 @@ static BOOL default_update_display_devices( BOOL force, struct device_manager_ct */ static const DEVMODEW modes[] = { - { .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, + { .dmSize = sizeof(DEVMODEW), + .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, .dmBitsPerPel = 32, .dmPelsWidth = 640, .dmPelsHeight = 480, .dmDisplayFrequency = 60, }, - { .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, + { .dmSize = sizeof(DEVMODEW), + .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, .dmBitsPerPel = 32, .dmPelsWidth = 800, .dmPelsHeight = 600, .dmDisplayFrequency = 60, }, - { .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, + { .dmSize = sizeof(DEVMODEW), + .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, .dmBitsPerPel = 32, .dmPelsWidth = 1024, .dmPelsHeight = 768, .dmDisplayFrequency = 60, }, - { .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, + { .dmSize = sizeof(DEVMODEW), + .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, .dmBitsPerPel = 16, .dmPelsWidth = 640, .dmPelsHeight = 480, .dmDisplayFrequency = 60, }, - { .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, + { .dmSize = sizeof(DEVMODEW), + .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, .dmBitsPerPel = 16, .dmPelsWidth = 800, .dmPelsHeight = 600, .dmDisplayFrequency = 60, }, - { .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, + { .dmSize = sizeof(DEVMODEW), + .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, .dmBitsPerPel = 16, .dmPelsWidth = 1024, .dmPelsHeight = 768, .dmDisplayFrequency = 60, }, }; static const DWORD source_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE; struct pci_id pci_id = {0}; struct gdi_monitor monitor = {0}; - DEVMODEW mode = {{0}}; + DEVMODEW mode = {.dmSize = sizeof(mode)};
if (!force) return TRUE;
@@ -1838,6 +1844,7 @@ static void add_virtual_modes( struct device_manager_ctx *ctx, const DEVMODEW *c { DEVMODEW mode = { + .dmSize = sizeof(mode), .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, .dmDisplayFrequency = 60, .dmBitsPerPel = depths[i], @@ -1872,7 +1879,7 @@ static void add_virtual_modes( struct device_manager_ctx *ctx, const DEVMODEW *c
static BOOL add_virtual_source( struct device_manager_ctx *ctx ) { - DEVMODEW current, initial = ctx->primary, maximum = ctx->primary; + DEVMODEW current = {.dmSize = sizeof(current)}, initial = ctx->primary, maximum = ctx->primary; struct source virtual_source = { .state_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE,
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/wineandroid.drv/init.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index c8d997b7aa4..9a06d8f147b 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -282,6 +282,7 @@ UINT ANDROID_UpdateDisplayDevices( const struct gdi_device_manager *device_manag }; const DEVMODEW mode = { + .dmSize = sizeof(mode), .dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, .dmBitsPerPel = screen_bpp, .dmPelsWidth = screen_width, .dmPelsHeight = screen_height, .dmDisplayFrequency = 60,
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/display.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index c8e29cbf908..828203d2b77 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -97,7 +97,7 @@ static BOOL display_mode_is_supported(CGDisplayModeRef display_mode) }
-static void display_mode_to_devmode(CGDirectDisplayID display_id, CGDisplayModeRef display_mode, DEVMODEW *devmode) +static void display_mode_to_devmode_fields(CGDirectDisplayID display_id, CGDisplayModeRef display_mode, DEVMODEW *devmode) { uint32_t io_flags; double rotation; @@ -847,7 +847,11 @@ static DEVMODEW *display_get_modes(CGDirectDisplayID display_id, int *modes_coun for (i = 0; i < count; i++) { CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); - display_mode_to_devmode(display_id, mode, devmodes + i); + + memset(devmode + i, 0, sizeof(*devmodes)); + devmodes[i].dmSize = sizeof(*devmodes); + + display_mode_to_devmode_fields(display_id, mode, devmodes + i);
if (retina_enabled && display_mode_matches_descriptor(mode, desc)) { @@ -892,7 +896,7 @@ static void display_get_current_mode(struct macdrv_display *display, DEVMODEW *d devmode->dmPosition.y = CGRectGetMinY(display->frame); devmode->dmFields |= DM_POSITION;
- display_mode_to_devmode(display_id, display_mode, devmode); + display_mode_to_devmode_fields(display_id, display_mode, devmode); if (retina_enabled) { struct display_mode_descriptor *desc = create_original_display_mode_descriptor(display_id);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 166 ++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 82 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index d25ac89f130..52620b5040e 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1441,6 +1441,90 @@ static void add_monitor( const struct gdi_monitor *gdi_monitor, void *param ) } }
+static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW *modes, void *param ); + +static void add_virtual_modes( struct device_manager_ctx *ctx, const DEVMODEW *current, + const DEVMODEW *initial, const DEVMODEW *maximum ) +{ + static struct screen_size + { + unsigned int width; + unsigned int height; + } screen_sizes[] = { + /* 4:3 */ + { 320, 240}, + { 400, 300}, + { 512, 384}, + { 640, 480}, + { 768, 576}, + { 800, 600}, + {1024, 768}, + {1152, 864}, + {1280, 960}, + {1400, 1050}, + {1600, 1200}, + {2048, 1536}, + /* 5:4 */ + {1280, 1024}, + {2560, 2048}, + /* 16:9 */ + {1280, 720}, + {1366, 768}, + {1600, 900}, + {1920, 1080}, + {2560, 1440}, + {3840, 2160}, + /* 16:10 */ + { 320, 200}, + { 640, 400}, + {1280, 800}, + {1440, 900}, + {1680, 1050}, + {1920, 1200}, + {2560, 1600} + }; + UINT depths[] = {8, 16, initial->dmBitsPerPel}, i, j, modes_count; + DEVMODEW *modes; + + if (!(modes = malloc( ARRAY_SIZE(depths) * (ARRAY_SIZE(screen_sizes) + 2) * sizeof(*modes) ))) return; + + for (modes_count = i = 0; i < ARRAY_SIZE(depths); ++i) + { + DEVMODEW mode = + { + .dmSize = sizeof(mode), + .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, + .dmDisplayFrequency = 60, + .dmBitsPerPel = depths[i], + }; + + for (j = 0; j < ARRAY_SIZE(screen_sizes); ++j) + { + mode.dmPelsWidth = screen_sizes[j].width; + mode.dmPelsHeight = screen_sizes[j].height; + + if (mode.dmPelsWidth > maximum->dmPelsWidth || mode.dmPelsHeight > maximum->dmPelsWidth) continue; + if (mode.dmPelsWidth == maximum->dmPelsWidth && mode.dmPelsHeight == maximum->dmPelsWidth) continue; + if (mode.dmPelsWidth == initial->dmPelsWidth && mode.dmPelsHeight == initial->dmPelsHeight) continue; + modes[modes_count++] = mode; + } + + mode.dmPelsWidth = initial->dmPelsWidth; + mode.dmPelsHeight = initial->dmPelsHeight; + modes[modes_count++] = mode; + + if (maximum->dmPelsWidth != initial->dmPelsWidth || maximum->dmPelsWidth != initial->dmPelsHeight) + { + mode.dmPelsWidth = maximum->dmPelsWidth; + mode.dmPelsHeight = maximum->dmPelsHeight; + modes[modes_count++] = mode; + } + } + + add_modes( current, modes_count, modes, ctx ); + free( modes ); +} + static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW *modes, void *param ) { struct device_manager_ctx *ctx = param; @@ -1795,88 +1879,6 @@ static BOOL get_default_desktop_size( DWORD *width, DWORD *height ) return TRUE; }
-static void add_virtual_modes( struct device_manager_ctx *ctx, const DEVMODEW *current, - const DEVMODEW *initial, const DEVMODEW *maximum ) -{ - static struct screen_size - { - unsigned int width; - unsigned int height; - } screen_sizes[] = { - /* 4:3 */ - { 320, 240}, - { 400, 300}, - { 512, 384}, - { 640, 480}, - { 768, 576}, - { 800, 600}, - {1024, 768}, - {1152, 864}, - {1280, 960}, - {1400, 1050}, - {1600, 1200}, - {2048, 1536}, - /* 5:4 */ - {1280, 1024}, - {2560, 2048}, - /* 16:9 */ - {1280, 720}, - {1366, 768}, - {1600, 900}, - {1920, 1080}, - {2560, 1440}, - {3840, 2160}, - /* 16:10 */ - { 320, 200}, - { 640, 400}, - {1280, 800}, - {1440, 900}, - {1680, 1050}, - {1920, 1200}, - {2560, 1600} - }; - UINT depths[] = {8, 16, initial->dmBitsPerPel}, i, j, modes_count; - DEVMODEW *modes; - - if (!(modes = malloc( ARRAY_SIZE(depths) * (ARRAY_SIZE(screen_sizes) + 2) * sizeof(*modes) ))) return; - - for (modes_count = i = 0; i < ARRAY_SIZE(depths); ++i) - { - DEVMODEW mode = - { - .dmSize = sizeof(mode), - .dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY, - .dmDisplayFrequency = 60, - .dmBitsPerPel = depths[i], - }; - - for (j = 0; j < ARRAY_SIZE(screen_sizes); ++j) - { - mode.dmPelsWidth = screen_sizes[j].width; - mode.dmPelsHeight = screen_sizes[j].height; - - if (mode.dmPelsWidth > maximum->dmPelsWidth || mode.dmPelsHeight > maximum->dmPelsWidth) continue; - if (mode.dmPelsWidth == maximum->dmPelsWidth && mode.dmPelsHeight == maximum->dmPelsWidth) continue; - if (mode.dmPelsWidth == initial->dmPelsWidth && mode.dmPelsHeight == initial->dmPelsHeight) continue; - modes[modes_count++] = mode; - } - - mode.dmPelsWidth = initial->dmPelsWidth; - mode.dmPelsHeight = initial->dmPelsHeight; - modes[modes_count++] = mode; - - if (maximum->dmPelsWidth != initial->dmPelsWidth || maximum->dmPelsWidth != initial->dmPelsHeight) - { - mode.dmPelsWidth = maximum->dmPelsWidth; - mode.dmPelsHeight = maximum->dmPelsHeight; - modes[modes_count++] = mode; - } - } - - add_modes( current, modes_count, modes, ctx ); - free( modes ); -} - static BOOL add_virtual_source( struct device_manager_ctx *ctx ) { DEVMODEW current = {.dmSize = sizeof(current)}, initial = ctx->primary, maximum = ctx->primary;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 52620b5040e..f3bff159b59 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -615,7 +615,7 @@ static unsigned int query_reg_subkey_value( HKEY hkey, const char *name, KEY_VAL return size; }
-static BOOL reade_source_from_registry( unsigned int index, struct source *source, char *gpu_path ) +static BOOL read_source_from_registry( unsigned int index, struct source *source, char *gpu_path ) { char buffer[4096]; KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer; @@ -1761,7 +1761,7 @@ static BOOL update_display_cache_from_registry(void) source->refcount = 1; source->id = source_id;
- if (!reade_source_from_registry( source_id, source, path ) || + if (!read_source_from_registry( source_id, source, path ) || !(source->gpu = find_gpu_from_path( path ))) { free( source->modes );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 52 +++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 15 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index f3bff159b59..f6866f81b1e 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1441,10 +1441,8 @@ static void add_monitor( const struct gdi_monitor *gdi_monitor, void *param ) } }
-static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW *modes, void *param ); - -static void add_virtual_modes( struct device_manager_ctx *ctx, const DEVMODEW *current, - const DEVMODEW *initial, const DEVMODEW *maximum ) +static DEVMODEW *get_virtual_modes( const DEVMODEW *current, const DEVMODEW *initial, + const DEVMODEW *maximum, UINT32 *modes_count ) { static struct screen_size { @@ -1483,12 +1481,12 @@ static void add_virtual_modes( struct device_manager_ctx *ctx, const DEVMODEW *c {1920, 1200}, {2560, 1600} }; - UINT depths[] = {8, 16, initial->dmBitsPerPel}, i, j, modes_count; + UINT depths[] = {8, 16, initial->dmBitsPerPel}, i, j, count; DEVMODEW *modes;
- if (!(modes = malloc( ARRAY_SIZE(depths) * (ARRAY_SIZE(screen_sizes) + 2) * sizeof(*modes) ))) return; + modes = malloc( ARRAY_SIZE(depths) * (ARRAY_SIZE(screen_sizes) + 2) * sizeof(*modes) );
- for (modes_count = i = 0; i < ARRAY_SIZE(depths); ++i) + for (count = i = 0; modes && i < ARRAY_SIZE(depths); ++i) { DEVMODEW mode = { @@ -1506,29 +1504,31 @@ static void add_virtual_modes( struct device_manager_ctx *ctx, const DEVMODEW *c if (mode.dmPelsWidth > maximum->dmPelsWidth || mode.dmPelsHeight > maximum->dmPelsWidth) continue; if (mode.dmPelsWidth == maximum->dmPelsWidth && mode.dmPelsHeight == maximum->dmPelsWidth) continue; if (mode.dmPelsWidth == initial->dmPelsWidth && mode.dmPelsHeight == initial->dmPelsHeight) continue; - modes[modes_count++] = mode; + modes[count++] = mode; }
mode.dmPelsWidth = initial->dmPelsWidth; mode.dmPelsHeight = initial->dmPelsHeight; - modes[modes_count++] = mode; + modes[count++] = mode;
if (maximum->dmPelsWidth != initial->dmPelsWidth || maximum->dmPelsWidth != initial->dmPelsHeight) { mode.dmPelsWidth = maximum->dmPelsWidth; mode.dmPelsHeight = maximum->dmPelsHeight; - modes[modes_count++] = mode; + modes[count++] = mode; } }
- add_modes( current, modes_count, modes, ctx ); - free( modes ); + *modes_count = count; + return modes; }
static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW *modes, void *param ) { struct device_manager_ctx *ctx = param; - DEVMODEW dummy, detached = *current; + DEVMODEW dummy, detached = *current, virtual, *virtual_modes = NULL; + const DEVMODEW physical = modes_count == 1 ? *modes : *current; + UINT virtual_count;
TRACE( "current %s, modes_count %u, modes %p, param %p\n", debugstr_devmodew( current ), modes_count, modes, param );
@@ -1538,6 +1538,21 @@ static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW detached.dmPelsHeight = 0; if (!(ctx->source.state_flags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) current = &detached;
+ if (modes_count > 1 || current == &detached) + virtual_modes = NULL; + else + { + if (!read_source_mode( ctx->source_key, ENUM_CURRENT_SETTINGS, &virtual )) + virtual = physical; + + if ((virtual_modes = get_virtual_modes( &virtual, current, &physical, &virtual_count ))) + { + modes_count = virtual_count; + modes = virtual_modes; + current = &virtual; + } + } + if (current == &detached || !read_source_mode( ctx->source_key, ENUM_REGISTRY_SETTINGS, &dummy )) write_source_mode( ctx->source_key, ENUM_REGISTRY_SETTINGS, current ); write_source_mode( ctx->source_key, ENUM_CURRENT_SETTINGS, current ); @@ -1546,6 +1561,8 @@ static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW set_reg_value( ctx->source_key, modesW, REG_BINARY, modes, modes_count * sizeof(*modes) ); set_reg_value( ctx->source_key, mode_countW, REG_DWORD, &modes_count, sizeof(modes_count) ); ctx->source.mode_count = modes_count; + + free( virtual_modes ); }
static const struct gdi_device_manager device_manager = @@ -1881,7 +1898,7 @@ static BOOL get_default_desktop_size( DWORD *width, DWORD *height )
static BOOL add_virtual_source( struct device_manager_ctx *ctx ) { - DEVMODEW current = {.dmSize = sizeof(current)}, initial = ctx->primary, maximum = ctx->primary; + DEVMODEW current = {.dmSize = sizeof(current)}, initial = ctx->primary, maximum = ctx->primary, *modes; struct source virtual_source = { .state_flags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE, @@ -1889,6 +1906,7 @@ static BOOL add_virtual_source( struct device_manager_ctx *ctx ) .gpu = &ctx->gpu, }; struct gdi_monitor monitor = {0}; + UINT modes_count;
/* Wine specific config key where source settings will be held, symlinked with the logically indexed config key */ snprintf( virtual_source.path, sizeof(virtual_source.path), "%s\%s\Video\%s\Sources\%s", config_keyA, @@ -1923,7 +1941,11 @@ static BOOL add_virtual_source( struct device_manager_ctx *ctx ) monitor.rc_work.right = current.dmPelsWidth; monitor.rc_work.bottom = current.dmPelsHeight; add_monitor( &monitor, ctx ); - add_virtual_modes( ctx, ¤t, &initial, &maximum ); + + /* Expose the virtual source display modes as physical modes, to avoid DPI scaling */ + if (!(modes = get_virtual_modes( ¤t, &initial, &maximum, &modes_count ))) return STATUS_NO_MEMORY; + add_modes( ¤t, modes_count, modes, ctx ); + free( modes );
return STATUS_SUCCESS; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index f6866f81b1e..9d215939f39 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -39,6 +39,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(system);
+#define WINE_ENUM_PHYSICAL_SETTINGS ((DWORD) -3)
static HKEY video_key, enum_key, control_key, config_key, volatile_base_key;
@@ -69,6 +70,7 @@ static const WCHAR yesW[] = {'Y','e','s',0}; static const WCHAR noW[] = {'N','o',0}; static const WCHAR modesW[] = {'M','o','d','e','s',0}; static const WCHAR mode_countW[] = {'M','o','d','e','C','o','u','n','t',0}; +static const WCHAR physicalW[] = {'P','h','y','s','i','c','a','l',0};
static const char guid_devclass_displayA[] = "{4D36E968-E325-11CE-BFC1-08002BE10318}"; static const WCHAR guid_devclass_displayW[] = @@ -108,6 +110,7 @@ struct source UINT state_flags; UINT monitor_count; UINT mode_count; + DEVMODEW physical; DEVMODEW *modes; };
@@ -425,10 +428,11 @@ static BOOL write_source_mode( HKEY hkey, UINT index, const DEVMODEW *mode ) { WCHAR bufferW[MAX_PATH] = {0};
- assert( index == ENUM_CURRENT_SETTINGS || index == ENUM_REGISTRY_SETTINGS ); + assert( index == ENUM_CURRENT_SETTINGS || index == ENUM_REGISTRY_SETTINGS || index == WINE_ENUM_PHYSICAL_SETTINGS );
if (index == ENUM_CURRENT_SETTINGS) asciiz_to_unicode( bufferW, "Current" ); else if (index == ENUM_REGISTRY_SETTINGS) asciiz_to_unicode( bufferW, "Registry" ); + else if (index == WINE_ENUM_PHYSICAL_SETTINGS) asciiz_to_unicode( bufferW, "Physical" ); else return FALSE;
return set_reg_value( hkey, bufferW, REG_BINARY, &mode->dmFields, sizeof(*mode) - offsetof(DEVMODEW, dmFields) ); @@ -440,10 +444,11 @@ static BOOL read_source_mode( HKEY hkey, UINT index, DEVMODEW *mode ) KEY_VALUE_PARTIAL_INFORMATION *value = (void *)value_buf; const char *key;
- assert( index == ENUM_CURRENT_SETTINGS || index == ENUM_REGISTRY_SETTINGS ); + assert( index == ENUM_CURRENT_SETTINGS || index == ENUM_REGISTRY_SETTINGS || index == WINE_ENUM_PHYSICAL_SETTINGS );
if (index == ENUM_CURRENT_SETTINGS) key = "Current"; else if (index == ENUM_REGISTRY_SETTINGS) key = "Registry"; + else if (index == WINE_ENUM_PHYSICAL_SETTINGS) key = "Physical"; else return FALSE;
if (!query_reg_ascii_value( hkey, key, value, sizeof(value_buf) )) return FALSE; @@ -641,6 +646,9 @@ static BOOL read_source_from_registry( unsigned int index, struct source *source if (query_reg_ascii_value( hkey, "StateFlags", value, sizeof(buffer) ) && value->Type == REG_DWORD) source->state_flags = *(const DWORD *)value->Data;
+ if (read_source_mode( hkey, WINE_ENUM_PHYSICAL_SETTINGS, &source->physical )) + source->physical.dmSize = sizeof(source->physical); + /* ModeCount */ if (query_reg_ascii_value( hkey, "ModeCount", value, sizeof(buffer) ) && value->Type == REG_DWORD) source->mode_count = *(const DWORD *)value->Data; @@ -1539,7 +1547,10 @@ static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW if (!(ctx->source.state_flags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) current = &detached;
if (modes_count > 1 || current == &detached) + { + reg_delete_value( ctx->source_key, physicalW ); virtual_modes = NULL; + } else { if (!read_source_mode( ctx->source_key, ENUM_CURRENT_SETTINGS, &virtual )) @@ -1550,6 +1561,8 @@ static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW modes_count = virtual_count; modes = virtual_modes; current = &virtual; + + write_source_mode( ctx->source_key, WINE_ENUM_PHYSICAL_SETTINGS, &physical ); } }
@@ -3332,6 +3345,7 @@ BOOL WINAPI NtUserEnumDisplaySettings( UNICODE_STRING *device, DWORD index, DEVM
if (index == ENUM_REGISTRY_SETTINGS) ret = source_get_registry_settings( source, devmode ); else if (index == ENUM_CURRENT_SETTINGS) ret = source_get_current_settings( source, devmode ); + else if (index == WINE_ENUM_PHYSICAL_SETTINGS) ret = FALSE; else ret = source_enum_display_settings( source, index, devmode, flags ); source_release( source );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 9d215939f39..6ae7c9fde2f 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -71,6 +71,7 @@ static const WCHAR noW[] = {'N','o',0}; static const WCHAR modesW[] = {'M','o','d','e','s',0}; static const WCHAR mode_countW[] = {'M','o','d','e','C','o','u','n','t',0}; static const WCHAR physicalW[] = {'P','h','y','s','i','c','a','l',0}; +static const WCHAR dpi_factorW[] = {'D','p','i','F','a','c','t','o','r',0};
static const char guid_devclass_displayA[] = "{4D36E968-E325-11CE-BFC1-08002BE10318}"; static const WCHAR guid_devclass_displayW[] = @@ -108,6 +109,7 @@ struct source unsigned int id; struct gpu *gpu; UINT state_flags; + float dpi_factor[2]; UINT monitor_count; UINT mode_count; DEVMODEW physical; @@ -538,7 +540,14 @@ static BOOL source_set_current_settings( const struct source *source, const DEVM if (!(hkey = reg_open_ascii_key( config_key, source->path ))) ret = FALSE; else { - ret = write_source_mode( hkey, ENUM_CURRENT_SETTINGS, mode ); + if ((ret = write_source_mode( hkey, ENUM_CURRENT_SETTINGS, mode )) && source->physical.dmSize) + { + float dpi_factor[2]; + dpi_factor[0] = (float)mode->dmPelsWidth / source->physical.dmPelsWidth; + dpi_factor[1] = (float)mode->dmPelsHeight / source->physical.dmPelsHeight; + set_reg_value( hkey, dpi_factorW, REG_BINARY, &dpi_factor, sizeof(dpi_factor) ); + } + NtClose( hkey ); }
@@ -666,6 +675,12 @@ static BOOL read_source_from_registry( unsigned int index, struct source *source } value = (void *)buffer;
+ /* DpiFactor */ + if (query_reg_value( hkey, dpi_factorW, value, sizeof(buffer) ) && value->Type == REG_BINARY) + memcpy( source->dpi_factor, (float *)value->Data, sizeof(source->dpi_factor) ); + else + source->dpi_factor[0] = source->dpi_factor[1] = 1.0; + /* DeviceID */ size = query_reg_ascii_value( hkey, "GPUID", value, sizeof(buffer) ); NtClose( hkey ); @@ -1536,6 +1551,7 @@ static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW struct device_manager_ctx *ctx = param; DEVMODEW dummy, detached = *current, virtual, *virtual_modes = NULL; const DEVMODEW physical = modes_count == 1 ? *modes : *current; + float dpi_factor[2]; UINT virtual_count;
TRACE( "current %s, modes_count %u, modes %p, param %p\n", debugstr_devmodew( current ), modes_count, modes, param ); @@ -1549,6 +1565,7 @@ static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW if (modes_count > 1 || current == &detached) { reg_delete_value( ctx->source_key, physicalW ); + reg_delete_value( ctx->source_key, dpi_factorW ); virtual_modes = NULL; } else @@ -1563,6 +1580,9 @@ static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW current = &virtual;
write_source_mode( ctx->source_key, WINE_ENUM_PHYSICAL_SETTINGS, &physical ); + dpi_factor[0] = (float)current->dmPelsWidth / physical.dmPelsWidth; + dpi_factor[1] = (float)current->dmPelsHeight / physical.dmPelsHeight; + set_reg_value( ctx->source_key, dpi_factorW, REG_BINARY, &dpi_factor, sizeof(dpi_factor) ); } }
From: Alexandros Frantzis alexandros.frantzis@collabora.com
The reporting of non-current wl_output modes is deprecated, and most compositors now report only the current display mode. --- dlls/winewayland.drv/display.c | 42 ++++------ dlls/winewayland.drv/wayland_output.c | 116 ++++---------------------- dlls/winewayland.drv/waylanddrv.h | 5 +- 3 files changed, 32 insertions(+), 131 deletions(-)
diff --git a/dlls/winewayland.drv/display.c b/dlls/winewayland.drv/display.c index a1dc925a183..9e43392bb20 100644 --- a/dlls/winewayland.drv/display.c +++ b/dlls/winewayland.drv/display.c @@ -73,10 +73,10 @@ static int output_info_cmp_primary_x_y(const void *va, const void *vb)
static inline BOOL output_info_overlap(struct output_info *a, struct output_info *b) { - return b->x < a->x + a->output->current_mode->width && - b->x + b->output->current_mode->width > a->x && - b->y < a->y + a->output->current_mode->height && - b->y + b->output->current_mode->height > a->y; + return b->x < a->x + a->output->mode.width && + b->x + b->output->mode.width > a->x && + b->y < a->y + a->output->mode.height && + b->y + b->output->mode.height > a->y; }
/* Map a point to one of the four quadrants of our 2d coordinate space: @@ -158,16 +158,16 @@ static BOOL output_info_array_resolve_overlaps(struct wl_array *output_info_arra rel_x = (move->output->logical_x - anchor->output->logical_x + (x_use_end ? move->output->logical_w : 0)) / (double)anchor->output->logical_w; - move->x = anchor->x + anchor->output->current_mode->width * rel_x - - (x_use_end ? move->output->current_mode->width : 0); + move->x = anchor->x + anchor->output->mode.width * rel_x - + (x_use_end ? move->output->mode.width : 0);
/* Similarly for the Y axis. */ y_use_end = move->output->logical_y < anchor->output->logical_y; rel_y = (move->output->logical_y - anchor->output->logical_y + (y_use_end ? move->output->logical_h : 0)) / (double)anchor->output->logical_h; - move->y = anchor->y + anchor->output->current_mode->height * rel_y - - (y_use_end ? move->output->current_mode->height : 0); + move->y = anchor->y + anchor->output->mode.height * rel_y - + (y_use_end ? move->output->mode.height : 0); } }
@@ -223,8 +223,8 @@ static void wayland_add_device_monitor(const struct gdi_device_manager *device_m struct gdi_monitor monitor = {0};
SetRect(&monitor.rc_monitor, output_info->x, output_info->y, - output_info->x + output_info->output->current_mode->width, - output_info->y + output_info->output->current_mode->height); + output_info->x + output_info->output->mode.width, + output_info->y + output_info->output->mode.height);
/* We don't have a direct way to get the work area in Wayland. */ monitor.rc_work = monitor.rc_monitor; @@ -250,28 +250,14 @@ static void populate_devmode(struct wayland_output_mode *output_mode, DEVMODEW * static void wayland_add_device_modes(const struct gdi_device_manager *device_manager, void *param, struct output_info *output_info) { - DEVMODEW *modes, current = {.dmSize = sizeof(current)}; - struct wayland_output_mode *output_mode; - int modes_count = 0; + DEVMODEW current = {.dmSize = sizeof(current)};
- if (!(modes = malloc(output_info->output->modes_count * sizeof(*modes)))) - return; - - populate_devmode(output_info->output->current_mode, ¤t); + populate_devmode(&output_info->output->mode, ¤t); current.dmFields |= DM_POSITION; current.dmPosition.x = output_info->x; current.dmPosition.y = output_info->y;
- RB_FOR_EACH_ENTRY(output_mode, &output_info->output->modes, - struct wayland_output_mode, entry) - { - DEVMODEW mode = {.dmSize = sizeof(mode)}; - populate_devmode(output_mode, &mode); - modes[modes_count++] = mode; - } - - device_manager->add_modes(¤t, modes_count, modes, param); - free(modes); + device_manager->add_modes(¤t, 0, NULL, param); }
/*********************************************************************** @@ -297,7 +283,7 @@ UINT WAYLAND_UpdateDisplayDevices(const struct gdi_device_manager *device_manage
wl_list_for_each(output, &process_wayland.output_list, link) { - if (!output->current.current_mode) continue; + if (!output->current.mode.width || !output->current.mode.height) continue; output_info = wl_array_add(&output_info_array, sizeof(*output_info)); if (output_info) output_info->output = &output->current; else ERR("Failed to allocate space for output_info\n"); diff --git a/dlls/winewayland.drv/wayland_output.c b/dlls/winewayland.drv/wayland_output.c index f76881a1770..656e59edbec 100644 --- a/dlls/winewayland.drv/wayland_output.c +++ b/dlls/winewayland.drv/wayland_output.c @@ -35,7 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv); static const int32_t default_refresh = 60000; static uint32_t next_output_id = 0;
-#define WAYLAND_OUTPUT_CHANGED_MODES 0x01 +#define WAYLAND_OUTPUT_CHANGED_MODE 0x01 #define WAYLAND_OUTPUT_CHANGED_NAME 0x02 #define WAYLAND_OUTPUT_CHANGED_LOGICAL_XY 0x04 #define WAYLAND_OUTPUT_CHANGED_LOGICAL_WH 0x08 @@ -44,65 +44,6 @@ static uint32_t next_output_id = 0; * Output handling */
-/* Compare a mode rb_tree key with the provided mode rb_entry and return -1 if - * the key compares less than the entry, 0 if the key compares equal to the - * entry, and 1 if the key compares greater than the entry. - * - * The comparison is based on comparing the width, height and refresh in that - * order. */ -static int wayland_output_mode_cmp_rb(const void *key, - const struct rb_entry *entry) -{ - const struct wayland_output_mode *key_mode = key; - const struct wayland_output_mode *entry_mode = - RB_ENTRY_VALUE(entry, const struct wayland_output_mode, entry); - - if (key_mode->width < entry_mode->width) return -1; - if (key_mode->width > entry_mode->width) return 1; - if (key_mode->height < entry_mode->height) return -1; - if (key_mode->height > entry_mode->height) return 1; - if (key_mode->refresh < entry_mode->refresh) return -1; - if (key_mode->refresh > entry_mode->refresh) return 1; - - return 0; -} - -static void wayland_output_state_add_mode(struct wayland_output_state *state, - int32_t width, int32_t height, - int32_t refresh, BOOL current) -{ - struct rb_entry *mode_entry; - struct wayland_output_mode *mode; - struct wayland_output_mode key = - { - .width = width, - .height = height, - .refresh = refresh, - }; - - mode_entry = rb_get(&state->modes, &key); - if (mode_entry) - { - mode = RB_ENTRY_VALUE(mode_entry, struct wayland_output_mode, entry); - } - else - { - mode = calloc(1, sizeof(*mode)); - if (!mode) - { - ERR("Failed to allocate space for wayland_output_mode\n"); - return; - } - mode->width = width; - mode->height = height; - mode->refresh = refresh; - rb_put(&state->modes, mode, &mode->entry); - state->modes_count++; - } - - if (current) state->current_mode = mode; -} - static void maybe_init_display_devices(void) { DWORD desktop_pid = 0; @@ -123,30 +64,13 @@ static void maybe_init_display_devices(void) NtUserPostMessage(desktop_hwnd, WM_WAYLAND_INIT_DISPLAY_DEVICES, 0, 0); }
-static void wayland_output_mode_free_rb(struct rb_entry *entry, void *ctx) -{ - free(RB_ENTRY_VALUE(entry, struct wayland_output_mode, entry)); -} - static void wayland_output_done(struct wayland_output *output) { - struct wayland_output_mode *mode; - /* Update current state from pending state. */ pthread_mutex_lock(&process_wayland.output_mutex);
- if (output->pending_flags & WAYLAND_OUTPUT_CHANGED_MODES) - { - RB_FOR_EACH_ENTRY(mode, &output->pending.modes, struct wayland_output_mode, entry) - { - wayland_output_state_add_mode(&output->current, - mode->width, mode->height, mode->refresh, - mode == output->pending.current_mode); - } - rb_destroy(&output->pending.modes, wayland_output_mode_free_rb, NULL); - rb_init(&output->pending.modes, wayland_output_mode_cmp_rb); - output->pending.modes_count = 0; - } + if (output->pending_flags & WAYLAND_OUTPUT_CHANGED_MODE) + output->current.mode = output->pending.mode;
if (output->pending_flags & WAYLAND_OUTPUT_CHANGED_NAME) { @@ -171,24 +95,19 @@ static void wayland_output_done(struct wayland_output *output)
/* Ensure the logical dimensions have sane values. */ if ((!output->current.logical_w || !output->current.logical_h) && - output->current.current_mode) + output->current.mode.width && output->current.mode.height) { - output->current.logical_w = output->current.current_mode->width; - output->current.logical_h = output->current.current_mode->height; + output->current.logical_w = output->current.mode.width; + output->current.logical_h = output->current.mode.height; }
pthread_mutex_unlock(&process_wayland.output_mutex);
- TRACE("name=%s logical=%d,%d+%dx%d\n", + TRACE("name=%s logical=%d,%d+%dx%d mode=%dx%d@%d\n", output->current.name, output->current.logical_x, output->current.logical_y, - output->current.logical_w, output->current.logical_h); - - RB_FOR_EACH_ENTRY(mode, &output->current.modes, struct wayland_output_mode, entry) - { - TRACE("mode %dx%d @ %d %s\n", - mode->width, mode->height, mode->refresh, - output->current.current_mode == mode ? "*" : ""); - } + output->current.logical_w, output->current.logical_h, + output->current.mode.width, output->current.mode.height, + output->current.mode.refresh);
maybe_init_display_devices(); } @@ -208,13 +127,17 @@ static void output_handle_mode(void *data, struct wl_output *wl_output, { struct wayland_output *output = data;
+ /* Non-current output modes are deprecated. */ + if (!(flags & WL_OUTPUT_MODE_CURRENT)) return; + /* Windows apps don't expect a zero refresh rate, so use a default value. */ if (refresh == 0) refresh = default_refresh;
- wayland_output_state_add_mode(&output->pending, width, height, refresh, - (flags & WL_OUTPUT_MODE_CURRENT)); + output->pending.mode.width = width; + output->pending.mode.height = height; + output->pending.mode.refresh = refresh;
- output->pending_flags |= WAYLAND_OUTPUT_CHANGED_MODES; + output->pending_flags |= WAYLAND_OUTPUT_CHANGED_MODE; }
static void output_handle_done(void *data, struct wl_output *wl_output) @@ -322,10 +245,6 @@ BOOL wayland_output_create(uint32_t id, uint32_t version) wl_output_add_listener(output->wl_output, &output_listener, output);
wl_list_init(&output->link); - rb_init(&output->pending.modes, wayland_output_mode_cmp_rb); - output->pending.modes_count = 0; - rb_init(&output->current.modes, wayland_output_mode_cmp_rb); - output->current.modes_count = 0;
/* Have a fallback while we don't have compositor given name. */ name_len = snprintf(NULL, 0, "WaylandOutput%d", next_output_id); @@ -356,7 +275,6 @@ err:
static void wayland_output_state_deinit(struct wayland_output_state *state) { - rb_destroy(&state->modes, wayland_output_mode_free_rb, NULL); free(state->name); }
diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 7852c23b690..cabb508827c 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -135,7 +135,6 @@ struct wayland
struct wayland_output_mode { - struct rb_entry entry; int32_t width; int32_t height; int32_t refresh; @@ -143,9 +142,7 @@ struct wayland_output_mode
struct wayland_output_state { - int modes_count; - struct rb_tree modes; - struct wayland_output_mode *current_mode; + struct wayland_output_mode mode; char *name; int logical_x, logical_y; int logical_w, logical_h;
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Since a display reconfiguration may affect the compositor side scaling which we apply to a surface, instruct all surfaces to refresh themselves by committing an updated state based on the latest window state. --- dlls/winewayland.drv/waylanddrv.h | 1 + dlls/winewayland.drv/window.c | 64 +++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+)
diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index cabb508827c..7598ec998b6 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -63,6 +63,7 @@ enum wayland_window_message WM_WAYLAND_INIT_DISPLAY_DEVICES = WM_WINE_FIRST_DRIVER_MSG, WM_WAYLAND_CONFIGURE, WM_WAYLAND_SET_FOREGROUND, + WM_WAYLAND_REFRESH, };
enum wayland_surface_config_state diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 3c41c57b7b5..0836a27c429 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -502,6 +502,16 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, wayland_win_data_release(data); }
+static inline LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, + UINT flags, UINT timeout, PDWORD_PTR res_ptr ) +{ + struct send_message_timeout_params params = { .flags = flags, .timeout = timeout }; + LRESULT res = NtUserMessageCall( hwnd, msg, wparam, lparam, ¶ms, + NtUserSendMessageTimeout, FALSE ); + if (res_ptr) *res_ptr = params.result; + return res; +} + static void wayland_resize_desktop(void) { RECT virtual_rect = NtUserGetVirtualScreenRect(); @@ -510,6 +520,7 @@ static void wayland_resize_desktop(void) virtual_rect.right - virtual_rect.left, virtual_rect.bottom - virtual_rect.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE); + send_message_timeout( HWND_BROADCAST, WM_WAYLAND_REFRESH, 0, 0, SMTO_ABORTIFHUNG, 2000, FALSE ); }
static void wayland_configure_window(HWND hwnd) @@ -625,6 +636,24 @@ static void wayland_configure_window(HWND hwnd) NtUserSetWindowPos(hwnd, 0, 0, 0, window_width, window_height, flags); }
+static void wayland_refresh_window(HWND hwnd) +{ + struct wayland_win_data *data; + + if (!(data = wayland_win_data_get(hwnd))) return; + + if (data->wayland_surface) + { + pthread_mutex_lock(&data->wayland_surface->mutex); + wayland_win_data_get_config(data, &data->wayland_surface->window); + if (wayland_surface_reconfigure(data->wayland_surface)) + wl_surface_commit(data->wayland_surface->wl_surface); + pthread_mutex_unlock(&data->wayland_surface->mutex); + } + + wayland_win_data_release(data); +} + /********************************************************************** * WAYLAND_WindowMessage */ @@ -642,6 +671,10 @@ LRESULT WAYLAND_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) case WM_WAYLAND_SET_FOREGROUND: NtUserSetForegroundWindow(hwnd); return 0; + case WM_WAYLAND_REFRESH: + wayland_refresh_window(hwnd); + NtUserInvalidateRect( hwnd, NULL, TRUE ); + return 0; default: FIXME("got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, (long)wp, lp); return 0; @@ -777,3 +810,34 @@ struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd)
return surface; } + +/********************************************************************** + * enum_process_windows + */ +void enum_process_windows(void (*cb)(HWND hwnd)) +{ + struct wayland_win_data *data; + HWND *hwnds = NULL; + UINT num_hwnds = 0, i = 0; + + pthread_mutex_lock(&win_data_mutex); + + RB_FOR_EACH_ENTRY(data, &win_data_rb, struct wayland_win_data, entry) + ++num_hwnds; + + if (num_hwnds && (hwnds = malloc(num_hwnds * sizeof(*hwnds)))) + { + RB_FOR_EACH_ENTRY(data, &win_data_rb, struct wayland_win_data, entry) + hwnds[i++] = data->hwnd; + } + else + { + num_hwnds = 0; + } + + pthread_mutex_unlock(&win_data_mutex); + + for (i = 0; i < num_hwnds; i++) cb(hwnds[i]); + + free(hwnds); +}
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Depending on the display mode emulation and DPI settings, the window scale factor may be less than 0.5 which will be rounded to 0. Since 0 is not acceptable value for the buffer scale, use 1 instead. --- dlls/winewayland.drv/wayland_pointer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index df76a4e9954..b9de01aba1a 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -630,7 +630,7 @@ static void wayland_pointer_update_cursor_surface(double scale) * support wp_viewport for cursor surfaces, so also set the buffer * scale. Note that setting the viewport destination overrides * the buffer scale, so it's fine to set both. */ - wl_surface_set_buffer_scale(cursor->wl_surface, round(scale)); + wl_surface_set_buffer_scale(cursor->wl_surface, max(1, round(scale))); if (cursor->wp_viewport) { wp_viewport_set_destination(cursor->wp_viewport,
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 38 +++++++++++++++++++++++++++++--------- dlls/win32u/window.c | 6 +++++- 2 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 6ae7c9fde2f..e782833b9bb 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2077,13 +2077,33 @@ static void release_display_dc( HDC hdc ) pthread_mutex_unlock( &display_dc_lock ); }
+static UINT get_source_dpi( struct source *source ) +{ + if (!source) return system_dpi; + return system_dpi * max( source->dpi_factor[0], source->dpi_factor[1] ); +} + /********************************************************************** * get_monitor_dpi */ -UINT get_monitor_dpi( HMONITOR monitor ) +UINT get_monitor_dpi( HMONITOR handle ) { - /* FIXME: use the monitor DPI instead */ - return system_dpi; + struct monitor *monitor; + UINT dpi = system_dpi; + + if (!lock_display_devices()) return system_dpi; + + LIST_FOR_EACH_ENTRY(monitor, &monitors, struct monitor, entry) + { + if (monitor->handle == handle) + { + dpi = get_source_dpi( monitor->source ); + break; + } + } + + unlock_display_devices(); + return dpi; }
/********************************************************************** @@ -2091,8 +2111,8 @@ UINT get_monitor_dpi( HMONITOR monitor ) */ UINT get_win_monitor_dpi( HWND hwnd ) { - /* FIXME: use the monitor DPI instead */ - return system_dpi; + HMONITOR handle = monitor_from_window( hwnd, MONITOR_DEFAULTTONEAREST, 0 ); + return get_monitor_dpi( handle ); }
/* copied from user32 GetAwarenessFromDpiAwarenessContext, make sure to keep that in sync */ @@ -2294,7 +2314,7 @@ static BOOL is_window_rect_full_screen( const RECT *rect )
if (!is_monitor_active( monitor ) || monitor->is_clone) continue;
- monrect = map_dpi_rect( monitor->rc_monitor, get_monitor_dpi( monitor->handle ), + monrect = map_dpi_rect( monitor->rc_monitor, get_source_dpi( monitor->source ), get_thread_dpi() );
if (rect->left <= monrect.left && rect->right >= monrect.right && @@ -3441,7 +3461,7 @@ static BOOL should_enumerate_monitor( struct monitor *monitor, const POINT *orig if (!is_monitor_active( monitor )) return FALSE; if (monitor->is_clone) return FALSE;
- *rect = map_dpi_rect( monitor->rc_monitor, get_monitor_dpi( monitor->handle ), + *rect = map_dpi_rect( monitor->rc_monitor, get_source_dpi( monitor->source ), get_thread_dpi() ); OffsetRect( rect, -origin->x, -origin->y ); return intersect_rect( rect, rect, limit ); @@ -3558,7 +3578,7 @@ BOOL get_monitor_info( HMONITOR handle, MONITORINFO *info )
if ((dpi_to = get_thread_dpi())) { - dpi_from = get_monitor_dpi( handle ); + dpi_from = get_source_dpi( monitor->source ); info->rcMonitor = map_dpi_rect( info->rcMonitor, dpi_from, dpi_to ); info->rcWork = map_dpi_rect( info->rcWork, dpi_from, dpi_to ); } @@ -3595,7 +3615,7 @@ HMONITOR monitor_from_rect( const RECT *rect, UINT flags, UINT dpi )
if (!is_monitor_active( monitor ) || monitor->is_clone) continue;
- monitor_rect = map_dpi_rect( monitor->rc_monitor, get_monitor_dpi( monitor->handle ), system_dpi ); + monitor_rect = map_dpi_rect( monitor->rc_monitor, get_source_dpi( monitor->source ), system_dpi ); if (intersect_rect( &intersect, &monitor_rect, &r )) { /* check for larger intersecting area */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 13dd1c8d80a..178c21d244d 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -903,7 +903,11 @@ UINT get_dpi_for_window( HWND hwnd ) if (win != WND_OTHER_PROCESS) { ret = win->dpi; - if (!ret) ret = get_win_monitor_dpi( hwnd ); + if (!ret) + { + HMONITOR monitor = monitor_from_rect( &win->window_rect, MONITOR_DEFAULTTONEAREST, 0 ); + ret = get_monitor_dpi( monitor ); + } release_win_ptr( win ); } else
I'm very interested in this since we also have a need for virtual mode switching on the Mac side, but re: the discussion in !5057, would this result in the application getting a different result from e.g. `GetDpiForMonitor` after switching to a virtual mode?
Yes you're right, however I think I've found some possible way to implement this, still with DPI. Native seems to already have different display source DPI values (https://learn.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shell...), which can all be queried. The `MDT_RAW_DPI` setting seems appropriate for this feature.
Actually it looks like this might just be what Windows does, I'll write some more tests.
This merge request was closed by Rémi Bernon.