user32/tests: Add DisplayConfigSetDeviceInfo() tests.
Test that DisplayConfigSetDeviceInfo() can be used for getting and setting display DPI. Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
20dc5f378c
commit
2d51077a22
|
@ -19,34 +19,49 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
|
||||
#include "wine/test.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
#include "winreg.h"
|
||||
#include "winternl.h"
|
||||
#include "ddk/d3dkmthk.h"
|
||||
#include "wine/heap.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static HMODULE hdll;
|
||||
static LONG (WINAPI *pGetDisplayConfigBufferSizes)(UINT32,UINT32*,UINT32*);
|
||||
static BOOL (WINAPI *pGetDpiForMonitorInternal)(HMONITOR,UINT,UINT*,UINT*);
|
||||
static LONG (WINAPI *pQueryDisplayConfig)(UINT32,UINT32*,DISPLAYCONFIG_PATH_INFO*,UINT32*,
|
||||
DISPLAYCONFIG_MODE_INFO*,DISPLAYCONFIG_TOPOLOGY_ID*);
|
||||
static LONG (WINAPI *pDisplayConfigGetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER*);
|
||||
static LONG (WINAPI *pDisplayConfigSetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER*);
|
||||
static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
|
||||
|
||||
static NTSTATUS (WINAPI *pD3DKMTCloseAdapter)(const D3DKMT_CLOSEADAPTER*);
|
||||
static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromGdiDisplayName)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME*);
|
||||
|
||||
static void init_function_pointers(void)
|
||||
{
|
||||
hdll = GetModuleHandleA("user32.dll");
|
||||
HMODULE user32 = GetModuleHandleA("user32.dll");
|
||||
HMODULE gdi32 = GetModuleHandleA("gdi32.dll");
|
||||
|
||||
#define GET_PROC(func) \
|
||||
p ## func = (void*)GetProcAddress(hdll, #func); \
|
||||
if(!p ## func) \
|
||||
trace("GetProcAddress(%s) failed\n", #func);
|
||||
#define GET_PROC(module, func) \
|
||||
p##func = (void *)GetProcAddress(module, #func); \
|
||||
if (!p##func) \
|
||||
trace("GetProcAddress(%s, %s) failed.\n", #module, #func);
|
||||
|
||||
GET_PROC(GetDisplayConfigBufferSizes)
|
||||
GET_PROC(QueryDisplayConfig)
|
||||
GET_PROC(DisplayConfigGetDeviceInfo)
|
||||
GET_PROC(SetThreadDpiAwarenessContext)
|
||||
GET_PROC(user32, GetDisplayConfigBufferSizes)
|
||||
GET_PROC(user32, GetDpiForMonitorInternal)
|
||||
GET_PROC(user32, QueryDisplayConfig)
|
||||
GET_PROC(user32, DisplayConfigGetDeviceInfo)
|
||||
GET_PROC(user32, DisplayConfigSetDeviceInfo)
|
||||
GET_PROC(user32, SetThreadDpiAwarenessContext)
|
||||
|
||||
GET_PROC(gdi32, D3DKMTCloseAdapter)
|
||||
GET_PROC(gdi32, D3DKMTOpenAdapterFromGdiDisplayName)
|
||||
|
||||
#undef GET_PROC
|
||||
}
|
||||
|
@ -68,6 +83,23 @@ static void flush_events(void)
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned int get_primary_dpi(void)
|
||||
{
|
||||
DPI_AWARENESS_CONTEXT old_context;
|
||||
UINT dpi_x = 0, dpi_y = 0;
|
||||
POINT point = {0, 0};
|
||||
HMONITOR monitor;
|
||||
|
||||
if (!pSetThreadDpiAwarenessContext || !pGetDpiForMonitorInternal)
|
||||
return 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int get_bitmap_stride(int width, int bpp)
|
||||
{
|
||||
return ((width * bpp + 15) >> 3) & ~1;
|
||||
|
@ -1959,6 +1991,85 @@ static void test_display_config(void)
|
|||
test_DisplayConfigGetDeviceInfo();
|
||||
}
|
||||
|
||||
static void test_DisplayConfigSetDeviceInfo(void)
|
||||
{
|
||||
static const unsigned int scales[] = {100, 125, 150, 175, 200, 225, 250, 300, 350, 400, 450, 500};
|
||||
int current_scale, current_scale_idx, recommended_scale_idx, step, dpi, old_dpi;
|
||||
D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc;
|
||||
DISPLAYCONFIG_GET_SOURCE_DPI_SCALE get_scale_req;
|
||||
DISPLAYCONFIG_SET_SOURCE_DPI_SCALE set_scale_req;
|
||||
D3DKMT_CLOSEADAPTER close_adapter_desc;
|
||||
NTSTATUS status;
|
||||
LONG ret;
|
||||
|
||||
#define CHECK_FUNC(func) \
|
||||
if (!p##func) \
|
||||
{ \
|
||||
skip("%s() is unavailable.\n", #func); \
|
||||
return; \
|
||||
}
|
||||
|
||||
CHECK_FUNC(D3DKMTCloseAdapter)
|
||||
CHECK_FUNC(D3DKMTOpenAdapterFromGdiDisplayName)
|
||||
CHECK_FUNC(DisplayConfigGetDeviceInfo)
|
||||
CHECK_FUNC(DisplayConfigSetDeviceInfo)
|
||||
CHECK_FUNC(GetDpiForMonitorInternal)
|
||||
CHECK_FUNC(SetThreadDpiAwarenessContext)
|
||||
|
||||
#undef CHECK_FUNC
|
||||
|
||||
lstrcpyW(open_adapter_gdi_desc.DeviceName, L"\\\\.\\DISPLAY1");
|
||||
status = pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc);
|
||||
ok(status == STATUS_SUCCESS, "D3DKMTOpenAdapterFromGdiDisplayName failed, status %#x.\n", status);
|
||||
|
||||
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;
|
||||
ret = pDisplayConfigGetDeviceInfo(&get_scale_req.header);
|
||||
if (ret != NO_ERROR)
|
||||
{
|
||||
skip("DisplayConfigGetDeviceInfo failed, returned %d.\n", ret);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
dpi = get_primary_dpi();
|
||||
old_dpi = dpi;
|
||||
current_scale = dpi * 100 / 96;
|
||||
for (current_scale_idx = 0; current_scale_idx < ARRAY_SIZE(scales); ++current_scale_idx)
|
||||
{
|
||||
if (scales[current_scale_idx] == current_scale)
|
||||
break;
|
||||
}
|
||||
ok(scales[current_scale_idx] == current_scale, "Failed to find current scale.\n");
|
||||
recommended_scale_idx = current_scale_idx - get_scale_req.curRelativeScaleStep;
|
||||
|
||||
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;
|
||||
for (step = get_scale_req.minRelativeScaleStep; step <= get_scale_req.maxRelativeScaleStep; ++step)
|
||||
{
|
||||
set_scale_req.relativeScaleStep = step;
|
||||
ret = pDisplayConfigSetDeviceInfo(&set_scale_req.header);
|
||||
ok(ret == NO_ERROR, "DisplayConfigSetDeviceInfo failed, returned %d.\n", ret);
|
||||
|
||||
dpi = scales[step + recommended_scale_idx] * 96 / 100;
|
||||
ok(dpi == get_primary_dpi(), "Expected %d, got %d.\n", get_primary_dpi(), dpi);
|
||||
}
|
||||
|
||||
/* Restore to the original scale */
|
||||
set_scale_req.relativeScaleStep = get_scale_req.curRelativeScaleStep;
|
||||
ret = pDisplayConfigSetDeviceInfo(&set_scale_req.header);
|
||||
ok(ret == NO_ERROR, "DisplayConfigSetDeviceInfo failed, returned %d.\n", ret);
|
||||
ok(old_dpi == get_primary_dpi(), "Expected %d, got %d.\n", get_primary_dpi(), old_dpi);
|
||||
|
||||
failed:
|
||||
close_adapter_desc.hAdapter = open_adapter_gdi_desc.hAdapter;
|
||||
status = pD3DKMTCloseAdapter(&close_adapter_desc);
|
||||
ok(status == STATUS_SUCCESS, "Got unexpected return code %#x.\n", status);
|
||||
}
|
||||
|
||||
static BOOL CALLBACK test_handle_proc(HMONITOR full_monitor, HDC hdc, LPRECT rect, LPARAM lparam)
|
||||
{
|
||||
MONITORINFO monitor_info = {sizeof(monitor_info)};
|
||||
|
@ -2283,6 +2394,7 @@ START_TEST(monitor)
|
|||
init_function_pointers();
|
||||
test_enumdisplaydevices();
|
||||
test_ChangeDisplaySettingsEx();
|
||||
test_DisplayConfigSetDeviceInfo();
|
||||
test_EnumDisplayMonitors();
|
||||
test_monitors();
|
||||
test_work_area();
|
||||
|
|
|
@ -3286,18 +3286,20 @@ typedef struct _RGNDATA {
|
|||
typedef BOOL (CALLBACK *ABORTPROC)(HDC, INT);
|
||||
|
||||
typedef enum {
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION = 7,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION = 8,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO = 9,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE = 10,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL = 11,
|
||||
DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xffffffff
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_SOURCE_DPI_SCALE = (int)-4,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_DPI_SCALE = (int)-3,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = (int)1,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = (int)2,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = (int)3,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = (int)4,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = (int)5,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = (int)6,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION = (int)7,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION = (int)8,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO = (int)9,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE = (int)10,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL = (int)11,
|
||||
DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = (int)0xffffffff
|
||||
} DISPLAYCONFIG_DEVICE_INFO_TYPE;
|
||||
|
||||
typedef struct DISPLAYCONFIG_DEVICE_INFO_HEADER {
|
||||
|
@ -3638,6 +3640,31 @@ typedef struct DISPLAYCONFIG_SDR_WHITE_LEVEL {
|
|||
ULONG SDRWhiteLevel;
|
||||
} DISPLAYCONFIG_SDR_WHITE_LEVEL;
|
||||
|
||||
/* Scale steps are relative to the recommended scale. For example:
|
||||
* Scale : 100% 125% 150% 175% 200% 225% 250% 300% 350% 400% 450% 500%
|
||||
* DPI : 96 120 144 168 192 216 240 288 336 384 432 480
|
||||
* ^ ^ ^ ^
|
||||
* | | Recommended scale, step is 0. |
|
||||
* | Current scale, step is -2. Max scale step is 6.
|
||||
* Minimum scale, step is -4.
|
||||
*
|
||||
* The scale values can be found in the display settings drop-down. The algorithm to calculate the
|
||||
* recommended scale is unclear.
|
||||
*/
|
||||
typedef struct DISPLAYCONFIG_GET_SOURCE_DPI_SCALE
|
||||
{
|
||||
DISPLAYCONFIG_DEVICE_INFO_HEADER header;
|
||||
int minRelativeScaleStep; /* Minimum scale step relative to the recommended scale */
|
||||
int curRelativeScaleStep; /* Current scale step relative to the recommended scale */
|
||||
int maxRelativeScaleStep; /* Maximum scale step relative to the recommended scale */
|
||||
} DISPLAYCONFIG_GET_SOURCE_DPI_SCALE;
|
||||
|
||||
typedef struct DISPLAYCONFIG_SET_SOURCE_DPI_SCALE
|
||||
{
|
||||
DISPLAYCONFIG_DEVICE_INFO_HEADER header;
|
||||
int relativeScaleStep; /* Target scale step relative to the recommended scale */
|
||||
} DISPLAYCONFIG_SET_SOURCE_DPI_SCALE;
|
||||
|
||||
#define DISPLAYCONFIG_PATH_MODE_IDX_INVALID 0xffffffff
|
||||
#define DISPLAYCONFIG_PATH_TARGET_MODE_IDX_INVALID 0xffff
|
||||
#define DISPLAYCONFIG_PATH_DESKTOP_IMAGE_IDX_INVALID 0xffff
|
||||
|
|
Loading…
Reference in New Issue