From: Rémi Bernon <rbernon(a)codeweavers.com> When a process closes all of its window then opens a new one, Windows often allows it to get its "foreground process" status back, as long as it didn't actively give foreground to another process. On Wine the activate_other_window logic, or the host window manager, might have given focus to a different, non-parent, process already and we are preventing the old process from activating any window again. This relaxes the restriction a bit more, and allows new windows to be activated once after their creation, regardless of whether their owner is the foreground process or not. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=59075 --- server/queue.c | 6 +++--- server/user.h | 3 ++- server/window.c | 7 ++++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/server/queue.c b/server/queue.c index 6e818691139..3e8ab2ef48a 100644 --- a/server/queue.c +++ b/server/queue.c @@ -3817,18 +3817,18 @@ DECL_HANDLER(set_foreground_window) struct thread *thread = NULL; struct desktop *desktop; struct msg_queue *queue = get_current_queue(); - int is_desktop = 0; + int is_desktop = 0, set_foreground = 0; if (!queue || !(desktop = get_thread_desktop( current, 0 ))) return; - if (!(thread = make_window_foreground( desktop, req->handle, &is_desktop )) || + if (!(thread = make_window_foreground( desktop, req->handle, &is_desktop, &set_foreground )) || !thread->queue || !thread->queue->input) { set_win32_error( ERROR_INVALID_WINDOW_HANDLE ); goto done; } - if (!req->internal) + if (set_foreground && !req->internal) { if (!current->process->set_foreground) current->process->set_foreground = 1; else if (!is_current_process_foreground( desktop ) && queue->input && desktop->foreground_input && diff --git a/server/user.h b/server/user.h index bbc1ac676e7..9f6c3dcaf0f 100644 --- a/server/user.h +++ b/server/user.h @@ -174,7 +174,8 @@ extern void post_desktop_message( struct desktop *desktop, unsigned int message, extern void free_window_handle( struct window *win ); extern void destroy_thread_windows( struct thread *thread ); extern int is_child_window( user_handle_t parent, user_handle_t child ); -extern struct thread *make_window_foreground( struct desktop *desktop, user_handle_t window, int *is_desktop ); +extern struct thread *make_window_foreground( struct desktop *desktop, user_handle_t window, + int *is_desktop, int *set_foreground ); extern int is_window_visible( user_handle_t window ); extern int is_window_transparent( user_handle_t window ); extern int make_window_active( user_handle_t window ); diff --git a/server/window.c b/server/window.c index ad5279f205d..d58f643fde9 100644 --- a/server/window.c +++ b/server/window.c @@ -81,6 +81,7 @@ struct window unsigned int is_linked : 1; /* is it linked into the parent z-order list? */ unsigned int is_layered : 1; /* has layered info been set? */ unsigned int is_orphan : 1; /* is window orphaned */ + unsigned int set_foreground : 1;/* has window been foreground once */ unsigned int color_key; /* color key for a layered window */ unsigned int alpha; /* alpha value for a layered window */ unsigned int layered_flags; /* flags for a layered window */ @@ -666,6 +667,7 @@ static struct window *create_window( struct window *parent, struct window *owner win->is_linked = 0; win->is_layered = 0; win->is_orphan = 0; + win->set_foreground = 0; win->monitor_dpi = USER_DEFAULT_SCREEN_DPI; win->user_data = 0; win->text = NULL; @@ -787,13 +789,16 @@ int is_child_window( user_handle_t parent, user_handle_t child ) } /* return the window thread if window can be set as foreground window */ -struct thread *make_window_foreground( struct desktop *desktop, user_handle_t window, int *is_desktop ) +struct thread *make_window_foreground( struct desktop *desktop, user_handle_t window, + int *is_desktop, int *set_foreground ) { struct window *win = get_user_object( window, NTUSER_OBJ_WINDOW ); if (!win || !win->thread || win->desktop != desktop) return NULL; if ((win->style & (WS_POPUP | WS_CHILD)) == WS_CHILD) return NULL; *is_desktop = win == win->desktop->top_window; + *set_foreground = win->set_foreground; + win->set_foreground = 1; return (struct thread *)grab_object( win->thread ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9668