[Win32k]
[reactos.git] / reactos / win32ss / user / ntuser / focus.c
index 8529f05..65ebe51 100644 (file)
@@ -84,6 +84,7 @@ 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)))
    { 
@@ -127,6 +128,8 @@ co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate)
 
       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);
 
@@ -136,27 +139,26 @@ co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate)
          HWND *List, *phWnd;
 
          List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow()));
-         if (List)
+         if ( List )
          {
-            if (OldTID)
+            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)
+            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);
@@ -227,6 +229,38 @@ IntFindChildWindowToOwner(PWND Root, PWND Owner)
    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.
  */
@@ -305,10 +339,17 @@ co_IntSetForegroundAndFocusWindow(PWND Wnd, BOOL MouseActivate)
    { 
       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;
-   }
+   } 
 
-//// Fix FG Bounce with regedit but breaks test_SFW todos 
+   //  Fix FG Bounce with regedit.
    if (hWndPrev != hWnd )
    {
       if (PrevForegroundQueue &&
@@ -316,6 +357,13 @@ co_IntSetForegroundAndFocusWindow(PWND Wnd, BOOL MouseActivate)
           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 );
       }
    }
@@ -547,8 +595,11 @@ co_UserSetFocus(PWND Window)
          }
       }
 
+      // 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 ( !Window || ThreadQueue == Window->head.pti->MessageQueue)
+      if (ThreadQueue == Window->head.pti->MessageQueue)
          /* set the current thread focus window */
          ThreadQueue->spwndFocus = Window;