diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index 19e8a2c9dfc..3ddbd808c33 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -104,10 +104,6 @@ static void CDECL nulldrv_SetCapture( HWND hwnd, UINT flags ) { } -static void CDECL nulldrv_SetFocus( HWND hwnd ) -{ -} - static void CDECL nulldrv_SetParent( HWND hwnd, HWND parent, HWND old_parent ) { } @@ -212,7 +208,7 @@ static struct user_driver_funcs lazy_load_driver = nulldrv_ReleaseDC, NULL, nulldrv_SetCapture, - nulldrv_SetFocus, + NULL, NULL, nulldrv_SetParent, NULL, @@ -259,7 +255,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v SET_USER_FUNC(MsgWaitForMultipleObjectsEx); SET_USER_FUNC(ReleaseDC); SET_USER_FUNC(SetCapture); - SET_USER_FUNC(SetFocus); SET_USER_FUNC(SetParent); SET_USER_FUNC(SetWindowIcon); SET_USER_FUNC(SetWindowStyle); diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c index d4b8545bfc1..4998ac2feb6 100644 --- a/dlls/user32/focus.c +++ b/dlls/user32/focus.c @@ -30,198 +30,6 @@ #include "imm.h" #include "user_private.h" #include "wine/server.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(win); - - -/***************************************************************** - * set_focus_window - * - * Change the focus window, sending the WM_SETFOCUS and WM_KILLFOCUS messages - */ -static HWND set_focus_window( HWND hwnd ) -{ - HWND previous = 0, ime_default; - BOOL ret; - - SERVER_START_REQ( set_focus_window ) - { - req->handle = wine_server_user_handle( hwnd ); - if ((ret = !wine_server_call_err( req ))) - previous = wine_server_ptr_handle( reply->previous ); - } - SERVER_END_REQ; - if (!ret) return 0; - if (previous == hwnd) return previous; - - if (previous) - { - SendMessageW( previous, WM_KILLFOCUS, (WPARAM)hwnd, 0 ); - - ime_default = ImmGetDefaultIMEWnd( previous ); - if (ime_default) - SendMessageW( ime_default, WM_IME_INTERNAL, IME_INTERNAL_DEACTIVATE, (LPARAM)previous ); - - if (hwnd != GetFocus()) return previous; /* changed by the message */ - } - if (IsWindow(hwnd)) - { - USER_Driver->pSetFocus(hwnd); - - ime_default = ImmGetDefaultIMEWnd( hwnd ); - if (ime_default) - SendMessageW( ime_default, WM_IME_INTERNAL, IME_INTERNAL_ACTIVATE, (LPARAM)hwnd ); - - if (previous) - NtUserNotifyWinEvent( EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, 0 ); - - SendMessageW( hwnd, WM_SETFOCUS, (WPARAM)previous, 0 ); - } - return previous; -} - - -/******************************************************************* - * set_active_window - */ -static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus ) -{ - HWND previous = GetActiveWindow(); - BOOL ret; - DWORD old_thread, new_thread; - CBTACTIVATESTRUCT cbt; - - if (previous == hwnd) - { - if (prev) *prev = hwnd; - return TRUE; - } - - /* call CBT hook chain */ - cbt.fMouse = mouse; - cbt.hWndActive = previous; - if (HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt, TRUE )) return FALSE; - - if (IsWindow(previous)) - { - SendMessageW( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd ); - SendMessageW( previous, WM_ACTIVATE, - MAKEWPARAM( WA_INACTIVE, IsIconic(previous) ), (LPARAM)hwnd ); - } - - SERVER_START_REQ( set_active_window ) - { - req->handle = wine_server_user_handle( hwnd ); - if ((ret = !wine_server_call_err( req ))) - previous = wine_server_ptr_handle( reply->previous ); - } - SERVER_END_REQ; - if (!ret) return FALSE; - if (prev) *prev = previous; - if (previous == hwnd) return TRUE; - - if (hwnd) - { - /* send palette messages */ - if (SendMessageW( hwnd, WM_QUERYNEWPALETTE, 0, 0 )) - SendMessageTimeoutW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0, - SMTO_ABORTIFHUNG, 2000, NULL ); - if (!IsWindow(hwnd)) return FALSE; - } - - old_thread = previous ? GetWindowThreadProcessId( previous, NULL ) : 0; - new_thread = hwnd ? GetWindowThreadProcessId( hwnd, NULL ) : 0; - - if (old_thread != new_thread) - { - HWND *list, *phwnd; - - if ((list = WIN_ListChildren( GetDesktopWindow() ))) - { - if (old_thread) - { - for (phwnd = list; *phwnd; phwnd++) - { - if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread) - SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread ); - } - } - if (new_thread) - { - for (phwnd = list; *phwnd; phwnd++) - { - if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread) - SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread ); - } - } - HeapFree( GetProcessHeap(), 0, list ); - } - } - - if (IsWindow(hwnd)) - { - SendMessageW( hwnd, WM_NCACTIVATE, hwnd == NtUserGetForegroundWindow(), (LPARAM)previous ); - SendMessageW( hwnd, WM_ACTIVATE, - MAKEWPARAM( mouse ? WA_CLICKACTIVE : WA_ACTIVE, IsIconic(hwnd) ), - (LPARAM)previous ); - if (NtUserGetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow()) - PostMessageW( GetDesktopWindow(), WM_PARENTNOTIFY, WM_NCACTIVATE, (LPARAM)hwnd ); - } - - /* now change focus if necessary */ - if (focus) - { - GUITHREADINFO info; - - info.cbSize = sizeof(info); - NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ); - /* Do not change focus if the window is no more active */ - if (hwnd == info.hwndActive) - { - if (!info.hwndFocus || !hwnd || NtUserGetAncestor( info.hwndFocus, GA_ROOT ) != hwnd) - set_focus_window( hwnd ); - } - } - - return TRUE; -} - - -/******************************************************************* - * set_foreground_window - */ -static BOOL set_foreground_window( HWND hwnd, BOOL mouse ) -{ - BOOL ret, send_msg_old = FALSE, send_msg_new = FALSE; - HWND previous = 0; - - SERVER_START_REQ( set_foreground_window ) - { - req->handle = wine_server_user_handle( hwnd ); - if ((ret = !wine_server_call_err( req ))) - { - previous = wine_server_ptr_handle( reply->previous ); - send_msg_old = reply->send_msg_old; - send_msg_new = reply->send_msg_new; - } - } - SERVER_END_REQ; - - if (ret && previous != hwnd) - { - 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 ); - } - return ret; -} /******************************************************************* @@ -231,7 +39,7 @@ static BOOL set_foreground_window( HWND hwnd, BOOL mouse ) */ BOOL FOCUS_MouseActivate( HWND hwnd ) { - return set_foreground_window( hwnd, TRUE ); + return NtUserCallHwndParam( hwnd, TRUE, NtUserSetForegroundWindow ); } @@ -240,10 +48,7 @@ BOOL FOCUS_MouseActivate( HWND hwnd ) */ BOOL WINAPI SetForegroundWindow( HWND hwnd ) { - TRACE( "%p\n", hwnd ); - - hwnd = WIN_GetFullHandle( hwnd ); - return set_foreground_window( hwnd, FALSE ); + return NtUserCallHwndParam( hwnd, FALSE, NtUserSetForegroundWindow ); } diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index b483d68c3f3..32100c1e407 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -147,6 +147,7 @@ static const struct user_callbacks user_funcs = RedrawWindow, SendMessageTimeoutW, SendMessageW, + SendNotifyMessageW, SetWindowPos, WaitForInputIdle, WindowFromDC, diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 439e6e0c20b..33ce86a1675 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -1329,3 +1329,42 @@ HWND WINAPI NtUserSetFocus( HWND hwnd ) /* change focus and send messages */ return set_focus_window( hwnd ); } + +/******************************************************************* + * set_foreground_window + */ +BOOL set_foreground_window( HWND hwnd, BOOL mouse ) +{ + BOOL ret, send_msg_old = FALSE, send_msg_new = FALSE; + HWND previous = 0; + + if (mouse) hwnd = get_full_window_handle( hwnd ); + + SERVER_START_REQ( set_foreground_window ) + { + req->handle = wine_server_user_handle( hwnd ); + if ((ret = !wine_server_call_err( req ))) + { + previous = wine_server_ptr_handle( reply->previous ); + send_msg_old = reply->send_msg_old; + send_msg_new = reply->send_msg_new; + } + } + 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, FNID_SENDNOTIFYMESSAGE, 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, + 0, FNID_SENDNOTIFYMESSAGE, FALSE ); + else /* new window belongs to us */ + ret = set_active_window( hwnd, NULL, mouse, TRUE ); + } + return ret; +} diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index ea9b2a93f2c..6eeef1f8d49 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -125,6 +125,12 @@ LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) return user_callbacks->pSendMessageW( hwnd, msg, wparam, lparam ); } +/* see SendNotifyMessageW */ +static BOOL send_notify_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) +{ + return user_callbacks && user_callbacks->pSendNotifyMessageW( hwnd, msg, wparam, lparam ); +} + /* see PostMessageW */ LRESULT post_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { @@ -132,3 +138,16 @@ LRESULT post_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) if (!user_callbacks) return 0; return user_callbacks->pPostMessageW( hwnd, msg, wparam, lparam ); } + +BOOL WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, + ULONG_PTR result_info, DWORD type, BOOL ansi ) +{ + switch (type) + { + case FNID_SENDNOTIFYMESSAGE: + return send_notify_message( hwnd, msg, wparam, lparam, ansi ); + default: + FIXME( "%p %x %lx %lx %lx %x %x\n", hwnd, msg, wparam, lparam, result_info, type, ansi ); + } + return 0; +} diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index e380006a6c4..61d00d30a37 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -34,6 +34,7 @@ struct user_callbacks BOOL (WINAPI *pRedrawWindow)( HWND, const RECT*, HRGN, UINT ); LRESULT (WINAPI *pSendMessageTimeoutW)( HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR ); LRESULT (WINAPI *pSendMessageW)( HWND, UINT, WPARAM, LPARAM ); + BOOL (WINAPI *pSendNotifyMessageW)( HWND, UINT, WPARAM, LPARAM ); BOOL (WINAPI *pSetWindowPos)( HWND, HWND, INT, INT, INT, INT, UINT ); DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD ); HWND (WINAPI *pWindowFromDC)( HDC ); diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 72d69f22b64..9e50537625e 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -289,6 +289,7 @@ extern LONG global_key_state_counter DECLSPEC_HIDDEN; extern HWND get_active_window(void) DECLSPEC_HIDDEN; extern BOOL get_cursor_pos( POINT *pt ) DECLSPEC_HIDDEN; extern DWORD get_input_state(void) DECLSPEC_HIDDEN; +extern BOOL set_foreground_window( HWND hwnd, BOOL mouse ) DECLSPEC_HIDDEN; /* message.c */ extern LRESULT post_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 912c3f34926..9e03fffeffd 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1945,6 +1945,8 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) return is_child( hwnd, UlongToHandle(param) ); case NtUserMonitorFromWindow: return HandleToUlong( monitor_from_window( hwnd, param, NtUserMonitorFromWindow )); + case NtUserSetForegroundWindow: + return set_foreground_window( hwnd, param ); /* temporary exports */ case NtUserIsWindowDrawable: return is_window_drawable( hwnd, param ); diff --git a/include/ntuser.h b/include/ntuser.h index 2d5fc521090..b4e48f8ff5f 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -173,10 +173,17 @@ enum NtUserGetWindowWord, NtUserIsChild, NtUserMonitorFromWindow, + NtUserSetForegroundWindow, /* temporary exports */ NtUserIsWindowDrawable, }; +/* NtUserMessageCall codes */ +enum +{ + FNID_SENDNOTIFYMESSAGE = 0x02b7, +}; + /* color index used to retrieve system 55aa brush */ #define COLOR_55AA_BRUSH 0x100