Module: wine Branch: master Commit: f7303cf7b6f57c7b0baa1dc4f1a1f600d5ce0f61 URL: https://gitlab.winehq.org/wine/wine/-/commit/f7303cf7b6f57c7b0baa1dc4f1a1f60...
Author: Rémi Bernon rbernon@codeweavers.com Date: Sat Jan 27 22:00:12 2024 +0100
server: Keep a list of threads connected to each desktop.
---
server/thread.h | 1 + server/user.h | 1 + server/winstation.c | 53 +++++++++++++++++++++++++++++++---------------------- 3 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/server/thread.h b/server/thread.h index 8dcf966a90a..766ed78a72f 100644 --- a/server/thread.h +++ b/server/thread.h @@ -51,6 +51,7 @@ struct thread struct object obj; /* object header */ struct list entry; /* entry in system-wide 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; thread_id_t id; /* thread id */ struct list mutex_list; /* list of currently owned mutexes */ diff --git a/server/user.h b/server/user.h index 1acd0638520..c3ca90d5a77 100644 --- a/server/user.h +++ b/server/user.h @@ -70,6 +70,7 @@ struct desktop struct winstation *winstation; /* winstation this desktop belongs to */ timeout_t input_time; /* last time this desktop had the input */ 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 *msg_window; /* HWND_MESSAGE top window */ struct hook_table *global_hooks; /* table of global hooks on this desktop */ diff --git a/server/winstation.c b/server/winstation.c index 00afe0119ff..f6fe5fd9e57 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -273,6 +273,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned desktop->close_timeout = NULL; desktop->foreground_input = NULL; desktop->users = 0; + list_init( &desktop->threads ); memset( &desktop->cursor, 0, sizeof(desktop->cursor) ); memset( desktop->keystate, 0, sizeof(desktop->keystate) ); 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 */ -static void add_desktop_user( struct desktop *desktop ) +static void add_desktop_thread( struct desktop *desktop, struct thread *thread ) { - desktop->users++; - if (desktop->close_timeout) + list_add_tail( &desktop->threads, &thread->desktop_entry ); + + if (!thread->process->is_system) { - remove_timeout_user( desktop->close_timeout ); - desktop->close_timeout = NULL; + desktop->users++; + 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 */ -static void remove_desktop_user( struct desktop *desktop ) +static void remove_desktop_thread( struct desktop *desktop, struct thread *thread ) { 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 */ - 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 ); + list_remove( &thread->desktop_entry ); + + 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 */ @@ -390,7 +402,7 @@ void set_thread_default_desktop( struct thread *thread, struct desktop *desktop, if (thread->desktop) return; /* nothing to do */
thread->desktop = handle; - if (!thread->process->is_system) add_desktop_user( desktop ); + add_desktop_thread( desktop, thread ); }
/* 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 (!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 */ - else - { - remove_desktop_user( desktop ); - release_object( desktop ); - } + remove_desktop_thread( desktop, thread ); + release_object( desktop ); }
if (close) @@ -730,10 +739,10 @@ DECL_HANDLER(set_thread_desktop) else { 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_user( old_desktop ); + if (old_desktop) remove_desktop_thread( old_desktop, current ); + add_desktop_thread( new_desktop, current ); } }