From fd9f645b23cd380174ab00dea58a8aa9ae8512b4 Mon Sep 17 00:00:00 2001
From: Jiajin Cui <cuijiajin@uniontech.com>
Date: Wed, 1 Jul 2020 18:50:36 +0800
Subject: [PATCH v6 4/4] server: Make that subwindows shouldn't change existing
 WS_EX_TOPMOST extended styles.

Signed-off-by: Jiajin Cui <cuijiajin@uniontech.com>
---
 dlls/user32/tests/msg.c |  2 +-
 dlls/user32/tests/win.c | 16 +++----
 server/window.c         | 97 +++++++++++++++++++++++++++--------------
 3 files changed, 73 insertions(+), 42 deletions(-)

diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index 92b14ef52c..284ea57470 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -5802,7 +5802,7 @@ static void test_setwindowpos(void)
                              hwnd, 0, GetModuleHandleA(NULL), NULL);
     ok_sequence(WmCreateChildtopmostSeq, "CreateChildWindow", FALSE);
     ok(hwnd_A != NULL, "Failed to create child witch WS_EX_TOPMOST\n");
-    todo_wine ok(GetWindowLongA(hwnd_A, GWL_EXSTYLE) & WS_EX_TOPMOST, "%p: expected topmost\n", hwnd_A);
+    ok(GetWindowLongA(hwnd_A, GWL_EXSTYLE) & WS_EX_TOPMOST, "%p: expected topmost\n", hwnd_A);
 
     /* repeat */
     flush_events();
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index 18ef4f0f74..33cdc43c13 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -3036,42 +3036,42 @@ static void test_child_topmost_zorder(HWND hwnd_D)
                              hwnd_D, 0, GetModuleHandleA(NULL), NULL);
     check_z_order(hwnd_C, hwnd_B, 0, 0, FALSE);
     check_z_order(hwnd_B, hwnd_A, hwnd_C, 0, FALSE);
-todo_wine check_z_order(hwnd_A, 0, hwnd_B, 0, TRUE);
+    check_z_order(hwnd_A, 0, hwnd_B, 0, TRUE);
 
     SetWindowPos(hwnd_A, HWND_TOP, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE);
     check_z_order(hwnd_C, hwnd_B, hwnd_A, 0, FALSE);
     check_z_order(hwnd_B, 0, hwnd_C, 0, FALSE);
-todo_wine check_z_order(hwnd_A, hwnd_C, 0, 0, TRUE);
+    check_z_order(hwnd_A, hwnd_C, 0, 0, TRUE);
 
     SetWindowPos(hwnd_A, HWND_TOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE);
     check_z_order(hwnd_C, hwnd_B, hwnd_A, 0, FALSE);
     check_z_order(hwnd_B, 0, hwnd_C, 0, FALSE);
-todo_wine check_z_order(hwnd_A, hwnd_C, 0, 0, TRUE);
+    check_z_order(hwnd_A, hwnd_C, 0, 0, TRUE);
 
     SetWindowPos(hwnd_B, HWND_TOP, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE);
     check_z_order(hwnd_C, 0, hwnd_A, 0, FALSE);
     check_z_order(hwnd_B, hwnd_A, 0, 0, FALSE);
-todo_wine check_z_order(hwnd_A, hwnd_C, hwnd_B, 0, TRUE);
+    check_z_order(hwnd_A, hwnd_C, hwnd_B, 0, TRUE);
 
     SetWindowPos(hwnd_A, HWND_NOTOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE);
     check_z_order(hwnd_C, 0, hwnd_A, 0, FALSE);
     check_z_order(hwnd_B, hwnd_A, 0, 0, FALSE);
-todo_wine check_z_order(hwnd_A, hwnd_C, hwnd_B, 0, TRUE);
+    check_z_order(hwnd_A, hwnd_C, hwnd_B, 0, TRUE);
 
     SetWindowPos(hwnd_A, HWND_BOTTOM, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE);
     check_z_order(hwnd_C, hwnd_A, hwnd_B, 0, FALSE);
     check_z_order(hwnd_B, hwnd_C, 0, 0, FALSE);
-todo_wine check_z_order(hwnd_A, 0, hwnd_C, 0, TRUE);
+    check_z_order(hwnd_A, 0, hwnd_C, 0, TRUE);
 
     SetWindowPos(hwnd_C, HWND_TOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE);
     check_z_order(hwnd_C, hwnd_A, hwnd_B, 0, FALSE);
     check_z_order(hwnd_B, hwnd_C, 0, 0, FALSE);
-todo_wine check_z_order(hwnd_A, 0, hwnd_C, 0, TRUE);
+    check_z_order(hwnd_A, 0, hwnd_C, 0, TRUE);
 
     SetWindowPos(hwnd_C, HWND_TOP, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE);
     check_z_order(hwnd_C, hwnd_B, 0, 0, FALSE);
     check_z_order(hwnd_B, hwnd_A, hwnd_C, 0, FALSE);
-todo_wine check_z_order(hwnd_A, 0, hwnd_B, 0, TRUE);
+    check_z_order(hwnd_A, 0, hwnd_B, 0, TRUE);
 
     DestroyWindow(hwnd_A);
     DestroyWindow(hwnd_B);
diff --git a/server/window.c b/server/window.c
index 3a88b7f34f..3e7b2d5007 100644
--- a/server/window.c
+++ b/server/window.c
@@ -191,52 +191,83 @@ static unsigned int get_monitor_dpi( struct window *win )
 /* link a window at the right place in the siblings list */
 static void link_window( struct window *win, struct window *previous )
 {
-    if (previous == WINPTR_NOTOPMOST)
+    if (win->style & WS_CHILD)
     {
-        if (!(win->ex_style & WS_EX_TOPMOST) && win->is_linked) return;  /* nothing to do */
-        win->ex_style &= ~WS_EX_TOPMOST;
-        previous = WINPTR_TOP;  /* fallback to the HWND_TOP case */
-    }
+        if (previous == WINPTR_NOTOPMOST)
+        {
+            if (!(win->ex_style & WS_EX_TOPMOST) && win->is_linked) return;  /* nothing to do */
+            previous = WINPTR_TOP;  /* fallback to the HWND_TOP case */
+        }
 
-    list_remove( &win->entry );  /* unlink it from the previous location */
+        list_remove( &win->entry );  /* unlink it from the previous location */
 
-    if (previous == WINPTR_BOTTOM)
-    {
-        list_add_tail( &win->parent->children, &win->entry );
-        win->ex_style &= ~WS_EX_TOPMOST;
-    }
-    else if (previous == WINPTR_TOPMOST)
-    {
-        list_add_head( &win->parent->children, &win->entry );
-        win->ex_style |= WS_EX_TOPMOST;
+        if (previous == WINPTR_BOTTOM)
+        {
+            list_add_tail( &win->parent->children, &win->entry );
+        }
+        else if (previous == WINPTR_TOPMOST)
+        {
+            list_add_head( &win->parent->children, &win->entry );
+        }
+        else if (previous == WINPTR_TOP)
+        {
+            struct list *entry = win->parent->children.next;
+            list_add_before( entry, &win->entry );
+        }
+        else
+        {
+            list_add_after( &previous->entry, &win->entry );
+        }
     }
-    else if (previous == WINPTR_TOP)
+    else
     {
-        struct list *entry = win->parent->children.next;
-        if (!(win->ex_style & WS_EX_TOPMOST))  /* put it above the first non-topmost window */
+        if (previous == WINPTR_NOTOPMOST)
+        {
+            if (!(win->ex_style & WS_EX_TOPMOST) && win->is_linked) return;  /* nothing to do */
+            win->ex_style &= ~WS_EX_TOPMOST;
+            previous = WINPTR_TOP;  /* fallback to the HWND_TOP case */
+        }
+
+        list_remove( &win->entry );  /* unlink it from the previous location */
+
+        if (previous == WINPTR_BOTTOM)
+        {
+            list_add_tail( &win->parent->children, &win->entry );
+            win->ex_style &= ~WS_EX_TOPMOST;
+        }
+        else if (previous == WINPTR_TOPMOST)
         {
-            while (entry != &win->parent->children)
+            list_add_head( &win->parent->children, &win->entry );
+            win->ex_style |= WS_EX_TOPMOST;
+        }
+        else if (previous == WINPTR_TOP)
+        {
+            struct list *entry = win->parent->children.next;
+            if (!(win->ex_style & WS_EX_TOPMOST))  /* put it above the first non-topmost window */
             {
-                struct window *next = LIST_ENTRY( entry, struct window, entry );
-                if (!(next->ex_style & WS_EX_TOPMOST)) break;
-                if (next->handle == win->owner)  /* keep it above owner */
+                while (entry != &win->parent->children)
                 {
-                    win->ex_style |= WS_EX_TOPMOST;
-                    break;
+                    struct window *next = LIST_ENTRY( entry, struct window, entry );
+                    if (!(next->ex_style & WS_EX_TOPMOST)) break;
+                    if (next->handle == win->owner)  /* keep it above owner */
+                    {
+                        win->ex_style |= WS_EX_TOPMOST;
+                        break;
+                    }
+                    entry = entry->next;
                 }
-                entry = entry->next;
             }
+            list_add_before( entry, &win->entry );
         }
-        list_add_before( entry, &win->entry );
-    }
-    else
-    {
-        list_add_after( &previous->entry, &win->entry );
-        if (!(previous->ex_style & WS_EX_TOPMOST)) win->ex_style &= ~WS_EX_TOPMOST;
         else
         {
-            struct window *next = get_next_window( win );
-            if (next && (next->ex_style & WS_EX_TOPMOST)) win->ex_style |= WS_EX_TOPMOST;
+            list_add_after( &previous->entry, &win->entry );
+            if (!(previous->ex_style & WS_EX_TOPMOST)) win->ex_style &= ~WS_EX_TOPMOST;
+            else
+            {
+                struct window *next = get_next_window( win );
+                if (next && (next->ex_style & WS_EX_TOPMOST)) win->ex_style |= WS_EX_TOPMOST;
+            }
         }
     }
 
-- 
2.20.1

