From: Alexandros Frantzis alexandros.frantzis@collabora.com
If when updating the foreground window, both the old and new active window belong to the same thread, even if it's not the current thread, activate the new window without explicitly deactivating the previous one. This matches the current behavior of the code when both windows belong to the current thread.
This avoids the transient deactivation of the target thread which can lead to unwanted side effects (e.g., some apps may minimize when they become inactive). --- dlls/win32u/input.c | 16 ++++++++++------ include/wine/server_protocol.h | 4 ++-- server/protocol.def | 9 +++++---- server/queue.c | 2 ++ server/request.h | 1 + server/trace.c | 1 + 6 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 3ee46f0bfcf..a04c8980b92 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2056,7 +2056,7 @@ HWND WINAPI NtUserSetFocus( HWND hwnd ) */ BOOL set_foreground_window( HWND hwnd, BOOL mouse ) { - BOOL ret, send_msg_old = FALSE, send_msg_new = FALSE; + BOOL ret, send_msg_old = FALSE, send_msg_new = FALSE, deactivate_old = FALSE; HWND previous = 0;
if (mouse) hwnd = get_full_window_handle( hwnd ); @@ -2069,17 +2069,21 @@ BOOL set_foreground_window( HWND hwnd, BOOL mouse ) previous = wine_server_ptr_handle( reply->previous ); send_msg_old = reply->send_msg_old; send_msg_new = reply->send_msg_new; + deactivate_old = reply->deactivate_old; } } SERVER_END_REQ;
if (ret && previous != hwnd) { - if (send_msg_old) /* old window belongs to other thread */ - NtUserMessageCall( previous, WM_WINE_SETACTIVEWINDOW, 0, 0, - 0, NtUserSendNotifyMessage, FALSE ); - else if (send_msg_new) /* old window belongs to us but new one to other thread */ - ret = set_active_window( 0, NULL, mouse, TRUE ); + if (deactivate_old) + { + if (send_msg_old) /* old window belongs to other thread */ + NtUserMessageCall( previous, WM_WINE_SETACTIVEWINDOW, 0, 0, + 0, NtUserSendNotifyMessage, FALSE ); + else if (send_msg_new) /* old window belongs to us but new one to other thread */ + ret = set_active_window( 0, NULL, mouse, TRUE ); + }
if (send_msg_new) /* new window belongs to other thread */ NtUserMessageCall( hwnd, WM_WINE_SETACTIVEWINDOW, (WPARAM)hwnd, 0, diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 139a7bca69e..0870a631fbe 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4050,7 +4050,7 @@ struct set_foreground_window_reply user_handle_t previous; int send_msg_old; int send_msg_new; - char __pad_20[4]; + int deactivate_old; };
@@ -6507,7 +6507,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 786 +#define SERVER_PROTOCOL_VERSION 788
/* ### protocol_version end ### */
diff --git a/server/protocol.def b/server/protocol.def index 5d60e7fcda3..2ea410afea7 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2900,11 +2900,12 @@ enum coords_relative
/* Set the system foreground window */ @REQ(set_foreground_window) - user_handle_t handle; /* handle to the foreground window */ + user_handle_t handle; /* handle to the foreground window */ @REPLY - user_handle_t previous; /* handle to the previous foreground window */ - int send_msg_old; /* whether we have to send a msg to the old window */ - int send_msg_new; /* whether we have to send a msg to the new window */ + user_handle_t previous; /* handle to the previous foreground window */ + int send_msg_old; /* whether we have to send a msg to the old window */ + int send_msg_new; /* whether we have to send a msg to the new window */ + int deactivate_old; /* whether we have to explicitly deactivate the old window */ @END
/* Set the current thread focus window */ diff --git a/server/queue.c b/server/queue.c index 0558bd111f9..0d19039e05f 100644 --- a/server/queue.c +++ b/server/queue.c @@ -3216,11 +3216,13 @@ DECL_HANDLER(set_foreground_window) reply->previous = desktop->foreground_input ? desktop->foreground_input->active : 0; reply->send_msg_old = (reply->previous && desktop->foreground_input != queue->input); reply->send_msg_new = FALSE; + reply->deactivate_old = FALSE;
if (is_valid_foreground_window( req->handle ) && (thread = get_window_thread( req->handle )) && thread->queue->input->desktop == desktop) { + reply->deactivate_old = (desktop->foreground_input != thread->queue->input); set_foreground_input( desktop, thread->queue->input ); reply->send_msg_new = (desktop->foreground_input != queue->input); } diff --git a/server/request.h b/server/request.h index 89d5a621b16..5185229b483 100644 --- a/server/request.h +++ b/server/request.h @@ -1808,6 +1808,7 @@ C_ASSERT( sizeof(struct set_foreground_window_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_foreground_window_reply, previous) == 8 ); C_ASSERT( FIELD_OFFSET(struct set_foreground_window_reply, send_msg_old) == 12 ); C_ASSERT( FIELD_OFFSET(struct set_foreground_window_reply, send_msg_new) == 16 ); +C_ASSERT( FIELD_OFFSET(struct set_foreground_window_reply, deactivate_old) == 20 ); C_ASSERT( sizeof(struct set_foreground_window_reply) == 24 ); C_ASSERT( FIELD_OFFSET(struct set_focus_window_request, handle) == 12 ); C_ASSERT( sizeof(struct set_focus_window_request) == 16 ); diff --git a/server/trace.c b/server/trace.c index 1b65d2b977e..141acebb85b 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3534,6 +3534,7 @@ static void dump_set_foreground_window_reply( const struct set_foreground_window fprintf( stderr, " previous=%08x", req->previous ); fprintf( stderr, ", send_msg_old=%d", req->send_msg_old ); fprintf( stderr, ", send_msg_new=%d", req->send_msg_new ); + fprintf( stderr, ", deactivate_old=%d", req->deactivate_old ); }
static void dump_set_focus_window_request( const struct set_focus_window_request *req )