HWND APIENTRY NtUserSetActiveWindow(HWND hWnd) { USER_REFERENCE_ENTRY Ref; DECLARE_RETURN(HWND); TRACE("Enter NtUserSetActiveWindow(%x)\n", hWnd); UserEnterExclusive(); if (hWnd) { PWND Window; PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; HWND hWndPrev; if (!(Window = UserGetWindowObject(hWnd))) { RETURN( 0); } pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; if (Window->head.pti->MessageQueue != ThreadQueue) { EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); RETURN( 0); } UserRefObjectCo(Window, &Ref); hWndPrev = co_IntSetActiveWindow(Window); UserDerefObjectCo(Window); RETURN( hWndPrev); } else { RETURN( co_IntSetActiveWindow(0)); } CLEANUP: TRACE("Leave NtUserSetActiveWindow, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }
HWND FASTCALL co_UserSetFocus(PWND Wnd OPTIONAL) { if (Wnd) { PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; HWND hWndPrev; PWND TopWnd; USER_REFERENCE_ENTRY Ref; ASSERT_REFS_CO(Wnd); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; if (Wnd->style & (WS_MINIMIZE | WS_DISABLED)) { return( (ThreadQueue ? ThreadQueue->FocusWindow : 0)); } if (Wnd->head.pti->MessageQueue != ThreadQueue) { EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); return( 0); } TopWnd = UserGetAncestor(Wnd, GA_ROOT); if (TopWnd && TopWnd->head.h != UserGetActiveWindow()) { // PWND WndTops = UserGetWindowObject(hWndTop); UserRefObjectCo(TopWnd, &Ref); co_IntSetActiveWindow(TopWnd); UserDerefObjectCo(TopWnd); } hWndPrev = co_IntSetFocusWindow(Wnd); return( hWndPrev); } else { return( co_IntSetFocusWindow(NULL)); } }
BOOL FASTCALL UserSetActiveWindow(PWND Wnd) { if (Wnd) // Must have a window! { if ((Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; return co_IntSetActiveWindow(Wnd, FALSE, TRUE, FALSE); } /* Yes your eye are not deceiving you~! First part of wines Win.c test_SetActiveWindow: flush_events( TRUE ); ShowWindow(hwnd, SW_HIDE); SetFocus(0); SetActiveWindow(0); check_wnd_state(0, 0, 0, 0); <-- This should pass if ShowWindow does it's job!!! As of 10/28/2012 it does! */ return FALSE; }
HWND APIENTRY NtUserSetActiveWindow(HWND hWnd) { USER_REFERENCE_ENTRY Ref; HWND hWndPrev; PWND Window; DECLARE_RETURN(HWND); TRACE("Enter NtUserSetActiveWindow(%x)\n", hWnd); UserEnterExclusive(); Window = NULL; if (hWnd) { if (!(Window = UserGetWindowObject(hWnd))) { ERR("NtUserSetActiveWindow: Invalid handle 0x%p!\n",hWnd); RETURN( NULL); } } if (!Window || Window->head.pti->MessageQueue == gptiCurrent->MessageQueue) { hWndPrev = gptiCurrent->MessageQueue->spwndActive ? UserHMGetHandle(gptiCurrent->MessageQueue->spwndActive) : NULL; if (Window) UserRefObjectCo(Window, &Ref); co_IntSetActiveWindow(Window, NULL, FALSE, TRUE, FALSE); if (Window) UserDerefObjectCo(Window); RETURN( hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0 ); } RETURN( NULL); CLEANUP: TRACE("Leave NtUserSetActiveWindow, ret=%p\n",_ret_); UserLeave(); END_CLEANUP; }
HWND FASTCALL co_UserSetFocus(PWND Window) { HWND hWndPrev = 0; PWND pwndTop; PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; if (Window) ASSERT_REFS_CO(Window); pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; ASSERT(ThreadQueue != 0); TRACE("Enter SetFocus hWnd 0x%p pti 0x%p\n",Window ? UserHMGetHandle(Window) : 0, pti ); hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; if (Window != 0) { if (hWndPrev == UserHMGetHandle(Window)) { return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0; /* Nothing to do */ } if (Window->head.pti->MessageQueue != ThreadQueue) { ERR("SetFocus Must have the same Q!\n"); return 0; } /* Check if we can set the focus to this window */ for (pwndTop = Window; pwndTop != NULL; pwndTop = pwndTop->spwndParent) { if (pwndTop->style & (WS_MINIMIZED|WS_DISABLED)) return 0; if ((pwndTop->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) break; } if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev)) { ERR("SetFocus 1 WH_CBT Call Hook return!\n"); return 0; } /* Activate pwndTop if needed. */ if (pwndTop != ThreadQueue->spwndActive) { PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Keep it based on desktop. if (ThreadQueue != ForegroundQueue && IsAllowedFGActive(pti, pwndTop)) // Rule 2 & 3. { //ERR("SetFocus: Set Foreground!\n"); if (!(pwndTop->style & WS_VISIBLE)) { pti->ppi->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; } if (!co_IntSetForegroundAndFocusWindow(pwndTop, FALSE)) { ERR("SetFocus: Set Foreground and Focus Failed!\n"); return 0; } } /* Set Active when it is needed. */ if (pwndTop != ThreadQueue->spwndActive) { //ERR("SetFocus: Set Active!\n"); if (!co_IntSetActiveWindow(pwndTop, FALSE, FALSE, FALSE)) { ERR("SetFocus: Set Active Failed!\n"); return 0; } } /* Abort if window destroyed */ if (Window->state2 & WNDS2_INDESTROY) return 0; /* Do not change focus if the window is no longer active */ if (pwndTop != ThreadQueue->spwndActive) { ERR("SetFocus: Top window did not go active!\n"); return 0; } } // Check again! SetActiveWindow could have set the focus via WM_ACTIVATE. hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0; IntSendFocusMessages( pti, Window); TRACE("Focus: %p -> %p\n", hWndPrev, Window->head.h); } else /* NULL hwnd passed in */ { if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev)) { ERR("SetFocus: 2 WH_CBT Call Hook return!\n"); return 0; } /* set the current thread focus window null */ IntSendFocusMessages( pti, NULL); } return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0; }
/* MSDN: The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true: * The process is the foreground process. * The process was started by the foreground process. * The process received the last input event. * There is no foreground process. * The foreground process is being debugged. * The foreground is not locked (see LockSetForegroundWindow). * The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo). * No menus are active. */ static BOOL FASTCALL co_IntSetForegroundAndFocusWindow( _In_ PWND Wnd, _In_ BOOL MouseActivate) { HWND hWnd = Wnd ? UserHMGetHandle(Wnd) : NULL; HWND hWndPrev = NULL; PWND pWndPrev = NULL; PUSER_MESSAGE_QUEUE PrevForegroundQueue; PTHREADINFO pti; BOOL fgRet = FALSE, Ret = FALSE; if (Wnd) ASSERT_REFS_CO(Wnd); //ERR("SetForegroundAndFocusWindow(%x, %s)\n", hWnd, (MouseActivate ? "TRUE" : "FALSE")); PrevForegroundQueue = IntGetFocusMessageQueue(); // Use this active desktop. pti = PsGetCurrentThreadWin32Thread(); if (PrevForegroundQueue) { // Same Window Q as foreground just do active. if (Wnd && Wnd->head.pti->MessageQueue == PrevForegroundQueue) { //ERR("Same Window Q as foreground just do active.\n"); if (pti->MessageQueue == PrevForegroundQueue) { // Same WQ and TQ go active. //ERR("Same WQ and TQ go active.\n"); Ret = co_IntSetActiveWindow(Wnd, MouseActivate, TRUE, FALSE); } else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd) { // Same WQ and it is active. //ERR("Same WQ and it is active.\n"); Ret = TRUE; } else { // Same WQ as FG but not the same TQ send active. //ERR("Same WQ as FG but not the same TQ send active.\n"); co_IntSendMessage(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate ); Ret = TRUE; } return Ret; } hWndPrev = PrevForegroundQueue->spwndActive ? UserHMGetHandle(PrevForegroundQueue->spwndActive) : 0; pWndPrev = PrevForegroundQueue->spwndActive; } if ( (( !IsFGLocked() || pti->ppi == gppiInputProvider ) && ( CanForceFG(pti->ppi) || pti->TIF_flags & (TIF_SYSTEMTHREAD|TIF_CSRSSTHREAD|TIF_ALLOWFOREGROUNDACTIVATE) )) || pti->ppi == ppiScrnSaver ) { //ToggleFGActivate(pti); // win.c line 2662 fail if (Wnd) { IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue); gptiForeground = Wnd->head.pti; //ERR("Set Foreground pti 0x%p Q 0x%p hWnd 0x%p\n",Wnd->head.pti, Wnd->head.pti->MessageQueue,Wnd->head.h); } else { IntSetFocusMessageQueue(NULL); gptiForeground = NULL; //ERR("Set Foreground pti 0x0 Q 0x0 hWnd 0x0\n"); } /* Henri Verbeet, What happens is that we get the WM_WINE_SETACTIVEWINDOW message sent by the other thread after we already changed the foreground window back to our own window. */ //ERR("SFAFW: 1\n"); FindRemoveAsyncMsg(Wnd, 0); // Do this to fix test_SFW todos! fgRet = TRUE; } // Fix FG Bounce with regedit. if (hWndPrev != hWnd ) { if (PrevForegroundQueue && fgRet && PrevForegroundQueue->spwndActive) { //ERR("SFGW: Send NULL to 0x%x\n",hWndPrev); if (pti->MessageQueue == PrevForegroundQueue) { //ERR("SFGW: TI same as Prev TI\n"); co_IntSetActiveWindow(NULL, FALSE, TRUE, FALSE); } else if (pWndPrev) { //ERR("SFGW Deactivate: TI not same as Prev TI\n"); // No real reason to wait here. co_IntSendMessageNoWait(hWndPrev, WM_ASYNC_SETACTIVEWINDOW, 0, 0 ); } } } if (!Wnd) return FALSE; // Always return false. if (pti->MessageQueue == Wnd->head.pti->MessageQueue) { //ERR("Same PQ and WQ go active.\n"); Ret = co_IntSetActiveWindow(Wnd, MouseActivate, TRUE, FALSE); } else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd) { //ERR("Same Active and Wnd.\n"); Ret = TRUE; } else { //ERR("Activate Not same PQ and WQ and Wnd.\n"); co_IntSendMessageNoWait(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate ); Ret = TRUE; } return Ret && fgRet; }