This starts using MDT_RAW_DPI in the drivers, and provides the necessary raw/virt monitor information to wineserver. For now, this should not change much, as MDT_RAW_DPI is still the same as MDT_DEFAULT_DPI, but later it will return the DPI of the physical mode while MDT_DEFAULT_DPI will return a DPI for the possibly virtualized current display mode.
-- v2: server: Use the monitor infos to compute the virtual screen rect. win32u: Inform wineserver about the winstation monitors. win32u: Move some monitor info getter code around. win32u: Use MDT_RAW_DPI monitor DPI type in the drivers. win32u: Implement get_win_monitor_dpi.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 50020ed80d0..911ce6c0e40 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2377,9 +2377,35 @@ static UINT get_monitor_dpi( HMONITOR handle, UINT type, UINT *x, UINT *y ) */ UINT get_win_monitor_dpi( HWND hwnd, UINT *raw_dpi ) { - /* FIXME: use the monitor DPI instead */ - *raw_dpi = system_dpi; - return system_dpi; + UINT dpi = NTUSER_DPI_CONTEXT_GET_DPI( get_window_dpi_awareness_context( hwnd ) ); + HWND parent = get_parent( hwnd ); + RECT rect = {0}; + WND *win; + + if (!(win = get_win_ptr( hwnd ))) + { + RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); + return 0; + } + + 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 0; + } + /* avoid recursive calls from get_window_rects for the process windows */ + else if ((parent = win->parent)) + { + release_win_ptr( win ); + return get_win_monitor_dpi( parent, raw_dpi ); + } + else + { + rect = win->rects.window; + release_win_ptr( win ); + } + + return monitor_dpi_from_rect( rect, dpi, raw_dpi ); }
/* keep in sync with user32 */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/clipboard.c | 16 +++++--- dlls/win32u/clipping.c | 5 ++- dlls/win32u/input.c | 35 ++++++---------- dlls/win32u/message.c | 6 ++- dlls/win32u/sysparams.c | 56 +++++++++++++++++++++++++- dlls/win32u/win32u_private.h | 5 ++- dlls/win32u/window.c | 30 +++++++------- dlls/wineandroid.drv/init.c | 2 +- dlls/wineandroid.drv/window.c | 4 +- dlls/winemac.drv/window.c | 2 +- dlls/winewayland.drv/wayland_surface.c | 4 +- dlls/winewayland.drv/window.c | 2 +- dlls/winex11.drv/display.c | 4 +- dlls/winex11.drv/event.c | 2 +- dlls/winex11.drv/init.c | 2 +- dlls/winex11.drv/mouse.c | 4 +- dlls/winex11.drv/opengl.c | 4 +- dlls/winex11.drv/vulkan.c | 4 +- dlls/winex11.drv/window.c | 2 +- dlls/winex11.drv/x11drv.h | 2 +- 20 files changed, 123 insertions(+), 68 deletions(-)
diff --git a/dlls/win32u/clipboard.c b/dlls/win32u/clipboard.c index e8d16291cd1..ee75a239efc 100644 --- a/dlls/win32u/clipboard.c +++ b/dlls/win32u/clipboard.c @@ -770,16 +770,17 @@ LRESULT drag_drop_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void return KeUserModeCallback( NtUserDragDropLeave, 0, 0, &ret_ptr, &ret_len ); case WINE_DRAG_DROP_DRAG: { + RECT rect = {LOWORD(wparam), HIWORD(wparam), LOWORD(wparam), HIWORD(wparam)}; struct drag_drop_drag_params params = { .hwnd = hwnd, - .point.x = LOWORD(wparam), - .point.y = HIWORD(wparam), .effect = lparam, }; - UINT raw_dpi;
- params.point = map_dpi_point( params.point, get_win_monitor_dpi( hwnd, &raw_dpi ), get_thread_dpi() ); + rect = map_rect_raw_to_virt( rect, get_thread_dpi() ); + params.point.x = rect.left; + params.point.y = rect.top; + if (KeUserModeCallback( NtUserDragDropDrag, ¶ms, sizeof(params), &ret_ptr, &ret_len ) || ret_len != sizeof(DWORD)) return DROPEFFECT_NONE; return *(DWORD *)ret_ptr; @@ -796,9 +797,9 @@ LRESULT drag_drop_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void { struct drag_drop_post_params *params; const DROPFILES *drop = (DROPFILES *)lparam; + RECT rect = {drop->pt.x, drop->pt.y, drop->pt.x, drop->pt.y}; UINT drop_size = wparam, size; NTSTATUS status; - UINT raw_dpi;
size = offsetof(struct drag_drop_post_params, drop) + drop_size; if (!(params = malloc( size ))) return STATUS_NO_MEMORY; @@ -806,7 +807,10 @@ LRESULT drag_drop_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void params->drop_size = drop_size; memcpy( ¶ms->drop, drop, drop_size );
- params->drop.pt = map_dpi_point( params->drop.pt, get_win_monitor_dpi( hwnd, &raw_dpi ), get_thread_dpi() ); + rect = map_rect_raw_to_virt( rect, get_thread_dpi() ); + params->drop.pt.x = rect.left; + params->drop.pt.y = rect.top; + status = KeUserModeCallback( NtUserDragDropPost, params, size, &ret_ptr, &ret_len ); free( params ); return status; diff --git a/dlls/win32u/clipping.c b/dlls/win32u/clipping.c index 3681b542fc3..610c2b430e3 100644 --- a/dlls/win32u/clipping.c +++ b/dlls/win32u/clipping.c @@ -463,11 +463,12 @@ INT WINAPI NtGdiGetRandomRgn( HDC hDC, HRGN hRgn, INT iCode ) if (ret > 0 && (iCode & NTGDI_RGN_MONITOR_DPI)) { HWND hwnd = NtUserWindowFromDC( hDC ); - UINT raw_dpi, monitor_dpi = get_win_monitor_dpi( hwnd, &raw_dpi ); + UINT raw_dpi; HRGN region;
+ get_win_monitor_dpi( hwnd, &raw_dpi ); NtGdiOffsetRgn( hRgn, -dc->attr->vis_rect.left, -dc->attr->vis_rect.top ); - region = map_dpi_region( hRgn, get_dpi_for_window( hwnd ), monitor_dpi ); + region = map_dpi_region( hRgn, get_dpi_for_window( hwnd ), raw_dpi ); NtGdiCombineRgn( hRgn, region, 0, RGN_COPY ); NtGdiDeleteObjectApp( region ); } diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 0640b34ac2e..c976b57b39f 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -709,11 +709,8 @@ BOOL WINAPI NtUserSetCursorPos( INT x, INT y ) RECT rect = {x, y, x, y}; BOOL ret; INT prev_x, prev_y, new_x, new_y; - UINT dpi, raw_dpi; - - dpi = monitor_dpi_from_rect( rect, get_thread_dpi(), &raw_dpi ); - rect = map_dpi_rect( rect, get_thread_dpi(), dpi );
+ rect = map_rect_virt_to_raw( rect, get_thread_dpi() ); SERVER_START_REQ( set_cursor ) { req->flags = SET_CURSOR_POS; @@ -743,7 +740,6 @@ BOOL get_cursor_pos( POINT *pt ) DWORD last_change = 0; NTSTATUS status; RECT rect; - UINT dpi, raw_dpi;
if (!pt) return FALSE;
@@ -760,8 +756,7 @@ BOOL get_cursor_pos( POINT *pt ) if (!ret) return FALSE;
SetRect( &rect, pt->x, pt->y, pt->x, pt->y ); - dpi = monitor_dpi_from_rect( rect, get_thread_dpi(), &raw_dpi ); - rect = map_dpi_rect( rect, dpi, get_thread_dpi() ); + rect = map_rect_raw_to_virt( rect, get_thread_dpi() ); *pt = *(POINT *)&rect.left; return ret; } @@ -2357,6 +2352,7 @@ BOOL set_ime_composition_rect( HWND hwnd, RECT rect ) { if (!NtUserIsWindow( hwnd )) return FALSE; NtUserMapWindowPoints( hwnd, 0, (POINT *)&rect, 2, 0 /* per-monitor DPI */ ); + rect = map_rect_virt_to_raw( rect, 0 /* per-monitor DPI */ ); return user_driver->pSetIMECompositionRect( NtUserGetAncestor( hwnd, GA_ROOT ), rect ); }
@@ -2561,7 +2557,8 @@ BOOL clip_fullscreen_window( HWND hwnd, BOOL reset )
ctx = set_thread_dpi_awareness_context( NTUSER_DPI_PER_MONITOR_AWARE ); monitor_info = monitor_info_from_window( hwnd, MONITOR_DEFAULTTONEAREST ); - virtual_rect = get_virtual_screen_rect( 0, MDT_DEFAULT ); + virtual_rect = get_virtual_screen_rect( get_thread_dpi(), MDT_DEFAULT ); + rect = map_rect_virt_to_raw( monitor_info.rcMonitor, get_thread_dpi() ); set_thread_dpi_awareness_context( ctx );
if (!grab_fullscreen) @@ -2575,7 +2572,7 @@ BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) SERVER_START_REQ( set_cursor ) { req->flags = SET_CURSOR_CLIP | SET_CURSOR_FSCLIP; - req->clip = wine_server_rectangle( monitor_info.rcMonitor ); + req->clip = wine_server_rectangle( rect ); ret = !wine_server_call( req ); } SERVER_END_REQ; @@ -2595,7 +2592,7 @@ BOOL WINAPI NtUserGetPointerInfoList( UINT32 id, POINTER_INPUT_TYPE type, UINT_P return FALSE; }
-BOOL get_clip_cursor( RECT *rect, UINT dpi ) +BOOL get_clip_cursor( RECT *rect, UINT dpi, MONITOR_DPI_TYPE type ) { struct object_lock lock = OBJECT_LOCK_INIT; const desktop_shm_t *desktop_shm; @@ -2606,20 +2603,14 @@ BOOL get_clip_cursor( RECT *rect, UINT dpi ) while ((status = get_shared_desktop( &lock, &desktop_shm )) == STATUS_PENDING) *rect = wine_server_get_rect( desktop_shm->cursor.clip );
- if (!status) - { - UINT ctx = set_thread_dpi_awareness_context( NTUSER_DPI_PER_MONITOR_AWARE ); - UINT raw_dpi, dpi_from = monitor_dpi_from_rect( *rect, get_thread_dpi(), &raw_dpi ); - *rect = map_dpi_rect( *rect, dpi_from, dpi ); - set_thread_dpi_awareness_context( ctx ); - } + if (!status && type == MDT_EFFECTIVE_DPI) *rect = map_rect_raw_to_virt( *rect, dpi ); return !status; }
BOOL process_wine_clipcursor( HWND hwnd, UINT flags, BOOL reset ) { struct user_thread_info *thread_info = get_user_thread_info(); - RECT rect, virtual_rect = get_virtual_screen_rect( 0, MDT_DEFAULT ); + RECT rect, virtual_rect = get_virtual_screen_rect( 0, MDT_RAW_DPI ); BOOL was_clipping, empty = !!(flags & SET_CURSOR_NOCLIP);
TRACE( "hwnd %p, flags %#x, reset %u\n", hwnd, flags, reset ); @@ -2636,7 +2627,7 @@ BOOL process_wine_clipcursor( HWND hwnd, UINT flags, BOOL reset ) if (!grab_pointer) return TRUE;
/* we are clipping if the clip rectangle is smaller than the screen */ - get_clip_cursor( &rect, 0 ); + get_clip_cursor( &rect, 0, MDT_RAW_DPI ); intersect_rect( &rect, &rect, &virtual_rect ); if (EqualRect( &rect, &virtual_rect )) empty = TRUE; if (empty && !(flags & SET_CURSOR_FSCLIP)) @@ -2657,17 +2648,15 @@ BOOL process_wine_clipcursor( HWND hwnd, UINT flags, BOOL reset ) */ BOOL WINAPI NtUserClipCursor( const RECT *rect ) { - UINT dpi_from = get_thread_dpi(), dpi_to, raw_dpi; - BOOL ret; RECT new_rect; + BOOL ret;
TRACE( "Clipping to %s\n", wine_dbgstr_rect(rect) );
if (rect) { if (rect->left > rect->right || rect->top > rect->bottom) return FALSE; - dpi_to = monitor_dpi_from_rect( *rect, dpi_from, &raw_dpi ); - new_rect = map_dpi_rect( *rect, dpi_from, dpi_to ); + new_rect = map_rect_virt_to_raw( *rect, get_thread_dpi() ); rect = &new_rect; }
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index fd41bd670ce..af1a7e5b8ec 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2637,14 +2637,18 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar HWND hwnd_filter, UINT first, UINT last, BOOL remove ) { struct ntuser_thread_info *thread_info = NtUserGetThreadInfo(); + RECT rect = {msg->pt.x, msg->pt.y, msg->pt.x, msg->pt.y}; UINT context; BOOL ret = FALSE;
thread_info->msg_source.deviceType = msg_data->source.device; thread_info->msg_source.originId = msg_data->source.origin;
- /* hardware messages are always in physical coords */ + /* hardware messages are always in raw physical coords */ context = set_thread_dpi_awareness_context( NTUSER_DPI_PER_MONITOR_AWARE ); + rect = map_rect_raw_to_virt( rect, get_thread_dpi() ); + msg->pt.x = rect.left; + msg->pt.y = rect.top;
if (msg->message == WM_INPUT || msg->message == WM_INPUT_DEVICE_CHANGE) ret = process_rawinput_message( msg, hw_id, msg_data ); diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 911ce6c0e40..327bb5cce9c 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2360,6 +2360,60 @@ static RECT monitors_get_union_rect( UINT dpi, MONITOR_DPI_TYPE type ) return rect; }
+static RECT map_monitor_rect( struct monitor *monitor, RECT rect, UINT dpi_from, MONITOR_DPI_TYPE type_from, + UINT dpi_to, MONITOR_DPI_TYPE type_to ) +{ + UINT x, y; + if (!dpi_from) dpi_from = monitor_get_dpi( monitor, type_from, &x, &y ); + if (!dpi_to) dpi_to = monitor_get_dpi( monitor, type_to, &x, &y ); + return map_dpi_rect( rect, dpi_from, dpi_to ); +} + +/* map a monitor rect from MDT_RAW_DPI to MDT_DEFAULT coordinates */ +RECT map_rect_raw_to_virt( RECT rect, UINT dpi_to ) +{ + RECT pos = {rect.left, rect.top, rect.left, rect.top}; + struct monitor *monitor; + + if (!lock_display_devices()) return rect; + if ((monitor = get_monitor_from_rect( pos, MONITOR_DEFAULTTONEAREST, 0, MDT_RAW_DPI ))) + rect = map_monitor_rect( monitor, rect, 0, MDT_RAW_DPI, dpi_to, MDT_DEFAULT ); + unlock_display_devices(); + + return rect; +} + +/* map a monitor rect from MDT_DEFAULT to MDT_RAW_DPI coordinates */ +RECT map_rect_virt_to_raw( RECT rect, UINT dpi_from ) +{ + RECT pos = {rect.left, rect.top, rect.left, rect.top}; + struct monitor *monitor; + + if (!lock_display_devices()) return rect; + if ((monitor = get_monitor_from_rect( pos, MONITOR_DEFAULTTONEAREST, dpi_from, MDT_DEFAULT ))) + rect = map_monitor_rect( monitor, rect, dpi_from, MDT_DEFAULT, 0, MDT_RAW_DPI ); + unlock_display_devices(); + + return rect; +} + +/* map (absolute) window rects from MDT_DEFAULT to MDT_RAW_DPI coordinates */ +struct window_rects map_window_rects_virt_to_raw( struct window_rects rects, UINT dpi_from ) +{ + struct monitor *monitor; + + if (!lock_display_devices()) return rects; + if ((monitor = get_monitor_from_rect( rects.window, MONITOR_DEFAULTTONEAREST, dpi_from, MDT_DEFAULT ))) + { + rects.visible = map_monitor_rect( monitor, rects.visible, dpi_from, MDT_DEFAULT, 0, MDT_RAW_DPI ); + rects.window = map_monitor_rect( monitor, rects.window, dpi_from, MDT_DEFAULT, 0, MDT_RAW_DPI ); + rects.client = map_monitor_rect( monitor, rects.client, dpi_from, MDT_DEFAULT, 0, MDT_RAW_DPI ); + } + unlock_display_devices(); + + return rects; +} + static UINT get_monitor_dpi( HMONITOR handle, UINT type, UINT *x, UINT *y ) { struct monitor *monitor; @@ -6794,7 +6848,7 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code ) return enum_clipboard_formats( arg );
case NtUserCallOneParam_GetClipCursor: - return get_clip_cursor( (RECT *)arg, get_thread_dpi() ); + return get_clip_cursor( (RECT *)arg, get_thread_dpi(), MDT_DEFAULT );
case NtUserCallOneParam_GetCursorPos: return get_cursor_pos( (POINT *)arg ); diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 8956f83af75..f25e94a0db1 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -106,7 +106,7 @@ extern BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus, DW extern BOOL set_ime_composition_rect( HWND hwnd, RECT rect ); extern void toggle_caret( HWND hwnd ); extern void update_mouse_tracking_info( HWND hwnd ); -extern BOOL get_clip_cursor( RECT *rect, UINT dpi ); +extern BOOL get_clip_cursor( RECT *rect, UINT dpi, MONITOR_DPI_TYPE type ); extern BOOL process_wine_clipcursor( HWND hwnd, UINT flags, BOOL reset ); extern BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ); extern USHORT map_scan_to_kbd_vkey( USHORT scan, HKL layout ); @@ -186,6 +186,9 @@ extern RECT map_dpi_rect( RECT rect, UINT dpi_from, UINT dpi_to ); extern HRGN map_dpi_region( HRGN region, UINT dpi_from, UINT dpi_to ); extern struct window_rects map_dpi_window_rects( struct window_rects rects, UINT dpi_from, UINT dpi_to ); extern BOOL message_beep( UINT i ); +extern RECT map_rect_raw_to_virt( RECT rect, UINT dpi_to ); +extern RECT map_rect_virt_to_raw( RECT rect, UINT dpi_from ); +extern struct window_rects map_window_rects_virt_to_raw( struct window_rects rects, UINT dpi_from ); extern POINT point_phys_to_win_dpi( HWND hwnd, POINT pt ); extern POINT point_thread_to_win_dpi( HWND hwnd, POINT pt ); extern RECT rect_thread_to_win_dpi( HWND hwnd, RECT rect ); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 47ace040c37..997fd167d11 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1855,7 +1855,7 @@ static RECT get_visible_rect( HWND hwnd, BOOL shaped, UINT style, UINT ex_style,
static BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rect ) { - RECT virtual_rect = get_virtual_screen_rect( 0, MDT_DEFAULT ); + RECT virtual_rect = get_virtual_screen_rect( 0, MDT_RAW_DPI );
*surface_rect = *visible_rect;
@@ -1910,7 +1910,7 @@ static struct window_surface *get_window_surface( HWND hwnd, UINT swp_flags, BOO HWND parent = NtUserGetAncestor( hwnd, GA_PARENT ); struct window_surface *new_surface; struct window_rects monitor_rects; - UINT raw_dpi, monitor_dpi, style, ex_style; + UINT raw_dpi, style, ex_style; RECT dummy; HRGN shape;
@@ -1918,14 +1918,16 @@ static struct window_surface *get_window_surface( HWND hwnd, UINT swp_flags, BOO ex_style = NtUserGetWindowLongW( hwnd, GWL_EXSTYLE ); is_child = parent && parent != NtUserGetDesktopWindow();
- if (is_child) monitor_dpi = get_win_monitor_dpi( parent, &raw_dpi ); - else monitor_dpi = monitor_dpi_from_rect( rects->window, get_thread_dpi(), &raw_dpi ); + if (is_child) get_win_monitor_dpi( parent, &raw_dpi ); + else monitor_dpi_from_rect( rects->window, get_thread_dpi(), &raw_dpi );
if (get_window_region( hwnd, FALSE, &shape, &dummy )) shaped = FALSE; else if ((shaped = !!shape)) NtGdiDeleteObjectApp( shape );
rects->visible = rects->window; - monitor_rects = map_dpi_window_rects( *rects, get_thread_dpi(), monitor_dpi ); + if (is_child) monitor_rects = map_dpi_window_rects( *rects, get_thread_dpi(), raw_dpi ); + else monitor_rects = map_window_rects_virt_to_raw( *rects, get_thread_dpi() ); + if (!user_driver->pWindowPosChanging( hwnd, swp_flags, shaped, &monitor_rects )) needs_surface = FALSE; else if (is_child) needs_surface = FALSE; else if (swp_flags & SWP_HIDEWINDOW) needs_surface = FALSE; @@ -1950,7 +1952,7 @@ static struct window_surface *get_window_surface( HWND hwnd, UINT swp_flags, BOO else if (create_layered || is_layered) needs_surface = TRUE;
if (needs_surface) - create_window_surface( hwnd, create_layered, surface_rect, monitor_dpi, &new_surface ); + create_window_surface( hwnd, create_layered, surface_rect, raw_dpi, &new_surface ); else if (new_surface && new_surface != &dummy_surface) { window_surface_release( new_surface ); @@ -2025,7 +2027,8 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru valid_rects = NULL; }
- monitor_rects = map_dpi_window_rects( *new_rects, get_thread_dpi(), monitor_dpi ); + if (is_child) monitor_rects = map_dpi_window_rects( *new_rects, get_thread_dpi(), raw_dpi ); + else monitor_rects = map_window_rects_virt_to_raw( *new_rects, get_thread_dpi() );
SERVER_START_REQ( set_window_pos ) { @@ -2144,7 +2147,7 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, stru if (owner_hint) owner_hint = NtUserGetAncestor(owner_hint, GA_ROOT);
user_driver->pWindowPosChanged( hwnd, insert_after, owner_hint, swp_flags, is_fullscreen, &monitor_rects, - get_driver_window_surface( new_surface, monitor_dpi ) ); + get_driver_window_surface( new_surface, raw_dpi ) );
update_children_window_state( hwnd ); } @@ -2292,13 +2295,13 @@ int WINAPI NtUserSetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) { UINT swp_flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE; - UINT raw_dpi, dpi; + UINT raw_dpi; HRGN monitor_hrgn;
if (!redraw) swp_flags |= SWP_NOREDRAW;
- dpi = get_win_monitor_dpi( hwnd, &raw_dpi ); - monitor_hrgn = map_dpi_region( hrgn, get_thread_dpi(), dpi ); + get_win_monitor_dpi( hwnd, &raw_dpi ); + monitor_hrgn = map_dpi_region( hrgn, get_thread_dpi(), raw_dpi ); user_driver->pSetWindowRgn( hwnd, monitor_hrgn, redraw ); if (monitor_hrgn) NtGdiDeleteObjectApp( monitor_hrgn );
@@ -5732,12 +5735,9 @@ static BOOL set_dialog_info( HWND hwnd, void *info )
static BOOL set_raw_window_pos( HWND hwnd, RECT rect, UINT flags, BOOL internal ) { - UINT dpi, raw_dpi; - TRACE( "hwnd %p, rect %s, flags %#x, internal %u\n", hwnd, wine_dbgstr_rect(&rect), flags, internal );
- dpi = get_win_monitor_dpi( hwnd, &raw_dpi ); - rect = map_dpi_rect( rect, dpi, get_thread_dpi() ); + rect = map_rect_raw_to_virt( rect, get_thread_dpi() );
if (internal) { diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index 5e99d1d95e6..dbc3de1d933 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -78,7 +78,7 @@ void init_monitors( int width, int height ) monitor_rc_work = virtual_screen_rect;
if (!hwnd || !NtUserIsWindowVisible( hwnd )) return; - if (!NtUserGetWindowRect( hwnd, &rect, NtUserGetWinMonitorDpi( hwnd, MDT_DEFAULT ) )) return; + if (!NtUserGetWindowRect( hwnd, &rect, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) )) return; if (rect.top) monitor_rc_work.bottom = rect.top; else monitor_rc_work.top = rect.bottom; TRACE( "found tray %p %s work area %s\n", hwnd, diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 17d076d65b5..76aeadc6d6f 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -98,7 +98,7 @@ static struct android_win_data *alloc_win_data( HWND hwnd ) { data->hwnd = hwnd; data->window = create_ioctl_window( hwnd, FALSE, - (float)NtUserGetWinMonitorDpi( hwnd, MDT_DEFAULT ) / NtUserGetDpiForWindow( hwnd )); + (float)NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) / NtUserGetDpiForWindow( hwnd )); pthread_mutex_lock( &win_data_mutex ); win_data_context[context_idx(hwnd)] = data; } @@ -1101,7 +1101,7 @@ void ANDROID_SetParent( HWND hwnd, HWND parent, HWND old_parent ) TRACE( "win %p parent %p -> %p\n", hwnd, old_parent, parent );
data->parent = (parent == NtUserGetDesktopWindow()) ? 0 : parent; - ioctl_set_window_parent( hwnd, parent, (float)NtUserGetWinMonitorDpi( hwnd, MDT_DEFAULT ) / NtUserGetDpiForWindow( hwnd )); + ioctl_set_window_parent( hwnd, parent, (float)NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) / NtUserGetDpiForWindow( hwnd )); release_win_data( data ); }
diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 07874cf985e..f2cca652045 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -346,7 +346,7 @@ static void sync_window_min_max_info(HWND hwnd) { LONG style = NtUserGetWindowLongW(hwnd, GWL_STYLE); LONG exstyle = NtUserGetWindowLongW(hwnd, GWL_EXSTYLE); - UINT dpi = NtUserGetWinMonitorDpi(hwnd, MDT_DEFAULT); + UINT dpi = NtUserGetWinMonitorDpi(hwnd, MDT_RAW_DPI); RECT win_rect, primary_monitor_rect; MINMAXINFO minmax; LONG adjustedStyle; diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index b7ef362df5c..2178f5431cb 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -970,8 +970,8 @@ void wayland_client_surface_attach(struct wayland_client_surface *client, HWND t client->toplevel = toplevel; }
- NtUserGetClientRect(client->hwnd, &client_rect, NtUserGetWinMonitorDpi(client->hwnd, MDT_DEFAULT)); - NtUserMapWindowPoints(client->hwnd, toplevel, (POINT *)&client_rect, 2, NtUserGetWinMonitorDpi(client->hwnd, MDT_DEFAULT)); + NtUserGetClientRect(client->hwnd, &client_rect, NtUserGetWinMonitorDpi(client->hwnd, MDT_RAW_DPI)); + NtUserMapWindowPoints(client->hwnd, toplevel, (POINT *)&client_rect, 2, NtUserGetWinMonitorDpi(client->hwnd, MDT_RAW_DPI));
wayland_surface_reconfigure_client(surface, client, &client_rect); /* Commit to apply subsurface positioning. */ diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index b89cc97b08c..78e940a51a7 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -174,7 +174,7 @@ static void wayland_win_data_get_config(struct wayland_win_data *data, }
conf->state = window_state; - conf->scale = NtUserGetWinMonitorDpi(data->hwnd, MDT_DEFAULT) / 96.0; + conf->scale = NtUserGetWinMonitorDpi(data->hwnd, MDT_RAW_DPI) / 96.0; conf->visible = (style & WS_VISIBLE) == WS_VISIBLE; conf->managed = data->managed; } diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 070ab3efe2f..8d1a1dfd414 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -284,7 +284,7 @@ done:
POINT virtual_screen_to_root(INT x, INT y) { - RECT virtual = NtUserGetVirtualScreenRect( MDT_DEFAULT ); + RECT virtual = NtUserGetVirtualScreenRect( MDT_RAW_DPI ); POINT pt;
pt.x = x - virtual.left; @@ -294,7 +294,7 @@ POINT virtual_screen_to_root(INT x, INT y)
POINT root_to_virtual_screen(INT x, INT y) { - RECT virtual = NtUserGetVirtualScreenRect( MDT_DEFAULT ); + RECT virtual = NtUserGetVirtualScreenRect( MDT_RAW_DPI ); POINT pt;
pt.x = x + virtual.left; diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 7ae30f2ab3c..a1116d032e6 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -980,7 +980,7 @@ static BOOL X11DRV_Expose( HWND hwnd, XEvent *xev )
release_win_data( data );
- NtUserExposeWindowSurface( hwnd, flags, &rect, NtUserGetWinMonitorDpi( hwnd, MDT_DEFAULT ) ); + NtUserExposeWindowSurface( hwnd, flags, &rect, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); return TRUE; }
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 7963d9cbbc0..e0f465a2771 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -196,7 +196,7 @@ static HFONT X11DRV_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags )
BOOL needs_offscreen_rendering( HWND hwnd, BOOL known_child ) { - if (NtUserGetDpiForWindow( hwnd ) != NtUserGetWinMonitorDpi( hwnd, MDT_DEFAULT )) return TRUE; /* needs DPI scaling */ + if (NtUserGetDpiForWindow( hwnd ) != NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI )) return TRUE; /* needs DPI scaling */ if (NtUserGetAncestor( hwnd, GA_PARENT ) != NtUserGetDesktopWindow()) return TRUE; /* child window, needs compositing */ if (NtUserGetWindowRelative( hwnd, GW_CHILD )) return TRUE; /* window has children, needs compositing */ if (known_child) return TRUE; /* window is/have children, needs compositing */ diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index cbbb27d6798..f3c72b2d9f5 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -1677,7 +1677,7 @@ static BOOL map_raw_event_coords( XIRawEvent *event, INPUT *input ) if (!xinput2_available) return FALSE; if (event->deviceid != thread_data->xinput2_pointer) return FALSE;
- virtual_rect = NtUserGetVirtualScreenRect( MDT_DEFAULT ); + virtual_rect = NtUserGetVirtualScreenRect( MDT_RAW_DPI );
if (x->max <= x->min) x_scale = 1; else x_scale = (virtual_rect.right - virtual_rect.left) / (x->max - x->min); @@ -1747,7 +1747,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
static BOOL X11DRV_TouchEvent( HWND hwnd, XGenericEventCookie *xev ) { - RECT virtual = NtUserGetVirtualScreenRect( MDT_DEFAULT ); + RECT virtual = NtUserGetVirtualScreenRect( MDT_RAW_DPI ); INPUT input = {.type = INPUT_HARDWARE}; XIDeviceEvent *event = xev->data; int flags = 0; diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index d82fd01233d..594ffaea2dd 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -1898,8 +1898,8 @@ static void present_gl_drawable( HWND hwnd, HDC hdc, struct gl_drawable *gl, BOO
if (flush) XFlush( gdi_display );
- NtUserGetClientRect( hwnd, &rect_dst, NtUserGetWinMonitorDpi( hwnd, MDT_DEFAULT ) ); - NtUserMapWindowPoints( hwnd, toplevel, (POINT *)&rect_dst, 2, NtUserGetWinMonitorDpi( hwnd, MDT_DEFAULT ) ); + NtUserGetClientRect( hwnd, &rect_dst, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); + NtUserMapWindowPoints( hwnd, toplevel, (POINT *)&rect_dst, 2, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) );
if ((data = get_win_data( toplevel ))) { diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index 32fb87c1368..e7c187d5c67 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -231,8 +231,8 @@ static void X11DRV_vulkan_surface_presented( HWND hwnd, void *private, VkResult window = X11DRV_get_whole_window( toplevel ); region = get_dc_monitor_region( hwnd, hdc );
- NtUserGetClientRect( hwnd, &rect_dst, NtUserGetWinMonitorDpi( hwnd, MDT_DEFAULT ) ); - NtUserMapWindowPoints( hwnd, toplevel, (POINT *)&rect_dst, 2, NtUserGetWinMonitorDpi( hwnd, MDT_DEFAULT ) ); + NtUserGetClientRect( hwnd, &rect_dst, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); + NtUserMapWindowPoints( hwnd, toplevel, (POINT *)&rect_dst, 2, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) );
if ((data = get_win_data( toplevel ))) { diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index c9018e97b25..58786d962cf 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1864,7 +1864,7 @@ Window create_client_window( HWND hwnd, const XVisualInfo *visual, Colormap colo HWND parent = NtUserGetAncestor( hwnd, GA_PARENT ); if (parent == NtUserGetDesktopWindow() || NtUserGetAncestor( parent, GA_PARENT )) return 0; if (!(data = alloc_win_data( thread_init_display(), hwnd ))) return 0; - NtUserGetClientRect( hwnd, &data->rects.client, NtUserGetWinMonitorDpi( hwnd, MDT_DEFAULT ) ); + NtUserGetClientRect( hwnd, &data->rects.client, NtUserGetWinMonitorDpi( hwnd, MDT_RAW_DPI ) ); data->rects.window = data->rects.visible = data->rects.client; }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 50788524754..f1f0f97486b 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -852,7 +852,7 @@ extern void xim_set_focus( HWND hwnd, BOOL focus );
static inline BOOL is_window_rect_mapped( const RECT *rect ) { - RECT virtual_rect = NtUserGetVirtualScreenRect( MDT_DEFAULT ); + RECT virtual_rect = NtUserGetVirtualScreenRect( MDT_RAW_DPI ); return (rect->left < virtual_rect.right && rect->top < virtual_rect.bottom && max( rect->right, rect->left + 1 ) > virtual_rect.left &&
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 107 ++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 53 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 327bb5cce9c..dee0dd13d1b 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1759,6 +1759,60 @@ static BOOL is_monitor_primary( struct monitor *monitor ) return !!(source->state_flags & DISPLAY_DEVICE_PRIMARY_DEVICE); }
+/* display_lock must be held */ +static UINT monitor_get_dpi( struct monitor *monitor, MONITOR_DPI_TYPE type, UINT *dpi_x, UINT *dpi_y ) +{ + struct source *source = monitor->source; + float scale_x = 1.0, scale_y = 1.0; + UINT dpi; + + if (!source || !(dpi = source->dpi)) dpi = system_dpi; + *dpi_x = round( dpi * scale_x ); + *dpi_y = round( dpi * scale_y ); + return min( *dpi_x, *dpi_y ); +} + +/* display_lock must be held */ +static RECT monitor_get_rect( struct monitor *monitor, UINT dpi, MONITOR_DPI_TYPE type ) +{ + DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; + RECT rect = {0, 0, 1024, 768}; + struct source *source; + UINT dpi_from, x, y; + + /* services do not have any adapters, only a virtual monitor */ + if (!(source = monitor->source)) return rect; + + SetRectEmpty( &rect ); + if (!(source->state_flags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) return rect; + source_get_current_settings( source, ¤t_mode ); + + SetRect( &rect, current_mode.dmPosition.x, current_mode.dmPosition.y, + current_mode.dmPosition.x + current_mode.dmPelsWidth, + current_mode.dmPosition.y + current_mode.dmPelsHeight ); + + dpi_from = monitor_get_dpi( monitor, type, &x, &y ); + return map_dpi_rect( rect, dpi_from, dpi ); +} + +/* display_lock must be held */ +static void monitor_get_info( struct monitor *monitor, MONITORINFO *info, UINT dpi ) +{ + UINT x, y; + + info->rcMonitor = monitor_get_rect( monitor, dpi, MDT_DEFAULT ); + info->rcWork = map_dpi_rect( monitor->rc_work, monitor_get_dpi( monitor, MDT_DEFAULT, &x, &y ), dpi ); + info->dwFlags = is_monitor_primary( monitor ) ? MONITORINFOF_PRIMARY : 0; + + if (info->cbSize >= sizeof(MONITORINFOEXW)) + { + char buffer[CCHDEVICENAME]; + if (monitor->source) snprintf( buffer, sizeof(buffer), "\\.\DISPLAY%d", monitor->source->id + 1 ); + else strcpy( buffer, "WinDisc" ); + asciiz_to_unicode( ((MONITORINFOEXW *)info)->szDevice, buffer ); + } +} + static void enum_device_keys( const char *root, const WCHAR *classW, UINT class_size, void (*callback)(const char *) ) { char buffer[1024]; @@ -2215,59 +2269,6 @@ static void release_display_dc( HDC hdc ) pthread_mutex_unlock( &display_dc_lock ); }
-/* display_lock must be held */ -static UINT monitor_get_dpi( struct monitor *monitor, MONITOR_DPI_TYPE type, UINT *dpi_x, UINT *dpi_y ) -{ - struct source *source = monitor->source; - float scale_x = 1.0, scale_y = 1.0; - UINT dpi; - - if (!source || !(dpi = source->dpi)) dpi = system_dpi; - *dpi_x = round( dpi * scale_x ); - *dpi_y = round( dpi * scale_y ); - return min( *dpi_x, *dpi_y ); -} - -/* display_lock must be held */ -static RECT monitor_get_rect( struct monitor *monitor, UINT dpi, MONITOR_DPI_TYPE type ) -{ - DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; - RECT rect = {0, 0, 1024, 768}; - struct source *source; - UINT dpi_from, x, y; - - /* services do not have any adapters, only a virtual monitor */ - if (!(source = monitor->source)) return rect; - - SetRectEmpty( &rect ); - if (!(source->state_flags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) return rect; - source_get_current_settings( source, ¤t_mode ); - - SetRect( &rect, current_mode.dmPosition.x, current_mode.dmPosition.y, - current_mode.dmPosition.x + current_mode.dmPelsWidth, - current_mode.dmPosition.y + current_mode.dmPelsHeight ); - - dpi_from = monitor_get_dpi( monitor, type, &x, &y ); - return map_dpi_rect( rect, dpi_from, dpi ); -} - -static void monitor_get_info( struct monitor *monitor, MONITORINFO *info, UINT dpi ) -{ - UINT x, y; - - info->rcMonitor = monitor_get_rect( monitor, dpi, MDT_DEFAULT ); - info->rcWork = map_dpi_rect( monitor->rc_work, monitor_get_dpi( monitor, MDT_DEFAULT, &x, &y ), dpi ); - info->dwFlags = is_monitor_primary( monitor ) ? MONITORINFOF_PRIMARY : 0; - - if (info->cbSize >= sizeof(MONITORINFOEXW)) - { - char buffer[CCHDEVICENAME]; - if (monitor->source) snprintf( buffer, sizeof(buffer), "\\.\DISPLAY%d", monitor->source->id + 1 ); - else strcpy( buffer, "WinDisc" ); - asciiz_to_unicode( ((MONITORINFOEXW *)info)->szDevice, buffer ); - } -} - /* display_lock must be held */ static struct monitor *get_monitor_from_rect( RECT rect, UINT flags, UINT dpi, MONITOR_DPI_TYPE type ) {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 42 +++++++++++++++++++++++++++++++++++++++-- server/protocol.def | 17 +++++++++++++++++ server/trace.c | 18 ++++++++++++++++++ server/user.h | 2 ++ server/winstation.c | 24 +++++++++++++++++++++++ 5 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index dee0dd13d1b..60667a39cf8 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1699,6 +1699,8 @@ static void add_modes( const DEVMODEW *current, UINT modes_count, const DEVMODEW set_reg_value( source->key, modesW, REG_BINARY, modes, modes_count * sizeof(*modes) ); set_reg_value( source->key, mode_countW, REG_DWORD, &modes_count, sizeof(modes_count) ); source->mode_count = modes_count; + source->current = *current; + source->physical = physical;
free( virtual_modes ); } @@ -1813,6 +1815,37 @@ static void monitor_get_info( struct monitor *monitor, MONITORINFO *info, UINT d } }
+/* display_lock must be held */ +static void set_winstation_monitors(void) +{ + struct monitor_info *infos, *info; + struct monitor *monitor; + UINT count, x, y; + + if (!(count = list_count( &monitors ))) return; + if (!(info = infos = calloc( count, sizeof(*infos) ))) return; + + 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->virt = wine_server_rectangle( monitor_get_rect( monitor, 0, MDT_EFFECTIVE_DPI ) ); + info->raw = wine_server_rectangle( monitor_get_rect( monitor, 0, MDT_RAW_DPI ) ); + info++; + } + + SERVER_START_REQ( set_winstation_monitors ) + { + wine_server_add_data( req, infos, count * sizeof(*infos) ); + wine_server_call( req ); + } + SERVER_END_REQ; + + free( infos ); +} + static void enum_device_keys( const char *root, const WCHAR *classW, UINT class_size, void (*callback)(const char *) ) { char buffer[1024]; @@ -1979,6 +2012,8 @@ static BOOL update_display_cache_from_registry(void)
if ((ret = !list_empty( &sources ) && !list_empty( &monitors ))) last_query_display_time = key.LastWriteTime.QuadPart; + + set_winstation_monitors(); pthread_mutex_unlock( &display_lock ); release_display_device_init_mutex( mutex ); return ret; @@ -2153,7 +2188,7 @@ static UINT update_display_devices( struct device_manager_ctx *ctx ) return status; }
-static void add_vulkan_only_gpus( struct device_manager_ctx *ctx ) +static void commit_display_devices( struct device_manager_ctx *ctx ) { struct vulkan_gpu *gpu, *next;
@@ -2162,6 +2197,8 @@ static void add_vulkan_only_gpus( struct device_manager_ctx *ctx ) TRACE( "adding vulkan-only gpu uuid %s, name %s\n", debugstr_guid(&gpu->uuid), debugstr_a(gpu->name)); add_gpu( gpu->name, &gpu->pci_id, &gpu->uuid, ctx ); } + + set_winstation_monitors(); }
BOOL update_display_cache( BOOL force ) @@ -2180,6 +2217,7 @@ BOOL update_display_cache( BOOL force ) pthread_mutex_lock( &display_lock ); clear_display_devices(); list_add_tail( &monitors, &virtual_monitor.entry ); + set_winstation_monitors(); pthread_mutex_unlock( &display_lock ); return TRUE; } @@ -2188,7 +2226,7 @@ BOOL update_display_cache( BOOL force ) else { if (!get_vulkan_gpus( &ctx.vulkan_gpus )) WARN( "Failed to find any vulkan GPU\n" ); - if (!(status = update_display_devices( &ctx ))) add_vulkan_only_gpus( &ctx ); + if (!(status = update_display_devices( &ctx ))) commit_display_devices( &ctx ); else WARN( "Failed to update display devices, status %#x\n", status ); release_display_manager_ctx( &ctx ); } diff --git a/server/protocol.def b/server/protocol.def index ac22f9853e5..9ecb14cbac4 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -896,6 +896,17 @@ struct directory_entry /* VARARG(type,unicode_str,type_len); */ };
+struct monitor_info +{ + rectangle_t raw; /* host / physical position of the monitor rect */ + rectangle_t virt; /* client / virtual position of the monitor rect */ + unsigned int flags; /* MONITOR_FLAG_* flags for the monitor */ + unsigned int dpi; /* physical DPI for the monitor */ +}; +#define MONITOR_FLAG_PRIMARY 0x01 +#define MONITOR_FLAG_CLONE 0x02 +#define MONITOR_FLAG_INACTIVE 0x04 + /****************************************************************/ /* shared session mapping structures */
@@ -2802,6 +2813,12 @@ enum coords_relative @END
+/* Update the process current window station monitors */ +@REQ(set_winstation_monitors) + VARARG(infos,monitor_infos); /* window station monitors */ +@END + + /* Get the process current window station */ @REQ(get_process_winstation) @REPLY diff --git a/server/trace.c b/server/trace.c index 7142c37218a..82e86313027 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1511,6 +1511,24 @@ static void dump_varargs_directory_entries( const char *prefix, data_size_t size fputc( '}', stderr ); }
+static void dump_varargs_monitor_infos( const char *prefix, data_size_t size ) +{ + const struct monitor_info *monitor = cur_data; + data_size_t len = size / sizeof(*monitor); + + fprintf( stderr,"%s{", prefix ); + while (len > 0) + { + dump_rectangle( "{raw:", &monitor->virt ); + dump_rectangle( ",virt:", &monitor->virt ); + fprintf( stderr, ",flags:%#x,dpi:%u", monitor->flags, monitor->dpi ); + fputc( '}', stderr ); + if (--len) fputc( ',', stderr ); + } + fputc( '}', stderr ); + remove_data( size ); +} + typedef void (*dump_func)( const void *req );
/* Everything below this line is generated automatically by tools/make_requests */ diff --git a/server/user.h b/server/user.h index 6f9612ffb93..7a61fa70214 100644 --- a/server/user.h +++ b/server/user.h @@ -52,6 +52,8 @@ struct winstation struct clipboard *clipboard; /* clipboard information */ struct atom_table *atom_table; /* global atom table */ struct namespace *desktop_names; /* namespace for desktops of this winstation */ + unsigned int monitor_count; /* number of monitors */ + struct monitor_info *monitors; /* window station monitors */ };
struct key_repeat diff --git a/server/winstation.c b/server/winstation.c index e5f4bfec357..1cd7d325fd1 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -147,6 +147,8 @@ static struct winstation *create_winstation( struct object *root, const struct u winstation->input_desktop = NULL; winstation->clipboard = NULL; winstation->atom_table = NULL; + winstation->monitors = NULL; + winstation->monitor_count = 0; list_add_tail( &winstation_list, &winstation->entry ); list_init( &winstation->desktops ); if (!(winstation->desktop_names = create_namespace( 7 ))) @@ -203,6 +205,7 @@ static void winstation_destroy( struct object *obj ) if (winstation->clipboard) release_object( winstation->clipboard ); if (winstation->atom_table) release_object( winstation->atom_table ); free( winstation->desktop_names ); + free( winstation->monitors ); }
/* retrieve the process window station, checking the handle access rights */ @@ -636,6 +639,27 @@ DECL_HANDLER(close_winstation) }
+/* set the process current window station monitors */ +DECL_HANDLER(set_winstation_monitors) +{ + struct winstation *winstation; + unsigned int size; + + if (!(winstation = (struct winstation *)get_handle_obj( current->process, current->process->winstation, + 0, &winstation_ops ))) + return; + + free( winstation->monitors ); + winstation->monitors = NULL; + winstation->monitor_count = 0; + + if ((size = get_req_data_size()) && (winstation->monitors = memdup( get_req_data(), size ))) + winstation->monitor_count = size / sizeof(*winstation->monitors); + + release_object( winstation ); +} + + /* get the process current window station */ DECL_HANDLER(get_process_winstation) {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 2 +- server/queue.c | 6 +++--- server/user.h | 33 ++++++++++++++++++++++++++++++++- server/window.c | 24 +++++++++++++++++++----- 4 files changed, 55 insertions(+), 10 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 60667a39cf8..f069f495620 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2307,7 +2307,7 @@ static void release_display_dc( HDC hdc ) pthread_mutex_unlock( &display_dc_lock ); }
-/* display_lock must be held */ +/* display_lock must be held, keep in sync with server/window.c */ static struct monitor *get_monitor_from_rect( RECT rect, UINT flags, UINT dpi, MONITOR_DPI_TYPE type ) { struct monitor *monitor, *primary = NULL, *nearest = NULL, *found = NULL; diff --git a/server/queue.c b/server/queue.c index c99c8d8661b..127a4766458 100644 --- a/server/queue.c +++ b/server/queue.c @@ -472,7 +472,7 @@ static int is_cursor_clipped( struct desktop *desktop ) { const desktop_shm_t *desktop_shm = desktop->shared; rectangle_t top_rect, clip_rect = desktop_shm->cursor.clip; - get_top_window_rectangle( desktop, &top_rect ); + get_virtual_screen_rect( desktop, &top_rect, 1 ); return !is_rect_equal( &clip_rect, &top_rect ); }
@@ -603,7 +603,7 @@ void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, unsig unsigned int old_flags; int x, y;
- get_top_window_rectangle( desktop, &top_rect ); + get_virtual_screen_rect( desktop, &top_rect, 1 ); if (rect) { new_rect = *rect; @@ -2522,7 +2522,7 @@ static void queue_pointer_message( struct pointer *pointer, int repeated ) struct message *msg; int x, y;
- get_top_window_rectangle( desktop, &top_rect ); + get_virtual_screen_rect( desktop, &top_rect, 0 ); x = LOWORD(input->hw.lparam) * (top_rect.right - top_rect.left) / 65535; y = HIWORD(input->hw.lparam) * (top_rect.bottom - top_rect.top) / 65535;
diff --git a/server/user.h b/server/user.h index 7a61fa70214..c8514f776b3 100644 --- a/server/user.h +++ b/server/user.h @@ -21,6 +21,7 @@ #ifndef __WINE_SERVER_USER_H #define __WINE_SERVER_USER_H
+#include <limits.h> #include "wine/server_protocol.h" #include "unicode.h"
@@ -173,7 +174,7 @@ extern int rect_in_region( struct region *region, const rectangle_t *rect ); /* window functions */
extern struct process *get_top_window_owner( struct desktop *desktop ); -extern void get_top_window_rectangle( struct desktop *desktop, rectangle_t *rect ); +extern void get_virtual_screen_rect( struct desktop *desktop, rectangle_t *rect, int is_raw ); extern void post_desktop_message( struct desktop *desktop, unsigned int message, lparam_t wparam, lparam_t lparam ); extern void free_window_handle( struct window *win ); @@ -276,6 +277,36 @@ static inline int intersect_rect( rectangle_t *dst, const rectangle_t *src1, con return !is_rect_empty( dst ); }
+static inline void reset_bounds( rectangle_t *bounds ) +{ + bounds->left = bounds->top = INT_MAX; + bounds->right = bounds->bottom = INT_MIN; +} + +static inline void union_rect( rectangle_t *dest, const rectangle_t *src1, const rectangle_t *src2 ) +{ + if (is_rect_empty( src1 )) + { + if (is_rect_empty( src2 )) + { + reset_bounds( dest ); + return; + } + else *dest = *src2; + } + else + { + if (is_rect_empty( src2 )) *dest = *src1; + else + { + dest->left = min( src1->left, src2->left ); + dest->right = max( src1->right, src2->right ); + dest->top = min( src1->top, src2->top ); + dest->bottom = max( src1->bottom, src2->bottom ); + } + } +} + /* validate a window handle and return the full handle */ static inline user_handle_t get_valid_window_handle( user_handle_t win ) { diff --git a/server/window.c b/server/window.c index 412592fbc71..f40f81f428b 100644 --- a/server/window.c +++ b/server/window.c @@ -240,6 +240,21 @@ static inline void update_pixel_format_flags( struct window *win ) win->paint_flags |= PAINT_PIXEL_FORMAT_CHILD; }
+static rectangle_t monitors_get_union_rect( struct winstation *winstation, int is_raw ) +{ + struct monitor_info *monitor, *end; + rectangle_t rect = {0}; + + for (monitor = winstation->monitors, end = monitor + winstation->monitor_count; monitor < end; monitor++) + { + rectangle_t monitor_rect = is_raw ? monitor->raw : monitor->virt; + if (monitor->flags & (MONITOR_FLAG_CLONE | MONITOR_FLAG_INACTIVE)) continue; + union_rect( &rect, &rect, &monitor_rect ); + } + + return rect; +} + /* get the per-monitor DPI for a window */ static unsigned int get_monitor_dpi( struct window *win ) { @@ -499,10 +514,9 @@ struct process *get_top_window_owner( struct desktop *desktop ) }
/* get the top window size of a given desktop */ -void get_top_window_rectangle( struct desktop *desktop, rectangle_t *rect ) +void get_virtual_screen_rect( struct desktop *desktop, rectangle_t *rect, int is_raw ) { - struct window *win = desktop->top_window; - *rect = win ? win->window_rect : empty_rect; + *rect = monitors_get_union_rect( desktop->winstation, is_raw ); }
/* post a message to the desktop window */ @@ -893,7 +907,7 @@ static int get_window_children_from_point( struct window *parent, int x, int y, return 1; }
-/* get handle of root of top-most window containing point */ +/* get handle of root of top-most window containing point (in absolute raw coords) */ user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y ) { struct window *ptr; @@ -910,7 +924,7 @@ user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y ) return desktop->top_window->handle; }
-/* return thread of top-most window containing point (in absolute coords) */ +/* return thread of top-most window containing point (in absolute raw coords) */ struct thread *window_thread_from_point( user_handle_t scope, int x, int y ) { struct window *win = get_user_object( scope, USER_WINDOW );
v2: Don't set WinSta0 permanent, update processes window station monitor info every time it's being updated, from the host or from the registry. It'll make an additional wineserver request on every process when the display cache is updated from the registry, but hopefully that's not too bad (it happens after a whole lot of other registry related requests anyway). We could perhaps later consider to use this to update the cache instead of registry operations, to save some requests.
This merge request was approved by Huw Davies.