From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/win32u/sysparams.c | 132 ++++++++++++++++++++++++++-------------- 1 file changed, 86 insertions(+), 46 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index e33ff6e60e5..9bcd9d58720 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1880,6 +1880,52 @@ static UINT monitor_get_dpi( struct monitor *monitor, MONITOR_DPI_TYPE type, UIN return min( *dpi_x, *dpi_y ); }
+/* display_lock must be held */ +static RECT map_monitor_rect( struct monitor *monitor, RECT rect, UINT dpi_from, MONITOR_DPI_TYPE type_from, + UINT dpi_to, MONITOR_DPI_TYPE type_to ) +{ + UINT x, y; + + assert( type_from != type_to ); + + if (monitor->source) + { + DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}, *mode_from, *mode_to; + UINT num, den, dpi; + + source_get_current_settings( monitor->source, ¤t_mode ); + + dpi = monitor_get_dpi( monitor, MDT_DEFAULT, &x, &y ); + if (!dpi_from) dpi_from = dpi; + if (!dpi_to) dpi_to = dpi; + + if (type_from == MDT_RAW_DPI) + { + monitor_virt_to_raw_ratio( monitor, &den, &num ); + mode_from = &monitor->source->physical; + mode_to = ¤t_mode; + } + else + { + monitor_virt_to_raw_ratio( monitor, &num, &den ); + mode_from = ¤t_mode; + mode_to = &monitor->source->physical; + } + + rect = map_dpi_rect( rect, dpi_from, dpi * 2 ); + OffsetRect( &rect, -mode_from->dmPosition.x * 2 - mode_from->dmPelsWidth, + -mode_from->dmPosition.y * 2 - mode_from->dmPelsHeight ); + rect = map_dpi_rect( rect, den, num ); + OffsetRect( &rect, mode_to->dmPosition.x * 2 + mode_to->dmPelsWidth, + mode_to->dmPosition.y * 2 + mode_to->dmPelsHeight ); + return map_dpi_rect( rect, dpi * 2, dpi_to ); + } + + if (!dpi_from) dpi_from = monitor_get_dpi( monitor, type_from, &x, &y ); + if (!dpi_to) dpi_to = monitor_get_dpi( monitor, type_to, &x, &y ); + return map_dpi_rect( rect, dpi_from, dpi_to ); +} + /* display_lock must be held */ static RECT monitor_get_rect( struct monitor *monitor, UINT dpi, MONITOR_DPI_TYPE type ) { @@ -1911,9 +1957,48 @@ static void monitor_get_info( struct monitor *monitor, MONITORINFO *info, UINT d UINT x, y;
info->rcMonitor = monitor_get_rect( monitor, dpi, MDT_DEFAULT ); - info->rcWork = map_dpi_rect( monitor->rc_work, monitor_get_dpi( monitor, MDT_DEFAULT, &x, &y ), dpi ); info->dwFlags = is_monitor_primary( monitor ) ? MONITORINFOF_PRIMARY : 0;
+ if (emulate_modeset) + { + struct source *source; + RECT rect, taskbar; + + if (!(source = monitor->source)) + { + SetRect( &rect, 0, 0, 1024, 768 ); + info->rcWork = map_dpi_rect( rect, monitor_get_dpi( monitor, MDT_DEFAULT, &x, &y ), dpi ); + } + else if (!(source->state_flags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) + { + SetRectEmpty( &info->rcWork ); + } + else + { + /* Store the task bar size (non-negative) at each side in a RECT for scaling */ + taskbar.left = monitor->rc_work.left - source->physical.dmPosition.x; + taskbar.top = monitor->rc_work.top - source->physical.dmPosition.y; + taskbar.right = source->physical.dmPosition.x + source->physical.dmPelsWidth - monitor->rc_work.right; + taskbar.bottom = source->physical.dmPosition.y + source->physical.dmPelsHeight - monitor->rc_work.bottom; + + /* Scale down the area occupied by taskbar. For example, if the height of the taskbar is + * 100 on 3840x2160. Then changing to emulated 1920x1080 should report a taskbar of height + * 50 because the taskbar height is constant from the perspective of the host system */ + taskbar = map_monitor_rect( monitor, taskbar, 0, MDT_RAW_DPI, dpi, MDT_DEFAULT ); + + rect = monitor_get_rect( monitor, 0, MDT_DEFAULT ); + rect.left += taskbar.left; + rect.top += taskbar.top; + rect.right -= taskbar.right; + rect.bottom -= taskbar.bottom; + info->rcWork = map_dpi_rect( rect, monitor_get_dpi( monitor, MDT_DEFAULT, &x, &y ), dpi ); + } + } + else + { + info->rcWork = map_dpi_rect( monitor->rc_work, monitor_get_dpi( monitor, MDT_DEFAULT, &x, &y ), dpi ); + } + if (info->cbSize >= sizeof(MONITORINFOEXW)) { char buffer[CCHDEVICENAME]; @@ -2526,51 +2611,6 @@ static RECT monitors_get_union_rect( UINT dpi, MONITOR_DPI_TYPE type ) return rect; }
-static RECT map_monitor_rect( struct monitor *monitor, RECT rect, UINT dpi_from, MONITOR_DPI_TYPE type_from, - UINT dpi_to, MONITOR_DPI_TYPE type_to ) -{ - UINT x, y; - - assert( type_from != type_to ); - - if (monitor->source) - { - DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}, *mode_from, *mode_to; - UINT num, den, dpi; - - source_get_current_settings( monitor->source, ¤t_mode ); - - dpi = monitor_get_dpi( monitor, MDT_DEFAULT, &x, &y ); - if (!dpi_from) dpi_from = dpi; - if (!dpi_to) dpi_to = dpi; - - if (type_from == MDT_RAW_DPI) - { - monitor_virt_to_raw_ratio( monitor, &den, &num ); - mode_from = &monitor->source->physical; - mode_to = ¤t_mode; - } - else - { - monitor_virt_to_raw_ratio( monitor, &num, &den ); - mode_from = ¤t_mode; - mode_to = &monitor->source->physical; - } - - rect = map_dpi_rect( rect, dpi_from, dpi * 2 ); - OffsetRect( &rect, -mode_from->dmPosition.x * 2 - mode_from->dmPelsWidth, - -mode_from->dmPosition.y * 2 - mode_from->dmPelsHeight ); - rect = map_dpi_rect( rect, den, num ); - OffsetRect( &rect, mode_to->dmPosition.x * 2 + mode_to->dmPelsWidth, - mode_to->dmPosition.y * 2 + mode_to->dmPelsHeight ); - return map_dpi_rect( rect, dpi * 2, dpi_to ); - } - - if (!dpi_from) dpi_from = monitor_get_dpi( monitor, type_from, &x, &y ); - if (!dpi_to) dpi_to = monitor_get_dpi( monitor, type_to, &x, &y ); - return map_dpi_rect( rect, dpi_from, dpi_to ); -} - /* map a monitor rect from MDT_RAW_DPI to MDT_DEFAULT coordinates */ RECT map_rect_raw_to_virt( RECT rect, UINT dpi_to ) {