[PATCH v4 2/4] server: Correctly expose composited parent window and its child on position change.
Jinoh Kang
wine at gitlab.winehq.org
Thu Jun 16 20:42:08 CDT 2022
From: Jinoh Kang <jinoh.kang.kr at gmail.com>
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53153
Signed-off-by: Jinoh Kang <jinoh.kang.kr at 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 c62b25446a2..317dd9e48dc 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -9295,7 +9295,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 ) ? is_zorder_redraw :
- ((extest->style & WS_CLIPCHILDREN) == 0 || is_composited) )
+ ((extest->style & WS_CLIPCHILDREN) == 0 && !is_composited) )
ok( !!rgn_equal, "Parent update region shall match expected region\n" );
if (!rgn_equal && winetest_debug > 0)
@@ -9354,7 +9354,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 ) ? is_zorder_redraw :
- ((extest->style & WS_CLIPCHILDREN) == 0 || is_composited) )
+ ((extest->style & WS_CLIPCHILDREN) == 0 && !is_composited) )
ok( !!rgn_equal, "Child update region shall match expected region\n" );
if (!rgn_equal && winetest_debug > 0)
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 ))
{
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/231
More information about the wine-devel
mailing list