Fixed a number of bugs in the handling of window parent and owner and
added a regression test (based on the work of Bill Medland).

diff --git a/server/window.c b/server/window.c
index c5f836e..e513b87 100644
--- a/server/window.c
+++ b/server/window.c
@@ -53,7 +53,7 @@
 struct window
 {
     struct window   *parent;          /* parent window */
-    struct window   *owner;           /* owner of this window */
+    user_handle_t    owner;           /* owner of this window */
     struct window   *first_child;     /* first child in Z-order */
     struct window   *last_child;      /* last child in Z-order */
     struct window   *first_unlinked;  /* first child not linked in the Z-order list */
@@ -110,11 +110,7 @@
 
     if (parent)
     {
-        if (win->parent != parent)
-        {
-            win->owner = NULL;  /* reset owner if changing parent */
-            win->parent = parent;
-        }
+        win->parent = parent;
         if ((win->prev = previous))
         {
             if ((win->next = previous->next)) win->next->prev = win;
@@ -241,16 +237,6 @@
     while (win->first_child) destroy_window( win->first_child );
     while (win->first_unlinked) destroy_window( win->first_unlinked );
 
-    /* reset siblings owner */
-    if (win->parent)
-    {
-        struct window *ptr;
-        for (ptr = win->parent->first_child; ptr; ptr = ptr->next)
-            if (ptr->owner == win) ptr->owner = NULL;
-        for (ptr = win->parent->first_unlinked; ptr; ptr = ptr->next)
-            if (ptr->owner == win) ptr->owner = NULL;
-    }
-
     if (win->thread->queue)
     {
         if (win->paint_count) inc_queue_paint_count( win->thread, -win->paint_count );
@@ -276,7 +262,7 @@
         return NULL;
     }
     win->parent         = parent;
-    win->owner          = owner;
+    win->owner          = owner ? owner->handle : 0;
     win->first_child    = NULL;
     win->last_child     = NULL;
     win->first_unlinked = NULL;
@@ -390,6 +376,7 @@
         {
             if (!(top_window = create_window( NULL, NULL, req->atom ))) return;
             top_window->thread = NULL;  /* no thread owns the desktop */
+            top_window->style  = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
         }
         reply->handle = top_window->handle;
     }
@@ -400,9 +387,9 @@
         if (!(parent = get_window( req->parent ))) return;
         if (req->owner && !(owner = get_window( req->owner ))) return;
         if (owner == top_window) owner = NULL;
-        else if (owner && owner->parent != parent)
+        else if (owner && parent != top_window)
         {
-            /* owner must be a sibling of the new window */
+            /* an owned window must be created as top-level */
             set_error( STATUS_ACCESS_DENIED );
             return;
         }
@@ -464,17 +451,17 @@
 DECL_HANDLER(set_window_owner)
 {
     struct window *win = get_window( req->handle );
-    struct window *owner = get_window( req->owner );
+    struct window *owner = NULL;
 
-    if (!win || !owner) return;
-    if (owner->parent != win->parent)
+    if (!win) return;
+    if (req->owner && !(owner = get_window( req->owner ))) return;
+    if (win == top_window)
     {
-        /* owner has to be a sibling of window */
         set_error( STATUS_ACCESS_DENIED );
         return;
     }
-    win->owner = owner;
-    reply->full_owner = owner->handle;
+    reply->prev_owner = win->owner;
+    reply->full_owner = win->owner = owner ? owner->handle : 0;
 }
 
 
@@ -502,7 +489,13 @@
 DECL_HANDLER(set_window_info)
 {
     struct window *win = get_window( req->handle );
+
     if (!win) return;
+    if (req->flags && win == top_window)
+    {
+        set_error( STATUS_ACCESS_DENIED );
+        return;
+    }
     reply->old_style     = win->style;
     reply->old_ex_style  = win->ex_style;
     reply->old_id        = win->id;
@@ -578,7 +571,7 @@
     {
         struct window *parent = win->parent;
         reply->parent        = parent->handle;
-        reply->owner         = win->owner ? win->owner->handle : 0;
+        reply->owner         = win->owner;
         reply->next_sibling  = win->next ? win->next->handle : 0;
         reply->prev_sibling  = win->prev ? win->prev->handle : 0;
         reply->first_sibling = parent->first_child ? parent->first_child->handle : 0;