[PATCH 2/3] gdi32: Report correct HORZRES and VERTRES values for GetDeviceCaps() with DCs on a specific monitor.
Zhiyi Zhang
zzhang at codeweavers.com
Wed Jan 20 02:39:59 CST 2021
Fix DLC Quest uses the primary monitor size to render when in fullscreen mode on non-primary monitors.
Signed-off-by: Zhiyi Zhang <zzhang at 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);
--
2.27.0
More information about the wine-devel
mailing list