diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index 513bf8538f8..66600a71472 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -136,7 +136,6 @@ static void dpiaware_init(void) static const struct user_callbacks user_funcs = { CopyImage, - GetWindowRect, RedrawWindow, SendMessageTimeoutW, SendMessageW, diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 14077d2c77b..ba46440bc36 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -88,7 +88,7 @@ void WINAPI SwitchToThisWindow( HWND hwnd, BOOL alt_tab ) */ BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) { - BOOL ret = WIN_GetRectangles( hwnd, COORDS_SCREEN, rect, NULL ); + BOOL ret = NtUserCallHwndParam( hwnd, (UINT_PTR)rect, NtUserGetWindowRect ); if (ret) TRACE( "hwnd %p %s\n", hwnd, wine_dbgstr_rect(rect) ); return ret; } diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 80c50433ecd..0b7ad9d2e77 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -30,7 +30,6 @@ struct dce; struct user_callbacks { HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT ); - BOOL (WINAPI *pGetWindowRect)( HWND hwnd, LPRECT rect ); BOOL (WINAPI *pRedrawWindow)( HWND, const RECT*, HRGN, UINT ); LRESULT (WINAPI *pSendMessageTimeoutW)( HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR ); LRESULT (WINAPI *pSendMessageW)( HWND, UINT, WPARAM, LPARAM ); diff --git a/dlls/win32u/region.c b/dlls/win32u/region.c index e524dd66f34..a51388c2fcb 100644 --- a/dlls/win32u/region.c +++ b/dlls/win32u/region.c @@ -1376,8 +1376,7 @@ BOOL mirror_window_region( HWND hwnd, HRGN hrgn ) { RECT rect; - if (!user_callbacks) return FALSE; - user_callbacks->pGetWindowRect( hwnd, &rect ); + if (!get_window_rect( hwnd, &rect )) return FALSE; return mirror_region( hrgn, hrgn, rect.right - rect.left ) != ERROR; } diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 3bcc2df007a..cffb45b2ef3 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1513,7 +1513,7 @@ RECT get_display_rect( const WCHAR *display ) return map_dpi_rect( rect, system_dpi, get_thread_dpi() ); } -static RECT get_primary_monitor_rect( UINT dpi ) +RECT get_primary_monitor_rect( UINT dpi ) { struct monitor *monitor; RECT rect = {0}; diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 42426a512f0..988a009d874 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -285,6 +285,7 @@ extern LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) extern RECT get_display_rect( const WCHAR *display ) DECLSPEC_HIDDEN; extern UINT get_monitor_dpi( HMONITOR monitor ) DECLSPEC_HIDDEN; extern UINT get_win_monitor_dpi( HWND hwnd ) DECLSPEC_HIDDEN; +extern RECT get_primary_monitor_rect( UINT dpi ) DECLSPEC_HIDDEN; extern UINT get_system_dpi(void) DECLSPEC_HIDDEN; extern int get_system_metrics( int index ) DECLSPEC_HIDDEN; extern UINT get_thread_dpi(void) DECLSPEC_HIDDEN; @@ -303,6 +304,7 @@ extern HWND get_desktop_window(void) DECLSPEC_HIDDEN; extern HWND is_current_thread_window( HWND hwnd ) DECLSPEC_HIDDEN; extern void flush_window_surfaces( BOOL idle ) DECLSPEC_HIDDEN; extern DWORD get_window_long( HWND hwnd, INT offset ) DECLSPEC_HIDDEN; +extern BOOL get_window_rect( HWND hwnd, RECT *rect ) DECLSPEC_HIDDEN; extern void register_window_surface( struct window_surface *old, struct window_surface *new ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 8aa794421d2..84aa052a231 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -28,7 +28,7 @@ #include "ntstatus.h" #define WIN32_NO_STATUS -#include "win32u_private.h" +#include "ntgdi_private.h" #include "ntuser_private.h" #include "wine/server.h" #include "wine/debug.h" @@ -988,6 +988,156 @@ HANDLE WINAPI NtUserRemoveProp( HWND hwnd, const WCHAR *str ) return (HANDLE)ret; } +static void mirror_rect( const RECT *window_rect, RECT *rect ) +{ + int width = window_rect->right - window_rect->left; + int tmp = rect->left; + rect->left = width - rect->right; + rect->right = width - tmp; +} + +/*********************************************************************** + * get_window_rects + * + * Get the window and client rectangles. + */ +static BOOL get_window_rects( HWND hwnd, enum coords_relative relative, RECT *window_rect, + RECT *client_rect, UINT dpi ) +{ + WND *win = get_win_ptr( hwnd ); + BOOL ret = TRUE; + + if (!win) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return FALSE; + } + if (win == WND_DESKTOP) + { + RECT rect; + rect.left = rect.top = 0; + if (hwnd == get_hwnd_message_parent()) + { + rect.right = 100; + rect.bottom = 100; + rect = map_dpi_rect( rect, get_dpi_for_window( hwnd ), dpi ); + } + else + { + rect = get_primary_monitor_rect( dpi ); + } + if (window_rect) *window_rect = rect; + if (client_rect) *client_rect = rect; + return TRUE; + } + if (win != WND_OTHER_PROCESS) + { + UINT window_dpi = get_dpi_for_window( hwnd ); + RECT window = win->window_rect; + RECT client = win->client_rect; + + switch (relative) + { + case COORDS_CLIENT: + OffsetRect( &window, -win->client_rect.left, -win->client_rect.top ); + OffsetRect( &client, -win->client_rect.left, -win->client_rect.top ); + if (win->dwExStyle & WS_EX_LAYOUTRTL) + mirror_rect( &win->client_rect, &window ); + break; + case COORDS_WINDOW: + OffsetRect( &window, -win->window_rect.left, -win->window_rect.top ); + OffsetRect( &client, -win->window_rect.left, -win->window_rect.top ); + if (win->dwExStyle & WS_EX_LAYOUTRTL) + mirror_rect( &win->window_rect, &client ); + break; + case COORDS_PARENT: + if (win->parent) + { + WND *parent = get_win_ptr( win->parent ); + if (parent == WND_DESKTOP) break; + if (!parent || parent == WND_OTHER_PROCESS) + { + release_win_ptr( win ); + goto other_process; + } + if (parent->flags & WIN_CHILDREN_MOVED) + { + release_win_ptr( parent ); + release_win_ptr( win ); + goto other_process; + } + if (parent->dwExStyle & WS_EX_LAYOUTRTL) + { + mirror_rect( &parent->client_rect, &window ); + mirror_rect( &parent->client_rect, &client ); + } + release_win_ptr( parent ); + } + break; + case COORDS_SCREEN: + while (win->parent) + { + WND *parent = get_win_ptr( win->parent ); + if (parent == WND_DESKTOP) break; + if (!parent || parent == WND_OTHER_PROCESS) + { + release_win_ptr( win ); + goto other_process; + } + release_win_ptr( win ); + if (parent->flags & WIN_CHILDREN_MOVED) + { + release_win_ptr( parent ); + goto other_process; + } + win = parent; + if (win->parent) + { + offset_rect( &window, win->client_rect.left, win->client_rect.top ); + offset_rect( &client, win->client_rect.left, win->client_rect.top ); + } + } + break; + } + if (window_rect) *window_rect = map_dpi_rect( window, window_dpi, dpi ); + if (client_rect) *client_rect = map_dpi_rect( client, window_dpi, dpi ); + release_win_ptr( win ); + return TRUE; + } + +other_process: + SERVER_START_REQ( get_window_rectangles ) + { + req->handle = wine_server_user_handle( hwnd ); + req->relative = relative; + req->dpi = dpi; + if ((ret = !wine_server_call_err( req ))) + { + if (window_rect) + { + window_rect->left = reply->window.left; + window_rect->top = reply->window.top; + window_rect->right = reply->window.right; + window_rect->bottom = reply->window.bottom; + } + if (client_rect) + { + client_rect->left = reply->client.left; + client_rect->top = reply->client.top; + client_rect->right = reply->client.right; + client_rect->bottom = reply->client.bottom; + } + } + } + SERVER_END_REQ; + return ret; +} + +/* see GetWindowRect */ +BOOL get_window_rect( HWND hwnd, RECT *rect ) +{ + return get_window_rects( hwnd, COORDS_SCREEN, rect, NULL, get_thread_dpi() ); +} /***************************************************************************** * NtUserGetLayeredWindowAttributes (win32u.@) @@ -1197,6 +1347,8 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) return get_window_long_ptr( hwnd, param, TRUE ); case NtUserGetWindowLongPtrW: return get_window_long_ptr( hwnd, param, FALSE ); + case NtUserGetWindowRect: + return get_window_rect( hwnd, (RECT *)param ); case NtUserGetWindowRelative: return HandleToUlong( get_window_relative( hwnd, param )); case NtUserGetWindowThread: diff --git a/include/ntuser.h b/include/ntuser.h index 20c8c2876f0..f5911d112a2 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -164,6 +164,7 @@ enum NtUserGetWindowLongW, NtUserGetWindowLongPtrA, NtUserGetWindowLongPtrW, + NtUserGetWindowRect, NtUserGetWindowRelative, NtUserGetWindowThread, NtUserGetWindowWord,