[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