[PATCH v2] user32: Always send WM_NCACTIVATE when changing the foreground window.
Alex Henrie
alexhenrie24 at gmail.com
Fri Mar 10 00:07:07 CST 2017
Fixes https://bugs.winehq.org/show_bug.cgi?id=7198
v2: Use the wineserver to determine if the new foreground window is
already active in its thread.
Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
dlls/user32/focus.c | 32 ++++++++++++++++++++------------
dlls/user32/tests/msg.c | 30 +++++++++++++++++++++++++++---
include/wine/server_protocol.h | 4 ++--
server/protocol.def | 1 +
server/queue.c | 1 +
server/request.h | 1 +
server/trace.c | 1 +
7 files changed, 53 insertions(+), 17 deletions(-)
diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c
index f1c883167e..42d1a2b4ab 100644
--- a/dlls/user32/focus.c
+++ b/dlls/user32/focus.c
@@ -182,8 +182,8 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
*/
static BOOL set_foreground_window( HWND hwnd, BOOL mouse )
{
- BOOL ret, send_msg_old = FALSE, send_msg_new = FALSE;
- HWND previous = 0;
+ BOOL ret, send_msg_old, send_msg_new, activate_new;
+ HWND previous;
SERVER_START_REQ( set_foreground_window )
{
@@ -193,22 +193,30 @@ static 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;
+ activate_new = reply->activate_new;
}
}
SERVER_END_REQ;
- if (ret && previous != hwnd)
+ if (!ret || previous == hwnd)
+ return ret;
+
+ if (send_msg_old) /* old window belongs to other thread */
+ SendNotifyMessageW( previous, WM_WINE_SETACTIVEWINDOW, 0, 0 );
+ 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 (!activate_new)
{
- if (send_msg_old) /* old window belongs to other thread */
- SendNotifyMessageW( previous, WM_WINE_SETACTIVEWINDOW, 0, 0 );
- 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 */
- SendNotifyMessageW( hwnd, WM_WINE_SETACTIVEWINDOW, (WPARAM)hwnd, 0 );
- else /* new window belongs to us */
- ret = set_active_window( hwnd, NULL, mouse, TRUE );
+ SendNotifyMessageW( hwnd, WM_NCACTIVATE, 1, (LPARAM)hwnd );
+ return ret;
}
+
+ if (send_msg_new) /* new window belongs to other thread */
+ SendNotifyMessageW( hwnd, WM_WINE_SETACTIVEWINDOW, (WPARAM)hwnd, 0 );
+ else /* new window belongs to us */
+ ret = set_active_window( hwnd, NULL, mouse, TRUE );
+
return ret;
}
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index 23c261e2ac..3b3ca5c62b 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -13294,6 +13294,11 @@ static void test_SetActiveWindow(void)
if (ret == hwnd) ok_sequence(SetActiveWindowSeq1, "SetActiveWindow(hwnd), hwnd visible", TRUE);
flush_sequence();
+ trace("SetActiveWindow(hwnd), hwnd visible and already active\n");
+ ret = SetActiveWindow(hwnd);
+ if (ret == hwnd) ok_sequence(WmEmptySeq, "SetActiveWindow(hwnd), hwnd visible and already active", FALSE);
+ flush_sequence();
+
trace("SetActiveWindow(popup), hwnd visible, popup visible\n");
ret = SetActiveWindow(popup);
ok( ret == hwnd, "Failed to SetActiveWindow(popup), popup visible\n");
@@ -13321,7 +13326,7 @@ static void test_SetActiveWindow(void)
DestroyWindow(hwnd);
}
-static const struct message SetForegroundWindowSeq[] =
+static const struct message SetForegroundWindowSeq0[] =
{
{ WM_NCACTIVATE, sent|wparam, 0 },
{ WM_GETTEXT, sent|defwinproc|optional },
@@ -13333,6 +13338,14 @@ static const struct message SetForegroundWindowSeq[] =
{ 0 }
};
+static const struct message SetForegroundWindowSeq1[] =
+{
+ { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_GETTEXT, sent|defwinproc|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, /* FIXME: Missing in Wine */
+ { 0 }
+};
+
static void test_SetForegroundWindow(void)
{
HWND hwnd;
@@ -13347,10 +13360,21 @@ static void test_SetForegroundWindow(void)
trace("SetForegroundWindow( 0 )\n");
SetForegroundWindow( 0 );
ok_sequence(WmEmptySeq, "SetForegroundWindow( 0 ) away from foreground top level window", FALSE);
+
trace("SetForegroundWindow( GetDesktopWindow() )\n");
SetForegroundWindow( GetDesktopWindow() );
- ok_sequence(SetForegroundWindowSeq, "SetForegroundWindow( desktop ) away from "
- "foreground top level window", FALSE);
+ ok_sequence(SetForegroundWindowSeq0, "SetForegroundWindow( desktop ) away from foreground top level window", FALSE);
+
+ trace("SetForegroundWindow to a background window that is already active\n");
+ SetActiveWindow( hwnd );
+ flush_sequence();
+ SetForegroundWindow( hwnd );
+ ok_sequence(SetForegroundWindowSeq1, "SetForegroundWindow to a background window that is already active", FALSE);
+
+ trace("SetForegroundWindow to the current foreground window\n");
+ SetForegroundWindow( hwnd );
+ ok_sequence(WmEmptySeq, "SetForegroundWindow to the current foreground window", FALSE);
+
trace("done\n");
DestroyWindow(hwnd);
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index ee9fdd12eb..6b59fb8911 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -4192,7 +4192,7 @@ struct set_foreground_window_reply
user_handle_t previous;
int send_msg_old;
int send_msg_new;
- char __pad_20[4];
+ int activate_new;
};
@@ -6412,6 +6412,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
};
-#define SERVER_PROTOCOL_VERSION 524
+#define SERVER_PROTOCOL_VERSION 525
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 60865a6ffc..4baa149f54 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2969,6 +2969,7 @@ enum coords_relative
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 activate_new; /* whether we have to activate the new window */
@END
/* Set the current thread focus window */
diff --git a/server/queue.c b/server/queue.c
index c479b388bd..957ea6d608 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -2957,6 +2957,7 @@ DECL_HANDLER(set_foreground_window)
{
set_foreground_input( desktop, thread->queue->input );
reply->send_msg_new = (desktop->foreground_input != queue->input);
+ reply->activate_new = (thread->queue->input->active != req->handle);
}
else set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
diff --git a/server/request.h b/server/request.h
index cd396ee3df..a0b494f1ac 100644
--- a/server/request.h
+++ b/server/request.h
@@ -1914,6 +1914,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, activate_new) == 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 e0ce45af6d..854b8a6849 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3537,6 +3537,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, ", activate_new=%d", req->activate_new );
}
static void dump_set_focus_window_request( const struct set_focus_window_request *req )
--
2.12.0
More information about the wine-patches
mailing list