server: When moving/resizing a window crop the update region against the new rectangle of the parents.
This commit is contained in:
parent
f8f8e7ef51
commit
e02969ddf0
|
@ -5783,6 +5783,38 @@ static void test_paint_messages(void)
|
|||
DestroyWindow( hparent );
|
||||
ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
|
||||
|
||||
/* tests for moving windows off-screen (needs simple WS_POPUP windows) */
|
||||
|
||||
hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_POPUP | WS_VISIBLE,
|
||||
100, 100, 200, 200, 0, 0, 0, NULL);
|
||||
ok (hparent != 0, "Failed to create parent window\n");
|
||||
|
||||
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
|
||||
10, 10, 100, 100, hparent, 0, 0, NULL);
|
||||
ok (hchild != 0, "Failed to create child window\n");
|
||||
|
||||
ShowWindow( hparent, SW_SHOW );
|
||||
UpdateWindow( hparent );
|
||||
UpdateWindow( hchild );
|
||||
flush_events();
|
||||
flush_sequence();
|
||||
|
||||
/* moving child outside of parent boundaries changes update region */
|
||||
SetRect( &rect, 0, 0, 40, 40 );
|
||||
RedrawWindow( hchild, &rect, 0, RDW_INVALIDATE | RDW_ERASE );
|
||||
SetRectRgn( hrgn, 0, 0, 40, 40 );
|
||||
check_update_rgn( hchild, hrgn );
|
||||
MoveWindow( hchild, -10, 10, 100, 100, FALSE );
|
||||
SetRectRgn( hrgn, 10, 0, 40, 40 );
|
||||
check_update_rgn( hchild, hrgn );
|
||||
MoveWindow( hchild, -10, -10, 100, 100, FALSE );
|
||||
SetRectRgn( hrgn, 10, 10, 40, 40 );
|
||||
check_update_rgn( hchild, hrgn );
|
||||
|
||||
DestroyWindow( hparent );
|
||||
ok(!IsWindow(hchild), "child must be destroyed with its parent\n");
|
||||
flush_sequence();
|
||||
|
||||
DeleteObject( hrgn );
|
||||
DeleteObject( hrgn2 );
|
||||
}
|
||||
|
|
|
@ -876,6 +876,16 @@ static inline int intersect_rect( rectangle_t *dst, const rectangle_t *src1, con
|
|||
}
|
||||
|
||||
|
||||
/* offset the coordinates of a rectangle */
|
||||
static inline void offset_rect( rectangle_t *rect, int offset_x, int offset_y )
|
||||
{
|
||||
rect->left += offset_x;
|
||||
rect->top += offset_y;
|
||||
rect->right += offset_x;
|
||||
rect->bottom += offset_y;
|
||||
}
|
||||
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
|
@ -990,6 +1000,38 @@ struct window_class* get_window_class( user_handle_t window )
|
|||
return win->class;
|
||||
}
|
||||
|
||||
/* determine the window visible rectangle, i.e. window or client rect cropped by parent rects */
|
||||
/* the returned rectangle is in window coordinates; return 0 if rectangle is empty */
|
||||
static int get_window_visible_rect( struct window *win, rectangle_t *rect, int frame )
|
||||
{
|
||||
int offset_x = 0, offset_y = 0;
|
||||
|
||||
if (!(win->style & WS_VISIBLE)) return 0;
|
||||
|
||||
*rect = frame ? win->window_rect : win->client_rect;
|
||||
if (!is_desktop_window(win))
|
||||
{
|
||||
offset_x = win->window_rect.left;
|
||||
offset_y = win->window_rect.top;
|
||||
}
|
||||
|
||||
while (win->parent)
|
||||
{
|
||||
win = win->parent;
|
||||
if (!(win->style & WS_VISIBLE) || win->style & WS_MINIMIZE) return 0;
|
||||
if (!is_desktop_window(win))
|
||||
{
|
||||
offset_x += win->client_rect.left;
|
||||
offset_y += win->client_rect.top;
|
||||
offset_rect( rect, win->client_rect.left, win->client_rect.top );
|
||||
}
|
||||
if (!intersect_rect( rect, rect, &win->client_rect )) return 0;
|
||||
if (!intersect_rect( rect, rect, &win->window_rect )) return 0;
|
||||
}
|
||||
offset_rect( rect, -offset_x, -offset_y );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* return a copy of the specified region cropped to the window client or frame rectangle, */
|
||||
/* 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 )
|
||||
|
@ -1413,6 +1455,7 @@ static void set_window_pos( struct window *win, struct window *previous,
|
|||
struct region *old_vis_rgn = NULL, *exposed_rgn = NULL;
|
||||
const rectangle_t old_window_rect = win->window_rect;
|
||||
const rectangle_t old_client_rect = win->client_rect;
|
||||
rectangle_t rect;
|
||||
int client_changed, frame_changed;
|
||||
int visible = (win->style & WS_VISIBLE) || (swp_flags & SWP_SHOWWINDOW);
|
||||
|
||||
|
@ -1461,22 +1504,22 @@ static void set_window_pos( struct window *win, struct window *previous,
|
|||
|
||||
/* crop update region to the new window rect */
|
||||
|
||||
if (win->update_region &&
|
||||
(window_rect->right - window_rect->left < old_window_rect.right - old_window_rect.left ||
|
||||
window_rect->bottom - window_rect->top < old_window_rect.bottom - old_window_rect.top))
|
||||
if (win->update_region)
|
||||
{
|
||||
if (get_window_visible_rect( win, &rect, 1 ))
|
||||
{
|
||||
struct region *tmp = create_empty_region();
|
||||
if (tmp)
|
||||
{
|
||||
set_region_rect( tmp, window_rect );
|
||||
if (!is_desktop_window(win))
|
||||
offset_region( tmp, -window_rect->left, -window_rect->top );
|
||||
set_region_rect( tmp, &rect );
|
||||
if (intersect_region( tmp, win->update_region, tmp ))
|
||||
set_update_region( win, tmp );
|
||||
else
|
||||
free_region( tmp );
|
||||
}
|
||||
}
|
||||
else set_update_region( win, NULL ); /* visible rect is empty */
|
||||
}
|
||||
|
||||
if (swp_flags & SWP_NOREDRAW) goto done; /* do not repaint anything */
|
||||
|
||||
|
|
Loading…
Reference in New Issue