user32: Add support for RTL window layouts in MapWindowPoints.

This commit is contained in:
Alexandre Julliard 2010-09-22 20:27:52 +02:00
parent cf72f406ec
commit 5702324b37
7 changed files with 113 additions and 41 deletions

View File

@ -6164,6 +6164,44 @@ static void test_winregion(void)
DestroyWindow(hwnd);
}
static void test_rtl_layout(void)
{
HWND parent, child;
RECT r;
POINT pt;
if (!pSetProcessDefaultLayout)
{
win_skip( "SetProcessDefaultLayout not supported\n" );
return;
}
parent = CreateWindowExA(WS_EX_LAYOUTRTL, "static", NULL, WS_POPUP, 100, 100, 300, 300, NULL, 0, 0, NULL);
child = CreateWindowExA(0, "static", NULL, WS_CHILD, 10, 10, 20, 20, parent, 0, 0, NULL);
GetWindowRect( parent, &r );
ok( r.left == 100 && r.right == 400, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
GetClientRect( parent, &r );
ok( r.left == 0 && r.right == 300, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
GetClientRect( child, &r );
ok( r.left == 0 && r.right == 20, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
MapWindowPoints( child, parent, (POINT *)&r, 2 );
ok( r.left == 10 && r.right == 30, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
GetWindowRect( child, &r );
ok( r.left == 370 && r.right == 390, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
ok( r.left == 10 && r.right == 30, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
GetWindowRect( child, &r );
MapWindowPoints( NULL, parent, (POINT *)&r, 1 );
MapWindowPoints( NULL, parent, (POINT *)&r + 1, 1 );
ok( r.left == 30 && r.right == 10, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
pt.x = pt.y = 12;
MapWindowPoints( child, parent, &pt, 1 );
ok( pt.x == 22 && pt.y == 22, "wrong point %d,%d\n", pt.x, pt.y );
DestroyWindow( child );
DestroyWindow( parent );
}
START_TEST(win)
{
HMODULE user32 = GetModuleHandleA( "user32.dll" );
@ -6218,6 +6256,7 @@ START_TEST(win)
test_capture_2();
test_capture_3(hwndMain, hwndMain2);
test_capture_4();
test_rtl_layout();
test_CreateWindow();
test_parent_owner();

View File

@ -422,75 +422,83 @@ HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
* Calculate the offset between the origin of the two windows. Used
* to implement MapWindowPoints.
*/
static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset )
static POINT WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, BOOL *mirrored )
{
WND * wndPtr;
POINT offset;
BOOL mirror_from, mirror_to;
HWND hwnd;
offset->x = offset->y = 0;
offset.x = offset.y = 0;
*mirrored = mirror_from = mirror_to = FALSE;
/* Translate source window origin to screen coords */
if (hwndFrom)
{
HWND hwnd = hwndFrom;
while (hwnd)
if (!(wndPtr = WIN_GetPtr( hwndFrom ))) return offset;
if (wndPtr == WND_OTHER_PROCESS) goto other_process;
if (wndPtr != WND_DESKTOP)
{
if (hwnd == hwndTo) return;
if (!(wndPtr = WIN_GetPtr( hwnd )))
if (wndPtr->dwExStyle & WS_EX_LAYOUTRTL)
{
ERR( "bad hwndFrom = %p\n", hwnd );
return;
mirror_from = TRUE;
offset.x += wndPtr->rectClient.right - wndPtr->rectClient.left;
}
if (wndPtr == WND_DESKTOP) break;
if (wndPtr == WND_OTHER_PROCESS) goto other_process;
if (wndPtr->parent)
while (wndPtr != WND_DESKTOP)
{
offset->x += wndPtr->rectClient.left;
offset->y += wndPtr->rectClient.top;
offset.x += wndPtr->rectClient.left;
offset.y += wndPtr->rectClient.top;
hwnd = wndPtr->parent;
WIN_ReleasePtr( wndPtr );
if (!(wndPtr = WIN_GetPtr( hwnd ))) break;
if (wndPtr == WND_OTHER_PROCESS) goto other_process;
}
hwnd = wndPtr->parent;
WIN_ReleasePtr( wndPtr );
}
}
/* Translate origin to destination window coords */
if (hwndTo)
{
HWND hwnd = hwndTo;
while (hwnd)
if (!(wndPtr = WIN_GetPtr( hwndTo ))) return offset;
if (wndPtr == WND_OTHER_PROCESS) goto other_process;
if (wndPtr != WND_DESKTOP)
{
if (!(wndPtr = WIN_GetPtr( hwnd )))
if (wndPtr->dwExStyle & WS_EX_LAYOUTRTL)
{
ERR( "bad hwndTo = %p\n", hwnd );
return;
mirror_to = TRUE;
offset.x -= wndPtr->rectClient.right - wndPtr->rectClient.left;
}
if (wndPtr == WND_DESKTOP) break;
if (wndPtr == WND_OTHER_PROCESS) goto other_process;
if (wndPtr->parent)
while (wndPtr != WND_DESKTOP)
{
offset->x -= wndPtr->rectClient.left;
offset->y -= wndPtr->rectClient.top;
offset.x -= wndPtr->rectClient.left;
offset.y -= wndPtr->rectClient.top;
hwnd = wndPtr->parent;
WIN_ReleasePtr( wndPtr );
if (!(wndPtr = WIN_GetPtr( hwnd ))) break;
if (wndPtr == WND_OTHER_PROCESS) goto other_process;
}
hwnd = wndPtr->parent;
WIN_ReleasePtr( wndPtr );
}
}
return;
*mirrored = mirror_from ^ mirror_to;
if (mirror_from) offset.x = -offset.x;
return offset;
other_process: /* one of the parents may belong to another process, do it the hard way */
offset->x = offset->y = 0;
offset.x = offset.y = 0;
SERVER_START_REQ( get_windows_offset )
{
req->from = wine_server_user_handle( hwndFrom );
req->to = wine_server_user_handle( hwndTo );
if (!wine_server_call( req ))
{
offset->x = reply->x;
offset->y = reply->y;
offset.x = reply->x;
offset.y = reply->y;
*mirrored = reply->mirror;
}
}
SERVER_END_REQ;
return offset;
}
@ -499,14 +507,21 @@ static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset )
*/
INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count )
{
POINT offset;
BOOL mirrored;
POINT offset = WINPOS_GetWinOffset( hwndFrom, hwndTo, &mirrored );
UINT i;
WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
while (count--)
for (i = 0; i < count; i++)
{
lppt->x += offset.x;
lppt->y += offset.y;
lppt++;
lppt[i].x += offset.x;
lppt[i].y += offset.y;
if (mirrored) lppt[i].x = -lppt[i].x;
}
if (mirrored && count == 2) /* special case for rectangle */
{
int tmp = lppt[0].x;
lppt[0].x = lppt[1].x;
lppt[1].x = tmp;
}
return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
}

View File

@ -3328,6 +3328,8 @@ struct get_windows_offset_reply
struct reply_header __header;
int x;
int y;
int mirror;
char __pad_20[4];
};
@ -5517,6 +5519,6 @@ union generic_reply
struct set_cursor_reply set_cursor_reply;
};
#define SERVER_PROTOCOL_VERSION 409
#define SERVER_PROTOCOL_VERSION 410
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -2383,6 +2383,7 @@ enum coords_relative
@REPLY
int x; /* x coordinate offset */
int y; /* y coordinate offset */
int mirror; /* whether to mirror the x coordinate */
@END

View File

@ -1605,7 +1605,8 @@ C_ASSERT( FIELD_OFFSET(struct get_windows_offset_request, to) == 16 );
C_ASSERT( sizeof(struct get_windows_offset_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_windows_offset_reply, x) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_windows_offset_reply, y) == 12 );
C_ASSERT( sizeof(struct get_windows_offset_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_windows_offset_reply, mirror) == 16 );
C_ASSERT( sizeof(struct get_windows_offset_reply) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_visible_region_request, window) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_visible_region_request, flags) == 16 );
C_ASSERT( sizeof(struct get_visible_region_request) == 24 );

View File

@ -2839,6 +2839,7 @@ static void dump_get_windows_offset_reply( const struct get_windows_offset_reply
{
fprintf( stderr, " x=%d", req->x );
fprintf( stderr, ", y=%d", req->y );
fprintf( stderr, ", mirror=%d", req->mirror );
}
static void dump_get_visible_region_request( const struct get_visible_region_request *req )

View File

@ -2193,11 +2193,17 @@ DECL_HANDLER(set_window_text)
DECL_HANDLER(get_windows_offset)
{
struct window *win;
int mirror_from = 0, mirror_to = 0;
reply->x = reply->y = 0;
if (req->from)
{
if (!(win = get_window( req->from ))) return;
if (win->ex_style & WS_EX_LAYOUTRTL)
{
mirror_from = 1;
reply->x += win->client_rect.right - win->client_rect.left - 1;
}
while (win && !is_desktop_window(win))
{
reply->x += win->client_rect.left;
@ -2208,6 +2214,11 @@ DECL_HANDLER(get_windows_offset)
if (req->to)
{
if (!(win = get_window( req->to ))) return;
if (win->ex_style & WS_EX_LAYOUTRTL)
{
mirror_to = 1;
reply->x -= win->client_rect.right - win->client_rect.left - 1;
}
while (win && !is_desktop_window(win))
{
reply->x -= win->client_rect.left;
@ -2215,6 +2226,8 @@ DECL_HANDLER(get_windows_offset)
win = win->parent;
}
}
if (mirror_from) reply->x = -reply->x;
reply->mirror = mirror_from ^ mirror_to;
}