From 7295b6746d64709106c235d02ab109c45e47f397 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 7 Sep 2010 14:31:30 +0200 Subject: [PATCH] user32: Add support for fetching window rectangles relative to various origins. --- dlls/user32/win.c | 78 ++++++++++++++++++++++++---------- dlls/user32/win.h | 3 +- dlls/user32/winpos.c | 20 ++------- dlls/winex11.drv/window.c | 5 ++- include/wine/server_protocol.h | 11 ++++- server/protocol.def | 8 ++++ server/request.h | 3 +- server/trace.c | 1 + server/window.c | 31 ++++++++++++-- 9 files changed, 112 insertions(+), 48 deletions(-) diff --git a/dlls/user32/win.c b/dlls/user32/win.c index bbc7fc2e191..d128c33de39 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -652,7 +652,7 @@ ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits ) * * Get the window and client rectangles. */ -BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient ) +BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWindow, RECT *rectClient ) { WND *win = WIN_GetPtr( hwnd ); BOOL ret = TRUE; @@ -678,38 +678,70 @@ BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient ) } if (rectWindow) *rectWindow = rect; if (rectClient) *rectClient = rect; + return TRUE; } - else if (win == WND_OTHER_PROCESS) + if (win != WND_OTHER_PROCESS) { - SERVER_START_REQ( get_window_rectangles ) + RECT window_rect = win->rectWindow, client_rect = win->rectClient; + + switch (relative) { - req->handle = wine_server_user_handle( hwnd ); - if ((ret = !wine_server_call_err( req ))) + case COORDS_CLIENT: + OffsetRect( &window_rect, -win->rectClient.left, -win->rectClient.top ); + OffsetRect( &client_rect, -win->rectClient.left, -win->rectClient.top ); + break; + case COORDS_WINDOW: + OffsetRect( &window_rect, -win->rectWindow.left, -win->rectWindow.top ); + OffsetRect( &client_rect, -win->rectWindow.left, -win->rectWindow.top ); + break; + case COORDS_PARENT: + break; + case COORDS_SCREEN: + while (win->parent) { - if (rectWindow) + WND *parent = WIN_GetPtr( win->parent ); + if (parent == WND_DESKTOP) break; + if (!parent || parent == WND_OTHER_PROCESS) { - rectWindow->left = reply->window.left; - rectWindow->top = reply->window.top; - rectWindow->right = reply->window.right; - rectWindow->bottom = reply->window.bottom; - } - if (rectClient) - { - rectClient->left = reply->client.left; - rectClient->top = reply->client.top; - rectClient->right = reply->client.right; - rectClient->bottom = reply->client.bottom; + WIN_ReleasePtr( win ); + goto other_process; } + WIN_ReleasePtr( win ); + win = parent; + OffsetRect( &window_rect, -win->rectClient.left, -win->rectClient.top ); + OffsetRect( &client_rect, -win->rectClient.left, -win->rectClient.top ); } + break; } - SERVER_END_REQ; - } - else - { - if (rectWindow) *rectWindow = win->rectWindow; - if (rectClient) *rectClient = win->rectClient; + if (rectWindow) *rectWindow = window_rect; + if (rectClient) *rectClient = client_rect; WIN_ReleasePtr( win ); } + +other_process: + SERVER_START_REQ( get_window_rectangles ) + { + req->handle = wine_server_user_handle( hwnd ); + req->relative = relative; + if ((ret = !wine_server_call_err( req ))) + { + if (rectWindow) + { + rectWindow->left = reply->window.left; + rectWindow->top = reply->window.top; + rectWindow->right = reply->window.right; + rectWindow->bottom = reply->window.bottom; + } + if (rectClient) + { + rectClient->left = reply->client.left; + rectClient->top = reply->client.top; + rectClient->right = reply->client.right; + rectClient->bottom = reply->client.bottom; + } + } + } + SERVER_END_REQ; return ret; } diff --git a/dlls/user32/win.h b/dlls/user32/win.h index d4d5f1a3cc7..631cc9649dd 100644 --- a/dlls/user32/win.h +++ b/dlls/user32/win.h @@ -28,6 +28,7 @@ #include #include "user_private.h" +#include "wine/server_protocol.h" struct tagCLASS; struct tagDIALOGINFO; @@ -81,7 +82,7 @@ extern HWND WIN_IsCurrentProcess( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND WIN_IsCurrentThread( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND WIN_SetOwner( HWND hwnd, HWND owner ) DECLSPEC_HIDDEN; extern ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits ) DECLSPEC_HIDDEN; -extern BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient ) DECLSPEC_HIDDEN; +extern BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWindow, RECT *rectClient ) DECLSPEC_HIDDEN; extern LRESULT WIN_DestroyWindow( HWND hwnd ) DECLSPEC_HIDDEN; extern void WIN_DestroyThreadWindows( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN; diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index e72f7fcee18..f3a0f78ad63 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -93,12 +93,8 @@ void WINAPI SwitchToThisWindow( HWND hwnd, BOOL alt_tab ) */ BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) { - BOOL ret = WIN_GetRectangles( hwnd, rect, NULL ); - if (ret) - { - MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 ); - TRACE( "hwnd %p (%s)\n", hwnd, wine_dbgstr_rect(rect) ); - } + BOOL ret = WIN_GetRectangles( hwnd, COORDS_SCREEN, rect, NULL ); + if (ret) TRACE( "hwnd %p %s\n", hwnd, wine_dbgstr_rect(rect) ); return ret; } @@ -235,15 +231,7 @@ int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw ) */ BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect ) { - BOOL ret; - - if ((ret = WIN_GetRectangles( hwnd, NULL, rect ))) - { - rect->right -= rect->left; - rect->bottom -= rect->top; - rect->left = rect->top = 0; - } - return ret; + return WIN_GetRectangles( hwnd, COORDS_CLIENT, NULL, rect ); } @@ -407,7 +395,7 @@ HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags) for (i = 0; list[i]; i++) { - if (!WIN_GetRectangles( list[i], &rect, NULL )) continue; + if (!WIN_GetRectangles( list[i], COORDS_PARENT, &rect, NULL )) continue; if (!PtInRect( &rect, pt )) continue; if (uFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED)) { diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 8957a44822b..99dbf4906a4 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1930,9 +1930,10 @@ BOOL CDECL X11DRV_CreateDesktopWindow( HWND hwnd ) SERVER_START_REQ( get_window_rectangles ) { req->handle = wine_server_user_handle( hwnd ); + req->relative = COORDS_CLIENT; wine_server_call( req ); - width = reply->window.right - reply->window.left; - height = reply->window.bottom - reply->window.top; + width = reply->window.right; + height = reply->window.bottom; } SERVER_END_REQ; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 6a9c1de8057..b6999567215 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3268,6 +3268,8 @@ struct get_window_rectangles_request { struct request_header __header; user_handle_t handle; + int relative; + char __pad_20[4]; }; struct get_window_rectangles_reply { @@ -3276,6 +3278,13 @@ struct get_window_rectangles_reply rectangle_t visible; rectangle_t client; }; +enum coords_relative +{ + COORDS_CLIENT, + COORDS_WINDOW, + COORDS_PARENT, + COORDS_SCREEN +}; @@ -5506,6 +5515,6 @@ union generic_reply struct set_cursor_reply set_cursor_reply; }; -#define SERVER_PROTOCOL_VERSION 407 +#define SERVER_PROTOCOL_VERSION 408 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index c3d2c1d677a..e3e078d8977 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2344,11 +2344,19 @@ enum message_type /* Get the window and client rectangles of a window */ @REQ(get_window_rectangles) user_handle_t handle; /* handle to the window */ + int relative; /* coords relative to (see below) */ @REPLY rectangle_t window; /* window rectangle */ rectangle_t visible; /* visible part of the window rectangle */ rectangle_t client; /* client rectangle */ @END +enum coords_relative +{ + COORDS_CLIENT, /* relative to client area */ + COORDS_WINDOW, /* relative to whole window area */ + COORDS_PARENT, /* relative to parent's client area */ + COORDS_SCREEN /* relative to screen origin */ +}; /* Get the window text */ diff --git a/server/request.h b/server/request.h index cb3f2d93e44..6cb37b3dfa6 100644 --- a/server/request.h +++ b/server/request.h @@ -1589,7 +1589,8 @@ C_ASSERT( FIELD_OFFSET(struct set_window_pos_reply, new_style) == 8 ); C_ASSERT( FIELD_OFFSET(struct set_window_pos_reply, new_ex_style) == 12 ); C_ASSERT( sizeof(struct set_window_pos_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_request, handle) == 12 ); -C_ASSERT( sizeof(struct get_window_rectangles_request) == 16 ); +C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_request, relative) == 16 ); +C_ASSERT( sizeof(struct get_window_rectangles_request) == 24 ); C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_reply, window) == 8 ); C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_reply, visible) == 24 ); C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_reply, client) == 40 ); diff --git a/server/trace.c b/server/trace.c index 408fe147c7f..6f0e01ebd2c 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2795,6 +2795,7 @@ static void dump_set_window_pos_reply( const struct set_window_pos_reply *req ) static void dump_get_window_rectangles_request( const struct get_window_rectangles_request *req ) { fprintf( stderr, " handle=%08x", req->handle ); + fprintf( stderr, ", relative=%d", req->relative ); } static void dump_get_window_rectangles_reply( const struct get_window_rectangles_reply *req ) diff --git a/server/window.c b/server/window.c index 5fdfd13f2d0..2013b3164fb 100644 --- a/server/window.c +++ b/server/window.c @@ -2122,11 +2122,34 @@ DECL_HANDLER(get_window_rectangles) { struct window *win = get_window( req->handle ); - if (win) + if (!win) return; + + reply->window = win->window_rect; + reply->visible = win->visible_rect; + reply->client = win->client_rect; + + switch (req->relative) { - reply->window = win->window_rect; - reply->visible = win->visible_rect; - reply->client = win->client_rect; + case COORDS_CLIENT: + offset_rect( &reply->window, -win->client_rect.left, -win->client_rect.top ); + offset_rect( &reply->visible, -win->client_rect.left, -win->client_rect.top ); + offset_rect( &reply->client, -win->client_rect.left, -win->client_rect.top ); + break; + case COORDS_WINDOW: + offset_rect( &reply->window, -win->window_rect.left, -win->window_rect.top ); + offset_rect( &reply->visible, -win->window_rect.left, -win->window_rect.top ); + offset_rect( &reply->client, -win->window_rect.left, -win->window_rect.top ); + break; + case COORDS_PARENT: + break; + case COORDS_SCREEN: + client_to_screen_rect( win->parent, &reply->window ); + client_to_screen_rect( win->parent, &reply->visible ); + client_to_screen_rect( win->parent, &reply->client ); + break; + default: + set_error( STATUS_INVALID_PARAMETER ); + break; } }