Fix DLC Quest uses the primary monitor size to render when in fullscreen mode on non-primary monitors.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/gdi32/dc.c | 18 +++++++++++ dlls/gdi32/driver.c | 64 ++++++++++++++++++++++++++++++++++++++-- dlls/gdi32/gdi_private.h | 4 +++ dlls/gdi32/tests/dc.c | 4 --- 4 files changed, 83 insertions(+), 7 deletions(-)
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index a9a37d9efe7..830fabf6e78 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -623,6 +623,7 @@ BOOL WINAPI RestoreDC( HDC hdc, INT level ) HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, const DEVMODEW *initData ) { + const WCHAR *display, *p; HDC hdc; DC * dc; const struct gdi_dc_funcs *funcs; @@ -663,6 +664,23 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, } }
+ if (is_display_device( driver )) + display = driver; + else if (is_display_device( device )) + display = device; + else + display = NULL; + + if (display) + { + /* Copy only the display name. For example, \.\DISPLAY1 in \.\DISPLAY1\Monitor0 */ + p = display + 12; + while (iswdigit( *p )) + ++p; + lstrcpynW( dc->display, display, p - display + 1 ); + dc->display[p - display] = '\0'; + } + dc->vis_rect.left = 0; dc->vis_rect.top = 0; dc->vis_rect.right = GetDeviceCaps( hdc, DESKTOPHORZRES ); diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index e2528ece046..bb98c554238 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -81,7 +81,9 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION driver_section = { &critsect_debug, -1, 0, 0, 0, 0 };
+static BOOL (WINAPI *pEnumDisplayMonitors)(HDC, LPRECT, MONITORENUMPROC, LPARAM); static HWND (WINAPI *pGetDesktopWindow)(void); +static BOOL (WINAPI *pGetMonitorInfoW)(HMONITOR, LPMONITORINFO); static INT (WINAPI *pGetSystemMetrics)(INT); static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
@@ -137,10 +139,13 @@ static const struct gdi_dc_funcs *get_display_driver(void) /********************************************************************** * is_display_device */ -static BOOL is_display_device( LPCWSTR name ) +BOOL is_display_device( LPCWSTR name ) { const WCHAR *p = name;
+ if (!name) + return FALSE; + if (wcsnicmp( name, L"\\.\DISPLAY", lstrlenW(L"\\.\DISPLAY") )) return FALSE;
p += lstrlenW(L"\\.\DISPLAY"); @@ -237,10 +242,33 @@ void CDECL __wine_set_display_driver( HMODULE module ) HeapFree( GetProcessHeap(), 0, driver );
user32 = LoadLibraryA( "user32.dll" ); + pGetMonitorInfoW = (void *)GetProcAddress( user32, "GetMonitorInfoW" ); pGetSystemMetrics = (void *)GetProcAddress( user32, "GetSystemMetrics" ); + pEnumDisplayMonitors = (void *)GetProcAddress( user32, "EnumDisplayMonitors" ); pSetThreadDpiAwarenessContext = (void *)GetProcAddress( user32, "SetThreadDpiAwarenessContext" ); }
+struct monitor_info +{ + const WCHAR *name; + RECT rect; +}; + +static BOOL CALLBACK monitor_enum_proc( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lparam ) +{ + struct monitor_info *info = (struct monitor_info *)lparam; + MONITORINFOEXW mi; + + mi.cbSize = sizeof(mi); + pGetMonitorInfoW( monitor, (MONITORINFO *)&mi ); + if (!lstrcmpiW( info->name, mi.szDevice )) + { + info->rect = mi.rcMonitor; + return FALSE; + } + + return TRUE; +}
static INT CDECL nulldrv_AbortDoc( PHYSDEV dev ) { @@ -378,8 +406,38 @@ static INT CDECL nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap ) GetDeviceCaps( dev->hdc, LOGPIXELSX ) * 10 ); case VERTSIZE: return MulDiv( GetDeviceCaps( dev->hdc, VERTRES ), 254, GetDeviceCaps( dev->hdc, LOGPIXELSY ) * 10 ); - case HORZRES: return pGetSystemMetrics ? pGetSystemMetrics( SM_CXSCREEN ) : 640; - case VERTRES: return pGetSystemMetrics ? pGetSystemMetrics( SM_CYSCREEN ) : 480; + case HORZRES: + { + DC *dc = get_nulldrv_dc( dev ); + struct monitor_info info; + + if (dc->display[0] && pEnumDisplayMonitors && pGetMonitorInfoW) + { + info.name = dc->display; + SetRectEmpty( &info.rect ); + pEnumDisplayMonitors( NULL, NULL, monitor_enum_proc, (LPARAM)&info ); + if (!IsRectEmpty( &info.rect )) + return info.rect.right - info.rect.left; + } + + return pGetSystemMetrics ? pGetSystemMetrics( SM_CXSCREEN ) : 640; + } + case VERTRES: + { + DC *dc = get_nulldrv_dc( dev ); + struct monitor_info info; + + if (dc->display[0] && pEnumDisplayMonitors && pGetMonitorInfoW) + { + info.name = dc->display; + SetRectEmpty( &info.rect ); + pEnumDisplayMonitors( NULL, NULL, monitor_enum_proc, (LPARAM)&info ); + if (!IsRectEmpty( &info.rect )) + return info.rect.bottom - info.rect.top; + } + + return pGetSystemMetrics ? pGetSystemMetrics( SM_CYSCREEN ) : 480; + } case BITSPIXEL: return 32; case PLANES: return 1; case NUMBRUSHES: return -1; diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 8d917a795c0..2bf16e8eaf8 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -84,6 +84,7 @@ typedef struct tagDC int pixel_format; /* pixel format (for memory DCs) */ UINT aa_flags; /* anti-aliasing flags to pass to GetGlyphOutline for current font */ FLOAT miterLimit; + WCHAR display[CCHDEVICENAME]; /* Display name when created for a specific display device */
int flags; DWORD layout; @@ -487,6 +488,9 @@ typedef struct
#define WMFC_MAGIC 0x43464d57
+/* driver.c */ +extern BOOL is_display_device( LPCWSTR name ) DECLSPEC_HIDDEN; + /* path.c */
extern void free_gdi_path( struct gdi_path *path ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/tests/dc.c b/dlls/gdi32/tests/dc.c index aa6917d432d..963b62f4e15 100644 --- a/dlls/gdi32/tests/dc.c +++ b/dlls/gdi32/tests/dc.c @@ -1769,11 +1769,9 @@ static void test_multi_monitor_dc(void) ok(!!hdc, "CreateDCA %s failed.\n", dd.DeviceName);
value = GetDeviceCaps(hdc, HORZRES); - todo_wine_if(dm.dmPelsWidth != GetSystemMetrics(SM_CXSCREEN)) ok(value == dm.dmPelsWidth, "Expected %d, got %d.\n", dm.dmPelsWidth, value);
value = GetDeviceCaps(hdc, VERTRES); - todo_wine_if(dm.dmPelsHeight != GetSystemMetrics(SM_CYSCREEN)) ok(value == dm.dmPelsHeight, "Expected %d, got %d.\n", dm.dmPelsHeight, value);
value = GetDeviceCaps(hdc, DESKTOPHORZRES); @@ -1813,11 +1811,9 @@ static void test_multi_monitor_dc(void) }
value = GetDeviceCaps(hdc, HORZRES); - todo_wine_if(dm2.dmPelsWidth != GetSystemMetrics(SM_CXSCREEN)) ok(value == dm2.dmPelsWidth, "Expected %d, got %d.\n", dm2.dmPelsWidth, value);
value = GetDeviceCaps(hdc, VERTRES); - todo_wine_if(dm2.dmPelsHeight != GetSystemMetrics(SM_CYSCREEN)) ok(value == dm2.dmPelsHeight, "Expected %d, got %d.\n", dm2.dmPelsHeight, value);
value = GetDeviceCaps(hdc, DESKTOPHORZRES);