[PATCH 2/7] uxtheme/tests: Add GetThemePartSize() tests.

Zhiyi Zhang zzhang at codeweavers.com
Wed Sep 1 01:37:29 CDT 2021


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/uxtheme/tests/system.c | 268 ++++++++++++++++++++++++++++++++++--
 1 file changed, 256 insertions(+), 12 deletions(-)

diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c
index 7f2e6d04aa4..b3b1afde14e 100644
--- a/dlls/uxtheme/tests/system.c
+++ b/dlls/uxtheme/tests/system.c
@@ -20,9 +20,15 @@
 
 #include <stdarg.h>
 
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+
 #include "windows.h"
+#include "winternl.h"
+#include "ddk/d3dkmthk.h"
 #include "vfwmsgs.h"
 #include "uxtheme.h"
+#include "vsstyle.h"
 
 #include "msg.h"
 #include "wine/test.h"
@@ -36,6 +42,14 @@ static HDC (WINAPI *pGetBufferedPaintDC)(HPAINTBUFFER);
 static HDC (WINAPI *pGetBufferedPaintTargetDC)(HPAINTBUFFER);
 static HRESULT (WINAPI *pGetBufferedPaintTargetRect)(HPAINTBUFFER, RECT *);
 
+static LONG (WINAPI *pDisplayConfigGetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER *);
+static LONG (WINAPI *pDisplayConfigSetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER *);
+static BOOL (WINAPI *pGetDpiForMonitorInternal)(HMONITOR, UINT, UINT *, UINT *);
+static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
+
+static NTSTATUS (WINAPI *pD3DKMTCloseAdapter)(const D3DKMT_CLOSEADAPTER *);
+static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromGdiDisplayName)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *);
+
 /* For message tests */
 enum seq_index
 {
@@ -48,20 +62,33 @@ static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
 
 static void init_funcs(void)
 {
-    HMODULE hUxtheme = GetModuleHandleA("uxtheme.dll");
+    HMODULE user32 = GetModuleHandleA("user32.dll");
+    HMODULE gdi32 = GetModuleHandleA("gdi32.dll");
+    HMODULE uxtheme = GetModuleHandleA("uxtheme.dll");
 
-#define UXTHEME_GET_PROC(func) p ## func = (void*)GetProcAddress(hUxtheme, #func)
-    UXTHEME_GET_PROC(BeginBufferedPaint);
-    UXTHEME_GET_PROC(BufferedPaintClear);
-    UXTHEME_GET_PROC(EndBufferedPaint);
-    UXTHEME_GET_PROC(GetBufferedPaintBits);
-    UXTHEME_GET_PROC(GetBufferedPaintDC);
-    UXTHEME_GET_PROC(GetBufferedPaintTargetDC);
-    UXTHEME_GET_PROC(GetBufferedPaintTargetRect);
-    UXTHEME_GET_PROC(BufferedPaintClear);
+#define GET_PROC(module, func)                       \
+    p##func = (void *)GetProcAddress(module, #func); \
+    if (!p##func)                                    \
+        trace("GetProcAddress(%s, %s) failed.\n", #module, #func);
 
-    UXTHEME_GET_PROC(OpenThemeDataEx);
-#undef UXTHEME_GET_PROC
+    GET_PROC(uxtheme, BeginBufferedPaint)
+    GET_PROC(uxtheme, BufferedPaintClear)
+    GET_PROC(uxtheme, EndBufferedPaint)
+    GET_PROC(uxtheme, GetBufferedPaintBits)
+    GET_PROC(uxtheme, GetBufferedPaintDC)
+    GET_PROC(uxtheme, GetBufferedPaintTargetDC)
+    GET_PROC(uxtheme, GetBufferedPaintTargetRect)
+    GET_PROC(uxtheme, OpenThemeDataEx)
+
+    GET_PROC(user32, DisplayConfigGetDeviceInfo)
+    GET_PROC(user32, DisplayConfigSetDeviceInfo)
+    GET_PROC(user32, GetDpiForMonitorInternal)
+    GET_PROC(user32, SetThreadDpiAwarenessContext)
+
+    GET_PROC(gdi32, D3DKMTCloseAdapter)
+    GET_PROC(gdi32, D3DKMTOpenAdapterFromGdiDisplayName)
+
+#undef GET_PROC
 }
 
 /* Try to make sure pending X events have been processed before continuing */
@@ -82,6 +109,113 @@ static void flush_events(void)
     }
 }
 
+static unsigned int get_primary_monitor_effective_dpi(void)
+{
+    DPI_AWARENESS_CONTEXT old_context;
+    UINT dpi_x = 0, dpi_y = 0;
+    POINT point = {0, 0};
+    HMONITOR monitor;
+
+    if (pSetThreadDpiAwarenessContext && pGetDpiForMonitorInternal)
+    {
+        old_context = pSetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
+        monitor = MonitorFromPoint(point, MONITOR_DEFAULTTOPRIMARY);
+        pGetDpiForMonitorInternal(monitor, 0, &dpi_x, &dpi_y);
+        pSetThreadDpiAwarenessContext(old_context);
+        return dpi_y;
+    }
+
+    return USER_DEFAULT_SCREEN_DPI;
+}
+
+static int get_dpi_scale_index(int dpi)
+{
+    static const int scales[] = {100, 125, 150, 175, 200, 225, 250, 300, 350, 400, 450, 500};
+    int scale, scale_idx;
+
+    scale = dpi * 100 / 96;
+    for (scale_idx = 0; scale_idx < ARRAY_SIZE(scales); ++scale_idx)
+    {
+        if (scales[scale_idx] == scale)
+            return scale_idx;
+    }
+
+    return -1;
+}
+
+static BOOL set_primary_monitor_effective_dpi(unsigned int primary_dpi)
+{
+    D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc;
+    DISPLAYCONFIG_GET_SOURCE_DPI_SCALE get_scale_req;
+    DISPLAYCONFIG_SET_SOURCE_DPI_SCALE set_scale_req;
+    int current_scale_idx, target_scale_idx;
+    D3DKMT_CLOSEADAPTER close_adapter_desc;
+    BOOL ret = FALSE;
+    LONG error;
+
+#define CHECK_FUNC(func)                       \
+    if (!p##func)                              \
+    {                                          \
+        skip("%s() is unavailable.\n", #func); \
+        return FALSE;                          \
+    }
+
+    CHECK_FUNC(D3DKMTCloseAdapter)
+    CHECK_FUNC(D3DKMTOpenAdapterFromGdiDisplayName)
+    CHECK_FUNC(DisplayConfigGetDeviceInfo)
+    CHECK_FUNC(DisplayConfigSetDeviceInfo)
+
+#undef CHECK_FUNC
+
+    lstrcpyW(open_adapter_gdi_desc.DeviceName, L"\\\\.\\DISPLAY1");
+    if (pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc) == STATUS_PROCEDURE_NOT_FOUND)
+    {
+        win_skip("D3DKMTOpenAdapterFromGdiDisplayName() is unavailable.\n");
+        return FALSE;
+    }
+
+    get_scale_req.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_DPI_SCALE;
+    get_scale_req.header.size = sizeof(get_scale_req);
+    get_scale_req.header.adapterId = open_adapter_gdi_desc.AdapterLuid;
+    get_scale_req.header.id = open_adapter_gdi_desc.VidPnSourceId;
+    error = pDisplayConfigGetDeviceInfo(&get_scale_req.header);
+    if (error != NO_ERROR)
+    {
+        skip("DisplayConfigGetDeviceInfo failed, returned %d.\n", error);
+        goto failed;
+    }
+
+    current_scale_idx = get_dpi_scale_index(get_primary_monitor_effective_dpi());
+    if (current_scale_idx == -1)
+    {
+        skip("Failed to find current scale index.\n");
+        goto failed;
+    }
+
+    target_scale_idx = get_dpi_scale_index(primary_dpi);
+    if (target_scale_idx < get_scale_req.minRelativeScaleStep
+        || target_scale_idx > get_scale_req.maxRelativeScaleStep)
+    {
+        skip("DPI %d is not available.\n", primary_dpi);
+        goto failed;
+    }
+
+    set_scale_req.header.type = DISPLAYCONFIG_DEVICE_INFO_SET_SOURCE_DPI_SCALE;
+    set_scale_req.header.size = sizeof(set_scale_req);
+    set_scale_req.header.adapterId = open_adapter_gdi_desc.AdapterLuid;
+    set_scale_req.header.id = open_adapter_gdi_desc.VidPnSourceId;
+    set_scale_req.relativeScaleStep = get_scale_req.curRelativeScaleStep + (target_scale_idx - current_scale_idx);
+    error = pDisplayConfigSetDeviceInfo(&set_scale_req.header);
+    if (error == NO_ERROR)
+        ret = get_primary_monitor_effective_dpi() == primary_dpi;
+    flush_events();
+
+failed:
+    close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
+    pD3DKMTCloseAdapter(&close_adapter_desc);
+    return ret;
+}
+
 static LRESULT WINAPI TestSetWindowThemeParentProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
     static LONG defwndproc_counter;
@@ -827,6 +961,115 @@ todo_wine
     DeleteDC(target);
 }
 
+static void test_GetThemePartSize(void)
+{
+    DPI_AWARENESS_CONTEXT old_context;
+    unsigned int old_dpi, current_dpi;
+    HTHEME htheme = NULL;
+    HWND hwnd = NULL;
+    SIZE size, size2;
+    HRESULT hr;
+    HDC hdc;
+
+    if (!pSetThreadDpiAwarenessContext)
+    {
+        win_skip("SetThreadDpiAwarenessContext is unavailable.\n");
+        return;
+    }
+
+    old_context = pSetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
+    current_dpi = get_primary_monitor_effective_dpi();
+    old_dpi = current_dpi;
+    /* DPI needs to be 50% larger than 96 to avoid the effect of TrueSizeStretchMark */
+    if (current_dpi < 192 && !set_primary_monitor_effective_dpi(192))
+    {
+        skip("Failed to set primary monitor dpi to 192.\n");
+        goto done;
+    }
+
+    hwnd = CreateWindowA("Button", "Test", WS_POPUP, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
+    htheme = OpenThemeData(hwnd, WC_BUTTONW);
+    if (!htheme)
+    {
+        skip("Theming is inactive.\n");
+        goto done;
+    }
+
+    hdc = GetDC(hwnd);
+    hr = GetThemePartSize(htheme, hdc, BP_CHECKBOX, CBS_CHECKEDNORMAL, NULL, TS_DRAW, &size);
+    ok(hr == S_OK, "GetThemePartSize failed, hr %#x.\n", hr);
+    hr = GetThemePartSize(htheme, NULL, BP_CHECKBOX, CBS_CHECKEDNORMAL, NULL, TS_DRAW, &size2);
+    ok(hr == S_OK, "GetThemePartSize failed, hr %#x.\n", hr);
+    todo_wine
+    ok(size2.cx == size.cx && size2.cy == size.cy, "Expected size %dx%d, got %dx%d.\n",
+       size.cx, size.cy, size2.cx, size2.cy);
+    ReleaseDC(hwnd, hdc);
+
+    /* Test that theme part size doesn't change even if DPI is changed */
+    if (!set_primary_monitor_effective_dpi(96))
+    {
+        skip("Failed to set primary monitor dpi to 96.\n");
+        goto done;
+    }
+
+    hdc = GetDC(hwnd);
+    hr = GetThemePartSize(htheme, hdc, BP_CHECKBOX, CBS_CHECKEDNORMAL, NULL, TS_DRAW, &size2);
+    ok(hr == S_OK, "GetThemePartSize failed, hr %#x.\n", hr);
+    ok(size2.cx == size.cx && size2.cy == size.cy, "Expected size %dx%d, got %dx%d.\n", size.cx,
+       size.cy, size2.cx, size2.cy);
+    hr = GetThemePartSize(htheme, NULL, BP_CHECKBOX, CBS_CHECKEDNORMAL, NULL, TS_DRAW, &size2);
+    ok(hr == S_OK, "GetThemePartSize failed, hr %#x.\n", hr);
+    ok(size2.cx == size.cx && size2.cy == size.cy, "Expected size %dx%d, got %dx%d.\n", size.cx,
+       size.cy, size2.cx, size2.cy);
+
+    /* Test that theme part size changes after DPI is changed and theme handle is reopened.
+     * If DPI awareness context is not DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2, theme part size
+     * still doesn't change, even after the theme handle is reopened. */
+    CloseThemeData(htheme);
+    htheme = OpenThemeData(hwnd, WC_BUTTONW);
+
+    hr = GetThemePartSize(htheme, hdc, BP_CHECKBOX, CBS_CHECKEDNORMAL, NULL, TS_DRAW, &size2);
+    ok(hr == S_OK, "GetThemePartSize failed, hr %#x.\n", hr);
+    ok(size2.cx != size.cx || size2.cy != size.cy, "Expected size not equal to %dx%d.\n", size.cx,
+       size.cy);
+    hr = GetThemePartSize(htheme, NULL, BP_CHECKBOX, CBS_CHECKEDNORMAL, NULL, TS_DRAW, &size2);
+    ok(hr == S_OK, "GetThemePartSize failed, hr %#x.\n", hr);
+    ok(size2.cx != size.cx || size2.cy != size.cy, "Expected size not equal to %dx%d.\n", size.cx,
+       size.cy);
+    ReleaseDC(hwnd, hdc);
+
+    /* Test that OpenThemeData() without a window will assume the DPI is 96 */
+    if (!set_primary_monitor_effective_dpi(192))
+    {
+        skip("Failed to set primary monitor dpi to 192.\n");
+        goto done;
+    }
+
+    CloseThemeData(htheme);
+    htheme = OpenThemeData(NULL, WC_BUTTONW);
+    size = size2;
+
+    hdc = GetDC(hwnd);
+    hr = GetThemePartSize(htheme, hdc, BP_CHECKBOX, CBS_CHECKEDNORMAL, NULL, TS_DRAW, &size2);
+    ok(hr == S_OK, "GetThemePartSize failed, hr %#x.\n", hr);
+    ok(size2.cx == size.cx && size2.cy == size.cy, "Expected size %dx%d, got %dx%d.\n", size.cx,
+       size.cy, size2.cx, size2.cy);
+    hr = GetThemePartSize(htheme, NULL, BP_CHECKBOX, CBS_CHECKEDNORMAL, NULL, TS_DRAW, &size2);
+    ok(hr == S_OK, "GetThemePartSize failed, hr %#x.\n", hr);
+    ok(size2.cx == size.cx && size2.cy == size.cy, "Expected size %dx%d, got %dx%d.\n", size.cx,
+       size.cy, size2.cx, size2.cy);
+    ReleaseDC(hwnd, hdc);
+
+done:
+    if (hwnd)
+        DestroyWindow(hwnd);
+    if (htheme)
+        CloseThemeData(htheme);
+    if (get_primary_monitor_effective_dpi() != old_dpi)
+        set_primary_monitor_effective_dpi(old_dpi);
+    pSetThreadDpiAwarenessContext(old_context);
+}
+
 START_TEST(system)
 {
     init_funcs();
@@ -842,6 +1085,7 @@ START_TEST(system)
     test_OpenThemeData();
     test_OpenThemeDataEx();
     test_GetCurrentThemeName();
+    test_GetThemePartSize();
     test_CloseThemeData();
     test_buffered_paint();
 }
-- 
2.30.2




More information about the wine-devel mailing list