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. * 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 ); WND *win = WIN_GetPtr( hwnd );
BOOL ret = TRUE; BOOL ret = TRUE;
@ -678,12 +678,51 @@ BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
} }
if (rectWindow) *rectWindow = rect; if (rectWindow) *rectWindow = rect;
if (rectClient) *rectClient = rect; if (rectClient) *rectClient = rect;
return TRUE;
} }
else if (win == WND_OTHER_PROCESS) if (win != WND_OTHER_PROCESS)
{ {
RECT window_rect = win->rectWindow, client_rect = win->rectClient;
switch (relative)
{
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)
{
WND *parent = WIN_GetPtr( win->parent );
if (parent == WND_DESKTOP) break;
if (!parent || parent == WND_OTHER_PROCESS)
{
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;
}
if (rectWindow) *rectWindow = window_rect;
if (rectClient) *rectClient = client_rect;
WIN_ReleasePtr( win );
}
other_process:
SERVER_START_REQ( get_window_rectangles ) SERVER_START_REQ( get_window_rectangles )
{ {
req->handle = wine_server_user_handle( hwnd ); req->handle = wine_server_user_handle( hwnd );
req->relative = relative;
if ((ret = !wine_server_call_err( req ))) if ((ret = !wine_server_call_err( req )))
{ {
if (rectWindow) if (rectWindow)
@ -703,13 +742,6 @@ BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
} }
} }
SERVER_END_REQ; SERVER_END_REQ;
}
else
{
if (rectWindow) *rectWindow = win->rectWindow;
if (rectClient) *rectClient = win->rectClient;
WIN_ReleasePtr( win );
}
return ret; return ret;
} }

View File

@ -28,6 +28,7 @@
#include <winuser.h> #include <winuser.h>
#include "user_private.h" #include "user_private.h"
#include "wine/server_protocol.h"
struct tagCLASS; struct tagCLASS;
struct tagDIALOGINFO; 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_IsCurrentThread( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND WIN_SetOwner( HWND hwnd, HWND owner ) 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 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 LRESULT WIN_DestroyWindow( HWND hwnd ) DECLSPEC_HIDDEN;
extern void WIN_DestroyThreadWindows( 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; 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 WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
{ {
BOOL ret = WIN_GetRectangles( hwnd, rect, NULL ); BOOL ret = WIN_GetRectangles( hwnd, COORDS_SCREEN, rect, NULL );
if (ret) if (ret) TRACE( "hwnd %p %s\n", hwnd, wine_dbgstr_rect(rect) );
{
MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
TRACE( "hwnd %p (%s)\n", hwnd, wine_dbgstr_rect(rect) );
}
return ret; return ret;
} }
@ -235,15 +231,7 @@ int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
*/ */
BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect ) BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
{ {
BOOL ret; return WIN_GetRectangles( hwnd, COORDS_CLIENT, NULL, rect );
if ((ret = WIN_GetRectangles( hwnd, NULL, rect )))
{
rect->right -= rect->left;
rect->bottom -= rect->top;
rect->left = rect->top = 0;
}
return ret;
} }
@ -407,7 +395,7 @@ HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
for (i = 0; list[i]; i++) 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 (!PtInRect( &rect, pt )) continue;
if (uFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED)) if (uFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED))
{ {

View File

@ -1930,9 +1930,10 @@ BOOL CDECL X11DRV_CreateDesktopWindow( HWND hwnd )
SERVER_START_REQ( get_window_rectangles ) SERVER_START_REQ( get_window_rectangles )
{ {
req->handle = wine_server_user_handle( hwnd ); req->handle = wine_server_user_handle( hwnd );
req->relative = COORDS_CLIENT;
wine_server_call( req ); wine_server_call( req );
width = reply->window.right - reply->window.left; width = reply->window.right;
height = reply->window.bottom - reply->window.top; height = reply->window.bottom;
} }
SERVER_END_REQ; SERVER_END_REQ;

View File

@ -3268,6 +3268,8 @@ struct get_window_rectangles_request
{ {
struct request_header __header; struct request_header __header;
user_handle_t handle; user_handle_t handle;
int relative;
char __pad_20[4];
}; };
struct get_window_rectangles_reply struct get_window_rectangles_reply
{ {
@ -3276,6 +3278,13 @@ struct get_window_rectangles_reply
rectangle_t visible; rectangle_t visible;
rectangle_t client; 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; struct set_cursor_reply set_cursor_reply;
}; };
#define SERVER_PROTOCOL_VERSION 407 #define SERVER_PROTOCOL_VERSION 408
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -2344,11 +2344,19 @@ enum message_type
/* Get the window and client rectangles of a window */ /* Get the window and client rectangles of a window */
@REQ(get_window_rectangles) @REQ(get_window_rectangles)
user_handle_t handle; /* handle to the window */ user_handle_t handle; /* handle to the window */
int relative; /* coords relative to (see below) */
@REPLY @REPLY
rectangle_t window; /* window rectangle */ rectangle_t window; /* window rectangle */
rectangle_t visible; /* visible part of the window rectangle */ rectangle_t visible; /* visible part of the window rectangle */
rectangle_t client; /* client rectangle */ rectangle_t client; /* client rectangle */
@END @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 */ /* 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( FIELD_OFFSET(struct set_window_pos_reply, new_ex_style) == 12 );
C_ASSERT( sizeof(struct set_window_pos_reply) == 16 ); C_ASSERT( sizeof(struct set_window_pos_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_request, handle) == 12 ); 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, window) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_reply, visible) == 24 ); C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_reply, visible) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_window_rectangles_reply, client) == 40 ); 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 ) static void dump_get_window_rectangles_request( const struct get_window_rectangles_request *req )
{ {
fprintf( stderr, " handle=%08x", req->handle ); 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 ) 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 ); struct window *win = get_window( req->handle );
if (win) if (!win) return;
{
reply->window = win->window_rect; reply->window = win->window_rect;
reply->visible = win->visible_rect; reply->visible = win->visible_rect;
reply->client = win->client_rect; reply->client = win->client_rect;
switch (req->relative)
{
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;
} }
} }