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.
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
Avoids losing monitor information when explorer is shutdown.
The info is still cached in the registry and we will only inform wineserver about display monitors when invalidating the cache. --- server/winstation.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/server/winstation.c b/server/winstation.c index e5f4bfec357..109715d77b3 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -154,6 +154,11 @@ static struct winstation *create_winstation( struct object *root, const struct u release_object( winstation ); return NULL; } + if (flags & WSF_VISIBLE) + { + grab_object( winstation ); + make_object_permanent( &winstation->obj ); + } } else clear_error(); } @@ -862,7 +867,15 @@ DECL_HANDLER(set_user_object_info) struct winstation *winstation = (struct winstation *)obj; reply->is_desktop = 0; reply->old_obj_flags = winstation->flags; - if (req->flags & SET_USER_OBJECT_SET_FLAGS) winstation->flags = req->obj_flags; + if (req->flags & SET_USER_OBJECT_SET_FLAGS) + { + if (!(winstation->flags & WSF_VISIBLE) && (req->obj_flags & WSF_VISIBLE)) + { + grab_object( winstation ); + make_object_permanent( &winstation->obj ); + } + winstation->flags = req->obj_flags; + } } else {
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 | 34 +++++++++++++++++++++++++++++++--- server/protocol.def | 17 +++++++++++++++++ server/trace.c | 18 ++++++++++++++++++ server/user.h | 2 ++ server/winstation.c | 22 ++++++++++++++++++++++ 5 files changed, 90 insertions(+), 3 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index dee0dd13d1b..84462f1d3e2 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 ); } @@ -2153,15 +2155,41 @@ 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 monitor_info *infos, *info; struct vulkan_gpu *gpu, *next; + struct monitor *monitor; + UINT count, x, y;
LIST_FOR_EACH_ENTRY_SAFE( gpu, next, &ctx->vulkan_gpus, struct vulkan_gpu, entry ) { 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 ); } + + if ((count = list_count( &monitors )) && (infos = info = calloc( count, sizeof(*infos) ))) + { + 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_monitor_infos ) + { + wine_server_add_data( req, infos, count * sizeof(*infos) ); + wine_server_call( req ); + } + SERVER_END_REQ; + + free( infos ); + } }
BOOL update_display_cache( BOOL force ) @@ -2188,7 +2216,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 ); } @@ -2269,7 +2297,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/protocol.def b/server/protocol.def index ac22f9853e5..4c2aeb65b1e 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 */
@@ -2869,6 +2880,12 @@ enum coords_relative @END
+/* Update the winstation monitors */ +@REQ(set_monitor_infos) + VARARG(infos,monitor_infos); /* array of monitor_info */ +@END + + /* Get the thread current desktop */ @REQ(get_thread_desktop) thread_id_t tid; /* thread id */ 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..67b0ae2cc67 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 */ + struct monitor_info *monitors; /* monitors connected to the winstation */ + unsigned int monitor_count; /* number of connected monitors */ };
struct key_repeat diff --git a/server/winstation.c b/server/winstation.c index 109715d77b3..8265c720340 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 ))) @@ -208,6 +210,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 */ @@ -662,6 +665,25 @@ DECL_HANDLER(set_process_winstation) } }
+/* set the winstation monitors */ +DECL_HANDLER(set_monitor_infos) +{ + struct desktop *desktop = get_thread_desktop( current, 0 ); + struct winstation *winstation = get_visible_winstation(); + unsigned int size = get_req_data_size(); + + if (!winstation) return; + + free( winstation->monitors ); + winstation->monitors = NULL; + winstation->monitor_count = 0; + + if ((winstation->monitors = memdup( get_req_data(), size ))) + winstation->monitor_count = size / sizeof(*winstation->monitors); + + release_object( desktop ); +} + /* create a desktop */ DECL_HANDLER(create_desktop) {
From: Rémi Bernon rbernon@codeweavers.com
--- server/queue.c | 6 +++--- server/user.h | 33 ++++++++++++++++++++++++++++++++- server/window.c | 24 +++++++++++++++++++----- 3 files changed, 54 insertions(+), 9 deletions(-)
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 67b0ae2cc67..276d759d6da 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 );
Hmm I guess making WinSta0 permanent is what's breaking the tests... annoying :/