[Win32k]
[reactos.git] / reactos / win32ss / user / ntuser / focus.c
index 1fc4389..c58e1d0 100644 (file)
@@ -80,7 +80,7 @@ BOOL FASTCALL
 co_IntMakeWindowActive(PWND Window)
 {
   PWND spwndOwner;
-  if (Window)
+  if (VerifyWnd(Window))
   {  // Set last active for window and it's owner.
      spwndOwner = Window;
      while (spwndOwner->spwndOwner)
@@ -112,7 +112,8 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO
 
       /* Send palette messages */
       if (gpsi->PUSIFlags & PUSIF_PALETTEDISPLAY &&
-          co_IntPostOrSendMessage(UserHMGetHandle(Window), WM_QUERYNEWPALETTE, 0, 0))
+          //co_IntPostOrSendMessage(UserHMGetHandle(Window), WM_QUERYNEWPALETTE, 0, 0))
+          co_IntSendMessage(UserHMGetHandle(Window), WM_QUERYNEWPALETTE, 0, 0))
       {
          UserSendNotifyMessage( HWND_BROADCAST,
                                 WM_PALETTEISCHANGING,
@@ -132,11 +133,37 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO
             {
                UINT flags = SWP_NOSIZE | SWP_NOMOVE;
                if (Window == pwndTemp) flags |= SWP_NOACTIVATE;
+               //ERR("co_IntSendActivateMessages SetWindowPos! Async %d pti Q == FGQ %d\n",Async,pti->MessageQueue == gpqForeground);
                co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, flags);
             }
          }
       }
       ////
+      //// CORE-1161 and CORE-6651
+      if (Window->spwndPrev)
+      {
+         HWND *phwndTopLevel, *phwndCurrent;
+         PWND pwndCurrent, pwndDesktop;
+
+         pwndDesktop = UserGetDesktopWindow();
+         if (Window->spwndParent == pwndDesktop )
+         {
+            phwndTopLevel = IntWinListChildren(pwndDesktop);
+            phwndCurrent = phwndTopLevel;
+            while(*phwndCurrent)
+            {
+                pwndCurrent = UserGetWindowObject(*phwndCurrent);
+
+                if (pwndCurrent && pwndCurrent->spwndOwner == Window )
+                {
+                    co_WinPosSetWindowPos(pwndCurrent, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
+                }
+                phwndCurrent++;
+            }
+            ExFreePool(phwndTopLevel);
+          }
+      }
+      ////
       OldTID = WindowPrev ? IntGetWndThreadId(WindowPrev) : NULL;
       NewTID = IntGetWndThreadId(Window);
       ptiOld = WindowPrev ? WindowPrev->head.pti : NULL;
@@ -156,8 +183,7 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO
             if ( OldTID )
             {
                ptiOld->TIF_flags |= TIF_INACTIVATEAPPMSG;
-               ptiOld->pClientInfo->dwTIFlags = ptiOld->TIF_flags;
-
+               // Note: Do not set pci flags, this does crash!
                for (phWnd = List; *phWnd; ++phWnd)
                {
                   cWindow = ValidateHwndNoErr(*phWnd);
@@ -168,13 +194,11 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO
                   }
                }
                ptiOld->TIF_flags &= ~TIF_INACTIVATEAPPMSG;
-               ptiOld->pClientInfo->dwTIFlags = ptiOld->TIF_flags;
             }
             if ( NewTID )
             {  //// Prevents a resource crash due to reentrance!
                InAAPM = TRUE;
                pti->TIF_flags |= TIF_INACTIVATEAPPMSG;
-               pti->pClientInfo->dwTIFlags = pti->TIF_flags;
                ////
                for (phWnd = List; *phWnd; ++phWnd)
                {
@@ -205,12 +229,11 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO
 
       co_IntMakeWindowActive(Window);
 
-      UserDerefObjectCo(Window);
-
       /* FIXME: IntIsWindow */
+
       co_IntSendMessageNoWait( UserHMGetHandle(Window),
                                WM_NCACTIVATE,
-                              (WPARAM)(Window == gpqForeground->spwndActive),
+                              (WPARAM)(Window == (gpqForeground ? gpqForeground->spwndActive : NULL)),
                                0); //(LPARAM)hWndPrev);
 
       co_IntSendMessageNoWait( UserHMGetHandle(Window),
@@ -226,6 +249,7 @@ co_IntSendActivateMessages(PWND WindowPrev, PWND Window, BOOL MouseActivate, BOO
 
       Window->state &= ~WNDS_NONCPAINT;
 
+      UserDerefObjectCo(Window);
    }
    return InAAPM;
 }
@@ -253,12 +277,14 @@ IntSendFocusMessages( PTHREADINFO pti, PWND pWnd)
    {
       if (pWndPrev)
       {
-         co_IntPostOrSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, (WPARAM)UserHMGetHandle(pWnd), 0);
+         //co_IntPostOrSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, (WPARAM)UserHMGetHandle(pWnd), 0);
+         co_IntSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, (WPARAM)UserHMGetHandle(pWnd), 0);
       }
       if (ThreadQueue->spwndFocus == pWnd)
       {
          IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0);
-         co_IntPostOrSendMessage(UserHMGetHandle(pWnd), WM_SETFOCUS, (WPARAM)(pWndPrev ? UserHMGetHandle(pWndPrev) : NULL), 0);
+         //co_IntPostOrSendMessage(UserHMGetHandle(pWnd), WM_SETFOCUS, (WPARAM)(pWndPrev ? UserHMGetHandle(pWndPrev) : NULL), 0);
+         co_IntSendMessage(UserHMGetHandle(pWnd), WM_SETFOCUS, (WPARAM)(pWndPrev ? UserHMGetHandle(pWndPrev) : NULL), 0);
       }
    }
    else
@@ -266,7 +292,8 @@ IntSendFocusMessages( PTHREADINFO pti, PWND pWnd)
       if (pWndPrev)
       {
          IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
-         co_IntPostOrSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, 0, 0);
+         //co_IntPostOrSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, 0, 0);
+         co_IntSendMessage(UserHMGetHandle(pWndPrev), WM_KILLFOCUS, 0, 0);
       }
    }
 }
@@ -294,35 +321,75 @@ IntFindChildWindowToOwner(PWND Root, PWND Owner)
 }
 
 VOID FASTCALL
-FindRemoveAsyncMsg(PWND Wnd)
+FindRemoveAsyncMsg(PWND Wnd, WPARAM wParam)
 {
-   PUSER_MESSAGE_QUEUE MessageQueue;
+   PTHREADINFO pti;
    PUSER_SENT_MESSAGE Message;
    PLIST_ENTRY Entry;
 
    if (!Wnd) return;
 
-   MessageQueue = Wnd->head.pti->MessageQueue;
+   pti = Wnd->head.pti;
 
-   if (!IsListEmpty(&MessageQueue->SentMessagesListHead))
+   if (!IsListEmpty(&pti->SentMessagesListHead))
    {
       // Scan sent queue messages to see if we received async messages.
-      Entry = MessageQueue->SentMessagesListHead.Flink;
+      Entry = pti->SentMessagesListHead.Flink;
       Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
       do
       {
+         if (IsListEmpty(Entry)) return;
+         if (!Message) return;
+         Entry = Message->ListEntry.Flink;
+
          if (Message->Msg.message == WM_ASYNC_SETACTIVEWINDOW &&
              Message->Msg.hwnd == UserHMGetHandle(Wnd) &&
-             Message->Msg.wParam == 0 )
+             Message->Msg.wParam == wParam )
          {
-             TRACE("ASYNC SAW: Found one in the Sent Msg Queue! %p\n", Message->Msg.hwnd);
-             RemoveEntryList(Entry); // Purge the entry.
+             ERR("ASYNC SAW: Found one in the Sent Msg Queue! %p Activate/Deactivate %d\n", Message->Msg.hwnd,!!wParam);
+             RemoveEntryList(&Message->ListEntry); // Purge the entry.
+             ExFreePoolWithTag(Message, TAG_USRMSG);
          }
-         Entry = Message->ListEntry.Flink;
          Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
       }
-      while (Entry != &MessageQueue->SentMessagesListHead);
+      while (Entry != &pti->SentMessagesListHead);
+   }
+}
+
+BOOL FASTCALL
+ToggleFGActivate(PTHREADINFO pti)
+{
+   BOOL Ret;
+   PPROCESSINFO ppi = pti->ppi;
+
+   Ret = !!(pti->TIF_flags & TIF_ALLOWFOREGROUNDACTIVATE);
+   if (Ret)
+   {
+      pti->TIF_flags &= ~TIF_ALLOWFOREGROUNDACTIVATE;
+   }
+   else
+      Ret = !!(ppi->W32PF_flags & W32PF_ALLOWFOREGROUNDACTIVATE);
+
+   if (Ret)
+      ppi->W32PF_flags &= ~W32PF_ALLOWFOREGROUNDACTIVATE;
+   //ERR("ToggleFGActivate is %d\n",Ret);
+   return Ret;
+}
+
+BOOL FASTCALL
+IsAllowedFGActive(PTHREADINFO pti, PWND Wnd)
+{
+   // Not allowed if one or more,,
+   if (!ToggleFGActivate(pti) ||              // bits not set,
+        pti->rpdesk != gpdeskInputDesktop ||  // not current Desktop,
+        pti->MessageQueue == gpqForeground || // if already the queue foreground,
+        IsFGLocked() ||                       // foreground is locked,
+        Wnd->ExStyle & WS_EX_NOACTIVATE )     // or,,, does not become the foreground window when the user clicks it.
+   {
+      return FALSE;
    }
+   //ERR("IsAllowedFGActive is TRUE\n");
+   return TRUE;
 }
 
 /*
@@ -339,6 +406,7 @@ CanForceFG(PPROCESSINFO ppi)
         gppiInputProvider == ppi ||
        !gpqForeground
       ) return TRUE;
+   //ERR("CanForceFG is FALSE\n");
    return FALSE;
 }
 
@@ -356,37 +424,35 @@ CanForceFG(PPROCESSINFO ppi)
     * The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
     * No menus are active.
 */
-
-static BOOL FASTCALL
+static
+BOOL FASTCALL
 co_IntSetForegroundAndFocusWindow(
     _In_ PWND Wnd,
     _In_ BOOL MouseActivate)
 {
-   HWND hWnd;
+   HWND hWnd = Wnd ? UserHMGetHandle(Wnd) : NULL;
    HWND hWndPrev = NULL;
+   PWND pWndPrev = NULL;
    PUSER_MESSAGE_QUEUE PrevForegroundQueue;
    PTHREADINFO pti;
    BOOL fgRet = FALSE, Ret = FALSE;
 
-   ASSERT_REFS_CO(Wnd);
-   NT_ASSERT(Wnd != NULL);
-
-   hWnd = UserHMGetHandle(Wnd);
+   if (Wnd) ASSERT_REFS_CO(Wnd);
 
-   TRACE("SetForegroundAndFocusWindow(%x, %s)\n", hWnd, (MouseActivate ? "TRUE" : "FALSE"));
+   //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.
-      //ERR("Same Window Q as foreground just do active.\n");
       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, NULL, MouseActivate, TRUE, FALSE);
+            Ret = co_IntSetActiveWindow(Wnd, MouseActivate, TRUE, FALSE);
          }
          else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd)
          { // Same WQ and it is active.
@@ -396,13 +462,14 @@ co_IntSetForegroundAndFocusWindow(
          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_IntSendMessageNoWait(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate );
+            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 ) &&
@@ -410,16 +477,29 @@ co_IntSetForegroundAndFocusWindow(
         pti->ppi == ppiScrnSaver
       )
    {
-      IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue);
-      gptiForeground = Wnd->head.pti;
-      TRACE("Set Foreground pti 0x%p Q 0x%p\n",Wnd->head.pti, Wnd->head.pti->MessageQueue);
+
+      //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.
  */
-      FindRemoveAsyncMsg(Wnd); // Do this to fix test_SFW todos!
+      //ERR("SFAFW: 1\n");
+      FindRemoveAsyncMsg(Wnd, 0); // Do this to fix test_SFW todos!
+
       fgRet = TRUE;
    }
 
@@ -428,34 +508,41 @@ co_IntSetForegroundAndFocusWindow(
    {
       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, FALSE);
+            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 );
          }
-         else
-         co_IntSendMessageNoWait(hWndPrev, WM_ASYNC_SETACTIVEWINDOW, 0, 0 );
       }
    }
 
+   if (!Wnd) return FALSE; // Always return false.
+
    if (pti->MessageQueue == Wnd->head.pti->MessageQueue)
    {
-       Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE, FALSE);
+       //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;
 }
 
@@ -500,7 +587,7 @@ co_IntMouseActivateWindow(PWND Wnd)
 }
 
 BOOL FASTCALL
-co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus, BOOL Async)
+co_IntSetActiveWindow(PWND Wnd OPTIONAL, BOOL bMouse, BOOL bFocus, BOOL Async)
 {
    PTHREADINFO pti;
    PUSER_MESSAGE_QUEUE ThreadQueue;
@@ -509,38 +596,83 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus,
    HWND hWnd = 0;
    BOOL InAAPM;
    CBTACTIVATESTRUCT cbt;
-
+   //ERR("co_IntSetActiveWindow 1\n");
    if (Wnd)
    {
       ASSERT_REFS_CO(Wnd);
       hWnd = UserHMGetHandle(Wnd);
       if ((Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
       if (Wnd == UserGetDesktopWindow()) return FALSE;
+      //ERR("co_IntSetActiveWindow 1a hWnd 0x%p\n",hWnd);
    }
 
+   //ERR("co_IntSetActiveWindow 2\n");
    pti = PsGetCurrentThreadWin32Thread();
    ThreadQueue = pti->MessageQueue;
    ASSERT(ThreadQueue != 0);
 
    hWndPrev = ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : NULL;
-   if (Prev) *Prev = hWndPrev;
-   if (hWndPrev == hWnd) return TRUE;
 
    pWndChg = ThreadQueue->spwndActive; // Keep to notify of a preemptive switch.
 
-   if (Wnd)
+   while (Wnd)
    {
-      if (ThreadQueue != Wnd->head.pti->MessageQueue)
+      BOOL Ret, DoFG, AllowFG;
+
+      if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE;
+
+      if (ThreadQueue == Wnd->head.pti->MessageQueue)
       {
-         PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
+         if (IsAllowedFGActive(pti, Wnd))
+         {
+             DoFG = TRUE;
+         }
+         else
+         {
+             //ERR("co_IntSetActiveWindow 3 Go Out!\n");
+             break;
+         }
+         AllowFG = !pti->cVisWindows; // Nothing is visable.
+         //ERR("co_IntSetActiveWindow 3a DoFG = %d AllowFG = %d\n",DoFG,AllowFG);
+      }
+      else //if (ThreadQueue != Wnd->head.pti->MessageQueue)
+      {
+         //PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
          // Rule 1 & 4, We are foreground so set this FG window or NULL foreground....
-         if (!ForegroundQueue || ForegroundQueue == ThreadQueue)
+         //if (!ForegroundQueue || ForegroundQueue == ThreadQueue)
+         if (!gpqForeground || gpqForeground == ThreadQueue)
          {
-            return co_IntSetForegroundAndFocusWindow(Wnd, bMouse);
+            DoFG = TRUE;
          }
+         else
+            DoFG = FALSE;
+         if (DoFG)
+         {
+            if (pti->TIF_flags & TIF_ALLOWFOREGROUNDACTIVATE || pti->cVisWindows)
+               AllowFG = TRUE;
+            else
+               AllowFG = FALSE;
+         }
+         else
+            AllowFG = FALSE;
+         //ERR("co_IntSetActiveWindow 3b DoFG = %d AllowFG = %d\n",DoFG,AllowFG);
       }
-
-      if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE;
+      Ret = FALSE;
+      if (DoFG)
+      {
+         pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE;
+         //ERR("co_IntSetActiveWindow 3c FG set\n");
+         Ret = co_IntSetForegroundAndFocusWindow(Wnd, bMouse);
+         if (AllowFG)
+         {
+            pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE;
+         }
+         else
+         {
+            pti->TIF_flags &= ~TIF_ALLOWFOREGROUNDACTIVATE;
+         }
+      }
+      return Ret;
    }
 
    /* Call CBT hook chain */
@@ -562,14 +694,16 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus,
    if (WndPrev)
    {
       if (ThreadQueue == gpqForeground) gpqForegroundPrev = ThreadQueue;
-      if (!co_IntSendDeactivateMessages(hWndPrev, hWnd)) return FALSE;
+      if (!co_IntSendDeactivateMessages(UserHMGetHandle(WndPrev), hWnd)) return FALSE;
    }
 
+   WndPrev = ThreadQueue->spwndActive; // Again keep to save changing active.
+
    // While in calling message proc or hook:
    // Fail if a preemptive switch was made, current active not made previous,
    // focus window is dead or no longer the same thread queue.
    if ( ThreadQueue->spwndActivePrev != ThreadQueue->spwndActive ||
-        pWndChg != ThreadQueue->spwndActive ||
+        pWndChg != WndPrev ||
         (Wnd && !VerifyWnd(Wnd)) ||
         ThreadQueue != pti->MessageQueue )
    {
@@ -582,6 +716,8 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus,
    if (Wnd) Wnd->state |= WNDS_BEINGACTIVATED;
 
    IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
+   //// Breaks Atl-Esc/Tab via User32.
+   ////FindRemoveAsyncMsg(Wnd,(WPARAM)Wnd); // Clear out activate ASYNC messages.
 
    /* check if the specified window can be set in the input data of a given queue */
    if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue)
@@ -590,36 +726,61 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus,
       ThreadQueue->spwndActive = Wnd;
    }
 
+   WndPrev = VerifyWnd(ThreadQueue->spwndActivePrev); // Now should be set but verify it again.
+
    InAAPM = co_IntSendActivateMessages(WndPrev, Wnd, bMouse, Async);
 
    /* now change focus if necessary */
    if (bFocus && !(ThreadQueue->QF_flags & QF_FOCUSNULLSINCEACTIVE))
    {
       /* Do not change focus if the window is no longer active */
-      if (ThreadQueue->spwndActive == Wnd)
+      if (pti->MessageQueue->spwndActive != IntGetNonChildAncestor(pti->MessageQueue->spwndFocus))
       {
-         if (!ThreadQueue->spwndFocus ||
-             !Wnd ||
-              UserGetAncestor(ThreadQueue->spwndFocus, GA_ROOT) != Wnd)
-         {
-            co_UserSetFocus(Wnd);
-         }
+         PWND pWndSend = pti->MessageQueue->spwndActive;
+         // Clear focus if the active window is minimized.
+         if (pWndSend && pti->MessageQueue->spwndActive->style & WS_MINIMIZE) pWndSend = NULL;
+         // Send focus messages and if so, set the focus.
+         IntSendFocusMessages( pti, pWndSend);
       }
    }
 
    if (InAAPM)
    {
       pti->TIF_flags &= ~TIF_INACTIVATEAPPMSG;
-      pti->pClientInfo->dwTIFlags = pti->TIF_flags;
    }
 
    // FIXME: Used in the menu loop!!!
    //ThreadQueue->QF_flags |= QF_ACTIVATIONCHANGE;
 
+   //ERR("co_IntSetActiveWindow Exit\n");
    if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED;
    return (ThreadQueue->spwndActive == Wnd);
 }
 
+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 FASTCALL
 co_UserSetFocus(PWND Window)
 {
@@ -653,19 +814,13 @@ co_UserSetFocus(PWND Window)
       }
 
       /* Check if we can set the focus to this window */
-      pwndTop = Window;
-      for (;;)
+      //// Fixes wine win test_SetParent both "todo" line 3710 and 3720...
+      for (pwndTop = Window; pwndTop; pwndTop = pwndTop->spwndParent)
       {
          if (pwndTop->style & (WS_MINIMIZED|WS_DISABLED)) return 0;
-         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 ((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");
@@ -676,8 +831,13 @@ co_UserSetFocus(PWND Window)
       if (pwndTop != ThreadQueue->spwndActive)
       {
          PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Keep it based on desktop.
-         if (ThreadQueue != ForegroundQueue) // HACK see rule 2 & 3.
+         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");
@@ -688,7 +848,8 @@ co_UserSetFocus(PWND Window)
          /* Set Active when it is needed. */
          if (pwndTop != ThreadQueue->spwndActive)
          {
-            if (!co_IntSetActiveWindow(pwndTop, NULL, FALSE, FALSE, FALSE))
+            //ERR("SetFocus: Set Active!\n");
+            if (!co_IntSetActiveWindow(pwndTop, FALSE, FALSE, FALSE))
             {
                ERR("SetFocus: Set Active Failed!\n");
                return 0;
@@ -710,12 +871,10 @@ co_UserSetFocus(PWND Window)
 
       IntSendFocusMessages( pti, Window);
 
-      TRACE("Focus: %d -> %d\n", hWndPrev, Window->head.h);
+      TRACE("Focus: %p -> %p\n", hWndPrev, Window->head.h);
    }
    else /* NULL hwnd passed in */
    {
-//      if (!hWndPrev) return 0; /* nothing to do */
-
       if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
       {
          ERR("SetFocus: 2 WH_CBT Call Hook return!\n");
@@ -761,7 +920,7 @@ IntGetCapture(VOID)
    RETURN( ThreadQueue ? (ThreadQueue->spwndCapture ? UserHMGetHandle(ThreadQueue->spwndCapture) : 0) : 0);
 
 CLEANUP:
-   TRACE("Leave IntGetCapture, ret=%i\n",_ret_);
+   TRACE("Leave IntGetCapture, ret=%p\n", _ret_);
    END_CLEANUP;
 }
 
@@ -787,7 +946,7 @@ co_UserSetCapture(HWND hWnd)
       }
    }
 
-   hWndPrev = MsqSetStateWindow(ThreadQueue, MSQ_STATE_CAPTURE, hWnd);
+   hWndPrev = MsqSetStateWindow(pti, MSQ_STATE_CAPTURE, hWnd);
 
    if (hWndPrev)
    {
@@ -803,7 +962,8 @@ co_UserSetCapture(HWND hWnd)
    {
       if (ThreadQueue->MenuOwner && Window) ThreadQueue->QF_flags |= QF_CAPTURELOCKED;
 
-      co_IntPostOrSendMessage(hWndPrev, WM_CAPTURECHANGED, 0, (LPARAM)hWnd);
+      //co_IntPostOrSendMessage(hWndPrev, WM_CAPTURECHANGED, 0, (LPARAM)hWnd);
+      co_IntSendMessage(hWndPrev, WM_CAPTURECHANGED, 0, (LPARAM)hWnd);
 
       ThreadQueue->QF_flags &= ~QF_CAPTURELOCKED;
    }
@@ -815,8 +975,8 @@ co_UserSetCapture(HWND hWnd)
       MOUSEINPUT mi;
    /// These are HACKS!
       /* Also remove other windows if not capturing anymore */
-      MsqSetStateWindow(ThreadQueue, MSQ_STATE_MENUOWNER, NULL);
-      MsqSetStateWindow(ThreadQueue, MSQ_STATE_MOVESIZE, NULL);
+      MsqSetStateWindow(pti, MSQ_STATE_MENUOWNER, NULL);
+      MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, NULL);
    ///
       /* Somebody may have missed some mouse movements */
       mi.dx = 0;
@@ -857,7 +1017,7 @@ IntReleaseCapture(VOID)
 BOOL FASTCALL
 co_IntSetForegroundWindow(PWND Window)
 {
-   ASSERT_REFS_CO(Window);
+   if (Window) ASSERT_REFS_CO(Window);
 
    return co_IntSetForegroundAndFocusWindow(Window, FALSE);
 }
@@ -937,12 +1097,13 @@ IntAllowSetForegroundWindow(DWORD dwProcessId)
    }
    if (dwProcessId == ASFW_ANY)
    {  // All processes will be enabled to set the foreground window.
+      //ERR("ptiLastInput is CLEARED!!\n");
       ptiLastInput = NULL;
    }
    else
    {  // Rule #3, last input event in force.
-      ERR("Fixme: ptiLastInput is SET!!\n");
-      //ptiLastInput = ppi->ptiList;
+      ERR("ptiLastInput is SET!!\n");
+      //ptiLastInput = ppi->ptiList; // See CORE-6384 & CORE-7030.
       ObDereferenceObject(Process);
    }
    return TRUE;
@@ -962,7 +1123,7 @@ NtUserGetForegroundWindow(VOID)
    RETURN( UserGetForegroundWindow());
 
 CLEANUP:
-   TRACE("Leave NtUserGetForegroundWindow, ret=%i\n",_ret_);
+   TRACE("Leave NtUserGetForegroundWindow, ret=%p\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -975,7 +1136,7 @@ NtUserSetActiveWindow(HWND hWnd)
    PWND Window;
    DECLARE_RETURN(HWND);
 
-   TRACE("Enter NtUserSetActiveWindow(%x)\n", hWnd);
+   TRACE("Enter NtUserSetActiveWindow(%p)\n", hWnd);
    UserEnterExclusive();
 
    Window = NULL;
@@ -993,7 +1154,7 @@ NtUserSetActiveWindow(HWND hWnd)
    {
       hWndPrev = gptiCurrent->MessageQueue->spwndActive ? UserHMGetHandle(gptiCurrent->MessageQueue->spwndActive) : NULL;
       if (Window) UserRefObjectCo(Window, &Ref);
-      co_IntSetActiveWindow(Window, NULL, FALSE, TRUE, FALSE);
+      UserSetActiveWindow(Window);
       if (Window) UserDerefObjectCo(Window);
       RETURN( hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0 );
    }
@@ -1013,13 +1174,13 @@ NtUserSetCapture(HWND hWnd)
 {
    DECLARE_RETURN(HWND);
 
-   TRACE("Enter NtUserSetCapture(%x)\n", hWnd);
+   TRACE("Enter NtUserSetCapture(%p)\n", hWnd);
    UserEnterExclusive();
 
    RETURN( co_UserSetCapture(hWnd));
 
 CLEANUP:
-   TRACE("Leave NtUserSetCapture, ret=%i\n",_ret_);
+   TRACE("Leave NtUserSetCapture, ret=%p\n", _ret_);
    UserLeave();
    END_CLEANUP;
 }
@@ -1035,7 +1196,7 @@ NtUserSetFocus(HWND hWnd)
    DECLARE_RETURN(HWND);
    HWND ret;
 
-   TRACE("Enter NtUserSetFocus(%x)\n", hWnd);
+   TRACE("Enter NtUserSetFocus(%p)\n", hWnd);
    UserEnterExclusive();
 
    if (hWnd)