PUSER_MESSAGE_QUEUE gpqForeground = NULL;
PUSER_MESSAGE_QUEUE gpqForegroundPrev = NULL;
+PTHREADINFO gptiForeground = NULL;
+PPROCESSINFO gppiLockSFW = NULL;
+ULONG guSFWLockCount = 0; // Rule #8, No menus are active. So should be zero.
+PTHREADINFO ptiLastInput = NULL;
-HWND FASTCALL
-IntGetCaptureWindow(VOID)
+/*
+ Check locking of a process or one or more menus are active.
+*/
+BOOL FASTCALL
+IsFGLocked(VOID)
{
- PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
- return ForegroundQueue != NULL ? ForegroundQueue->CaptureWindow : 0;
+ return (gppiLockSFW || guSFWLockCount);
}
HWND FASTCALL
-UserGetFocusWindow(VOID)
+IntGetCaptureWindow(VOID)
{
- PTHREADINFO pti;
- PUSER_MESSAGE_QUEUE ThreadQueue;
-
- pti = PsGetCurrentThreadWin32Thread();
- ThreadQueue = pti->MessageQueue;
- /* Is it a foreground queue? */
- if (!ThreadQueue || ThreadQueue != IntGetFocusMessageQueue())
- return NULL;
- return ThreadQueue->FocusWindow;
+ PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
+ return ForegroundQueue != NULL ? ForegroundQueue->CaptureWindow : 0;
}
HWND FASTCALL
ThreadQueue = pti->MessageQueue;
if (!ThreadQueue)
return NULL;
- return ThreadQueue->FocusWindow;
+ return ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0;
}
VOID FASTCALL
}
}
+BOOL FASTCALL
+co_IntMakeWindowActive(PWND Window)
+{
+ PWND spwndOwner;
+ if (Window)
+ { // Set last active for window and it's owner.
+ Window->spwndLastActive = Window;
+ spwndOwner = Window->spwndOwner;
+ while (spwndOwner)
+ {
+ spwndOwner->spwndLastActive = Window;
+ spwndOwner = spwndOwner->spwndOwner;
+ }
+ return TRUE;
+ }
+ ERR("MakeWindowActive Failed!\n");
+ return FALSE;
+}
+
VOID FASTCALL
co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate)
{
USER_REFERENCE_ENTRY Ref, RefPrev;
PWND Window, WindowPrev = NULL;
+ HANDLE OldTID, NewTID;
+ PTHREADINFO ptiOld, ptiNew;
if ((Window = UserGetWindowObject(hWnd)))
{
}
if (Window)
- { // Set last active for window and it's owner.
- Window->hWndLastActive = hWnd;
- if (Window->spwndOwner)
- Window->spwndOwner->hWndLastActive = hWnd;
+ {
Window->state |= WNDS_ACTIVEFRAME;
+
+ if (Window->style & WS_MINIMIZE)
+ {
+ TRACE("Widow was minimized\n");
+ }
}
if (WindowPrev)
WindowPrev->state &= ~WNDS_ACTIVEFRAME;
- if (Window && WindowPrev)
+ OldTID = WindowPrev ? IntGetWndThreadId(WindowPrev) : NULL;
+ NewTID = Window ? IntGetWndThreadId(Window) : NULL;
+ ptiOld = WindowPrev ? WindowPrev->head.pti : NULL;
+ ptiNew = Window ? Window->head.pti : NULL;
+
+ TRACE("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID);
+
+ if (OldTID != NewTID)
{
PWND cWindow;
HWND *List, *phWnd;
- HANDLE OldTID = IntGetWndThreadId(WindowPrev);
- HANDLE NewTID = IntGetWndThreadId(Window);
-
- TRACE("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID);
- if (Window->style & WS_MINIMIZE)
- {
- TRACE("Widow was minimized\n");
- }
- if (OldTID != NewTID)
+ List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow()));
+ if ( List )
{
- List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow()));
- if (List)
+ if ( OldTID )
{
for (phWnd = List; *phWnd; ++phWnd)
{
cWindow = UserGetWindowObject(*phWnd);
-
- if (cWindow && (IntGetWndThreadId(cWindow) == OldTID))
+ if (cWindow && cWindow->head.pti == ptiOld)
{ // FALSE if the window is being deactivated,
// ThreadId that owns the window being activated.
co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID);
}
}
+ }
+ if ( NewTID )
+ {
for (phWnd = List; *phWnd; ++phWnd)
{
cWindow = UserGetWindowObject(*phWnd);
- if (cWindow && (IntGetWndThreadId(cWindow) == NewTID))
+ if (cWindow && cWindow->head.pti == ptiNew)
{ // TRUE if the window is being activated,
// ThreadId that owns the window being deactivated.
co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID);
}
}
- ExFreePool(List);
}
+ ExFreePool(List);
}
- UserDerefObjectCo(WindowPrev); // Now allow the previous window to die.
}
+ if (WindowPrev)
+ UserDerefObjectCo(WindowPrev); // Now allow the previous window to die.
UserDerefObjectCo(Window);
if (hWnd)
{
PWND pWnd = UserGetWindowObject(hWnd);
- IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0);
- co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0);
+ if (pWnd)
+ {
+ IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0);
+ co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0);
+ }
}
}
return NULL;
}
+VOID FASTCALL
+FindRemoveAsyncMsg(PWND Wnd)
+{
+ PUSER_MESSAGE_QUEUE MessageQueue;
+ PUSER_SENT_MESSAGE Message;
+ PLIST_ENTRY Entry;
+
+ if (!Wnd) return;
+
+ MessageQueue = Wnd->head.pti->MessageQueue;
+
+ if (!IsListEmpty(&MessageQueue->SentMessagesListHead))
+ {
+ // Scan sent queue messages to see if we received async messages.
+ Entry = MessageQueue->SentMessagesListHead.Flink;
+ Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
+ do
+ {
+ if (Message->Msg.message == WM_ASYNC_SETACTIVEWINDOW &&
+ Message->Msg.hwnd == UserHMGetHandle(Wnd) &&
+ Message->Msg.wParam == 0 )
+ {
+ TRACE("ASYNC SAW: Found one in the Sent Msg Queue! %p\n", Message->Msg.hwnd);
+ RemoveEntryList(Entry); // Purge the entry.
+ }
+ Entry = Message->ListEntry.Flink;
+ Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
+ }
+ while (Entry != &MessageQueue->SentMessagesListHead);
+ }
+}
+
+/*
+ Can the system force foreground from one or more conditions.
+ */
+BOOL FASTCALL
+CanForceFG(PPROCESSINFO ppi)
+{
+ if (!ptiLastInput ||
+ ptiLastInput->ppi == ppi ||
+ !gptiForeground ||
+ gptiForeground->ppi == ppi ||
+ ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_SETFOREGROUNDALLOWED) ||
+ gppiInputProvider == ppi ||
+ !gpqForeground
+ ) return TRUE;
+ return FALSE;
+}
+
/*
MSDN:
The system restricts which processes can set the foreground window. A process
* The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
* No menus are active.
*/
+
static BOOL FASTCALL
-co_IntSetForegroundAndFocusWindow(PWND Wnd, PWND FocusWindow, BOOL MouseActivate)
+co_IntSetForegroundAndFocusWindow(PWND Wnd, BOOL MouseActivate)
{
- CBTACTIVATESTRUCT cbt;
- HWND hWnd = Wnd->head.h;
+ HWND hWnd = UserHMGetHandle(Wnd);
HWND hWndPrev = NULL;
- HWND hWndFocus = FocusWindow->head.h;
- HWND hWndFocusPrev = NULL;
PUSER_MESSAGE_QUEUE PrevForegroundQueue;
+ PTHREADINFO pti;
+ BOOL fgRet = FALSE, Ret = FALSE;
ASSERT_REFS_CO(Wnd);
- TRACE("IntSetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd, hWndFocus, MouseActivate ? "TRUE" : "FALSE");
+ TRACE("SetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd, MouseActivate ? "TRUE" : "FALSE");
- if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
- {
- TRACE("Failed - Child\n");
- return FALSE;
- }
+ PrevForegroundQueue = IntGetFocusMessageQueue(); // Use this active desktop.
+ pti = PsGetCurrentThreadWin32Thread();
- if (0 == (Wnd->style & WS_VISIBLE) &&
- Wnd->head.pti->pEThread->ThreadsProcess != CsrProcess)
- {
- ERR("Failed - Invisible\n");
- return FALSE;
- }
+ if (PrevForegroundQueue)
+ { // Same Window Q as foreground just do active.
+ if (Wnd && Wnd->head.pti->MessageQueue == PrevForegroundQueue)
+ {
+ if (pti->MessageQueue == PrevForegroundQueue)
+ { // Same WQ and TQ go active.
+ Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE);
+ }
+ else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd)
+ { // Same WQ and it is active.
+ Ret = TRUE;
+ }
+ else
+ { // Same WQ as FG but not the same TQ send active.
+ co_IntSendMessageNoWait(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate );
+ Ret = TRUE;
+ }
+ return Ret;
+ }
- PrevForegroundQueue = IntGetFocusMessageQueue();
- if (PrevForegroundQueue != 0)
- {
- hWndPrev = PrevForegroundQueue->ActiveWindow;
- hWndFocusPrev = PrevForegroundQueue->FocusWindow;
+ hWndPrev = PrevForegroundQueue->spwndActive ? UserHMGetHandle(PrevForegroundQueue->spwndActive) : 0;
}
- if (hWndPrev == hWnd)
- {
- TRACE("Failed - Same\n");
- return TRUE;
- }
+ if ( (( !IsFGLocked() || pti->ppi == gppiInputProvider ) &&
+ ( CanForceFG(pti->ppi) || pti->TIF_flags & (TIF_SYSTEMTHREAD|TIF_CSRSSTHREAD|TIF_ALLOWFOREGROUNDACTIVATE) )) ||
+ pti->ppi == ppiScrnSaver
+ )
+ {
+ IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue);
+ gptiForeground = Wnd->head.pti;
+/*
+ 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.
+ */
+ FindRemoveAsyncMsg(Wnd); // Do this to fix test_SFW todos!
+ fgRet = TRUE;
+ }
- /* Call CBT hook chain */
- cbt.fMouse = MouseActivate;
- cbt.hWndActive = hWndPrev;
- if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt))
+ // Fix FG Bounce with regedit.
+ if (hWndPrev != hWnd )
{
- ERR("IntSetForegroundAndFocusWindow WH_CBT Call Hook return!\n");
- return 0;
+ if (PrevForegroundQueue &&
+ fgRet &&
+ Wnd->head.pti->MessageQueue != PrevForegroundQueue &&
+ 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, NULL, FALSE, TRUE);
+ }
+ else
+ co_IntSendMessageNoWait(hWndPrev, WM_ASYNC_SETACTIVEWINDOW, 0, 0 );
+ }
}
- co_IntSendDeactivateMessages(hWndPrev, hWnd);
- co_IntSendKillFocusMessages(hWndFocusPrev, hWndFocus);
-
-
- IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue);
-
- if (Wnd->head.pti->MessageQueue)
+ if (pti->MessageQueue == Wnd->head.pti->MessageQueue)
{
- Wnd->head.pti->MessageQueue->ActiveWindow = hWnd;
+ Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE);
}
-
- if (FocusWindow->head.pti->MessageQueue)
+ else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd)
{
- FocusWindow->head.pti->MessageQueue->FocusWindow = hWndFocus;
+ Ret = TRUE;
}
-
- if (PrevForegroundQueue != Wnd->head.pti->MessageQueue)
+ else
{
- /* FIXME: Send WM_ACTIVATEAPP to all thread windows. */
+ co_IntSendMessageNoWait(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate );
+ Ret = TRUE;
}
- co_IntSendSetFocusMessages(hWndFocusPrev, hWndFocus);
- co_IntSendActivateMessages(hWndPrev, hWnd, MouseActivate);
-
- return TRUE;
-}
-
-BOOL FASTCALL
-co_IntSetForegroundWindow(PWND Window) // FIXME: Can Window be NULL??
-{
- /*if (Window)*/ ASSERT_REFS_CO(Window);
-
- return co_IntSetForegroundAndFocusWindow(Window, Window, FALSE);
+ return Ret && fgRet;
}
BOOL FASTCALL
ASSERT_REFS_CO(Wnd);
- if(Wnd->style & WS_DISABLED)
+ if (Wnd->style & WS_DISABLED)
{
BOOL Ret;
PWND TopWnd;
PWND DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
- if(DesktopWindow)
+ if (DesktopWindow)
{
Top = IntFindChildWindowToOwner(DesktopWindow, Wnd);
- if((TopWnd = UserGetWindowObject(Top)))
+ if ((TopWnd = UserGetWindowObject(Top)))
{
UserRefObjectCo(TopWnd, &Ref);
Ret = co_IntMouseActivateWindow(TopWnd);
return FALSE;
}
-
TopWindow = UserGetAncestor(Wnd, GA_ROOT);
if (!TopWindow) return FALSE;
/* TMN: Check return valud from this function? */
UserRefObjectCo(TopWindow, &Ref);
- co_IntSetForegroundAndFocusWindow(TopWindow, Wnd, TRUE);
+ co_IntSetForegroundAndFocusWindow(TopWindow, TRUE);
UserDerefObjectCo(TopWindow);
return TRUE;
}
-HWND FASTCALL
-co_IntSetActiveWindow(PWND Wnd OPTIONAL)
+BOOL FASTCALL
+co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus)
{
PTHREADINFO pti;
PUSER_MESSAGE_QUEUE ThreadQueue;
CBTACTIVATESTRUCT cbt;
if (Wnd)
+ {
ASSERT_REFS_CO(Wnd);
+ hWnd = UserHMGetHandle(Wnd);
+ }
pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue;
ASSERT(ThreadQueue != 0);
- if (Wnd != 0)
- {
- if ((Wnd->style & (WS_POPUP | WS_CHILD)) == WS_CHILD)
+ hWndPrev = ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : NULL;
+ if (Prev) *Prev = hWndPrev;
+ if (hWndPrev == hWnd) return TRUE;
+
+ if (Wnd)
+ {
+ if (ThreadQueue != Wnd->head.pti->MessageQueue)
{
- /* Windows doesn't seem to return an error here */
- return ThreadQueue->ActiveWindow;
+ PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
+ // Rule 1 & 4, We are foreground so set this FG window or NULL foreground....
+ if (!ForegroundQueue || ForegroundQueue == ThreadQueue)
+ {
+ return co_IntSetForegroundAndFocusWindow(Wnd, bMouse);
+ }
}
- hWnd = Wnd->head.h;
- }
- hWndPrev = ThreadQueue->ActiveWindow;
- if (hWndPrev == hWnd)
- {
- return hWndPrev;
+ if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE;
}
/* Call CBT hook chain */
- cbt.fMouse = FALSE;
+ cbt.fMouse = bMouse;
cbt.hWndActive = hWndPrev;
if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt))
{
ERR("SetActiveWindow WH_CBT Call Hook return!\n");
- return 0;
+ return FALSE;
}
co_IntSendDeactivateMessages(hWndPrev, hWnd);
- ThreadQueue->ActiveWindow = hWnd;
+ if (Wnd) Wnd->state |= WNDS_BEINGACTIVATED;
- co_IntSendActivateMessages(hWndPrev, hWnd, FALSE);
+ IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
- /* FIXME */
- /* return IntIsWindow(hWndPrev) ? hWndPrev : 0;*/
- return hWndPrev;
+ /* check if the specified window can be set in the input data of a given queue */
+ if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue)
+ {
+ /* set the current thread active window */
+ if (!Wnd || co_IntMakeWindowActive(Wnd))
+ {
+ ThreadQueue->spwndActivePrev = ThreadQueue->spwndActive;
+ ThreadQueue->spwndActive = Wnd;
+ }
+ }
+
+ co_IntSendActivateMessages(hWndPrev, hWnd, bMouse);
+
+ /* now change focus if necessary */
+ if (bFocus)
+ {
+ /* Do not change focus if the window is no longer active */
+ if (ThreadQueue->spwndActive == Wnd)
+ {
+ if (!ThreadQueue->spwndFocus ||
+ !Wnd ||
+ UserGetAncestor(ThreadQueue->spwndFocus, GA_ROOT) != Wnd)
+ {
+ co_UserSetFocus(Wnd);
+ }
+ }
+ }
+
+ if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED;
+ return TRUE;
}
HWND FASTCALL
ThreadQueue = pti->MessageQueue;
ASSERT(ThreadQueue != 0);
- hWndPrev = ThreadQueue->FocusWindow;
+ hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0;
if (Window != 0)
{
- if (hWndPrev == Window->head.h)
+ if (hWndPrev == UserHMGetHandle(Window))
{
return hWndPrev; /* 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 )
+ pwndTop = Window;
+ for (;;)
{
if (pwndTop->style & (WS_MINIMIZED|WS_DISABLED)) return 0;
- if ((pwndTop->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) break;
+ if (!pwndTop->spwndParent || pwndTop->spwndParent == UserGetDesktopWindow())
+ {
+ if ((pwndTop->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return 0;
+ break;
+ }
+ if (pwndTop->spwndParent == UserGetMessageWindow()) return 0;
+ pwndTop = pwndTop->spwndParent;
}
if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev))
}
/* Activate pwndTop if needed. */
- if (pwndTop->head.h != ThreadQueue->ActiveWindow)
+ if (pwndTop != ThreadQueue->spwndActive)
{
- co_IntSetActiveWindow(pwndTop);
+ PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Keep it based on desktop.
+ if (ThreadQueue != ForegroundQueue) // HACK see rule 2 & 3.
+ {
+ 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)
+ {
+ if (!co_IntSetActiveWindow(pwndTop, NULL, 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->head.h != ThreadQueue->ActiveWindow)
+ if (pwndTop != ThreadQueue->spwndActive)
{
ERR("SetFocus Top window did not go active!\n");
return 0;
}
}
- ThreadQueue->FocusWindow = Window->head.h;
+ // Check again! SetActiveWindow could have set the focus via WM_ACTIVATE.
+ hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0;
+
+ /* check if the specified window can be set in the input data of a given queue */
+ if (ThreadQueue == Window->head.pti->MessageQueue)
+ /* set the current thread focus window */
+ ThreadQueue->spwndFocus = Window;
+
TRACE("Focus: %d -> %d\n", hWndPrev, Window->head.h);
co_IntSendKillFocusMessages(hWndPrev, Window->head.h);
co_IntSendSetFocusMessages(hWndPrev, Window->head.h);
}
- else
+ else /* NULL hwnd passed in */
{
- ThreadQueue->FocusWindow = 0;
+ if (!hWndPrev) return 0; /* nothing to do */
if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
{
ERR("SetFocusWindow 2 WH_CBT Call Hook return!\n");
return 0;
}
+ /* set the current thread focus window null */
+ ThreadQueue->spwndFocus = 0;
+
co_IntSendKillFocusMessages(hWndPrev, 0);
}
- return hWndPrev;
+ return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0;
}
HWND FASTCALL
PUSER_MESSAGE_QUEUE ForegroundQueue;
ForegroundQueue = IntGetFocusMessageQueue();
- return( ForegroundQueue != NULL ? ForegroundQueue->ActiveWindow : 0);
+ return( ForegroundQueue ? (ForegroundQueue->spwndActive ? UserHMGetHandle(ForegroundQueue->spwndActive) : 0) : 0);
}
HWND FASTCALL UserGetActiveWindow(VOID)
pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue;
- return( ThreadQueue ? ThreadQueue->ActiveWindow : 0);
+ return( ThreadQueue ? (ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : 0) : 0);
}
HWND APIENTRY
return hWndPrev;
}
+/*
+ API Call
+*/
BOOL
FASTCALL
IntReleaseCapture(VOID)
return TRUE;
}
+/*
+ API Call
+*/
+BOOL FASTCALL
+co_IntSetForegroundWindow(PWND Window)
+{
+ ASSERT_REFS_CO(Window);
+
+ return co_IntSetForegroundAndFocusWindow(Window, FALSE);
+}
+
+/*
+ API Call
+*/
+BOOL FASTCALL
+IntLockSetForegroundWindow(UINT uLockCode)
+{
+ ULONG Err = ERROR_ACCESS_DENIED;
+ PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
+ switch (uLockCode)
+ {
+ case LSFW_LOCK:
+ if ( CanForceFG(ppi) && !gppiLockSFW )
+ {
+ gppiLockSFW = ppi;
+ return TRUE;
+ }
+ break;
+ case LSFW_UNLOCK:
+ if ( gppiLockSFW == ppi)
+ {
+ gppiLockSFW = NULL;
+ return TRUE;
+ }
+ break;
+ default:
+ Err = ERROR_INVALID_PARAMETER;
+ }
+ EngSetLastError(Err);
+ return FALSE;
+}
+
+/*
+ API Call
+*/
+BOOL FASTCALL
+IntAllowSetForegroundWindow(DWORD dwProcessId)
+{
+ PPROCESSINFO ppi, ppiCur;
+ PEPROCESS Process = NULL;
+
+ ppi = NULL;
+ if (dwProcessId != ASFW_ANY)
+ {
+ if (!NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)dwProcessId, &Process)))
+ {
+ EngSetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ ppi = PsGetProcessWin32Process(Process);
+ if (!ppi)
+ {
+ ObDereferenceObject(Process);
+ return FALSE;
+ }
+ }
+ ppiCur = PsGetCurrentProcessWin32Process();
+ if (!CanForceFG(ppiCur))
+ {
+ if (Process) ObDereferenceObject(Process);
+ EngSetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ if (dwProcessId == ASFW_ANY)
+ { // All processes will be enabled to set the foreground window.
+ ptiLastInput = NULL;
+ }
+ else
+ { // Rule #3, last input event in force.
+ ptiLastInput = ppi->ptiList;
+ ObDereferenceObject(Process);
+ }
+ return TRUE;
+}
+
/*
* @implemented
*/
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)
{
- 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
+
+ if (!Window ||
+ Window->head.pti->MessageQueue == gptiCurrent->MessageQueue)
{
- RETURN( co_IntSetActiveWindow(0));
+ if (Window) UserRefObjectCo(Window, &Ref);
+ if (!co_IntSetActiveWindow(Window, &hWndPrev, FALSE, TRUE)) hWndPrev = NULL;
+ if (Window) UserDerefObjectCo(Window);
}
+ else
+ hWndPrev = NULL;
+
+ RETURN( hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0 );
CLEANUP:
TRACE("Leave NtUserSetActiveWindow, ret=%i\n",_ret_);