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 | 2 +- server/class.c | 5 +++++ server/user.h | 1 + server/window.c | 37 +++++++++++++++++++++++++++++-------- 4 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 67f58032cb3..a431e3b04d6 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -9257,7 +9257,7 @@ static void subtest_swp_paint_regions_( int line, int wrap_toplevel, LPCSTR pare rgn_equal = EqualRgn( hrgn_expect, hrgn_actual ); } todo_wine_if( !EqualRect( &rect_old, &rect_new ) && - ((extest->style & WS_CLIPCHILDREN) == 0 || region_op == RGN_OR) ) + (extest->style & WS_CLIPCHILDREN) == 0 && region_op != RGN_OR ) ok( !!rgn_equal, "Update region shall match expected region\n" );
flush_events(); 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..0356fe0c5cd 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 );
diff --git a/server/window.c b/server/window.c index 7675cd1103d..d007e38f49c 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 ) { @@ -1705,7 +1715,6 @@ static unsigned int get_window_update_flags( struct window *win, struct window * return 0; }
- /* 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, @@ -1732,21 +1741,33 @@ static struct region *expose_window( struct window *win, const rectangle_t *old_
if (win->parent && !is_desktop_window( win->parent )) { + struct region *parent_expose_rgn; + /* make it relative to the old window pos for subtracting */ 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) ? - subtract_region( new_vis_rgn, old_vis_rgn, new_vis_rgn ) : - xor_region( new_vis_rgn, old_vis_rgn, new_vis_rgn )) + if (is_window_composited( win->parent )) { - if (!is_region_empty( new_vis_rgn )) + parent_expose_rgn = xor_region( new_vis_rgn, old_vis_rgn, new_vis_rgn ); + if (parent_expose_rgn && !is_region_empty( parent_expose_rgn )) { - /* 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 ); + parent_expose_rgn = union_region( parent_expose_rgn, old_vis_rgn, parent_expose_rgn ); } } + else + { + parent_expose_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 (parent_expose_rgn && !is_region_empty( parent_expose_rgn )) + { + /* make it relative to parent */ + offset_region( parent_expose_rgn, old_window_rect->left, old_window_rect->top ); + redraw_window( win->parent, parent_expose_rgn, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); + } } free_region( new_vis_rgn ); return exposed_rgn;