server: Keep a list of threads connected to each desktop.

This commit is contained in:
Rémi Bernon 2024-01-27 22:00:12 +01:00 committed by Alexandre Julliard
parent 496eed7aaf
commit f7303cf7b6
3 changed files with 33 additions and 22 deletions

View file

@ -51,6 +51,7 @@ struct thread
struct object obj; /* object header */ struct object obj; /* object header */
struct list entry; /* entry in system-wide thread list */ struct list entry; /* entry in system-wide thread list */
struct list proc_entry; /* entry in per-process thread list */ struct list proc_entry; /* entry in per-process thread list */
struct list desktop_entry; /* entry in per-desktop thread list */
struct process *process; struct process *process;
thread_id_t id; /* thread id */ thread_id_t id; /* thread id */
struct list mutex_list; /* list of currently owned mutexes */ struct list mutex_list; /* list of currently owned mutexes */

View file

@ -70,6 +70,7 @@ struct desktop
struct winstation *winstation; /* winstation this desktop belongs to */ struct winstation *winstation; /* winstation this desktop belongs to */
timeout_t input_time; /* last time this desktop had the input */ timeout_t input_time; /* last time this desktop had the input */
struct list entry; /* entry in winstation list of desktops */ struct list entry; /* entry in winstation list of desktops */
struct list threads; /* list of threads connected to this desktop */
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 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 */

View file

@ -273,6 +273,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned
desktop->close_timeout = NULL; desktop->close_timeout = NULL;
desktop->foreground_input = NULL; desktop->foreground_input = NULL;
desktop->users = 0; desktop->users = 0;
list_init( &desktop->threads );
memset( &desktop->cursor, 0, sizeof(desktop->cursor) ); memset( &desktop->cursor, 0, sizeof(desktop->cursor) );
memset( desktop->keystate, 0, sizeof(desktop->keystate) ); memset( desktop->keystate, 0, sizeof(desktop->keystate) );
list_add_tail( &winstation->desktops, &desktop->entry ); list_add_tail( &winstation->desktops, &desktop->entry );
@ -362,26 +363,37 @@ static void close_desktop_timeout( void *private )
} }
/* add a user of the desktop and cancel the close timeout */ /* add a user of the desktop and cancel the close timeout */
static void add_desktop_user( struct desktop *desktop ) static void add_desktop_thread( struct desktop *desktop, struct thread *thread )
{ {
desktop->users++; list_add_tail( &desktop->threads, &thread->desktop_entry );
if (desktop->close_timeout)
if (!thread->process->is_system)
{ {
remove_timeout_user( desktop->close_timeout ); desktop->users++;
desktop->close_timeout = NULL; if (desktop->close_timeout)
{
remove_timeout_user( desktop->close_timeout );
desktop->close_timeout = NULL;
}
} }
} }
/* remove a user of the desktop and start the close timeout if necessary */ /* remove a user of the desktop and start the close timeout if necessary */
static void remove_desktop_user( struct desktop *desktop ) static void remove_desktop_thread( struct desktop *desktop, struct thread *thread )
{ {
struct process *process; struct process *process;
assert( desktop->users > 0 );
desktop->users--;
/* if we have one remaining user, it has to be the manager of the desktop window */ list_remove( &thread->desktop_entry );
if ((process = get_top_window_owner( desktop )) && desktop->users == process->running_threads && !desktop->close_timeout)
desktop->close_timeout = add_timeout_user( -TICKS_PER_SEC, close_desktop_timeout, desktop ); if (!thread->process->is_system)
{
assert( desktop->users > 0 );
desktop->users--;
/* if we have one remaining user, it has to be the manager of the desktop window */
if ((process = get_top_window_owner( desktop )) && desktop->users == process->running_threads && !desktop->close_timeout)
desktop->close_timeout = add_timeout_user( -TICKS_PER_SEC, close_desktop_timeout, desktop );
}
} }
/* set the thread default desktop handle */ /* set the thread default desktop handle */
@ -390,7 +402,7 @@ void set_thread_default_desktop( struct thread *thread, struct desktop *desktop,
if (thread->desktop) return; /* nothing to do */ if (thread->desktop) return; /* nothing to do */
thread->desktop = handle; thread->desktop = handle;
if (!thread->process->is_system) add_desktop_user( desktop ); add_desktop_thread( desktop, thread );
} }
/* set the process default desktop handle */ /* set the process default desktop handle */
@ -500,14 +512,11 @@ void release_thread_desktop( struct thread *thread, int close )
if (!(handle = thread->desktop)) return; if (!(handle = thread->desktop)) return;
if (!thread->process->is_system) if (!(desktop = get_desktop_obj( thread->process, handle, 0 ))) clear_error(); /* ignore errors */
else
{ {
if (!(desktop = get_desktop_obj( thread->process, handle, 0 ))) clear_error(); /* ignore errors */ remove_desktop_thread( desktop, thread );
else release_object( desktop );
{
remove_desktop_user( desktop );
release_object( desktop );
}
} }
if (close) if (close)
@ -730,10 +739,10 @@ DECL_HANDLER(set_thread_desktop)
else else
{ {
current->desktop = req->handle; /* FIXME: should we close the old one? */ current->desktop = req->handle; /* FIXME: should we close the old one? */
if (!current->process->is_system && old_desktop != new_desktop) if (old_desktop != new_desktop)
{ {
add_desktop_user( new_desktop ); if (old_desktop) remove_desktop_thread( old_desktop, current );
if (old_desktop) remove_desktop_user( old_desktop ); add_desktop_thread( new_desktop, current );
} }
} }