From: Paul Gofman pgofman@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58210 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38975 --- dlls/user32/tests/win.c | 10 ++++---- server/window.c | 54 +++++++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 23 deletions(-)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 08a1d0609cc..47ad916c05b 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -10968,7 +10968,7 @@ static void test_update_region(void) SetWindowPos(parent, NULL, 0, 0, 350, 200, SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE); GetUpdateRect(parent, &r, FALSE); GetClientRect(parent, &expect_rect); - todo_wine ok(EqualRect(&r, &expect_rect), "got %s, expected %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&expect_rect)); + ok(EqualRect(&r, &expect_rect), "got %s, expected %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&expect_rect)); ValidateRect(parent, NULL);
SetWindowPos(parent, NULL, 0, 0, 300, 150, SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE); @@ -10983,7 +10983,7 @@ static void test_update_region(void) SetWindowPos(parent, NULL, 0, 0, 350, 200, SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE); GetUpdateRect(parent, &r, FALSE); GetClientRect(parent, &expect_rect); - todo_wine ok(EqualRect(&r, &expect_rect), "got %s, expected %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&expect_rect)); + ok(EqualRect(&r, &expect_rect), "got %s, expected %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&expect_rect)); pump_messages(); RedrawWindow(parent, NULL, 0, RDW_VALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
@@ -10998,7 +10998,7 @@ static void test_update_region(void) SetWindowPos(hwnd, NULL, 0, 0, 210, 110, SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE); GetUpdateRect(hwnd, &r, FALSE); GetClientRect(hwnd, &expect_rect); - todo_wine ok(EqualRect(&r, &expect_rect), "got %s, expected %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&expect_rect)); + ok(EqualRect(&r, &expect_rect), "got %s, expected %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&expect_rect)); ValidateRect(hwnd, NULL); ValidateRect(parent, NULL); SetWindowPos(hwnd, NULL, 0, 0, 200, 100, SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE); @@ -11013,7 +11013,7 @@ static void test_update_region(void) SetWindowPos(hwnd, NULL, 0, 0, 210, 110, SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE); GetUpdateRect(hwnd, &r, FALSE); GetClientRect(hwnd, &expect_rect); - todo_wine ok(EqualRect(&r, &expect_rect), "got %s, expected %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&expect_rect)); + ok(EqualRect(&r, &expect_rect), "got %s, expected %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&expect_rect)); ValidateRect(hwnd, NULL); ValidateRect(parent, NULL); SetWindowPos(hwnd, NULL, 0, 0, 200, 100, SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE); @@ -11032,7 +11032,7 @@ static void test_update_region(void) GetClientRect(parent, &r); expect_rect.bottom = r.bottom - 150; GetUpdateRect(hwnd, &r, FALSE); - todo_wine ok(EqualRect(&r, &expect_rect), "got %s, expected %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&expect_rect)); + ok(EqualRect(&r, &expect_rect), "got %s, expected %s.\n", wine_dbgstr_rect(&r), wine_dbgstr_rect(&expect_rect)); ValidateRect(hwnd, NULL); ValidateRect(parent, NULL); SetWindowPos(hwnd, NULL, 0, 0, 200, 100, SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE); diff --git a/server/window.c b/server/window.c index 1eb815dfe3e..e7375440ca3 100644 --- a/server/window.c +++ b/server/window.c @@ -80,6 +80,8 @@ struct window unsigned int is_linked : 1; /* is it linked into the parent z-order list? */ unsigned int is_layered : 1; /* has layered info been set? */ unsigned int is_orphan : 1; /* is window orphaned */ + int is_update_region_full_frame : 1; /* the whole window rect is invalidated */ + int is_update_region_full_client : 1; /* the whole client rect is invalidated */ unsigned int color_key; /* color key for a layered window */ unsigned int alpha; /* alpha value for a layered window */ unsigned int layered_flags; /* flags for a layered window */ @@ -1451,8 +1453,9 @@ done:
/* set a region as new update region for the window */ -static void set_update_region( struct window *win, struct region *region ) +static void set_update_region( struct window *win, struct region *region, int clear_full_window ) { + if (clear_full_window) win->is_update_region_full_client = win->is_update_region_full_frame = 0; if (region && !is_region_empty( region )) { if (!win->update_region) inc_window_paint_count( win, 1 ); @@ -1481,7 +1484,7 @@ static int add_update_region( struct window *win, struct region *region ) free_region( region ); return 0; } - set_update_region( win, region ); + set_update_region( win, region, 0 ); return 1; }
@@ -1499,7 +1502,7 @@ static void crop_children_update_region( struct window *win, struct rectangle *r if (!rect) /* crop everything out */ { crop_children_update_region( child, NULL ); - set_update_region( child, NULL ); + set_update_region( child, NULL, 1 ); continue; }
@@ -1519,7 +1522,7 @@ static void crop_children_update_region( struct window *win, struct rectangle *r if (!(tmp = create_empty_region())) continue; set_region_rect( tmp, rect ); offset_region( tmp, -child->window_rect.left, -child->window_rect.top ); - if (intersect_region( tmp, child->update_region, tmp )) set_update_region( child, tmp ); + if (intersect_region( tmp, child->update_region, tmp )) set_update_region( child, tmp, 0 ); else free_region( tmp ); } } @@ -1543,7 +1546,7 @@ static void validate_non_client( struct window *win ) { set_region_rect( tmp, &rect ); if (intersect_region( tmp, win->update_region, tmp )) - set_update_region( win, tmp ); + set_update_region( win, tmp, 1 ); else free_region( tmp ); } @@ -1554,7 +1557,7 @@ static void validate_non_client( struct window *win ) /* validate a window completely so that we don't get any further paint messages for it */ static void validate_whole_window( struct window *win ) { - set_update_region( win, NULL ); + set_update_region( win, NULL, 1 );
if (win->paint_flags & PAINT_INTERNAL) { @@ -1605,7 +1608,7 @@ static void validate_parents( struct window *child ) offset_region( child->update_region, offset_x, offset_y ); if (subtract_region( tmp, win->update_region, child->update_region )) { - set_update_region( win, tmp ); + set_update_region( win, tmp, 1 ); tmp = NULL; } /* restore child coords */ @@ -1617,7 +1620,8 @@ static void validate_parents( struct window *child )
/* add/subtract a region (in client coordinates) to the update region of the window */ -static void redraw_window( struct window *win, struct region *region, int frame, unsigned int flags ) +static void redraw_window( struct window *win, struct region *region, int frame, unsigned int flags, + int invalidate_full_window ) { struct region *child_rgn, *tmp; struct window *child; @@ -1627,6 +1631,11 @@ static void redraw_window( struct window *win, struct region *region, int frame, if (!(tmp = crop_region_to_win_rect( win, region, frame ))) return;
if (!add_update_region( win, tmp )) return; + if (invalidate_full_window) + { + if (frame) win->is_update_region_full_frame = 1; + else win->is_update_region_full_client = 1; + }
if (flags & RDW_FRAME) win->paint_flags |= PAINT_NONCLIENT; if (flags & RDW_ERASE) win->paint_flags |= PAINT_ERASE; @@ -1635,7 +1644,7 @@ static void redraw_window( struct window *win, struct region *region, int frame, { if (!region && (flags & RDW_NOFRAME)) /* shortcut: validate everything */ { - set_update_region( win, NULL ); + set_update_region( win, NULL, 1 ); } else if (win->update_region) { @@ -1646,7 +1655,11 @@ static void redraw_window( struct window *win, struct region *region, int frame, free_region( tmp ); return; } - set_update_region( win, tmp ); + set_update_region( win, tmp, 1 ); + } + else + { + win->is_update_region_full_client = win->is_update_region_full_frame = 0; } if (flags & RDW_NOFRAME) validate_non_client( win ); if (flags & RDW_NOERASE) win->paint_flags &= ~(PAINT_ERASE | PAINT_DELAYED_ERASE); @@ -1688,7 +1701,7 @@ static void redraw_window( struct window *win, struct region *region, int frame, if (rect_in_region( child_rgn, &child->window_rect )) { offset_region( child_rgn, -child->client_rect.left, -child->client_rect.top ); - redraw_window( child, child_rgn, 1, flags ); + redraw_window( child, child_rgn, 1, flags, invalidate_full_window ); } } free_region( child_rgn ); @@ -1885,7 +1898,7 @@ static struct region *expose_window( struct window *win, const struct rectangle { /* make it relative to parent */ offset_region( new_vis_rgn, old_window_rect->left, old_window_rect->top ); - redraw_window( win->parent, new_vis_rgn, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); + redraw_window( win->parent, new_vis_rgn, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN, 0 ); } } } @@ -1962,6 +1975,11 @@ static void set_window_pos( struct window *win, struct window *previous,
if (win->update_region) { + if (win->is_update_region_full_client || win->is_update_region_full_frame) + { + if (get_window_visible_rect( win, &rect, win->is_update_region_full_frame )) + set_region_rect( win->update_region, &rect ); + } if (get_window_visible_rect( win, &rect, 1 )) { struct region *tmp = create_empty_region(); @@ -1969,12 +1987,12 @@ static void set_window_pos( struct window *win, struct window *previous, { set_region_rect( tmp, &rect ); if (intersect_region( tmp, win->update_region, tmp )) - set_update_region( win, tmp ); + set_update_region( win, tmp, 0 ); else free_region( tmp ); } } - else set_update_region( win, NULL ); /* visible rect is empty */ + else set_update_region( win, NULL, 1 ); /* visible rect is empty */ }
/* crop children regions to the new window rect */ @@ -2056,7 +2074,7 @@ static void set_window_pos( struct window *win, struct window *previous, }
if (exposed_rgn) - redraw_window( win, exposed_rgn, 1, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); + redraw_window( win, exposed_rgn, 1, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN, 0 );
done: if (old_vis_rgn) free_region( old_vis_rgn ); @@ -2081,7 +2099,7 @@ static void set_window_region( struct window *win, struct region *region, int re /* expose anything revealed by the change */ if (old_vis_rgn && ((exposed_rgn = expose_window( win, &win->window_rect, old_vis_rgn, 0 )))) { - redraw_window( win, exposed_rgn, 1, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); + redraw_window( win, exposed_rgn, 1, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN, 0 ); free_region( exposed_rgn ); }
@@ -2992,7 +3010,7 @@ DECL_HANDLER(redraw_window) } }
- redraw_window( win, region, (flags & RDW_INVALIDATE) && (flags & RDW_FRAME), flags ); + redraw_window( win, region, (flags & RDW_INVALIDATE) && (flags & RDW_FRAME), flags, !region ); if (region) free_region( region ); }
@@ -3168,7 +3186,7 @@ DECL_HANDLER(set_window_layered_info) win->layered_flags = req->flags; win->is_layered = 1; /* repaint since we know now it's not going to use UpdateLayeredWindow */ - if (!was_layered) redraw_window( win, 0, 1, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_ERASE | RDW_FRAME ); + if (!was_layered) redraw_window( win, 0, 1, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_ERASE | RDW_FRAME, 0 ); } else set_win32_error( ERROR_INVALID_WINDOW_HANDLE ); }