Exemple #1
0
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;
}
Exemple #2
0
BOOL FASTCALL
co_IntSetActiveWindow(PWND Wnd OPTIONAL, BOOL bMouse, BOOL bFocus, BOOL Async)
{
   PTHREADINFO pti;
   PUSER_MESSAGE_QUEUE ThreadQueue;
   PWND pWndChg, WndPrev; // State changes.
   HWND hWndPrev;
   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;

   pWndChg = ThreadQueue->spwndActive; // Keep to notify of a preemptive switch.

   while (Wnd)
   {
      BOOL Ret, DoFG, AllowFG;

      if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE;

      if (ThreadQueue == Wnd->head.pti->MessageQueue)
      {
         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 (!gpqForeground || gpqForeground == ThreadQueue)
         {
            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);
      }
      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 */
   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 FALSE;
   }

   if ( ThreadQueue->spwndActive && ThreadQueue->spwndActive->state & WNDS_DESTROYED )
      ThreadQueue->spwndActive = NULL;
   else
      ThreadQueue->spwndActivePrev = ThreadQueue->spwndActive;

   WndPrev = ThreadQueue->spwndActive; // Keep to save changing active.

   if (WndPrev)
   {
      if (ThreadQueue == gpqForeground) gpqForegroundPrev = ThreadQueue;
      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 != WndPrev ||
        (Wnd && !VerifyWnd(Wnd)) ||
        ThreadQueue != pti->MessageQueue )
   {
      ERR("SetActiveWindow: Summary ERROR, active state changed!\n");
      return FALSE;
   }

   if (!WndPrev) ThreadQueue->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE;

   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)
   {
      /* set the current thread active window */
      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 */
   //// Fixes CORE-6452 allows setting focus on window.
   if (bFocus && !(ThreadQueue->QF_flags & QF_FOCUSNULLSINCEACTIVE))
   {
      /* Do not change focus if the window is no longer active */
      if (pti->MessageQueue->spwndActive != IntGetNonChildAncestor(pti->MessageQueue->spwndFocus))
      {
         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;
   }

   // 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);
}