user32: Add support for RTL window layouts in MapWindowPoints.
This commit is contained in:
parent
cf72f406ec
commit
5702324b37
|
@ -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();
|
||||
|
|
|
@ -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) );
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue