From: Rémi Bernon rbernon@codeweavers.com
For user drivers to forcefully change foreground window, regardless of the restriction which will be introduced next.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58167 --- dlls/win32u/defwnd.c | 2 +- dlls/win32u/input.c | 7 ++++--- dlls/win32u/message.c | 4 ++-- dlls/win32u/win32u_private.h | 2 +- dlls/win32u/window.c | 7 +++++-- dlls/winemac.drv/window.c | 8 ++++---- dlls/winewayland.drv/window.c | 2 +- dlls/winex11.drv/event.c | 6 +++--- include/ntuser.h | 6 ++++++ server/protocol.def | 1 + 10 files changed, 28 insertions(+), 17 deletions(-)
diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index 870ef376e85..03662963db3 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -2206,7 +2206,7 @@ static LRESULT handle_nc_lbutton_down( HWND hwnd, WPARAM wparam, LPARAM lparam ) top = parent; }
- if (set_foreground_window( top, TRUE ) || (get_active_window() == top)) + if (set_foreground_window( top, TRUE, FALSE ) || (get_active_window() == top)) send_message( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lparam ); break; } diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index f431ab98a9f..57d054a9df6 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2168,7 +2168,7 @@ HWND WINAPI NtUserSetFocus( HWND hwnd ) if (call_hooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)hwnd, (LPARAM)previous, 0 )) return 0;
/* activate hwndTop if needed. */ - if (!(active = get_active_window()) && !set_foreground_window( hwndTop, FALSE )) return 0; + if (!(active = get_active_window()) && !set_foreground_window( hwndTop, FALSE, FALSE )) return 0; if (hwndTop != active) { if (!set_active_window( hwndTop, NULL, FALSE, FALSE, 0 )) return 0; @@ -2193,13 +2193,13 @@ HWND WINAPI NtUserSetFocus( HWND hwnd ) */ BOOL WINAPI NtUserSetForegroundWindow( HWND hwnd ) { - return set_foreground_window( hwnd, FALSE ); + return set_foreground_window( hwnd, FALSE, FALSE ); }
/******************************************************************* * set_foreground_window */ -BOOL set_foreground_window( HWND hwnd, BOOL mouse ) +BOOL set_foreground_window( HWND hwnd, BOOL mouse, BOOL internal ) { BOOL ret, send_msg_old = FALSE, send_msg_new = FALSE; DWORD new_thread_id; @@ -2211,6 +2211,7 @@ BOOL set_foreground_window( HWND hwnd, BOOL mouse ) SERVER_START_REQ( set_foreground_window ) { req->handle = wine_server_user_handle( hwnd ); + req->internal = internal; if ((ret = !wine_server_call_err( req ))) { previous = wine_server_ptr_handle( reply->previous ); diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 7da66fd1494..b28ce272099 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2231,7 +2231,7 @@ static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPAR if (!user_driver->pGetWindowStateUpdates( hwnd, &state_cmd, &swp_flags, &window_rect, &foreground )) return 0; window_rect = map_rect_raw_to_virt( window_rect, get_thread_dpi() );
- if (foreground) NtUserSetForegroundWindow( foreground ); + if (foreground) set_foreground_window( foreground, FALSE, TRUE ); switch (state_cmd) { case SC_RESTORE: @@ -2744,7 +2744,7 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H /* fall through */ case MA_ACTIVATE: case 0: - if (!set_foreground_window( hwndTop, TRUE )) eat_msg = TRUE; + if (!set_foreground_window( hwndTop, TRUE, FALSE )) eat_msg = TRUE; break; default: WARN( "unknown WM_MOUSEACTIVATE code %d\n", ret ); diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index ee76854c7e4..3b65bb25b53 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -95,7 +95,7 @@ extern DWORD get_input_state(void); extern DWORD get_last_input_time(void); extern BOOL get_async_keyboard_state( BYTE state[256] ); extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ); -extern BOOL set_foreground_window( HWND hwnd, BOOL mouse ); +extern BOOL set_foreground_window( HWND hwnd, BOOL mouse, BOOL force ); extern BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus, DWORD new_active_thread_id ); extern BOOL set_ime_composition_rect( HWND hwnd, RECT rect ); extern void toggle_caret( HWND hwnd ); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 00023632d13..450381c55f3 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -3943,7 +3943,7 @@ BOOL set_window_pos( WINDOWPOS *winpos, int parent_x, int parent_y ) if ((style & (WS_CHILD | WS_POPUP)) == WS_CHILD) send_message( winpos->hwnd, WM_CHILDACTIVATE, 0, 0 ); else if (!(style & WS_MINIMIZE)) - set_foreground_window( winpos->hwnd, FALSE ); + set_foreground_window( winpos->hwnd, FALSE, FALSE ); }
if(!(orig_flags & SWP_DEFERERASE)) @@ -4288,7 +4288,7 @@ static void activate_other_window( HWND hwnd ) TRACE( "win = %p fg = %p\n", hwnd_to, fg ); if (!fg || hwnd == fg) { - if (set_foreground_window( hwnd_to, FALSE )) return; + if (set_foreground_window( hwnd_to, FALSE, FALSE )) return; } if (NtUserSetActiveWindow( hwnd_to )) NtUserSetActiveWindow( 0 ); } @@ -5998,6 +5998,9 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code ) activate_other_window( hwnd ); return 0;
+ case NtUserCallHwnd_SetForegroundWindowInternal: + return set_foreground_window( hwnd, FALSE, TRUE ); + case NtUserCallHwnd_GetDpiForWindow: return get_dpi_for_window( hwnd );
diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 26ea212043d..acb90420bcd 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -1762,7 +1762,7 @@ void macdrv_window_got_focus(HWND hwnd, const macdrv_event *event) if (can_window_become_foreground(hwnd) && !(style & WS_MINIMIZE)) { TRACE("setting foreground window to %p\n", hwnd); - NtUserSetForegroundWindow(hwnd); + NtUserSetForegroundWindowInternal(hwnd); return; }
@@ -1786,7 +1786,7 @@ void macdrv_window_lost_focus(HWND hwnd, const macdrv_event *event) { send_message(hwnd, WM_CANCELMODE, 0, 0); if (hwnd == NtUserGetForegroundWindow()) - NtUserSetForegroundWindow(NtUserGetDesktopWindow()); + NtUserSetForegroundWindowInternal(NtUserGetDesktopWindow()); } }
@@ -1815,7 +1815,7 @@ void macdrv_app_deactivated(void) if (get_active_window() == NtUserGetForegroundWindow()) { TRACE("setting fg to desktop\n"); - NtUserSetForegroundWindow(NtUserGetDesktopWindow()); + NtUserSetForegroundWindowInternal(NtUserGetDesktopWindow()); } }
@@ -1978,7 +1978,7 @@ void macdrv_window_drag_begin(HWND hwnd, const macdrv_event *event) if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) { TRACE("setting foreground window to %p\n", hwnd); - NtUserSetForegroundWindow(hwnd); + NtUserSetForegroundWindowInternal(hwnd); } }
diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 939be6e3c08..b838fd84191 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -620,7 +620,7 @@ LRESULT WAYLAND_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) wayland_configure_window(hwnd); return 0; case WM_WAYLAND_SET_FOREGROUND: - NtUserSetForegroundWindow(hwnd); + NtUserSetForegroundWindowInternal(hwnd); return 0; default: FIXME("got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, (long)wp, lp); diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index f33db32839f..53c617d2d68 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -657,7 +657,7 @@ static void set_focus( Display *display, HWND focus, Time time )
if (!is_net_supported( x11drv_atom(_NET_ACTIVE_WINDOW) )) { - NtUserSetForegroundWindow( focus ); + NtUserSetForegroundWindowInternal( focus );
threadinfo.cbSize = sizeof(threadinfo); NtUserGetGUIThreadInfo( 0, &threadinfo ); @@ -879,7 +879,7 @@ static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev ) if (!hwnd) hwnd = x11drv_thread_data()->last_focus; if (hwnd && can_activate_window(hwnd)) set_focus( event->display, hwnd, CurrentTime ); } - else NtUserSetForegroundWindow( hwnd ); + else NtUserSetForegroundWindowInternal( hwnd ); return TRUE; }
@@ -910,7 +910,7 @@ static void focus_out( Display *display , HWND hwnd ) if (hwnd == NtUserGetForegroundWindow()) { TRACE( "lost focus, setting fg to desktop\n" ); - NtUserSetForegroundWindow( NtUserGetDesktopWindow() ); + NtUserSetForegroundWindowInternal( NtUserGetDesktopWindow() ); } } } diff --git a/include/ntuser.h b/include/ntuser.h index 664bcfe459d..438fca0f52d 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -1305,6 +1305,7 @@ enum NtUserCallHwnd_IsWindowEnabled, NtUserCallHwnd_IsWindowUnicode, NtUserCallHwnd_IsWindowVisible, + NtUserCallHwnd_SetForegroundWindowInternal, /* temporary exports */ NtUserGetFullWindowHandle, NtUserIsCurrentProcessWindow, @@ -1316,6 +1317,11 @@ static inline void NtUserActivateOtherWindow( HWND hwnd ) NtUserCallHwnd( hwnd, NtUserCallHwnd_ActivateOtherWindow ); }
+static inline BOOL NtUserSetForegroundWindowInternal( HWND hwnd ) +{ + return NtUserCallHwnd( hwnd, NtUserCallHwnd_SetForegroundWindowInternal ); +} + static inline void *NtUserGetDialogInfo( HWND hwnd ) { return (void *)NtUserCallHwnd( hwnd, NtUserCallHwnd_GetDialogInfo ); diff --git a/server/protocol.def b/server/protocol.def index 1881f0a628a..6712a661817 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3117,6 +3117,7 @@ enum coords_relative /* Set the system foreground window */ @REQ(set_foreground_window) user_handle_t handle; /* handle to the foreground window */ + int internal; /* foreground change comes from the host */ @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 */