Commit 548c9734 authored by Alexandre Julliard's avatar Alexandre Julliard

Allow the client rectangle to be of arbitrary size and dimensions,

regardless of the window rectangle.
parent 65853736
......@@ -502,7 +502,8 @@ static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPAR
GetClientRect(hwnd, &rc2);
DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
ok(EqualRect(&rc1, &rc2), "rects do not match\n");
ok(EqualRect(&rc1, &rc2), "rects do not match (%ld,%ld-%ld,%ld) / (%ld,%ld-%ld,%ld)\n",
rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom );
break;
}
case WM_NCCREATE:
......@@ -1664,21 +1665,59 @@ static void test_icons(void)
ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
}
static LRESULT WINAPI nccalcsize_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if (msg == WM_NCCALCSIZE)
{
RECT *rect = (RECT *)lparam;
/* first time around increase the rectangle, next time decrease it */
if (rect->left == 100) InflateRect( rect, 10, 10 );
else InflateRect( rect, -10, -10 );
return 0;
}
return DefWindowProc( hwnd, msg, wparam, lparam );
}
static void test_SetWindowPos(HWND hwnd)
{
RECT orig_win_rc;
RECT orig_win_rc, rect;
LONG_PTR old_proc;
BOOL is_win9x = GetWindowLongW(hwnd, GWL_WNDPROC) == 0;
/* Win9x truncates coordinates to 16-bit irrespectively */
if (is_win9x) return;
GetWindowRect(hwnd, &orig_win_rc);
SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
old_proc = SetWindowLongPtr( hwnd, GWLP_WNDPROC, (ULONG_PTR)nccalcsize_proc );
SetWindowPos(hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
GetWindowRect( hwnd, &rect );
ok( rect.left == 100 && rect.top == 100 && rect.right == 100 && rect.bottom == 100,
"invalid window rect %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
GetClientRect( hwnd, &rect );
MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
ok( rect.left == 90 && rect.top == 90 && rect.right == 110 && rect.bottom == 110,
"invalid client rect %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
SetWindowPos(hwnd, 0, 200, 200, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
GetWindowRect( hwnd, &rect );
ok( rect.left == 200 && rect.top == 200 && rect.right == 200 && rect.bottom == 200,
"invalid window rect %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
GetClientRect( hwnd, &rect );
MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
ok( rect.left == 210 && rect.top == 210 && rect.right == 190 && rect.bottom == 190,
"invalid client rect %ld,%ld-%ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom );
SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
orig_win_rc.right, orig_win_rc.bottom, 0);
SetWindowLongPtr( hwnd, GWLP_WNDPROC, old_proc );
/* Win9x truncates coordinates to 16-bit irrespectively */
if (!is_win9x)
{
SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
}
SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
orig_win_rc.right, orig_win_rc.bottom, 0);
......
......@@ -969,11 +969,6 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
if (rect.left < wndPtr->rectWindow.left) rect.left = wndPtr->rectWindow.left;
if (rect.right > wndPtr->rectWindow.right) rect.right = wndPtr->rectWindow.right;
if (rect.top < wndPtr->rectWindow.top) rect.top = wndPtr->rectWindow.top;
if (rect.bottom > wndPtr->rectWindow.bottom) rect.bottom = wndPtr->rectWindow.bottom;
if (rect.left > rect.right || rect.top > rect.bottom) rect = wndPtr->rectWindow;
/* yes, even if the CBT hook was called with HWND_TOP */
insert_after = ((wndPtr->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
......
......@@ -413,22 +413,14 @@ static UINT SWP_DoNCCalcSize( WINDOWPOS* pWinpos, const RECT* pNewWindowRect, RE
wvrFlags = SendMessageW( pWinpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params );
TRACE( "(%ld,%ld)-(%ld,%ld)\n", params.rgrc[0].left, params.rgrc[0].top,
params.rgrc[0].right, params.rgrc[0].bottom );
/* If the application sends back garbage, ignore it */
if (params.rgrc[0].left < pNewWindowRect->left) params.rgrc[0].left = pNewWindowRect->left;
if (params.rgrc[0].top < pNewWindowRect->top) params.rgrc[0].top = pNewWindowRect->top;
if (params.rgrc[0].right > pNewWindowRect->right) params.rgrc[0].right = pNewWindowRect->right;
if (params.rgrc[0].bottom > pNewWindowRect->bottom) params.rgrc[0].bottom = pNewWindowRect->bottom;
if (params.rgrc[0].left <= params.rgrc[0].right &&
params.rgrc[0].top <= params.rgrc[0].bottom)
*pNewClientRect = params.rgrc[0];
*pNewClientRect = params.rgrc[0];
if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
TRACE( "hwnd %p old win %s old client %s new win %s new client %s\n", pWinpos->hwnd,
wine_dbgstr_rect(&wndPtr->rectWindow), wine_dbgstr_rect(&wndPtr->rectClient),
wine_dbgstr_rect(pNewWindowRect), wine_dbgstr_rect(pNewClientRect) );
if( pNewClientRect->left != wndPtr->rectClient.left ||
pNewClientRect->top != wndPtr->rectClient.top )
pWinpos->flags &= ~SWP_NOCLIENTMOVE;
......
......@@ -645,6 +645,19 @@ static struct region *clip_children( struct window *parent, struct window *last,
}
/* set the region to the client rect clipped by the window rect, in parent-relative coordinates */
static void set_region_client_rect( struct region *region, struct window *win )
{
rectangle_t rect;
rect.left = max( win->window_rect.left, win->client_rect.left );
rect.top = max( win->window_rect.top, win->client_rect.top );
rect.right = min( win->window_rect.right, win->client_rect.right );
rect.bottom = min( win->window_rect.bottom, win->client_rect.bottom );
set_region_rect( region, &rect );
}
/* compute the visible region of a window */
static struct region *get_visible_region( struct window *win, struct window *top,
unsigned int flags )
......@@ -662,11 +675,8 @@ static struct region *get_visible_region( struct window *win, struct window *top
if ((flags & DCX_PARENTCLIP) && win != top && win->parent)
{
rectangle_t rect;
rect.left = rect.top = 0;
rect.right = win->parent->client_rect.right - win->parent->client_rect.left;
rect.bottom = win->parent->client_rect.bottom - win->parent->client_rect.top;
set_region_rect( region, &rect );
set_region_client_rect( region, win->parent );
offset_region( region, -win->parent->client_rect.left, -win->parent->client_rect.top );
offset_x = win->client_rect.left;
offset_y = win->client_rect.top;
}
......@@ -679,7 +689,7 @@ static struct region *get_visible_region( struct window *win, struct window *top
}
else
{
set_region_rect( region, &win->client_rect );
set_region_client_rect( region, win );
if (win->win_region && !intersect_window_region( region, win )) goto error;
offset_x = win->client_rect.left;
offset_y = win->client_rect.top;
......@@ -712,7 +722,7 @@ static struct region *get_visible_region( struct window *win, struct window *top
offset_x += win->client_rect.left;
offset_y += win->client_rect.top;
offset_region( region, win->client_rect.left, win->client_rect.top );
set_region_rect( tmp, &win->client_rect );
set_region_client_rect( tmp, win );
if (win->win_region && !intersect_window_region( tmp, win ))
{
free_region( tmp );
......@@ -748,27 +758,14 @@ struct window_class* get_window_class( user_handle_t window )
/* and converted from client to window coordinates. Helper for (in)validate_window. */
static struct region *crop_region_to_win_rect( struct window *win, struct region *region, int frame )
{
rectangle_t rect;
struct region *tmp = create_empty_region();
if (!tmp) return NULL;
/* get bounding rect in client coords */
if (frame)
{
rect.left = win->window_rect.left - win->client_rect.left;
rect.top = win->window_rect.top - win->client_rect.top;
rect.right = win->window_rect.right - win->client_rect.left;
rect.bottom = win->window_rect.bottom - win->client_rect.top;
}
else
{
rect.left = 0;
rect.top = 0;
rect.right = win->client_rect.right - win->client_rect.left;
rect.bottom = win->client_rect.bottom - win->client_rect.top;
}
set_region_rect( tmp, &rect );
if (frame) set_region_rect( tmp, &win->window_rect );
else set_region_client_rect( tmp, win );
offset_region( tmp, -win->client_rect.left, -win->client_rect.top );
/* intersect specified region with bounding rect */
if (region && !intersect_region( tmp, region, tmp )) goto done;
......@@ -831,8 +828,9 @@ static void validate_non_client( struct window *win )
rect.right = win->client_rect.right - win->window_rect.left;
rect.bottom = win->client_rect.bottom - win->window_rect.top;
if ((tmp = create_region( &rect, 1 )))
if ((tmp = create_empty_region()))
{
set_region_rect( tmp, &rect );
if (intersect_region( tmp, win->update_region, tmp ))
set_update_region( win, tmp );
else
......@@ -1056,23 +1054,6 @@ static void expose_window( struct window *win, struct window *top, struct region
}
/* validate that the specified window and client rects are valid */
static int validate_window_rectangles( const rectangle_t *window_rect, const rectangle_t *client_rect )
{
/* rectangles must be ordered properly */
if (window_rect->right < window_rect->left) return 0;
if (window_rect->bottom < window_rect->top) return 0;
if (client_rect->right < client_rect->left) return 0;
if (client_rect->bottom < client_rect->top) return 0;
/* client rect must be inside window rect */
if (client_rect->left < window_rect->left) return 0;
if (client_rect->right > window_rect->right) return 0;
if (client_rect->top < window_rect->top) return 0;
if (client_rect->bottom > window_rect->bottom) return 0;
return 1;
}
/* set the window and client rectangles, updating the update region if necessary */
static void set_window_pos( struct window *win, struct window *top, struct window *previous,
unsigned int swp_flags, const rectangle_t *window_rect,
......@@ -1138,18 +1119,16 @@ static void set_window_pos( struct window *win, struct window *top, struct windo
memcmp( window_rect, &old_window_rect, sizeof(old_window_rect) ) ||
memcmp( client_rect, &old_client_rect, sizeof(old_client_rect) ))
{
struct region *tmp;
/* subtract the valid portion of client rect from the total region */
if (!memcmp( client_rect, &old_client_rect, sizeof(old_client_rect) ))
tmp = create_region( client_rect, 1 );
else if (valid_rects)
tmp = create_region( &valid_rects[0], 1 );
else
tmp = create_empty_region();
struct region *tmp = create_empty_region();
if (tmp)
{
/* subtract the valid portion of client rect from the total region */
if (!memcmp( client_rect, &old_client_rect, sizeof(old_client_rect) ))
set_region_rect( tmp, client_rect );
else if (valid_rects)
set_region_rect( tmp, &valid_rects[0] );
set_region_rect( new_vis_rgn, window_rect );
if (subtract_region( tmp, new_vis_rgn, tmp ))
{
......@@ -1479,7 +1458,8 @@ DECL_HANDLER(set_window_pos)
if (previous == win) flags |= SWP_NOZORDER; /* nothing to do */
}
if (!validate_window_rectangles( &req->window, &req->client ))
/* window rectangle must be ordered properly */
if (req->window.right < req->window.left || req->window.bottom < req->window.top)
{
set_error( STATUS_INVALID_PARAMETER );
return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment