user32: Store the window DPI in the server.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2018-05-17 13:56:26 +02:00
parent e98963f2ab
commit f7b5b8975c
9 changed files with 129 additions and 41 deletions

View File

@ -3173,6 +3173,15 @@ BOOL WINAPI EnumDisplaySettingsExW(LPCWSTR lpszDeviceName, DWORD iModeNum,
static DPI_AWARENESS dpi_awareness;
/**********************************************************************
* get_monitor_dpi
*/
UINT get_monitor_dpi( HWND hwnd )
{
/* FIXME: use the monitor DPI instead */
return get_system_dpi();
}
/**********************************************************************
* SetProcessDpiAwarenessContext (USER32.@)
*/
@ -3308,28 +3317,6 @@ BOOL WINAPI GetDpiForMonitorInternal( HMONITOR monitor, UINT type, UINT *x, UINT
return TRUE;
}
/***********************************************************************
* GetDpiForWindow (USER32.@)
*/
UINT WINAPI GetDpiForWindow( HWND hwnd )
{
UINT dpi;
switch (GetAwarenessFromDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd )))
{
case DPI_AWARENESS_UNAWARE:
return USER_DEFAULT_SCREEN_DPI;
case DPI_AWARENESS_SYSTEM_AWARE:
return get_system_dpi();
case DPI_AWARENESS_PER_MONITOR_AWARE:
GetDpiForMonitorInternal( MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY ),
0 /* MDT_EFFECTIVE_DPI */, &dpi, NULL );
return dpi;
default:
return 0;
}
}
/**********************************************************************
* GetThreadDpiAwarenessContext (USER32.@)
*/

View File

@ -3526,6 +3526,7 @@ static void test_dpi_window(void)
DPI_AWARENESS_CONTEXT context, orig;
DPI_AWARENESS awareness;
ULONG_PTR i, j;
UINT dpi;
HWND hwnd, child, ret;
MSG msg = { 0, WM_USER + 1, 0, 0 };
@ -3544,6 +3545,9 @@ static void test_dpi_window(void)
context = pGetWindowDpiAwarenessContext( hwnd );
awareness = pGetAwarenessFromDpiAwarenessContext( context );
ok( awareness == i, "%lu: wrong awareness %u\n", i, awareness );
dpi = pGetDpiForWindow( hwnd );
ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
"%lu: got %u / %u\n", i, dpi, real_dpi );
msg.hwnd = hwnd;
for (j = DPI_AWARENESS_UNAWARE; j <= DPI_AWARENESS_PER_MONITOR_AWARE; j++)
{
@ -3556,22 +3560,34 @@ static void test_dpi_window(void)
context = pGetWindowDpiAwarenessContext( child );
awareness = pGetAwarenessFromDpiAwarenessContext( context );
ok( awareness == i, "%lu/%lu: wrong awareness %u\n", i, j, awareness );
dpi = pGetDpiForWindow( child );
ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
"%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
ret = SetParent( child, NULL );
ok( ret != 0, "SetParent failed err %u\n", GetLastError() );
context = pGetWindowDpiAwarenessContext( child );
awareness = pGetAwarenessFromDpiAwarenessContext( context );
ok( awareness == i, "%lu/%lu: wrong awareness %u\n", i, j, awareness );
dpi = pGetDpiForWindow( child );
ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
"%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
DestroyWindow( child );
child = CreateWindowA( "DpiTestClass", "Test",
WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
context = pGetWindowDpiAwarenessContext( child );
awareness = pGetAwarenessFromDpiAwarenessContext( context );
ok( awareness == j, "%lu/%lu: wrong awareness %u\n", i, j, awareness );
dpi = pGetDpiForWindow( child );
ok( dpi == (j == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
"%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
ret = SetParent( child, hwnd );
ok( ret != 0, "SetParent failed err %u\n", GetLastError() );
context = pGetWindowDpiAwarenessContext( child );
awareness = pGetAwarenessFromDpiAwarenessContext( context );
ok( awareness == i, "%lu/%lu: wrong awareness %u\n", i, j, awareness );
dpi = pGetDpiForWindow( child );
ok( dpi == (i == DPI_AWARENESS_UNAWARE ? USER_DEFAULT_SCREEN_DPI : real_dpi),
"%lu/%lu: got %u / %u\n", i, j, dpi, real_dpi );
DestroyWindow( child );
}
DestroyWindow( hwnd );
@ -3581,17 +3597,26 @@ static void test_dpi_window(void)
context = pGetWindowDpiAwarenessContext( (HWND)0xdeadbeef );
ok( !context, "got %p\n", context );
ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
dpi = pGetDpiForWindow( (HWND)0xdeadbeef );
ok( !dpi, "got %u\n", dpi );
ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_WINDOW_HANDLE,
"wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
context = pGetWindowDpiAwarenessContext( GetDesktopWindow() );
awareness = pGetAwarenessFromDpiAwarenessContext( context );
ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "wrong awareness %u\n", awareness );
dpi = pGetDpiForWindow( GetDesktopWindow() );
ok( dpi == real_dpi, "got %u / %u\n", dpi, real_dpi );
pSetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_UNAWARE );
SetLastError( 0xdeadbeef );
context = pGetWindowDpiAwarenessContext( GetDesktopWindow() );
awareness = pGetAwarenessFromDpiAwarenessContext( context );
ok( awareness == DPI_AWARENESS_PER_MONITOR_AWARE, "wrong awareness %u\n", awareness );
dpi = pGetDpiForWindow( GetDesktopWindow() );
ok( dpi == real_dpi, "got %u / %u\n", dpi, real_dpi );
pSetThreadDpiAwarenessContext( orig );
}

View File

@ -201,12 +201,14 @@ static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
struct tagCLASS *class = NULL;
int extra_bytes = 0;
DPI_AWARENESS awareness = GetAwarenessFromDpiAwarenessContext( GetThreadDpiAwarenessContext() );
UINT dpi = 0;
SERVER_START_REQ( create_window )
{
req->parent = wine_server_user_handle( parent );
req->owner = wine_server_user_handle( owner );
req->instance = wine_server_client_ptr( instance );
req->dpi = GetDpiForSystem();
req->awareness = awareness;
if (!(req->atom = get_int_atom_value( name )) && name)
wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
@ -216,6 +218,7 @@ static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
full_parent = wine_server_ptr_handle( reply->parent );
full_owner = wine_server_ptr_handle( reply->owner );
extra_bytes = reply->extra;
dpi = reply->dpi;
awareness = reply->awareness;
class = wine_server_get_ptr( reply->class_ptr );
}
@ -269,6 +272,7 @@ static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
win->class = class;
win->winproc = get_class_winproc( class );
win->cbWndExtra = extra_bytes;
win->dpi = dpi;
win->dpi_awareness = awareness;
InterlockedExchangePointer( &user_handles[index], win );
if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
@ -2217,6 +2221,39 @@ DPI_AWARENESS_CONTEXT WINAPI GetWindowDpiAwarenessContext( HWND hwnd )
}
/***********************************************************************
* GetDpiForWindow (USER32.@)
*/
UINT WINAPI GetDpiForWindow( HWND hwnd )
{
WND *win;
UINT ret = 0;
if (!(win = WIN_GetPtr( hwnd )))
{
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
return 0;
}
if (win == WND_DESKTOP) return get_monitor_dpi( GetDesktopWindow() );
if (win != WND_OTHER_PROCESS)
{
ret = win->dpi;
if (!ret) ret = get_monitor_dpi( hwnd );
WIN_ReleasePtr( win );
}
else
{
SERVER_START_REQ( get_window_info )
{
req->handle = wine_server_user_handle( hwnd );
if (!wine_server_call_err( req )) ret = reply->dpi;
}
SERVER_END_REQ;
}
return ret;
}
/**********************************************************************
* WIN_GetWindowLong
*
@ -3083,6 +3120,7 @@ HWND WINAPI SetParent( HWND hwnd, HWND parent )
{
old_parent = wine_server_ptr_handle( reply->old_parent );
wndPtr->parent = parent = wine_server_ptr_handle( reply->full_parent );
wndPtr->dpi = reply->dpi;
wndPtr->dpi_awareness = reply->awareness;
}

View File

@ -61,6 +61,7 @@ typedef struct tagWND
HICON hIcon; /* window's icon */
HICON hIconSmall; /* window's small icon */
HICON hIconSmall2; /* window's secondary small icon, derived from hIcon */
UINT dpi; /* window DPI */
DPI_AWARENESS dpi_awareness; /* DPI awareness */
struct window_surface *surface; /* Window surface if any */
struct tagDIALOGINFO *dlgInfo;/* Dialog additional info (dialogs only) */
@ -128,6 +129,7 @@ extern void WINPOS_ActivateOtherWindow( HWND hwnd ) DECLSPEC_HIDDEN;
extern UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) DECLSPEC_HIDDEN;
extern void WINPOS_SysCommandSizeMove( HWND hwnd, WPARAM wParam ) DECLSPEC_HIDDEN;
extern UINT get_monitor_dpi( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
const RECT *window_rect, const RECT *client_rect,
const RECT *valid_rects ) DECLSPEC_HIDDEN;

View File

@ -3443,9 +3443,9 @@ struct create_window_request
user_handle_t owner;
atom_t atom;
mod_handle_t instance;
int dpi;
int awareness;
/* VARARG(class,unicode_str); */
char __pad_36[4];
};
struct create_window_reply
{
@ -3455,8 +3455,8 @@ struct create_window_reply
user_handle_t owner;
int extra;
client_ptr_t class_ptr;
int dpi;
int awareness;
char __pad_36[4];
};
@ -3517,8 +3517,8 @@ struct get_window_info_reply
thread_id_t tid;
atom_t atom;
int is_unicode;
int dpi;
int awareness;
char __pad_36[4];
};
@ -3571,8 +3571,8 @@ struct set_parent_reply
struct reply_header __header;
user_handle_t old_parent;
user_handle_t full_parent;
int dpi;
int awareness;
char __pad_20[4];
};
@ -6509,6 +6509,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
};
#define SERVER_PROTOCOL_VERSION 550
#define SERVER_PROTOCOL_VERSION 551
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -2476,6 +2476,7 @@ enum message_type
user_handle_t owner; /* owner window */
atom_t atom; /* class atom */
mod_handle_t instance; /* module instance */
int dpi; /* system DPI */
int awareness; /* thread DPI awareness */
VARARG(class,unicode_str); /* class name */
@REPLY
@ -2484,6 +2485,7 @@ enum message_type
user_handle_t owner; /* full handle of owner */
int extra; /* number of extra bytes */
client_ptr_t class_ptr; /* pointer to class in client address space */
int dpi; /* window DPI if not per-monitor aware */
int awareness; /* window DPI awareness */
@END
@ -2523,6 +2525,7 @@ enum message_type
thread_id_t tid; /* thread owning the window */
atom_t atom; /* class atom */
int is_unicode; /* ANSI or unicode */
int dpi; /* window DPI */
int awareness; /* DPI awareness */
@END
@ -2564,6 +2567,7 @@ enum message_type
@REPLY
user_handle_t old_parent; /* old parent window */
user_handle_t full_parent; /* full handle of new parent */
int dpi; /* new window DPI if not per-monitor aware */
int awareness; /* new DPI awareness */
@END

View File

@ -1661,14 +1661,16 @@ C_ASSERT( FIELD_OFFSET(struct create_window_request, parent) == 12 );
C_ASSERT( FIELD_OFFSET(struct create_window_request, owner) == 16 );
C_ASSERT( FIELD_OFFSET(struct create_window_request, atom) == 20 );
C_ASSERT( FIELD_OFFSET(struct create_window_request, instance) == 24 );
C_ASSERT( FIELD_OFFSET(struct create_window_request, awareness) == 32 );
C_ASSERT( FIELD_OFFSET(struct create_window_request, dpi) == 32 );
C_ASSERT( FIELD_OFFSET(struct create_window_request, awareness) == 36 );
C_ASSERT( sizeof(struct create_window_request) == 40 );
C_ASSERT( FIELD_OFFSET(struct create_window_reply, handle) == 8 );
C_ASSERT( FIELD_OFFSET(struct create_window_reply, parent) == 12 );
C_ASSERT( FIELD_OFFSET(struct create_window_reply, owner) == 16 );
C_ASSERT( FIELD_OFFSET(struct create_window_reply, extra) == 20 );
C_ASSERT( FIELD_OFFSET(struct create_window_reply, class_ptr) == 24 );
C_ASSERT( FIELD_OFFSET(struct create_window_reply, awareness) == 32 );
C_ASSERT( FIELD_OFFSET(struct create_window_reply, dpi) == 32 );
C_ASSERT( FIELD_OFFSET(struct create_window_reply, awareness) == 36 );
C_ASSERT( sizeof(struct create_window_reply) == 40 );
C_ASSERT( FIELD_OFFSET(struct destroy_window_request, handle) == 12 );
C_ASSERT( sizeof(struct destroy_window_request) == 16 );
@ -1691,7 +1693,8 @@ C_ASSERT( FIELD_OFFSET(struct get_window_info_reply, pid) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_window_info_reply, tid) == 20 );
C_ASSERT( FIELD_OFFSET(struct get_window_info_reply, atom) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_window_info_reply, is_unicode) == 28 );
C_ASSERT( FIELD_OFFSET(struct get_window_info_reply, awareness) == 32 );
C_ASSERT( FIELD_OFFSET(struct get_window_info_reply, dpi) == 32 );
C_ASSERT( FIELD_OFFSET(struct get_window_info_reply, awareness) == 36 );
C_ASSERT( sizeof(struct get_window_info_reply) == 40 );
C_ASSERT( FIELD_OFFSET(struct set_window_info_request, flags) == 12 );
C_ASSERT( FIELD_OFFSET(struct set_window_info_request, is_unicode) == 14 );
@ -1717,7 +1720,8 @@ C_ASSERT( FIELD_OFFSET(struct set_parent_request, parent) == 16 );
C_ASSERT( sizeof(struct set_parent_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct set_parent_reply, old_parent) == 8 );
C_ASSERT( FIELD_OFFSET(struct set_parent_reply, full_parent) == 12 );
C_ASSERT( FIELD_OFFSET(struct set_parent_reply, awareness) == 16 );
C_ASSERT( FIELD_OFFSET(struct set_parent_reply, dpi) == 16 );
C_ASSERT( FIELD_OFFSET(struct set_parent_reply, awareness) == 20 );
C_ASSERT( sizeof(struct set_parent_reply) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_window_parents_request, handle) == 12 );
C_ASSERT( sizeof(struct get_window_parents_request) == 16 );

View File

@ -3038,6 +3038,7 @@ static void dump_create_window_request( const struct create_window_request *req
fprintf( stderr, ", owner=%08x", req->owner );
fprintf( stderr, ", atom=%04x", req->atom );
dump_uint64( ", instance=", &req->instance );
fprintf( stderr, ", dpi=%d", req->dpi );
fprintf( stderr, ", awareness=%d", req->awareness );
dump_varargs_unicode_str( ", class=", cur_size );
}
@ -3049,6 +3050,7 @@ static void dump_create_window_reply( const struct create_window_reply *req )
fprintf( stderr, ", owner=%08x", req->owner );
fprintf( stderr, ", extra=%d", req->extra );
dump_uint64( ", class_ptr=", &req->class_ptr );
fprintf( stderr, ", dpi=%d", req->dpi );
fprintf( stderr, ", awareness=%d", req->awareness );
}
@ -3093,6 +3095,7 @@ static void dump_get_window_info_reply( const struct get_window_info_reply *req
fprintf( stderr, ", tid=%04x", req->tid );
fprintf( stderr, ", atom=%04x", req->atom );
fprintf( stderr, ", is_unicode=%d", req->is_unicode );
fprintf( stderr, ", dpi=%d", req->dpi );
fprintf( stderr, ", awareness=%d", req->awareness );
}
@ -3131,6 +3134,7 @@ static void dump_set_parent_reply( const struct set_parent_reply *req )
{
fprintf( stderr, " old_parent=%08x", req->old_parent );
fprintf( stderr, ", full_parent=%08x", req->full_parent );
fprintf( stderr, ", dpi=%d", req->dpi );
fprintf( stderr, ", awareness=%d", req->awareness );
}

View File

@ -83,6 +83,7 @@ struct window
unsigned int color_key; /* color key for a layered window */
unsigned int alpha; /* alpha value for a layered window */
unsigned int layered_flags; /* flags for a layered window */
unsigned int dpi; /* window DPI or 0 if per-monitor aware */
DPI_AWARENESS dpi_awareness; /* DPI awareness mode */
lparam_t user_data; /* user-specific data */
WCHAR *text; /* window caption text */
@ -175,6 +176,14 @@ static inline void update_pixel_format_flags( struct window *win )
win->paint_flags |= PAINT_PIXEL_FORMAT_CHILD;
}
/* get the per-monitor DPI for a window */
static unsigned int get_monitor_dpi( struct window *win )
{
/* FIXME: we return the desktop window DPI for now */
while (!is_desktop_window( win )) win = win->parent;
return win->dpi ? win->dpi : USER_DEFAULT_SCREEN_DPI;
}
/* link a window at the right place in the siblings list */
static void link_window( struct window *win, struct window *previous )
{
@ -250,7 +259,11 @@ static int set_parent_window( struct window *win, struct window *parent )
win->parent = parent;
link_window( win, WINPTR_TOP );
if (!is_desktop_window( parent )) win->dpi_awareness = parent->dpi_awareness;
if (!is_desktop_window( parent ))
{
win->dpi = parent->dpi;
win->dpi_awareness = parent->dpi_awareness;
}
/* if parent belongs to a different thread and the window isn't */
/* top-level, attach the two threads */
@ -432,7 +445,7 @@ void post_desktop_message( struct desktop *desktop, unsigned int message,
/* create a new window structure (note: the window is not linked in the window tree) */
static struct window *create_window( struct window *parent, struct window *owner,
atom_t atom, mod_handle_t instance, DPI_AWARENESS dpi_awareness )
atom_t atom, mod_handle_t instance )
{
static const rectangle_t empty_rect;
int extra_bytes;
@ -469,8 +482,6 @@ static struct window *create_window( struct window *parent, struct window *owner
goto failed;
}
if (parent && !is_desktop_window( parent )) dpi_awareness = parent->dpi_awareness;
if (!(win = mem_alloc( sizeof(*win) + extra_bytes - 1 ))) goto failed;
if (!(win->handle = alloc_user_handle( win, USER_WINDOW ))) goto failed;
@ -490,7 +501,8 @@ static struct window *create_window( struct window *parent, struct window *owner
win->is_unicode = 1;
win->is_linked = 0;
win->is_layered = 0;
win->dpi_awareness = dpi_awareness;
win->dpi_awareness = DPI_AWARENESS_PER_MONITOR_AWARE;
win->dpi = 0;
win->user_data = 0;
win->text = NULL;
win->paint_flags = 0;
@ -1914,12 +1926,24 @@ DECL_HANDLER(create_window)
atom = cls_name.len ? find_global_atom( NULL, &cls_name ) : req->atom;
if (!(win = create_window( parent, owner, atom, req->instance, req->awareness ))) return;
if (!(win = create_window( parent, owner, atom, req->instance ))) return;
if (parent && !is_desktop_window( parent ))
{
win->dpi_awareness = parent->dpi_awareness;
win->dpi = parent->dpi;
}
else if (!parent || req->awareness != DPI_AWARENESS_PER_MONITOR_AWARE)
{
win->dpi_awareness = req->awareness;
win->dpi = req->dpi;
}
reply->handle = win->handle;
reply->parent = win->parent ? win->parent->handle : 0;
reply->owner = win->owner;
reply->extra = win->nb_extra_bytes;
reply->dpi = win->dpi;
reply->awareness = win->dpi_awareness;
reply->class_ptr = get_class_client_ptr( win->class );
}
@ -1941,6 +1965,7 @@ DECL_HANDLER(set_parent)
reply->old_parent = win->parent->handle;
reply->full_parent = parent ? parent->handle : 0;
set_parent_window( win, parent );
reply->dpi = win->dpi;
reply->awareness = win->dpi_awareness;
}
@ -1971,8 +1996,7 @@ DECL_HANDLER(get_desktop_window)
if (!desktop->top_window && force) /* create it */
{
if ((desktop->top_window = create_window( NULL, NULL, DESKTOP_ATOM, 0,
DPI_AWARENESS_PER_MONITOR_AWARE )))
if ((desktop->top_window = create_window( NULL, NULL, DESKTOP_ATOM, 0 )))
{
detach_window_thread( desktop->top_window );
desktop->top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
@ -1984,8 +2008,7 @@ DECL_HANDLER(get_desktop_window)
static const WCHAR messageW[] = {'M','e','s','s','a','g','e'};
static const struct unicode_str name = { messageW, sizeof(messageW) };
atom_t atom = add_global_atom( NULL, &name );
if (atom && (desktop->msg_window = create_window( NULL, NULL, atom, 0,
DPI_AWARENESS_PER_MONITOR_AWARE )))
if (atom && (desktop->msg_window = create_window( NULL, NULL, atom, 0 )))
{
detach_window_thread( desktop->msg_window );
desktop->msg_window->style = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
@ -2038,6 +2061,7 @@ DECL_HANDLER(get_window_info)
reply->last_active = win->handle;
reply->is_unicode = win->is_unicode;
reply->awareness = win->dpi_awareness;
reply->dpi = win->dpi ? win->dpi : get_monitor_dpi( win );
if (get_user_object( win->last_active, USER_WINDOW )) reply->last_active = win->last_active;
if (win->thread)
{