server: Support for closing the desktop window.
If a thread is owning the desktop window, when all other users of the desktop have exited, signal the owner to close the desktop (with a 1 second delay).
This commit is contained in:
parent
8cea993033
commit
f978f615d8
|
@ -570,6 +570,7 @@ static void process_killed( struct process *process )
|
||||||
|
|
||||||
assert( list_empty( &process->thread_list ));
|
assert( list_empty( &process->thread_list ));
|
||||||
gettimeofday( &process->end_time, NULL );
|
gettimeofday( &process->end_time, NULL );
|
||||||
|
close_process_desktop( process );
|
||||||
handles = process->handles;
|
handles = process->handles;
|
||||||
process->handles = NULL;
|
process->handles = NULL;
|
||||||
if (handles) release_object( handles );
|
if (handles) release_object( handles );
|
||||||
|
|
|
@ -52,12 +52,14 @@ struct winstation
|
||||||
|
|
||||||
struct desktop
|
struct desktop
|
||||||
{
|
{
|
||||||
struct object obj; /* object header */
|
struct object obj; /* object header */
|
||||||
unsigned int flags; /* desktop flags */
|
unsigned int flags; /* desktop flags */
|
||||||
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 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 */
|
||||||
|
unsigned int users; /* processes and threads using this desktop */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* user handles functions */
|
/* user handles functions */
|
||||||
|
@ -123,6 +125,8 @@ extern int rect_in_region( struct region *region, const rectangle_t *rect );
|
||||||
|
|
||||||
/* window functions */
|
/* window functions */
|
||||||
|
|
||||||
|
extern struct process *get_top_window_owner( struct desktop *desktop );
|
||||||
|
extern void close_desktop_window( struct desktop *desktop );
|
||||||
extern void destroy_window( struct window *win );
|
extern void destroy_window( struct window *win );
|
||||||
extern void destroy_thread_windows( struct thread *thread );
|
extern void destroy_thread_windows( struct thread *thread );
|
||||||
extern int is_child_window( user_handle_t parent, user_handle_t child );
|
extern int is_child_window( user_handle_t parent, user_handle_t child );
|
||||||
|
@ -150,6 +154,7 @@ extern struct winstation *get_process_winstation( struct process *process, unsig
|
||||||
extern struct desktop *get_thread_desktop( struct thread *thread, unsigned int access );
|
extern struct desktop *get_thread_desktop( struct thread *thread, unsigned int access );
|
||||||
extern void connect_process_winstation( struct process *process, const struct unicode_str *name );
|
extern void connect_process_winstation( struct process *process, const struct unicode_str *name );
|
||||||
extern void connect_process_desktop( struct process *process, const struct unicode_str *name );
|
extern void connect_process_desktop( struct process *process, const struct unicode_str *name );
|
||||||
|
extern void close_process_desktop( struct process *process );
|
||||||
extern void close_thread_desktop( struct thread *thread );
|
extern void close_thread_desktop( struct thread *thread );
|
||||||
|
|
||||||
#endif /* __WINE_SERVER_USER_H */
|
#endif /* __WINE_SERVER_USER_H */
|
||||||
|
|
|
@ -351,6 +351,21 @@ void destroy_window( struct window *win )
|
||||||
free( win );
|
free( win );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get the process owning the top window of a given desktop */
|
||||||
|
struct process *get_top_window_owner( struct desktop *desktop )
|
||||||
|
{
|
||||||
|
struct window *win = desktop->top_window;
|
||||||
|
if (!win || !win->thread) return NULL;
|
||||||
|
return win->thread->process;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attempt to close the desktop window when the last process using it is gone */
|
||||||
|
void close_desktop_window( struct desktop *desktop )
|
||||||
|
{
|
||||||
|
struct window *win = desktop->top_window;
|
||||||
|
if (win && win->thread) post_message( win->handle, WM_SYSCOMMAND, SC_CLOSE, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
/* create a new window structure (note: the window is not linked in the window tree) */
|
/* create a new window structure (note: the window is not linked in the window tree) */
|
||||||
static struct window *create_window( struct window *parent, struct window *owner,
|
static struct window *create_window( struct window *parent, struct window *owner,
|
||||||
atom_t atom, void *instance )
|
atom_t atom, void *instance )
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "request.h"
|
#include "request.h"
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
|
#include "file.h"
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,6 +200,8 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned
|
||||||
desktop->winstation = (struct winstation *)grab_object( winstation );
|
desktop->winstation = (struct winstation *)grab_object( winstation );
|
||||||
desktop->top_window = NULL;
|
desktop->top_window = NULL;
|
||||||
desktop->global_hooks = NULL;
|
desktop->global_hooks = NULL;
|
||||||
|
desktop->close_timeout = NULL;
|
||||||
|
desktop->users = 0;
|
||||||
list_add_tail( &winstation->desktops, &desktop->entry );
|
list_add_tail( &winstation->desktops, &desktop->entry );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,6 +236,7 @@ static void desktop_destroy( struct object *obj )
|
||||||
|
|
||||||
if (desktop->top_window) destroy_window( desktop->top_window );
|
if (desktop->top_window) destroy_window( desktop->top_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 );
|
||||||
list_remove( &desktop->entry );
|
list_remove( &desktop->entry );
|
||||||
release_object( desktop->winstation );
|
release_object( desktop->winstation );
|
||||||
}
|
}
|
||||||
|
@ -293,6 +297,12 @@ void connect_process_desktop( struct process *process, const struct unicode_str
|
||||||
if ((desktop = create_desktop( name, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 0, winstation )))
|
if ((desktop = create_desktop( name, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 0, winstation )))
|
||||||
{
|
{
|
||||||
process->desktop = alloc_handle( process, desktop, DESKTOP_ALL_ACCESS, 0 );
|
process->desktop = alloc_handle( process, desktop, DESKTOP_ALL_ACCESS, 0 );
|
||||||
|
desktop->users++;
|
||||||
|
if (desktop->close_timeout)
|
||||||
|
{
|
||||||
|
remove_timeout_user( desktop->close_timeout );
|
||||||
|
desktop->close_timeout = NULL;
|
||||||
|
}
|
||||||
release_object( desktop );
|
release_object( desktop );
|
||||||
}
|
}
|
||||||
release_object( winstation );
|
release_object( winstation );
|
||||||
|
@ -300,6 +310,37 @@ void connect_process_desktop( struct process *process, const struct unicode_str
|
||||||
clear_error(); /* ignore errors */
|
clear_error(); /* ignore errors */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void close_desktop_timeout( void *private )
|
||||||
|
{
|
||||||
|
struct desktop *desktop = private;
|
||||||
|
|
||||||
|
desktop->close_timeout = NULL;
|
||||||
|
unlink_named_object( &desktop->obj ); /* make sure no other process can open it */
|
||||||
|
close_desktop_window( desktop ); /* and signal the owner to quit */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close the desktop of a given process */
|
||||||
|
void close_process_desktop( struct process *process )
|
||||||
|
{
|
||||||
|
struct desktop *desktop;
|
||||||
|
|
||||||
|
if (process->desktop && (desktop = get_desktop_obj( process, process->desktop, 0 )))
|
||||||
|
{
|
||||||
|
assert( desktop->users > 0 );
|
||||||
|
desktop->users--;
|
||||||
|
/* if we have one remaining user, it has to be the manager of the desktop window */
|
||||||
|
if (desktop->users == 1 && get_top_window_owner( desktop ))
|
||||||
|
{
|
||||||
|
struct timeval when;
|
||||||
|
gettimeofday( &when, NULL );
|
||||||
|
add_timeout( &when, 1000 );
|
||||||
|
desktop->close_timeout = add_timeout_user( &when, close_desktop_timeout, desktop );
|
||||||
|
}
|
||||||
|
release_object( desktop );
|
||||||
|
}
|
||||||
|
clear_error(); /* ignore errors */
|
||||||
|
}
|
||||||
|
|
||||||
/* close the desktop of a given thread */
|
/* close the desktop of a given thread */
|
||||||
void close_thread_desktop( struct thread *thread )
|
void close_thread_desktop( struct thread *thread )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue