From: Alexandros Frantzis alexandros.frantzis@collabora.com
Emulate the visual effect of a display mode change, by scaling the window according to the ratios of the native vs current mode.
We find the proper native and current mode by utilizing the virtual display device information. --- dlls/winewayland.drv/display.c | 20 ++++++++++++++ dlls/winewayland.drv/waylanddrv.h | 2 ++ dlls/winewayland.drv/waylanddrv_main.c | 1 + dlls/winewayland.drv/window.c | 37 ++++++++++++++++++++++++++ 4 files changed, 60 insertions(+)
diff --git a/dlls/winewayland.drv/display.c b/dlls/winewayland.drv/display.c index f94ad73f1dc..1f4148ced57 100644 --- a/dlls/winewayland.drv/display.c +++ b/dlls/winewayland.drv/display.c @@ -325,3 +325,23 @@ BOOL WAYLAND_UpdateDisplayDevices(const struct gdi_device_manager *device_manage
return TRUE; } + +/*********************************************************************** + * NotifyVirtualDevices (WAYLAND.@) + */ +void WAYLAND_NotifyVirtualDevices(const struct gdi_virtual *virtual) +{ + const struct gdi_virtual *v = virtual; + size_t virtual_size; + + for (v = virtual; v->mode.dmSize; ++v) + TRACE("%s => %s\n", wine_dbgstr_w(v->mode.dmDeviceName), wine_dbgstr_w(v->virtual_id)); + + virtual_size = (v - virtual + 1) * sizeof(*v); + + pthread_mutex_lock(&process_wayland.output_mutex); + free(process_wayland.virtual); + process_wayland.virtual = malloc(virtual_size); + if (process_wayland.virtual) memcpy(process_wayland.virtual, virtual, virtual_size); + pthread_mutex_unlock(&process_wayland.output_mutex); +} diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 3dfe341b623..32928575629 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -128,6 +128,7 @@ struct wayland struct wayland_keyboard keyboard; struct wayland_pointer pointer; struct wl_list output_list; + struct gdi_virtual *virtual; /* Protects the output_list and the wayland_output.current states. */ pthread_mutex_t output_mutex; }; @@ -328,6 +329,7 @@ static inline BOOL asciiz_to_unicodez(WCHAR *dst, const char *src, size_t n) BOOL WAYLAND_ClipCursor(const RECT *clip, BOOL reset); LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); void WAYLAND_DestroyWindow(HWND hwnd); +void WAYLAND_NotifyVirtualDevices(const struct gdi_virtual *virtual); void WAYLAND_SetCursor(HWND hwnd, HCURSOR hcursor); LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam); BOOL WAYLAND_UpdateDisplayDevices(const struct gdi_device_manager *device_manager, diff --git a/dlls/winewayland.drv/waylanddrv_main.c b/dlls/winewayland.drv/waylanddrv_main.c index b60d282aacb..26279905dd6 100644 --- a/dlls/winewayland.drv/waylanddrv_main.c +++ b/dlls/winewayland.drv/waylanddrv_main.c @@ -35,6 +35,7 @@ static const struct user_driver_funcs waylanddrv_funcs = .pDesktopWindowProc = WAYLAND_DesktopWindowProc, .pDestroyWindow = WAYLAND_DestroyWindow, .pKbdLayerDescriptor = WAYLAND_KbdLayerDescriptor, + .pNotifyVirtualDevices = WAYLAND_NotifyVirtualDevices, .pReleaseKbdTables = WAYLAND_ReleaseKbdTables, .pSetCursor = WAYLAND_SetCursor, .pSysCommand = WAYLAND_SysCommand, diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index ac5da371e5c..2b044563a8d 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -158,6 +158,41 @@ static void wayland_win_data_release(struct wayland_win_data *data) pthread_mutex_unlock(&win_data_mutex); }
+static double get_window_mode_change_scale(HWND hwnd) +{ + MONITORINFOEXW mi = {.cbSize = sizeof(mi)}; + HMONITOR hmon; + struct gdi_virtual *virtual; + struct wayland_output *output; + double scale = 1.0; + WCHAR name[128]; + + if (!(hmon = NtUserMonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY)) || + !NtUserGetMonitorInfo(hmon, (MONITORINFO *)&mi)) + return 1.0; + + pthread_mutex_lock(&process_wayland.output_mutex); + + for (virtual = process_wayland.virtual; virtual && virtual->mode.dmSize; ++virtual) + { + if (wcscmp(virtual->mode.dmDeviceName, mi.szDevice)) continue; + wl_list_for_each(output, &process_wayland.output_list, link) + { + asciiz_to_unicodez(name, output->current.name, ARRAY_SIZE(name)); + if (wcscmp(name, virtual->virtual_id)) continue; + if (!output->current.mode.width || !output->current.mode.height) continue; + scale = min(output->current.mode.width / (double)virtual->mode.dmPelsWidth, + output->current.mode.height / (double)virtual->mode.dmPelsHeight); + break; + } + break; + } + + pthread_mutex_unlock(&process_wayland.output_mutex); + + return scale; +} + static void wayland_win_data_get_config(struct wayland_win_data *data, struct wayland_window_config *conf) { @@ -185,6 +220,8 @@ static void wayland_win_data_get_config(struct wayland_win_data *data,
conf->state = window_state; conf->scale = NtUserGetDpiForWindow(data->hwnd) / 96.0; + /* Adjust the window scale for the current display mode. */ + conf->scale /= get_window_mode_change_scale(data->hwnd); conf->visible = (style & WS_VISIBLE) == WS_VISIBLE; conf->managed = data->managed; }