From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/sysparams.c | 40 ++++-------------------------------- dlls/win32u/win32u_private.h | 5 +++++ dlls/win32u/window.c | 28 +++++++++++++++++++++---- server/protocol.def | 6 ++++-- server/window.c | 37 +++++++++++++++++++++++---------- 5 files changed, 63 insertions(+), 53 deletions(-) diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index e3a83d484dd..af73a6e65f8 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2465,14 +2465,18 @@ static void set_winstation_monitors( BOOL increment ) if (!(count = list_count( &monitors ))) return; if (!(info = infos = calloc( count, sizeof(*infos) ))) return; + TRACE( "increment %u\n", increment ); LIST_FOR_EACH_ENTRY( monitor, &monitors, struct monitor, entry ) { if (is_monitor_primary( monitor )) info->flags |= MONITOR_FLAG_PRIMARY; if (!is_monitor_active( monitor )) info->flags |= MONITOR_FLAG_INACTIVE; if (monitor->is_clone) info->flags |= MONITOR_FLAG_CLONE; info->dpi = monitor_get_dpi( monitor, MDT_EFFECTIVE_DPI, &x, &y ); + info->raw_dpi = monitor_get_dpi( monitor, MDT_RAW_DPI, &x, &y ); info->virt = wine_server_rectangle( monitor_get_rect( monitor, no_dpi, MDT_EFFECTIVE_DPI ) ); info->raw = wine_server_rectangle( monitor_get_rect( monitor, no_dpi, MDT_RAW_DPI ) ); + TRACE( " flags %#x virt %s dpi %s raw %s raw_dpi %s\n", info->flags, wine_dbgstr_rect( (RECT *)&info->virt ), + debugstr_ratio( info->dpi ), wine_dbgstr_rect( (RECT *)&info->raw ), debugstr_ratio( info->raw_dpi ) ); info++; } @@ -3140,42 +3144,6 @@ static struct ratio get_monitor_dpi( HMONITOR handle, UINT type, struct ratio *x return dpi; } -/********************************************************************** - * get_win_monitor_dpi - */ -struct ratio get_win_monitor_dpi( HWND hwnd, struct ratio *raw_dpi ) -{ - struct ratio dpi = {NTUSER_DPI_CONTEXT_GET_DPI( get_window_dpi_awareness_context( hwnd ) ), 1}; - HWND parent = get_parent( hwnd ); - RECT rect = {0}; - WND *win; - - if (!(win = get_win_ptr( hwnd ))) - { - RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); - return no_dpi; - } - - if (win == WND_DESKTOP) return monitor_dpi_from_rect( rect, get_thread_dpi(), raw_dpi ); - if (win == WND_OTHER_PROCESS) - { - if (!get_window_rect( hwnd, &rect, dpi )) return no_dpi; - } - /* avoid recursive calls from get_window_rects for the process windows */ - else if ((parent = win->parent) && parent != get_desktop_window()) - { - release_win_ptr( win ); - return get_win_monitor_dpi( parent, raw_dpi ); - } - else - { - rect = is_iconic( hwnd ) ? win->normal_rect : win->rects.window; - release_win_ptr( win ); - } - - return monitor_dpi_from_rect( rect, dpi, raw_dpi ); -} - /* keep in sync with user32 */ static BOOL is_valid_dpi_awareness_context( UINT context, UINT dpi ) { diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 6d0483311bb..b7a40367506 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -455,4 +455,9 @@ static inline UINT round_dpi( struct ratio dpi ) return (dpi.num + dpi.den / 2) / dpi.den; } +static inline const char *debugstr_ratio( struct ratio q ) +{ + return wine_dbg_sprintf( "%d:%d", q.num, q.den ); +} + #endif /* __WINE_WIN32U_PRIVATE */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index e5fe70409f0..a0efc9e10d5 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1112,6 +1112,27 @@ BOOL is_window_enabled( HWND hwnd ) return !(ret & WS_DISABLED); } +struct ratio get_win_monitor_dpi( HWND hwnd, struct ratio *raw_dpi ) +{ + struct object_lock lock = OBJECT_LOCK_INIT; + const window_shm_t *window_shm; + struct ratio dpi = no_dpi; + NTSTATUS status; + + while ((status = get_shared_window( hwnd, &lock, &window_shm )) == STATUS_PENDING) + { + *raw_dpi = window_shm->raw_dpi; + dpi = window_shm->dpi; + } + if (status) + { + RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); + return no_dpi; + } + + return dpi; +} + /* see GetWindowDpiAwarenessContext */ UINT get_window_dpi_awareness_context( HWND hwnd ) { @@ -2214,7 +2235,7 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru struct window_rects monitor_rects; WND *win; HWND owner_hint, surface_win = 0, toplevel; - struct ratio raw_dpi, monitor_dpi, dpi = get_thread_dpi(); + struct ratio raw_dpi, dpi = get_thread_dpi(); BOOL ret, is_layered, is_child, need_icons = FALSE; struct window_rects old_rects; RECT extra_rects[3]; @@ -2226,8 +2247,8 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru is_layered = new_surface && new_surface->alpha_mask; is_child = toplevel && toplevel != hwnd; - if (is_child) monitor_dpi = get_win_monitor_dpi( toplevel, &raw_dpi ); - else monitor_dpi = monitor_dpi_from_rect( new_rects->window, dpi, &raw_dpi ); + if (is_child) get_win_monitor_dpi( toplevel, &raw_dpi ); + else monitor_dpi_from_rect( new_rects->window, dpi, &raw_dpi ); get_window_rects( hwnd, COORDS_PARENT, &old_rects, dpi ); if (IsRectEmpty( &valid_rects[0] ) || is_layered) valid_rects = NULL; @@ -2248,7 +2269,6 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru req->handle = wine_server_user_handle( hwnd ); req->previous = wine_server_user_handle( insert_after ); req->swp_flags = swp_flags; - req->monitor_dpi = monitor_dpi; req->window = wine_server_rectangle( new_rects->window ); req->client = wine_server_rectangle( new_rects->client ); if (!EqualRect( &new_rects->window, &new_rects->visible ) || new_surface || valid_rects) diff --git a/server/protocol.def b/server/protocol.def index 2ba02303761..191f1deeffc 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -913,7 +913,8 @@ struct monitor_info struct rectangle raw; /* host / physical position of the monitor rect */ struct rectangle virt; /* client / virtual position of the monitor rect */ unsigned int flags; /* MONITOR_FLAG_* flags for the monitor */ - struct ratio dpi; /* physical DPI for the monitor */ + struct ratio dpi; /* effective DPI for the monitor */ + struct ratio raw_dpi; /* raw DPI for the monitor */ }; #define MONITOR_FLAG_PRIMARY 0x01 #define MONITOR_FLAG_CLONE 0x02 @@ -1084,6 +1085,8 @@ typedef volatile struct unsigned int fnid; /* builtin class FNID, or 0 */ unsigned int ansi; /* window wndproc is ansi */ int __pad; + struct ratio dpi; /* effective DPI of the window monitor */ + struct ratio raw_dpi; /* raw DPI of the window monitor */ data_size_t private_size; /* length of private extra bytes range */ data_size_t extra_size; /* size of the extra info */ struct window_info info; /* window info (GWLP_*) */ @@ -2796,7 +2799,6 @@ enum message_type @REQ(set_window_pos) unsigned short swp_flags; /* SWP_* flags */ unsigned short paint_flags; /* paint flags (see below) */ - struct ratio monitor_dpi; /* DPI of the window's monitor */ user_handle_t handle; /* handle to the window */ user_handle_t previous; /* previous window in Z order */ struct rectangle window; /* window rectangle (in parent coords) */ diff --git a/server/window.c b/server/window.c index 37ea9a9dc35..77f71f0f65a 100644 --- a/server/window.c +++ b/server/window.c @@ -83,7 +83,6 @@ 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 */ - struct ratio monitor_dpi; /* DPI of the window monitor */ WCHAR *text; /* window caption text */ data_size_t text_len; /* length of window caption */ unsigned int paint_flags; /* various painting flags */ @@ -324,7 +323,7 @@ static void map_point_raw_to_virt( struct desktop *desktop, int *x, int *y ) static struct ratio get_monitor_dpi( struct window *win ) { while (win->parent && !is_desktop_window( win->parent )) win = win->parent; - return win->monitor_dpi; + return win->shared->dpi; } static struct ratio get_window_dpi( struct window *win ) @@ -394,6 +393,20 @@ static int link_window( struct window *win, struct window *previous ) return old_prev != win->entry.prev; } +static void set_window_monitor_dpi( struct window *win ) +{ + struct monitor_info *info; + + if (!(info = get_monitor_from_rect( win->desktop->winstation, &win->window_rect, 0 ))) return; + + SHARED_WRITE_BEGIN( win->shared, window_shm_t ) + { + shared->dpi = info->dpi; + shared->raw_dpi = info->raw_dpi; + } + SHARED_WRITE_END; +} + /* change the parent of a window (or unlink the window if the new parent is NULL) */ static int set_parent_window( struct window *win, struct window *parent ) { @@ -415,14 +428,12 @@ static int set_parent_window( struct window *win, struct window *parent ) win->parent = (struct window *)grab_object( parent ); link_window( win, WINPTR_TOP ); - if (!is_desktop_window( parent )) + if (is_desktop_window( parent )) set_window_monitor_dpi( win ); + else SHARED_WRITE_BEGIN( win->shared, window_shm_t ) { - SHARED_WRITE_BEGIN( win->shared, window_shm_t ) - { - shared->dpi_context = parent->shared->dpi_context; - } - SHARED_WRITE_END; + shared->dpi_context = parent->shared->dpi_context; } + SHARED_WRITE_END; /* if parent belongs to a different thread and the window isn't */ /* top-level, attach the two threads */ @@ -662,8 +673,6 @@ static struct window *create_window( struct window *parent, struct window *owner win->is_layered = 0; win->is_orphan = 0; win->set_foreground = 0; - win->monitor_dpi.num = USER_DEFAULT_SCREEN_DPI; - win->monitor_dpi.den = 1; win->text = NULL; win->text_len = 0; win->paint_flags = 0; @@ -682,6 +691,10 @@ static struct window *create_window( struct window *parent, struct window *owner shared->dpi_context = NTUSER_DPI_PER_MONITOR_AWARE; shared->fnid = fnid; shared->private_size = private_size; + shared->dpi.num = USER_DEFAULT_SCREEN_DPI; + shared->dpi.den = 1; + shared->raw_dpi.num = USER_DEFAULT_SCREEN_DPI; + shared->raw_dpi.den = 1; shared->extra_size = extra_size; memset( (void *)&shared->info, 0, sizeof(shared->info) ); memset( (void *)shared->extra, 0, extra_size ); @@ -1951,6 +1964,9 @@ static void set_window_pos( struct window *win, struct window *previous, if (swp_flags & SWP_SHOWWINDOW) win->style |= WS_VISIBLE; else if (swp_flags & SWP_HIDEWINDOW) win->style &= ~WS_VISIBLE; + /* update window monitor dpi for toplevel windows */ + if (!win->parent || is_desktop_window( win->parent )) set_window_monitor_dpi( win ); + /* keep children at the same position relative to top right corner when the parent is mirrored */ if (win->ex_style & WS_EX_LAYOUTRTL) { @@ -2737,7 +2753,6 @@ DECL_HANDLER(set_window_pos) win->paint_flags = (win->paint_flags & ~PAINT_CLIENT_FLAGS) | (req->paint_flags & PAINT_CLIENT_FLAGS); if (win->paint_flags & PAINT_HAS_PIXEL_FORMAT) update_pixel_format_flags( win ); - win->monitor_dpi = req->monitor_dpi; old_style = win->style; old_window = win->window_rect; old_client = win->client_rect; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11301