Module: wine Branch: master Commit: 81e6edbda9334c2e2060ece2f163c393eac6cd9b URL: http://source.winehq.org/git/wine.git/?a=commit;h=81e6edbda9334c2e2060ece2f1...
Author: Alexandre Julliard julliard@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 );