user32: Add support for fetching window rectangles relative to various origins.

This commit is contained in:
Alexandre Julliard 2010-09-07 14:31:30 +02:00
parent 2349a5eb4f
commit 7295b6746d
9 changed files with 112 additions and 48 deletions

View File

@ -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;
}

View File

@ -28,6 +28,7 @@
#include <winuser.h>
#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;

View File

@ -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))
{

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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 );

View File

@ -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 )

View File

@ -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;
}
}