uxtheme/tests: Add GetThemePartSize() tests.
Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2d51077a22
commit
069ed533b4
|
@ -20,9 +20,15 @@
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "ntstatus.h"
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
|
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
|
#include "winternl.h"
|
||||||
|
#include "ddk/d3dkmthk.h"
|
||||||
#include "vfwmsgs.h"
|
#include "vfwmsgs.h"
|
||||||
#include "uxtheme.h"
|
#include "uxtheme.h"
|
||||||
|
#include "vsstyle.h"
|
||||||
|
|
||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
#include "wine/test.h"
|
#include "wine/test.h"
|
||||||
|
@ -36,6 +42,14 @@ static HDC (WINAPI *pGetBufferedPaintDC)(HPAINTBUFFER);
|
||||||
static HDC (WINAPI *pGetBufferedPaintTargetDC)(HPAINTBUFFER);
|
static HDC (WINAPI *pGetBufferedPaintTargetDC)(HPAINTBUFFER);
|
||||||
static HRESULT (WINAPI *pGetBufferedPaintTargetRect)(HPAINTBUFFER, RECT *);
|
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 */
|
/* For message tests */
|
||||||
enum seq_index
|
enum seq_index
|
||||||
{
|
{
|
||||||
|
@ -48,20 +62,33 @@ static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
|
||||||
|
|
||||||
static void init_funcs(void)
|
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)
|
#define GET_PROC(module, func) \
|
||||||
UXTHEME_GET_PROC(BeginBufferedPaint);
|
p##func = (void *)GetProcAddress(module, #func); \
|
||||||
UXTHEME_GET_PROC(BufferedPaintClear);
|
if (!p##func) \
|
||||||
UXTHEME_GET_PROC(EndBufferedPaint);
|
trace("GetProcAddress(%s, %s) failed.\n", #module, #func);
|
||||||
UXTHEME_GET_PROC(GetBufferedPaintBits);
|
|
||||||
UXTHEME_GET_PROC(GetBufferedPaintDC);
|
|
||||||
UXTHEME_GET_PROC(GetBufferedPaintTargetDC);
|
|
||||||
UXTHEME_GET_PROC(GetBufferedPaintTargetRect);
|
|
||||||
UXTHEME_GET_PROC(BufferedPaintClear);
|
|
||||||
|
|
||||||
UXTHEME_GET_PROC(OpenThemeDataEx);
|
GET_PROC(uxtheme, BeginBufferedPaint)
|
||||||
#undef UXTHEME_GET_PROC
|
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 */
|
/* 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 LRESULT WINAPI TestSetWindowThemeParentProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
static LONG defwndproc_counter;
|
static LONG defwndproc_counter;
|
||||||
|
@ -827,6 +961,115 @@ todo_wine
|
||||||
DeleteDC(target);
|
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)
|
START_TEST(system)
|
||||||
{
|
{
|
||||||
init_funcs();
|
init_funcs();
|
||||||
|
@ -842,6 +1085,7 @@ START_TEST(system)
|
||||||
test_OpenThemeData();
|
test_OpenThemeData();
|
||||||
test_OpenThemeDataEx();
|
test_OpenThemeDataEx();
|
||||||
test_GetCurrentThemeName();
|
test_GetCurrentThemeName();
|
||||||
|
test_GetThemePartSize();
|
||||||
test_CloseThemeData();
|
test_CloseThemeData();
|
||||||
test_buffered_paint();
|
test_buffered_paint();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue