Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com
-- v5: server: Don't invalidate the newly exposed child region on the parent if it doesn't clip children. server: Redraw composited window child when its z-order changes. server: Correctly expose composited parent window and its child on position change.
From: Jinoh Kang jinoh.kang.kr@gmail.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53153 Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/user32/tests/msg.c | 4 ++-- server/class.c | 5 +++++ server/user.h | 8 ++++++++ server/window.c | 23 +++++++++++++++++++++-- 4 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 76c30b7dfe5..9b4680bbcc1 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -9303,7 +9303,7 @@ static void subtest_swp_paint_regions_( int line, int wrap_toplevel, LPCSTR pare else { todo_wine_if( EqualRect( &rect_old, &rect_new ) ? is_zorder_redraw : - ((extest->style & WS_CLIPCHILDREN) == 0 || is_composited) ) + ((extest->style & WS_CLIPCHILDREN) == 0 && !is_composited) ) ok( !!rgn_ok, "Parent update region shall match expected region\n" ); }
@@ -9366,7 +9366,7 @@ static void subtest_swp_paint_regions_( int line, int wrap_toplevel, LPCSTR pare else { todo_wine_if( EqualRect( &rect_old, &rect_new ) ? is_zorder_redraw : - ((extest->style & WS_CLIPCHILDREN) == 0 || is_composited) ) + ((extest->style & WS_CLIPCHILDREN) == 0 && !is_composited) ) ok( !!rgn_ok, "Child update region shall match expected region\n" ); }
diff --git a/server/class.c b/server/class.c index e1e180bd97c..3231f366b26 100644 --- a/server/class.c +++ b/server/class.c @@ -141,6 +141,11 @@ int is_hwnd_message_class( struct window_class *class ) return (!class->local && class->atom == find_global_atom( NULL, &name )); }
+int get_class_style( struct window_class *class ) +{ + return class->style; +} + atom_t get_class_atom( struct window_class *class ) { return class->base_atom; diff --git a/server/user.h b/server/user.h index 55a0d35feff..9e91d427a3a 100644 --- a/server/user.h +++ b/server/user.h @@ -175,6 +175,7 @@ extern struct window_class *grab_class( struct process *process, atom_t atom, extern void release_class( struct window_class *class ); extern int is_desktop_class( struct window_class *class ); extern int is_hwnd_message_class( struct window_class *class ); +extern int get_class_style( struct window_class *class ); extern atom_t get_class_atom( struct window_class *class ); extern client_ptr_t get_class_client_ptr( struct window_class *class );
@@ -191,6 +192,13 @@ extern void close_process_desktop( struct process *process ); extern void set_thread_default_desktop( struct thread *thread, struct desktop *desktop, obj_handle_t handle ); extern void release_thread_desktop( struct thread *thread, int close );
+/* checks if two rectangles are identical */ +static inline int is_rect_equal( const rectangle_t *rect1, const rectangle_t *rect2 ) +{ + return (rect1->left == rect2->left && rect1->right == rect2->right && + rect1->top == rect2->top && rect1->bottom == rect2->bottom); +} + static inline int is_rect_empty( const rectangle_t *rect ) { return (rect->left >= rect->right || rect->top >= rect->bottom); diff --git a/server/window.c b/server/window.c index 7675cd1103d..6fc9f9f9e40 100644 --- a/server/window.c +++ b/server/window.c @@ -789,6 +789,16 @@ int is_window_transparent( user_handle_t window ) return (win->ex_style & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT); }
+static int is_window_using_parent_dc( struct window *win ) +{ + return (win->style & (WS_POPUP|WS_CHILD)) == WS_CHILD && (get_class_style( win->class ) & CS_PARENTDC) != 0; +} + +static int is_window_composited( struct window *win ) +{ + return (win->ex_style & WS_EX_COMPOSITED) != 0 && !is_window_using_parent_dc(win); +} + /* check if point is inside the window, and map to window dpi */ static int is_point_in_window( struct window *win, int *x, int *y, unsigned int dpi ) { @@ -1712,12 +1722,20 @@ static struct region *expose_window( struct window *win, const rectangle_t *old_ struct region *old_vis_rgn ) { struct region *new_vis_rgn, *exposed_rgn; + int is_composited = win->parent && is_window_composited( win->parent ); + + if (is_rect_equal( &win->window_rect, old_window_rect )) + { + return NULL; + }
if (!(new_vis_rgn = get_visible_region( win, DCX_WINDOW ))) return NULL;
if ((exposed_rgn = create_empty_region())) { - if (subtract_region( exposed_rgn, new_vis_rgn, old_vis_rgn ) && !is_region_empty( exposed_rgn )) + if ((is_composited ? union_region( exposed_rgn, new_vis_rgn, old_vis_rgn ) + : subtract_region( exposed_rgn, new_vis_rgn, old_vis_rgn )) && + !is_region_empty( exposed_rgn )) { /* make it relative to the new client area */ offset_region( exposed_rgn, win->window_rect.left - win->client_rect.left, @@ -1736,7 +1754,8 @@ static struct region *expose_window( struct window *win, const rectangle_t *old_ offset_region( new_vis_rgn, win->window_rect.left - old_window_rect->left, win->window_rect.top - old_window_rect->top );
- if ((win->parent->style & WS_CLIPCHILDREN) ? + if (is_composited ? union_region( new_vis_rgn, old_vis_rgn, new_vis_rgn ) : + (win->parent->style & WS_CLIPCHILDREN) ? subtract_region( new_vis_rgn, old_vis_rgn, new_vis_rgn ) : xor_region( new_vis_rgn, old_vis_rgn, new_vis_rgn )) {
From: Jinoh Kang jinoh.kang.kr@gmail.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53153 Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/user32/tests/msg.c | 8 ++++---- server/window.c | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 9b4680bbcc1..fb22f6042fe 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -9302,8 +9302,8 @@ static void subtest_swp_paint_regions_( int line, int wrap_toplevel, LPCSTR pare } else { - todo_wine_if( EqualRect( &rect_old, &rect_new ) ? is_zorder_redraw : - ((extest->style & WS_CLIPCHILDREN) == 0 && !is_composited) ) + todo_wine_if( !EqualRect( &rect_old, &rect_new ) && + (extest->style & WS_CLIPCHILDREN) == 0 && !is_composited ) ok( !!rgn_ok, "Parent update region shall match expected region\n" ); }
@@ -9365,8 +9365,8 @@ static void subtest_swp_paint_regions_( int line, int wrap_toplevel, LPCSTR pare } else { - todo_wine_if( EqualRect( &rect_old, &rect_new ) ? is_zorder_redraw : - ((extest->style & WS_CLIPCHILDREN) == 0 && !is_composited) ) + todo_wine_if( !EqualRect( &rect_old, &rect_new ) && + (extest->style & WS_CLIPCHILDREN) == 0 && !is_composited ) ok( !!rgn_ok, "Child update region shall match expected region\n" ); }
diff --git a/server/window.c b/server/window.c index 6fc9f9f9e40..7e418b7b3fa 100644 --- a/server/window.c +++ b/server/window.c @@ -1719,12 +1719,12 @@ static unsigned int get_window_update_flags( struct window *win, struct window * /* expose the areas revealed by a vis region change on the window parent */ /* returns the region exposed on the window itself (in client coordinates) */ static struct region *expose_window( struct window *win, const rectangle_t *old_window_rect, - struct region *old_vis_rgn ) + struct region *old_vis_rgn, int zorder_changed ) { struct region *new_vis_rgn, *exposed_rgn; int is_composited = win->parent && is_window_composited( win->parent );
- if (is_rect_equal( &win->window_rect, old_window_rect )) + if (is_rect_equal( &win->window_rect, old_window_rect ) && !(is_composited && zorder_changed)) { return NULL; } @@ -1785,6 +1785,7 @@ static void set_window_pos( struct window *win, struct window *previous, rectangle_t rect; int client_changed, frame_changed; int visible = (win->style & WS_VISIBLE) || (swp_flags & SWP_SHOWWINDOW); + int zorder_changed = 0;
if (win->parent && !is_visible( win->parent )) visible = 0;
@@ -1796,7 +1797,12 @@ static void set_window_pos( struct window *win, struct window *previous, win->visible_rect = *visible_rect; win->surface_rect = *surface_rect; win->client_rect = *client_rect; - if (!(swp_flags & SWP_NOZORDER) && win->parent) link_window( win, previous ); + if (!(swp_flags & SWP_NOZORDER) && win->parent) + { + struct list *old_prev = win->is_linked ? win->entry.prev : NULL; + link_window( win, previous ); + if (old_prev != win->entry.prev) zorder_changed = 1; + } if (swp_flags & SWP_SHOWWINDOW) win->style |= WS_VISIBLE; else if (swp_flags & SWP_HIDEWINDOW) win->style &= ~WS_VISIBLE;
@@ -1825,7 +1831,7 @@ static void set_window_pos( struct window *win, struct window *previous, /* expose anything revealed by the change */
if (!(swp_flags & SWP_NOREDRAW)) - exposed_rgn = expose_window( win, &old_window_rect, old_vis_rgn ); + exposed_rgn = expose_window( win, &old_window_rect, old_vis_rgn, zorder_changed );
if (!(win->style & WS_VISIBLE)) { @@ -1956,7 +1962,7 @@ static void set_window_region( struct window *win, struct region *region, int re win->win_region = region;
/* expose anything revealed by the change */ - if (old_vis_rgn && ((exposed_rgn = expose_window( win, &win->window_rect, old_vis_rgn )))) + 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 ); free_region( exposed_rgn ); @@ -1981,7 +1987,7 @@ void free_window_handle( struct window *win ) win->style &= ~WS_VISIBLE; if (vis_rgn) { - struct region *exposed_rgn = expose_window( win, &win->window_rect, vis_rgn ); + struct region *exposed_rgn = expose_window( win, &win->window_rect, vis_rgn, 0 ); if (exposed_rgn) free_region( exposed_rgn ); free_region( vis_rgn ); }
From: Jinoh Kang jinoh.kang.kr@gmail.com
This partly reverts e42eaaaf3a873d29b14f8f3a3617df2d0d4210ca.
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/user32/tests/msg.c | 4 ---- server/window.c | 6 ++---- 2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index fb22f6042fe..e36eb7125e6 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -9302,8 +9302,6 @@ static void subtest_swp_paint_regions_( int line, int wrap_toplevel, LPCSTR pare } else { - todo_wine_if( !EqualRect( &rect_old, &rect_new ) && - (extest->style & WS_CLIPCHILDREN) == 0 && !is_composited ) ok( !!rgn_ok, "Parent update region shall match expected region\n" ); }
@@ -9365,8 +9363,6 @@ static void subtest_swp_paint_regions_( int line, int wrap_toplevel, LPCSTR pare } else { - todo_wine_if( !EqualRect( &rect_old, &rect_new ) && - (extest->style & WS_CLIPCHILDREN) == 0 && !is_composited ) ok( !!rgn_ok, "Child update region shall match expected region\n" ); }
diff --git a/server/window.c b/server/window.c index 7e418b7b3fa..464967084c2 100644 --- a/server/window.c +++ b/server/window.c @@ -1754,10 +1754,8 @@ static struct region *expose_window( struct window *win, const rectangle_t *old_ offset_region( new_vis_rgn, win->window_rect.left - old_window_rect->left, win->window_rect.top - old_window_rect->top );
- if (is_composited ? union_region( new_vis_rgn, old_vis_rgn, new_vis_rgn ) : - (win->parent->style & WS_CLIPCHILDREN) ? - subtract_region( new_vis_rgn, old_vis_rgn, new_vis_rgn ) : - xor_region( new_vis_rgn, old_vis_rgn, new_vis_rgn )) + if (is_composited ? union_region( new_vis_rgn, old_vis_rgn, new_vis_rgn ) + : subtract_region( new_vis_rgn, old_vis_rgn, new_vis_rgn )) { if (!is_region_empty( new_vis_rgn )) {
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=125448
Your paranoid android.
=== w1064 (32 bit report) ===
user32: msg.c:13440: Test failed: coords not changed: (101 101) (101 101) msg.c:13458: Test failed: coords not changed: (101 101) (101 101)
=== debian11 (32 bit report) ===
comctl32: edit.c:3453: Test succeeded inside todo block: Set focus: marked "todo_wine" but succeeds listview.c:2201: Test succeeded inside todo block: Expected 0, got 0 listview.c:2211: Test succeeded inside todo block: Expected 0, got 0 listview.c:2221: Test succeeded inside todo block: Expected 0, got 0 listview.c:2201: Test succeeded inside todo block: Expected 0, got 0 listview.c:2211: Test succeeded inside todo block: Expected 0, got 0 listview.c:2221: Test succeeded inside todo block: Expected 0, got 0 misc.c:969: Test failed: Button 0x7: Expected color 0xff, got 0x808080. misc.c:963: Test succeeded inside todo block: Button 0xa: Expected color 0x808080, got 0x808080.
user32: msg.c:9651: Test failed: destroy child on thread exit: 1: the msg sequence is not complete: expected 000f - actual 0000 static.c:116: Test failed: pixel should NOT be painted black! static.c:116: Test failed: pixel should NOT be painted black! win.c:8503: Test failed: GetUpdateRect returned empty region win.c:8504: Test failed: rects do not match (0,0)-(0,0) / (10,10)-(40,40) win.c:8518: Test failed: WM_PAINT should have been received in parent win.c:8562: Test failed: GetUpdateRect returned empty region win.c:8563: Test failed: rects do not match (0,0)-(0,0) / (10,10)-(40,40) win.c:8577: Test failed: WM_PAINT should have been received in parent
=== debian11 (32 bit ar:MA report) ===
user32: msg.c:9651: Test failed: destroy child on thread exit: 1: the msg sequence is not complete: expected 000f - actual 0000
=== debian11 (32 bit de report) ===
user32: msg.c:9651: Test failed: destroy child on thread exit: 1: the msg sequence is not complete: expected 000f - actual 0000
=== debian11 (32 bit fr report) ===
user32: msg.c:9651: Test failed: destroy child on thread exit: 1: the msg sequence is not complete: expected 000f - actual 0000
=== debian11 (32 bit he:IL report) ===
user32: msg.c:9651: Test failed: destroy child on thread exit: 1: the msg sequence is not complete: expected 000f - actual 0000
=== debian11 (32 bit hi:IN report) ===
user32: msg.c:9651: Test failed: destroy child on thread exit: 1: the msg sequence is not complete: expected 000f - actual 0000
=== debian11 (32 bit ja:JP report) ===
user32: msg.c:9651: Test failed: destroy child on thread exit: 1: the msg sequence is not complete: expected 000f - actual 0000
=== debian11 (32 bit zh:CN report) ===
user32: msg.c:9651: Test failed: destroy child on thread exit: 1: the msg sequence is not complete: expected 000f - actual 0000
=== debian11 (32 bit WoW report) ===
user32: msg.c:9651: Test failed: destroy child on thread exit: 1: the msg sequence is not complete: expected 000f - actual 0000
=== debian11 (64 bit WoW report) ===
user32: msg.c:9651: Test failed: destroy child on thread exit: 1: the msg sequence is not complete: expected 000f - actual 0000