Alexandre Julliard : server: Add support for a top-level message parent window in parallel to the desktop window .

Alexandre Julliard julliard at winehq.org
Wed Jun 25 16:43:32 CDT 2008


Module: wine
Branch: master
Commit: 81e6edbda9334c2e2060ece2f163c393eac6cd9b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=81e6edbda9334c2e2060ece2f163c393eac6cd9b

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Jun 25 14:43:39 2008 +0200

server: Add support for a top-level message parent window in parallel to the desktop window.

---

 server/class.c      |    8 ++++++
 server/user.h       |    2 +
 server/window.c     |   65 +++++++++++++++++++++++++++++++-------------------
 server/winstation.c |    2 +
 4 files changed, 52 insertions(+), 25 deletions(-)

diff --git a/server/class.c b/server/class.c
index ae594df..5c30738 100644
--- a/server/class.c
+++ b/server/class.c
@@ -128,6 +128,14 @@ int is_desktop_class( struct window_class *class )
     return (class->atom == DESKTOP_ATOM && !class->local);
 }
 
+int is_hwnd_message_class( struct window_class *class )
+{
+    static const WCHAR messageW[] = {'M','e','s','s','a','g','e'};
+    static const struct unicode_str name = { messageW, sizeof(messageW) };
+
+    return (!class->local && class->atom == find_global_atom( NULL, &name ));
+}
+
 atom_t get_class_atom( struct window_class *class )
 {
     return class->atom;
diff --git a/server/user.h b/server/user.h
index f58f4d4..b12fccb 100644
--- a/server/user.h
+++ b/server/user.h
@@ -57,6 +57,7 @@ struct desktop
     struct winstation   *winstation;     /* winstation this desktop belongs to */
     struct list          entry;          /* entry in winstation list of desktops */
     struct window       *top_window;     /* desktop window for this desktop */
+    struct window       *msg_window;     /* HWND_MESSAGE top window */
     struct hook_table   *global_hooks;   /* table of global hooks on this desktop */
     struct timeout_user *close_timeout;  /* timeout before closing the desktop */
     unsigned int         users;          /* processes and threads using this desktop */
@@ -145,6 +146,7 @@ extern struct window_class *grab_class( struct process *process, atom_t atom,
                                         void *instance, int *extra_bytes );
 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 atom_t get_class_atom( struct window_class *class );
 extern void *get_class_client_ptr( struct window_class *class );
 
diff --git a/server/window.c b/server/window.c
index 8c87004..cae5603 100644
--- a/server/window.c
+++ b/server/window.c
@@ -393,8 +393,10 @@ void destroy_window( struct window *win )
     list_remove( &win->entry );
     if (is_desktop_window(win))
     {
-        assert( win->desktop->top_window == win );
-        win->desktop->top_window = NULL;
+        struct desktop *desktop = win->desktop;
+        assert( desktop->top_window == win || desktop->msg_window == win );
+        if (desktop->top_window == win) desktop->top_window = NULL;
+        else desktop->msg_window = NULL;
     }
     detach_window_thread( win );
     if (win->win_region) free_region( win->win_region );
@@ -426,7 +428,7 @@ static struct window *create_window( struct window *parent, struct window *owner
 {
     static const rectangle_t empty_rect;
     int extra_bytes;
-    struct window *win;
+    struct window *win = NULL;
     struct desktop *desktop;
     struct window_class *class;
 
@@ -438,6 +440,27 @@ static struct window *create_window( struct window *parent, struct window *owner
         return NULL;
     }
 
+    if (!parent)  /* null parent is only allowed for desktop or HWND_MESSAGE top window */
+    {
+        if (is_desktop_class( class ))
+            parent = desktop->top_window;  /* use existing desktop if any */
+        else if (is_hwnd_message_class( class ))
+            /* use desktop window if message window is already created */
+            parent = desktop->msg_window ? desktop->top_window : NULL;
+        else if (!(parent = desktop->top_window))  /* must already have a desktop then */
+        {
+            set_error( STATUS_ACCESS_DENIED );
+            goto failed;
+        }
+    }
+
+    /* parent must be on the same desktop */
+    if (parent && parent->desktop != desktop)
+    {
+        set_error( STATUS_ACCESS_DENIED );
+        goto failed;
+    }
+
     if (!(win = mem_alloc( sizeof(*win) + extra_bytes - 1 ))) goto failed;
     if (!(win->handle = alloc_user_handle( win, USER_WINDOW ))) goto failed;
 
@@ -468,20 +491,6 @@ static struct window *create_window( struct window *parent, struct window *owner
     list_init( &win->children );
     list_init( &win->unlinked );
 
-    /* parent must be on the same desktop */
-    if (parent && parent->desktop != desktop)
-    {
-        set_error( STATUS_ACCESS_DENIED );
-        goto failed;
-    }
-
-    /* if no parent, class must be the desktop */
-    if (!parent && !is_desktop_class( class ))
-    {
-        set_error( STATUS_ACCESS_DENIED );
-        goto failed;
-    }
-
     /* if parent belongs to a different thread and the window isn't */
     /* top-level, attach the two threads */
     if (parent && parent->thread && parent->thread != current && !is_desktop_window(parent))
@@ -498,9 +507,17 @@ static struct window *create_window( struct window *parent, struct window *owner
     else
     {
         list_init( &win->entry );
-        assert( !desktop->top_window );
-        desktop->top_window = win;
-        set_process_default_desktop( current->process, desktop, current->desktop );
+        if (is_desktop_class( class ))
+        {
+            assert( !desktop->top_window );
+            desktop->top_window = win;
+            set_process_default_desktop( current->process, desktop, current->desktop );
+        }
+        else
+        {
+            assert( !desktop->msg_window );
+            desktop->msg_window = win;
+        }
     }
 
     current->desktop_users++;
@@ -1708,20 +1725,18 @@ static void set_window_region( struct window *win, struct region *region, int re
 /* create a window */
 DECL_HANDLER(create_window)
 {
-    struct window *win, *parent, *owner = NULL;
+    struct window *win, *parent = NULL, *owner = NULL;
     struct unicode_str cls_name;
     atom_t atom;
 
     reply->handle = 0;
-
-    if (!req->parent) parent = get_desktop_window( current, 0 );
-    else if (!(parent = get_window( req->parent ))) return;
+    if (req->parent && !(parent = get_window( req->parent ))) return;
 
     if (req->owner)
     {
         if (!(owner = get_window( req->owner ))) return;
         if (is_desktop_window(owner)) owner = NULL;
-        else if (!is_desktop_window(parent))
+        else if (parent && !is_desktop_window(parent))
         {
             /* an owned window must be created as top-level */
             set_error( STATUS_ACCESS_DENIED );
diff --git a/server/winstation.c b/server/winstation.c
index 2ad4146..cfff0a4 100644
--- a/server/winstation.c
+++ b/server/winstation.c
@@ -227,6 +227,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned
             desktop->flags = flags;
             desktop->winstation = (struct winstation *)grab_object( winstation );
             desktop->top_window = NULL;
+            desktop->msg_window = NULL;
             desktop->global_hooks = NULL;
             desktop->close_timeout = NULL;
             desktop->users = 0;
@@ -270,6 +271,7 @@ static void desktop_destroy( struct object *obj )
     struct desktop *desktop = (struct desktop *)obj;
 
     if (desktop->top_window) destroy_window( desktop->top_window );
+    if (desktop->msg_window) destroy_window( desktop->msg_window );
     if (desktop->global_hooks) release_object( desktop->global_hooks );
     if (desktop->close_timeout) remove_timeout_user( desktop->close_timeout );
     list_remove( &desktop->entry );




More information about the wine-cvs mailing list