server: Add support for a top-level message parent window in parallel to the desktop window.
This commit is contained in:
parent
25e070c0ac
commit
81e6edbda9
|
@ -128,6 +128,14 @@ int is_desktop_class( struct window_class *class )
|
||||||
return (class->atom == DESKTOP_ATOM && !class->local);
|
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 )
|
atom_t get_class_atom( struct window_class *class )
|
||||||
{
|
{
|
||||||
return class->atom;
|
return class->atom;
|
||||||
|
|
|
@ -57,6 +57,7 @@ struct desktop
|
||||||
struct winstation *winstation; /* winstation this desktop belongs to */
|
struct winstation *winstation; /* winstation this desktop belongs to */
|
||||||
struct list entry; /* entry in winstation list of desktops */
|
struct list entry; /* entry in winstation list of desktops */
|
||||||
struct window *top_window; /* desktop window for this desktop */
|
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 hook_table *global_hooks; /* table of global hooks on this desktop */
|
||||||
struct timeout_user *close_timeout; /* timeout before closing the desktop */
|
struct timeout_user *close_timeout; /* timeout before closing the desktop */
|
||||||
unsigned int users; /* processes and threads using this 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 );
|
void *instance, int *extra_bytes );
|
||||||
extern void release_class( struct window_class *class );
|
extern void release_class( struct window_class *class );
|
||||||
extern int is_desktop_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 atom_t get_class_atom( struct window_class *class );
|
||||||
extern void *get_class_client_ptr( struct window_class *class );
|
extern void *get_class_client_ptr( struct window_class *class );
|
||||||
|
|
||||||
|
|
|
@ -393,8 +393,10 @@ void destroy_window( struct window *win )
|
||||||
list_remove( &win->entry );
|
list_remove( &win->entry );
|
||||||
if (is_desktop_window(win))
|
if (is_desktop_window(win))
|
||||||
{
|
{
|
||||||
assert( win->desktop->top_window == win );
|
struct desktop *desktop = win->desktop;
|
||||||
win->desktop->top_window = NULL;
|
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 );
|
detach_window_thread( win );
|
||||||
if (win->win_region) free_region( win->win_region );
|
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;
|
static const rectangle_t empty_rect;
|
||||||
int extra_bytes;
|
int extra_bytes;
|
||||||
struct window *win;
|
struct window *win = NULL;
|
||||||
struct desktop *desktop;
|
struct desktop *desktop;
|
||||||
struct window_class *class;
|
struct window_class *class;
|
||||||
|
|
||||||
|
@ -438,6 +440,27 @@ static struct window *create_window( struct window *parent, struct window *owner
|
||||||
return NULL;
|
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 = mem_alloc( sizeof(*win) + extra_bytes - 1 ))) goto failed;
|
||||||
if (!(win->handle = alloc_user_handle( win, USER_WINDOW ))) 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->children );
|
||||||
list_init( &win->unlinked );
|
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 */
|
/* if parent belongs to a different thread and the window isn't */
|
||||||
/* top-level, attach the two threads */
|
/* top-level, attach the two threads */
|
||||||
if (parent && parent->thread && parent->thread != current && !is_desktop_window(parent))
|
if (parent && parent->thread && parent->thread != current && !is_desktop_window(parent))
|
||||||
|
@ -498,10 +507,18 @@ static struct window *create_window( struct window *parent, struct window *owner
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
list_init( &win->entry );
|
list_init( &win->entry );
|
||||||
|
if (is_desktop_class( class ))
|
||||||
|
{
|
||||||
assert( !desktop->top_window );
|
assert( !desktop->top_window );
|
||||||
desktop->top_window = win;
|
desktop->top_window = win;
|
||||||
set_process_default_desktop( current->process, desktop, current->desktop );
|
set_process_default_desktop( current->process, desktop, current->desktop );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert( !desktop->msg_window );
|
||||||
|
desktop->msg_window = win;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
current->desktop_users++;
|
current->desktop_users++;
|
||||||
return win;
|
return win;
|
||||||
|
@ -1708,20 +1725,18 @@ static void set_window_region( struct window *win, struct region *region, int re
|
||||||
/* create a window */
|
/* create a window */
|
||||||
DECL_HANDLER(create_window)
|
DECL_HANDLER(create_window)
|
||||||
{
|
{
|
||||||
struct window *win, *parent, *owner = NULL;
|
struct window *win, *parent = NULL, *owner = NULL;
|
||||||
struct unicode_str cls_name;
|
struct unicode_str cls_name;
|
||||||
atom_t atom;
|
atom_t atom;
|
||||||
|
|
||||||
reply->handle = 0;
|
reply->handle = 0;
|
||||||
|
if (req->parent && !(parent = get_window( req->parent ))) return;
|
||||||
if (!req->parent) parent = get_desktop_window( current, 0 );
|
|
||||||
else if (!(parent = get_window( req->parent ))) return;
|
|
||||||
|
|
||||||
if (req->owner)
|
if (req->owner)
|
||||||
{
|
{
|
||||||
if (!(owner = get_window( req->owner ))) return;
|
if (!(owner = get_window( req->owner ))) return;
|
||||||
if (is_desktop_window(owner)) owner = NULL;
|
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 */
|
/* an owned window must be created as top-level */
|
||||||
set_error( STATUS_ACCESS_DENIED );
|
set_error( STATUS_ACCESS_DENIED );
|
||||||
|
|
|
@ -227,6 +227,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned
|
||||||
desktop->flags = flags;
|
desktop->flags = flags;
|
||||||
desktop->winstation = (struct winstation *)grab_object( winstation );
|
desktop->winstation = (struct winstation *)grab_object( winstation );
|
||||||
desktop->top_window = NULL;
|
desktop->top_window = NULL;
|
||||||
|
desktop->msg_window = NULL;
|
||||||
desktop->global_hooks = NULL;
|
desktop->global_hooks = NULL;
|
||||||
desktop->close_timeout = NULL;
|
desktop->close_timeout = NULL;
|
||||||
desktop->users = 0;
|
desktop->users = 0;
|
||||||
|
@ -270,6 +271,7 @@ static void desktop_destroy( struct object *obj )
|
||||||
struct desktop *desktop = (struct desktop *)obj;
|
struct desktop *desktop = (struct desktop *)obj;
|
||||||
|
|
||||||
if (desktop->top_window) destroy_window( desktop->top_window );
|
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->global_hooks) release_object( desktop->global_hooks );
|
||||||
if (desktop->close_timeout) remove_timeout_user( desktop->close_timeout );
|
if (desktop->close_timeout) remove_timeout_user( desktop->close_timeout );
|
||||||
list_remove( &desktop->entry );
|
list_remove( &desktop->entry );
|
||||||
|
|
Loading…
Reference in New Issue