Zhiyi Zhang : gdi32: Report correct HORZRES and VERTRES values for GetDeviceCaps() with DCs on a specific monitor.
Alexandre Julliard
julliard at winehq.org
Wed Jan 27 15:35:04 CST 2021
Module: wine
Branch: master
Commit: 2006f76b5fa06b1a3456cb56dd164e3688d480f0
URL: https://source.winehq.org/git/wine.git/?a=commit;h=2006f76b5fa06b1a3456cb56dd164e3688d480f0
Author: Zhiyi Zhang <zzhang at codeweavers.com>
Date: Sun Jan 24 12:14:20 2021 +0800
gdi32: Report correct HORZRES and VERTRES values for GetDeviceCaps() with DCs on a specific monitor.
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>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/gdi32/dc.c | 18 +++++++++++++
dlls/gdi32/driver.c | 64 ++++++++++++++++++++++++++++++++++++++++++---
dlls/gdi32/gdi_private.h | 4 +++
dlls/user32/tests/monitor.c | 4 +--
4 files changed, 85 insertions(+), 5 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/user32/tests/monitor.c b/dlls/user32/tests/monitor.c
index ee435a4faf4..08557867566 100644
--- a/dlls/user32/tests/monitor.c
+++ b/dlls/user32/tests/monitor.c
@@ -2085,7 +2085,7 @@ static void test_display_dc(void)
hdc = CreateDCA(dd.DeviceName, NULL, NULL, NULL);
ok(!!hdc, "CreateDCA %s failed.\n", dd.DeviceName);
- check_display_dc(hdc, &dm, TRUE);
+ check_display_dc(hdc, &dm, FALSE);
/* Tests after mode changes */
memset(&dm2, 0, sizeof(dm2));
@@ -2108,7 +2108,7 @@ static void test_display_dc(void)
continue;
}
- check_display_dc(hdc, &dm2, TRUE);
+ check_display_dc(hdc, &dm2, FALSE);
/* Tests after monitor detach */
if (!(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE))
More information about the wine-cvs
mailing list