Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

focusact.c File Reference

#include "precomp.h"

Go to the source code of this file.

Functions

BOOL RemoveEventMessage (PQ pq, DWORD dwQEvent, DWORD dwQEventStop)
void xxxDeactivate (PTHREADINFO pti, DWORD tidSetForeground)
void xxxSendFocusMessages (PTHREADINFO pti, PWND pwndReceive)
BOOL xxxActivateApp (PWND pwnd, AAS *paas)
BOOL FBadWindow (PWND pwnd)
void xxxUpdateTray (PWND pwnd)
BOOL xxxActivateThisWindow (PWND pwnd, DWORD tidLoseForeground, DWORD fFlags)
BOOL CanForceForeground (PPROCESSINFO ppi)
BOOL xxxAllowSetForegroundWindow (DWORD dwProcessId)
BOOL _LockSetForegroundWindow (UINT uLockCode)
void CleanupDecSFWLockCount (PVOID pIgnore)
BOOL xxxStubSetForegroundWindow (PWND pwnd)
BOOL xxxSetForegroundWindow (PWND pwnd, BOOL fFlash)
BOOL xxxSetForegroundWindow2 (PWND pwnd, PTHREADINFO pti, DWORD fFlags)
BOOL FRemoveForegroundActivate (PTHREADINFO pti)
BOOL FAllowForegroundActivate (PQ pq, PWND pwnd)
PWND xxxSetFocus (PWND pwnd)
PWND xxxSetActiveWindow (PWND pwnd)
BOOL xxxActivateWindow (PWND pwnd, UINT cmd)
PWND GNT_NextTopScan (PTHREADINFO pti, PWND pwnd, PWND pwndOwner)
PWND NTW_GetNextTop (PTHREADINFO pti, PWND pwnd)
PWND NTW_GetPrevTop (PTHREADINFO pti, PWND pwndCurrent)
PWND CheckTopLevelOnly (PWND pwnd)
PWND NextTopWindow (PTHREADINFO pti, PWND pwnd, PWND pwndSkip, DWORD flags)
void xxxCheckFocus (PWND pwnd)
VOID SetForegroundThread (PTHREADINFO pti)
VOID SetForegroundPriorityProcess (PPROCESSINFO ppi, PTHREADINFO pti, BOOL fSetForeground)
VOID SetForegroundPriority (PTHREADINFO pti, BOOL fSetForeground)


Function Documentation

BOOL _LockSetForegroundWindow UINT  uLockCode  ) 
 

Definition at line 1167 of file focusact.c.

References BOOL, CanForceForeground(), DWORD, FALSE, gppiLockSFW, NULL, PpiCurrent, and TRUE.

01169 { 01170 DWORD dwError; 01171 PPROCESSINFO ppiCurrent = PpiCurrent(); 01172 01173 switch (uLockCode) { 01174 case LSFW_LOCK: 01175 /* 01176 * If the caller cannot lock it or already locked, fail the call 01177 */ 01178 if (CanForceForeground(ppiCurrent) && (gppiLockSFW == NULL)) { 01179 gppiLockSFW = ppiCurrent; 01180 TAGMSG1(DBGTAG_FOREGROUND, "_LockSetForegroundWindow locked by %#p", ppiCurrent); 01181 } else { 01182 dwError = ERROR_ACCESS_DENIED; 01183 goto FailIt; 01184 } 01185 break; 01186 01187 case LSFW_UNLOCK: 01188 /* 01189 * If the caller didn't lock it, fail the call 01190 */ 01191 if (ppiCurrent == gppiLockSFW) { 01192 gppiLockSFW = NULL; 01193 TAGMSG0(DBGTAG_FOREGROUND, "_LockSetForegroundWindow UNLOCKED"); 01194 } else { 01195 dwError = ERROR_ACCESS_DENIED; 01196 goto FailIt; 01197 } 01198 break; 01199 01200 default: 01201 dwError = ERROR_INVALID_PARAMETER; 01202 goto FailIt; 01203 } 01204 01205 return TRUE; 01206 01207 FailIt: 01208 RIPERR0(dwError, RIP_VERBOSE, ""); 01209 return FALSE; 01210 }

BOOL CanForceForeground PPROCESSINFO  ppi  ) 
 

Definition at line 1056 of file focusact.c.

References BOOL, FALSE, glinp, gppiInputProvider, gpqForeground, gptiForeground, IsTimeFromLastRITEvent(), NULL, tagTHREADINFO::ppi, tagLASTINPUT::ptiLastWoken, TRUE, UP, and W32PF_ALLOWSETFOREGROUND.

Referenced by _LockSetForegroundWindow(), CheckAllowForeground(), NtUserSystemParametersInfo(), xxxAllowSetForegroundWindow(), xxxHardErrorControl(), xxxSendBSMtoDesktop(), and xxxSetForegroundWindow().

01057 { 01058 01059 if ((glinp.ptiLastWoken != NULL) 01060 && (glinp.ptiLastWoken->ppi != ppi) 01061 && (gptiForeground != NULL) 01062 && (gptiForeground->ppi != ppi) 01063 && !(ppi->W32PF_Flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_ALLOWSETFOREGROUND)) 01064 && (ppi != gppiInputProvider) 01065 && (gpqForeground != NULL) 01066 && 01067 #if DBG 01068 /* 01069 * When attaching the debugger to the foreground app, this function always 01070 * returns TRUE. In order to be able to debug anything related to this 01071 * function in such case, set this global to TRUE. 01072 */ 01073 (gfDebugForegroundIgnoreDebugPort 01074 || ( 01075 #endif 01076 (glinp.ptiLastWoken->ppi->Process->DebugPort == NULL) 01077 && (gptiForeground->ppi->Process->DebugPort == NULL) 01078 #if DBG 01079 )) 01080 #endif 01081 && !IsTimeFromLastRITEvent(UP(FOREGROUNDLOCKTIMEOUT))) { 01082 01083 return FALSE; 01084 } else { 01085 return TRUE; 01086 } 01087 01088 }

PWND CheckTopLevelOnly PWND  pwnd  ) 
 

Definition at line 2416 of file focusact.c.

References FNID_DESKTOP, GETFNID, NULL, and tagWND::spwndChild.

Referenced by NextTopWindow().

02418 { 02419 /* 02420 * fnid == -1 means this is a desktop window - find the first child 02421 * of this desktop, if it is one. 02422 */ 02423 while (pwnd != NULL && GETFNID(pwnd) == FNID_DESKTOP) { 02424 pwnd = pwnd->spwndChild; 02425 } 02426 02427 return pwnd; 02428 }

void CleanupDecSFWLockCount PVOID  pIgnore  ) 
 

Definition at line 1218 of file focusact.c.

References DecSFWLockCount().

01219 { 01220 DecSFWLockCount(); 01221 UNREFERENCED_PARAMETER(pIgnore); 01222 }

BOOL FAllowForegroundActivate PQ  pq,
PWND  pwnd
 

Definition at line 1761 of file focusact.c.

References BOOL, FALSE, FRemoveForegroundActivate(), gpqForeground, grpdeskRitInput, IsForegroundLocked(), NULL, PtiCurrent, tagTHREADINFO::rpdesk, TestWF, TestwndChild, TRUE, and WEFNOACTIVATE.

Referenced by xxxActivateWindow(), and xxxSetFocus().

01764 { 01765 PTHREADINFO ptiCurrent = PtiCurrent(); 01766 UserAssert(pwnd != NULL); 01767 /* 01768 * Bail if this guy doesn't have the foreground activate right. 01769 */ 01770 TAGMSG1(DBGTAG_FOREGROUND, "FAllowForegroundActivate FRemoveForegroundActivate %#p", ptiCurrent); 01771 if (!FRemoveForegroundActivate(ptiCurrent)) { 01772 return FALSE; 01773 } 01774 /* 01775 * Don't try to foreground activate if: 01776 * we're not on the right desktop. 01777 * we're already in the foreground 01778 * the foreground is locked 01779 * It'll fail in SetForegroundWindow2() anyway. This way 01780 * ActivateWindow() will still locally activate the window. 01781 */ 01782 if ((ptiCurrent->rpdesk != grpdeskRitInput) 01783 || (gpqForeground == pq) 01784 || IsForegroundLocked()) { 01785 TAGMSG0(DBGTAG_FOREGROUND, "FAllowForegroundActivate FALSE due to addtional checks"); 01786 return FALSE; 01787 } 01788 /* 01789 * noactivate windows cannot take the foreground unless explicitly requested. 01790 * Note that windows passed to this function are expected to be toplevel, which is 01791 * where this style has meaning. This might not be the case if AW_SKIP picked an 01792 * owner window which is not top level. Since noactivate doesn't apply to the owner 01793 * chain, it's OK to ignore this. 01794 */ 01795 #if DBG 01796 if (TestwndChild(pwnd)) { 01797 RIPMSG1(RIP_WARNING, "FAllowForegroundActivate pwnd %#p is not top level", pwnd); 01798 } 01799 #endif 01800 if (TestWF(pwnd, WEFNOACTIVATE)) { 01801 TAGMSG1(DBGTAG_FOREGROUND, "FAllowForegroundActivate noactivate window:%#p", pwnd); 01802 return FALSE; 01803 } 01804 01805 return TRUE; 01806 }

BOOL FBadWindow PWND  pwnd  ) 
 

Definition at line 365 of file focusact.c.

References BOOL, NULL, TestWF, WFDISABLED, and WFVISIBLE.

Referenced by xxxActivateWindow(), and xxxMenuWindowProc().

00367 { 00368 return (pwnd == NULL 00369 || !TestWF(pwnd, WFVISIBLE) 00370 || TestWF(pwnd, WFDISABLED)); 00371 }

BOOL FRemoveForegroundActivate PTHREADINFO  pti  ) 
 

Definition at line 1717 of file focusact.c.

References BOOL, ClearAppStarting(), tagTHREADINFO::ppi, TIF_ALLOWFOREGROUNDACTIVATE, and tagTHREADINFO::TIF_flags.

Referenced by FAllowForegroundActivate(), and xxxSetForegroundWindow().

01718 { 01719 BOOL fRemoved; 01720 PPROCESSINFO ppi; 01721 /* 01722 * W32PF_APPSTARTING gets turned off the first activate this process does. 01723 * We assume it's ready now for action. 01724 */ 01725 ppi = pti->ppi; 01726 if (ppi->W32PF_Flags & W32PF_APPSTARTING) { 01727 ClearAppStarting(ppi); 01728 } 01729 01730 /* 01731 * Remove the right if present. 01732 */ 01733 fRemoved = (pti->TIF_flags & TIF_ALLOWFOREGROUNDACTIVATE); 01734 if (fRemoved) { 01735 pti->TIF_flags &= ~TIF_ALLOWFOREGROUNDACTIVATE ; 01736 TAGMSG1(DBGTAG_FOREGROUND, "FRemoveForegroundActivate clear TIF %#p", pti); 01737 } else { 01738 fRemoved = (ppi->W32PF_Flags & W32PF_ALLOWFOREGROUNDACTIVATE); 01739 } 01740 if (fRemoved) { 01741 ppi->W32PF_Flags &= ~W32PF_ALLOWFOREGROUNDACTIVATE; 01742 TAGMSG1(DBGTAG_FOREGROUND, "FRemoveForegroundActivate clear W32PF %#p", ppi); 01743 } 01744 01745 return fRemoved; 01746 01747 }

PWND GNT_NextTopScan PTHREADINFO  pti,
PWND  pwnd,
PWND  pwndOwner
 

Definition at line 2300 of file focusact.c.

References DF_DESKWNDDESTROYED, tagDESKTOP::dwDTFlags, NULL, tagDESKTOP::pDeskInfo, tagTHREADINFO::rpdesk, tagDESKTOPINFO::spwnd, tagWND::spwndChild, tagWND::spwndNext, and tagWND::spwndOwner.

Referenced by NextTopWindow(), and NTW_GetNextTop().

02304 { 02305 if (pwnd == NULL) { 02306 UserAssert(pti->rpdesk != NULL && 02307 (pti->rpdesk->dwDTFlags & DF_DESKWNDDESTROYED) == 0); 02308 pwnd = pti->rpdesk->pDeskInfo->spwnd->spwndChild; 02309 } else { 02310 pwnd = pwnd->spwndNext; 02311 } 02312 02313 for (; pwnd != NULL; pwnd = pwnd->spwndNext) { 02314 if (pwnd->spwndOwner == pwndOwner) 02315 break; 02316 } 02317 02318 return pwnd; 02319 }

PWND NextTopWindow PTHREADINFO  pti,
PWND  pwnd,
PWND  pwndSkip,
DWORD  flags
 

Definition at line 2431 of file focusact.c.

References BOOL, CheckTopLevelOnly(), FALSE, GNT_NextTopScan(), NTW_GetNextTop(), NTW_GetPrevTop(), NTW_IGNORETOOLWINDOW, NTW_PREVIOUS, NULL, PWNDDESKTOP, TestWF, TRUE, WEFNOACTIVATE, WEFTOOLWINDOW, WFDISABLED, and WFVISIBLE.

Referenced by IsTopmostRealApp(), xxxActivateWindow(), xxxMenuWindowProc(), xxxNextWindow(), and xxxOldNextWindow().

02436 { 02437 BOOL fFoundFirstUnowned; 02438 PWND pwndPrev; 02439 PWND pwndStart = pwnd; 02440 PWND pwndFirstUnowned; 02441 02442 /* 02443 * If the search gets to the first unowned window TWICE (See NTW_GetNextTop), 02444 * we couldn't find a window 02445 */ 02446 pwndFirstUnowned = GNT_NextTopScan(pti, NULL, NULL); 02447 fFoundFirstUnowned = FALSE; 02448 02449 if (pwnd == NULL) { 02450 pwnd = NTW_GetNextTop(pti, NULL); 02451 02452 /* 02453 * Don't allow desktop windows. 02454 */ 02455 pwnd = pwndStart = CheckTopLevelOnly(pwnd); 02456 02457 if (pwnd == NULL) 02458 return NULL; // No more windows owned by the thread 02459 02460 goto Loop; 02461 } 02462 02463 /* 02464 * Don't allow desktop windows. 02465 */ 02466 pwnd = pwndStart = CheckTopLevelOnly(pwnd); 02467 if (pwnd == NULL) 02468 return NULL; // No more windows owned by this thread 02469 02470 /* 02471 * Don't allow desktop windows. 02472 */ 02473 pwndSkip = CheckTopLevelOnly(pwndSkip); 02474 02475 02476 02477 while (TRUE) { 02478 pwndPrev = pwnd; 02479 pwnd = ((flags & NTW_PREVIOUS) ? NTW_GetPrevTop(pti, pwnd) : NTW_GetNextTop(pti, pwnd)); 02480 02481 /* 02482 * If we've cycled to where we started, couldn't find one: return NULL 02483 */ 02484 if (pwnd == pwndStart) 02485 break; 02486 02487 if (pwnd == pwndFirstUnowned) { 02488 if (fFoundFirstUnowned) { 02489 break; 02490 } else { 02491 fFoundFirstUnowned = TRUE; 02492 } 02493 } 02494 02495 if (pwnd == NULL) 02496 break; 02497 02498 /* 02499 * If we've cycled over desktops, then return NULL because we'll 02500 * never hit pwndStart. 02501 */ 02502 if (PWNDDESKTOP(pwndStart) != PWNDDESKTOP(pwnd)) 02503 break; 02504 02505 /* 02506 * going nowhere is a bad sign. 02507 */ 02508 if (pwndPrev == pwnd) { 02509 /* 02510 * This is a temporary fix chosen because its safe. This case 02511 * was hit when a window failed the NCCREATE message and fell 02512 * into xxxFreeWindow and left the critical section after being 02513 * unlinked. The app then died and entered cleanup code and 02514 * tried to destroy this window again. 02515 */ 02516 break; 02517 } 02518 02519 Loop: 02520 if (pwnd == pwndSkip) 02521 continue; 02522 02523 /* 02524 * If it's visible, not disabled, not a noactivate window 02525 * and either we're not ignoringtool windows or it's not a 02526 * tool window, then we've got it. 02527 */ 02528 if (TestWF(pwnd, WFVISIBLE) && 02529 !TestWF(pwnd, WFDISABLED) && 02530 !TestWF(pwnd, WEFNOACTIVATE) && 02531 (!(flags & NTW_IGNORETOOLWINDOW) || !TestWF(pwnd, WEFTOOLWINDOW))) { 02532 02533 return pwnd; 02534 } 02535 } 02536 02537 return NULL; 02538 }

PWND NTW_GetNextTop PTHREADINFO  pti,
PWND  pwnd
 

Definition at line 2332 of file focusact.c.

References GNT_NextTopScan(), NULL, and tagWND::spwndOwner.

Referenced by NextTopWindow(), and NTW_GetPrevTop().

02335 { 02336 PWND pwndOwner; 02337 02338 if (pwnd == NULL) { 02339 goto ReturnFirst; 02340 } 02341 02342 /* 02343 * First look for any windows owned by this window 02344 * If that fails, then go up one level to our owner, 02345 * and look for next window owned by his owner. 02346 * This results in a depth-first ordering of the windows. 02347 */ 02348 02349 pwndOwner = pwnd; 02350 pwnd = NULL; 02351 02352 do { 02353 if ((pwnd = GNT_NextTopScan(pti, pwnd, pwndOwner)) != NULL) { 02354 return pwnd; 02355 } 02356 02357 pwnd = pwndOwner; 02358 if (pwnd != NULL) 02359 pwndOwner = pwnd->spwndOwner; 02360 02361 } while (pwnd != NULL); 02362 02363 ReturnFirst: 02364 02365 /* 02366 * If no more windows to enumerate, return the first unowned window. 02367 */ 02368 return GNT_NextTopScan(pti, NULL, NULL); 02369 }

PWND NTW_GetPrevTop PTHREADINFO  pti,
PWND  pwndCurrent
 

Definition at line 2382 of file focusact.c.

References NTW_GetNextTop(), and NULL.

Referenced by NextTopWindow().

02385 { 02386 PWND pwnd; 02387 PWND pwndPrev; 02388 02389 /* 02390 * Starting from beginning, loop thru the windows, saving the previous 02391 * one, until we find the window we're currently at. 02392 */ 02393 pwndPrev = NULL; 02394 02395 do { 02396 pwnd = NTW_GetNextTop(pti, pwndPrev); 02397 if (pwnd == pwndCurrent && pwndPrev != NULL) { 02398 break; 02399 } 02400 } while ((pwndPrev = pwnd) != NULL); 02401 02402 return pwndPrev; 02403 }

BOOL RemoveEventMessage PQ  pq,
DWORD  dwQEvent,
DWORD  dwQEventStop
 

Definition at line 1004 of file focusact.c.

References BOOL, DelQEntry(), tagQMSG::dwQEvent, FALSE, tagQ::idSysPeek, tagQ::mlInput, NULL, tagQMSG::pqmsgPrev, tagMLIST::pqmsgWriteLast, and TRUE.

Referenced by xxxActivateThisWindow(), and xxxSetForegroundWindow2().

01008 { 01009 PQMSG pqmsgT; 01010 PQMSG pqmsgPrev; 01011 BOOL bRemovedEvent = FALSE; 01012 01013 /* 01014 * Remove all events dwQEvent until finding dwQEventStop. 01015 */ 01016 for (pqmsgT = pq->mlInput.pqmsgWriteLast; pqmsgT != NULL; ) { 01017 01018 if (pqmsgT->dwQEvent == dwQEventStop) 01019 return(bRemovedEvent); 01020 01021 pqmsgPrev = pqmsgT->pqmsgPrev; 01022 01023 /* 01024 * If the event is found and is not the one being peeked, 01025 * delete it. 01026 */ 01027 if (pqmsgT->dwQEvent == dwQEvent && 01028 pqmsgT != (PQMSG)pq->idSysPeek) { 01029 DelQEntry(&(pq->mlInput), pqmsgT); 01030 bRemovedEvent = TRUE; 01031 } 01032 pqmsgT = pqmsgPrev; 01033 } 01034 return(bRemovedEvent); 01035 }

VOID SetForegroundPriority PTHREADINFO  pti,
BOOL  fSetForeground
 

Definition at line 2708 of file focusact.c.

References NULL, tagTHREADINFO::ppi, SetForegroundPriorityProcess(), TIF_CSRSSTHREAD, tagTHREADINFO::TIF_flags, TIF_SYSTEMTHREAD, and VOID().

Referenced by CheckProcessForeground(), NtUserYieldTask(), SetForegroundThread(), SetWakeBit(), xxxCreateThreadInfo(), xxxInternalGetMessage(), and xxxMoveSize().

02711 { 02712 UserAssert(pti != NULL); 02713 02714 /* 02715 * We don't want to change the priority of system or console threads 02716 */ 02717 if (pti->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD)) 02718 return; 02719 02720 SetForegroundPriorityProcess(pti->ppi, pti, fSetForeground); 02721 }

VOID SetForegroundPriorityProcess PPROCESSINFO  ppi,
PTHREADINFO  pti,
BOOL  fSetForeground
 

Definition at line 2648 of file focusact.c.

References FALSE, gppiForegroundOld, gppiScreenSaver, NULL, _EPROCESS::PriorityClass, PsProcessPriorityBackground, PsProcessPriorityForeground, PsProcessPrioritySpinning, PsSetProcessPriorityByClass(), tagTHREADINFO::TIF_flags, TIF_GLOBALHOOKER, and VOID().

Referenced by IdleTimerProc(), SetForegroundPriority(), and xxxActivateThisWindow().

02652 { 02653 PEPROCESS Process; 02654 UCHAR PriorityClassSave; 02655 02656 UserAssert(ppi != NULL); 02657 02658 Process = ppi->Process; 02659 UserAssert(ppi->Process != NULL); 02660 02661 if (ppi->W32PF_Flags & W32PF_IDLESCREENSAVER) { 02662 fSetForeground = FALSE; 02663 PriorityClassSave = Process->PriorityClass; 02664 Process->PriorityClass = PROCESS_PRIORITY_CLASS_IDLE; 02665 } 02666 02667 /* 02668 * If we previously delayed setting some process to the background 02669 * because a screen saver was starting up, do it now. 02670 */ 02671 if (gppiForegroundOld != NULL) { 02672 if (gppiForegroundOld == ppi) { 02673 gppiForegroundOld = NULL; 02674 } else if (ppi != gppiScreenSaver) { 02675 PsSetProcessPriorityByClass(gppiForegroundOld->Process, PsProcessPriorityBackground); 02676 gppiForegroundOld = NULL; 02677 } 02678 } 02679 02680 /* 02681 * If this app should be background, don't let it go foreground. 02682 * Foreground apps run at a higher base priority. 02683 */ 02684 if (ppi->W32PF_Flags & W32PF_FORCEBACKGROUNDPRIORITY) { 02685 if (pti != NULL && !(pti->TIF_flags & TIF_GLOBALHOOKER)) { 02686 PsSetProcessPriorityByClass(Process, PsProcessPrioritySpinning); 02687 } 02688 } else if (fSetForeground) { 02689 PsSetProcessPriorityByClass(Process, PsProcessPriorityForeground); 02690 } else if (pti != NULL && !(pti->TIF_flags & TIF_GLOBALHOOKER)) { 02691 /* 02692 * Don't adjust the priority of the current foreground process if 02693 * the new foreground process is a screen saver. 02694 */ 02695 if (gppiScreenSaver && gppiScreenSaver != ppi) { 02696 gppiForegroundOld = ppi; 02697 } else { 02698 PsSetProcessPriorityByClass(Process, PsProcessPriorityBackground); 02699 } 02700 } 02701 02702 if (ppi->W32PF_Flags & W32PF_IDLESCREENSAVER) { 02703 Process->PriorityClass = PriorityClassSave; 02704 } 02705 }

VOID SetForegroundThread PTHREADINFO  pti  ) 
 

Definition at line 2588 of file focusact.c.

References CBKEYSTATERECENTDOWN, ChangeForegroundKeyboardTable(), FALSE, gafAsyncKeyStateRecentDown, gpqForeground, gpsi, gptiForeground, gptiRit, NULL, tagTHREADINFO::ppi, tagTHREADINFO::pq, SetForegroundPriority(), tagTHREADINFO::spklActive, TRUE, and VOID().

Referenced by xxxDestroyThreadInfo(), xxxSendFocusMessages(), and xxxSetForegroundWindow2().

02590 { 02591 PKL pklPrev; 02592 02593 if (pti == gptiForeground) 02594 return; 02595 02596 /* 02597 * The foregorund thread must be on the foreground queue. 02598 * xxxSendFocusMessages obtains this pti from a window 02599 * received as a parameter. If the owner of the window 02600 * exited during a callback (in the caller), then the pti 02601 * will be gptiRit,which might not be in the foreground queue 02602 */ 02603 UserAssert((pti == NULL) 02604 || (pti->pq == gpqForeground) 02605 || (pti == gptiRit)); 02606 02607 /* 02608 * If we're changing gptiForeground to another process, 02609 * change the base priorities of the two processes. We 02610 * know that if either 'pti' or 'gptiForeground' is NULL 02611 * that both aren't NULL due to the first test in this 02612 * function. 02613 */ 02614 if ((pti == NULL) || (gptiForeground == NULL) || 02615 (pti->ppi != gptiForeground->ppi)) { 02616 if (gptiForeground != NULL) { 02617 gptiForeground->ppi->W32PF_Flags &= ~W32PF_FORCEBACKGROUNDPRIORITY; 02618 SetForegroundPriority(gptiForeground, FALSE); 02619 } 02620 02621 if (pti != NULL) { 02622 SetForegroundPriority(pti, TRUE); 02623 } 02624 } 02625 02626 if (gptiForeground) { 02627 pklPrev = gptiForeground->spklActive; 02628 } else { 02629 pklPrev = NULL; 02630 } 02631 gptiForeground = pti; 02632 if (gptiForeground && gptiForeground->spklActive) { 02633 ChangeForegroundKeyboardTable(pklPrev, gptiForeground->spklActive); 02634 } 02635 02636 /* 02637 * Clear recent down information in the async key state to prevent 02638 * spying by apps. 02639 */ 02640 RtlZeroMemory(gafAsyncKeyStateRecentDown, CBKEYSTATERECENTDOWN); 02641 02642 /* 02643 * Update the async key cache index. 02644 */ 02645 gpsi->dwAsyncKeyCache++; 02646 }

BOOL xxxActivateApp PWND  pwnd,
AAS paas
 

Definition at line 336 of file focusact.c.

References BOOL, CheckLock, tagAAS::fActivating, tagAAS::fQueueNotify, GETPTI, tagAAS::ptiNotify, QueueNotifyMessage(), tagAAS::tidActDeact, TRUE, and xxxSendMessage().

Referenced by CancelInputState(), xxxActivateThisWindow(), and xxxDeactivate().

00339 { 00340 CheckLock(pwnd); 00341 00342 if (GETPTI(pwnd) == paas->ptiNotify) { 00343 00344 if (paas->fQueueNotify) { 00345 QueueNotifyMessage(pwnd, WM_ACTIVATEAPP, paas->fActivating, 00346 paas->tidActDeact); 00347 } else { 00348 xxxSendMessage(pwnd, WM_ACTIVATEAPP, paas->fActivating, 00349 paas->tidActDeact); 00350 } 00351 } 00352 00353 return TRUE; 00354 }

BOOL xxxActivateThisWindow PWND  pwnd,
DWORD  tidLoseForeground,
DWORD  fFlags
 

Definition at line 472 of file focusact.c.

References ATW_ASYNC, ATW_MOUSE, ATW_NOZORDER, ATW_SETFOCUS, BOOL, BWL_ENUMLIST, CheckLock, ClrWF, dwFlags, DWORD, tagAAS::fActivating, FALSE, tagAAS::fQueueNotify, FWINABLE, GETPTI, GetTopLevelWindow(), glinp, gppiScreenSaver, gpqForeground, gpqForegroundPrev, grpdeskRitInput, tagWND::head, HMIsMarkDestroy, HW, HWq, IsHooked, IsVisible(), Lock, NtGetTickCount(), NULL, tagDESKTOP::pDeskInfo, tagTHREADINFO::pq, PtiCurrent, tagPROCESSINFO::ptiMainThread, tagAAS::ptiNotify, PUSIF_PALETTEDISPLAY, PWND_BROADCAST, PWND_TOP, PWNDDESKTOP, QEVENT_ACTIVATE, QEVENT_DEACTIVATE, QF_ACTIVATIONCHANGE, QF_EVENTDEACTIVATEREMOVED, tagQ::QF_flags, QF_FOCUSNULLSINCEACTIVE, RemoveEventMessage(), tagTHREADINFO::rpdesk, tagPROCESSINFO::rpdeskStartup, SetForegroundPriorityProcess(), SetWF, tagDESKTOPINFO::spwnd, tagQ::spwndActive, tagQ::spwndActivePrev, tagWND::spwndChild, tagQ::spwndFocus, tagWND::spwndLastActive, tagWND::spwndNext, tagWND::spwndOwner, TEST_PUSIF, TestWF, ThreadLockPti, ThreadLockWithPti, ThreadUnlock, ThreadUnlockPti, tagAAS::tidActDeact, TIDq, tagTHREADINFO::TIF_flags, TIF_INACTIVATEAPPMSG, tagLASTINPUT::timeLastInputMessage, TRUE, WEF_USEPWNDTHREAD, WFBEINGACTIVATED, WFCHILD, WFDESTROYED, WFFRAMEON, WFMINIMIZED, WFNONCPAINT, WFVISIBLE, WHF_CBT, WNDENUMPROC_PWND, xxxActivateApp(), xxxCallHook(), xxxInternalEnumWindow(), xxxMakeWindowForegroundWithState(), xxxSendFocusMessages(), xxxSendMessage(), xxxSendNotifyMessage(), xxxSetWindowPos(), xxxUpdateTray(), and xxxWindowEvent().

Referenced by xxxActivateWindow(), xxxActiveWindowTracking(), xxxMenuWindowProc(), xxxMNCloseHierarchy(), xxxMNEndMenuState(), xxxProcessEventMessage(), xxxSetFocus(), and xxxSetForegroundWindow2().

00476 { 00477 PTHREADINFO ptiCurrent = PtiCurrent(); 00478 PWND pwndT, pwndActivePrev, pwndActiveSave; 00479 TL tlpwndActive; 00480 TL tlpwndChild; 00481 TL tlpwndActivePrev; 00482 WPARAM wParam; 00483 BOOL fSetActivateAppBit; 00484 00485 BOOL fMouse = (BOOL)(fFlags & ATW_MOUSE); 00486 BOOL fSetFocus = (BOOL)(fFlags & ATW_SETFOCUS); 00487 BOOL fAsync = (BOOL)(fFlags & ATW_ASYNC); 00488 00489 #if DBG 00490 PQ pqSave = ptiCurrent->pq; 00491 #endif 00492 00493 00494 CheckLock(pwnd); 00495 00496 /* 00497 * If pwnd is NULL, then we can't do anything. 00498 */ 00499 if ((pwnd == NULL) || (pwnd == PWNDDESKTOP(pwnd))) { 00500 return FALSE; 00501 } 00502 00503 /* 00504 * Don't activate a window that has been destroyed. 00505 */ 00506 if (HMIsMarkDestroy(pwnd)) 00507 return FALSE; 00508 00509 /* 00510 * We don't activate top-level windows of a different queue. 00511 */ 00512 if (GETPTI(pwnd)->pq != ptiCurrent->pq) { 00513 return FALSE; 00514 } 00515 00516 pwndActiveSave = ptiCurrent->pq->spwndActive; 00517 00518 /* 00519 * Do the change-in-activation if the two-windows are different, 00520 * and if we're not recursing 00521 */ 00522 if ((pwnd != pwndActiveSave) && !TestWF(pwnd, WFBEINGACTIVATED)) { 00523 00524 /* 00525 * Ask the CBT hook whether it is OK to activate this window. 00526 */ 00527 { 00528 CBTACTIVATESTRUCT CbtActivateParams; 00529 00530 if (IsHooked(ptiCurrent, WHF_CBT)) { 00531 00532 CbtActivateParams.fMouse = fMouse; 00533 CbtActivateParams.hWndActive = HW(pwndActiveSave); 00534 00535 if (xxxCallHook(HCBT_ACTIVATE, 00536 (WPARAM)HWq(pwnd), (LPARAM)&CbtActivateParams, WH_CBT)) { 00537 return FALSE; 00538 } 00539 } 00540 } 00541 00542 ptiCurrent->pq->QF_flags &= ~QF_EVENTDEACTIVATEREMOVED; 00543 00544 /* 00545 * If the active window went away but somehow was left referenced 00546 * in the queue, then we do not want to do any deactivation of 00547 * that window. 00548 * 00549 * Don't thread lock this because the next thing we do with it 00550 * is just an equality check. 00551 * 00552 * A DBG check is placed in xxxDestroyWindow to attempt to 00553 * catch the situation where we return from the function with 00554 * the destroyed window set in the active (pq). If that situation 00555 * can be detected and solved, then this conditional might be 00556 * removed: ChrisWil - 08/22/95. 00557 */ 00558 if (ptiCurrent->pq->spwndActive && TestWF(ptiCurrent->pq->spwndActive, WFDESTROYED)) { 00559 Lock(&ptiCurrent->pq->spwndActive, NULL); 00560 } else { 00561 Lock(&ptiCurrent->pq->spwndActivePrev, ptiCurrent->pq->spwndActive); 00562 } 00563 pwndActivePrev = ptiCurrent->pq->spwndActive; 00564 00565 /* 00566 * If there was a previously active window, 00567 * and we're in the foreground then assign 00568 * gpqForegroundPrev to ourself. 00569 */ 00570 if ((pwndActivePrev != NULL) && (ptiCurrent->pq == gpqForeground)) { 00571 gpqForegroundPrev = ptiCurrent->pq; 00572 } 00573 00574 /* 00575 * Deactivate currently active window if possible. 00576 */ 00577 if (pwndActivePrev != NULL) { 00578 ThreadLockWithPti(ptiCurrent, pwndActivePrev, &tlpwndActive); 00579 00580 /* 00581 * The active window can prevent itself from losing the 00582 * activation by returning FALSE to this WM_NCACTIVATE message 00583 */ 00584 wParam = MAKELONG(WA_INACTIVE, TestWF(pwndActivePrev, WFMINIMIZED)); 00585 if (!xxxSendMessage(pwndActivePrev, WM_NCACTIVATE, 00586 wParam, (LPARAM)HWq(pwnd))) { 00587 ThreadUnlock(&tlpwndActive); 00588 return FALSE; 00589 } 00590 00591 xxxSendMessage(pwndActivePrev, WM_ACTIVATE, wParam, (LPARAM)HWq(pwnd)); 00592 00593 ThreadUnlock(&tlpwndActive); 00594 } 00595 00596 /* 00597 * If the activation changed while we were gone, we'd better 00598 * not send any more messages, since they'd go to the wrong window. 00599 * (and, they've already been sent anyhow) 00600 */ 00601 if (ptiCurrent->pq->spwndActivePrev != ptiCurrent->pq->spwndActive || 00602 pwndActiveSave != ptiCurrent->pq->spwndActive) { 00603 #if DBG 00604 if (ptiCurrent->pq->spwndActivePrev == ptiCurrent->pq->spwndActive) { 00605 RIPMSG0(RIP_WARNING, "xxxActivateThisWindow: ptiCurrent->pq->spwndActive changed in callbacks"); 00606 } 00607 #endif 00608 return FALSE; 00609 } 00610 00611 /* 00612 * If the window being activated has been destroyed, don't 00613 * do anything else. Making it the active window in this 00614 * case can cause console to hang during shutdown. 00615 */ 00616 if (HMIsMarkDestroy(pwnd)) 00617 return FALSE; 00618 00619 /* 00620 * Before we lock the new pwndActivate, make sure we're still 00621 * on the same queue. 00622 */ 00623 if (GETPTI(pwnd)->pq != ptiCurrent->pq) { 00624 RIPMSG1(RIP_WARNING, "xxxActivateThisWindow: Queue unattached:%#p", pqSave); 00625 return FALSE; 00626 } 00627 00628 /* 00629 * This bit, which means the app set the focus to NULL after becoming 00630 * active, doesn't make sense if the app is just becoming active, so 00631 * clear it in this case. It is used below in this routine to 00632 * determine whether to send focus messages (read comment in this 00633 * routine). 00634 */ 00635 if (ptiCurrent->pq->spwndActive == NULL) 00636 ptiCurrent->pq->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE; 00637 00638 Lock(&ptiCurrent->pq->spwndActive, pwnd); 00639 00640 /* 00641 * Tp prevent recursion, set pwnd's WFBEINGACTIVATED bit. 00642 * Recursion can happen if we have an activation battle with other 00643 * threads which keep changing ptiCurrent->pq->spwndActive behind our 00644 * callbacks. 00645 * WARNING: Do NOT return from this routine without clearing this bit! 00646 */ 00647 SetWF(pwnd, WFBEINGACTIVATED); 00648 00649 if (FWINABLE()) { 00650 xxxWindowEvent(EVENT_SYSTEM_FOREGROUND, pwnd, OBJID_WINDOW, INDEXID_OBJECT, WEF_USEPWNDTHREAD); 00651 } 00652 00653 /* 00654 * Remove all async activates up to the next async deactivate. We 00655 * do this so that any queued activates don't reset this synchronous 00656 * activation state we're now setting. Only remove up till the next 00657 * deactivate because active state is synchronized with reading 00658 * input from the input queue. 00659 * 00660 * For example, an activate event gets put in an apps queue. Before 00661 * processing it the app calls ActivateWindow(), which is synchronous. 00662 * You want the ActivateWindow() to win because it is newer 00663 * information. 00664 * 00665 * msmail32 demonstrates this. Minimize msmail. Alt-tab to it. It 00666 * brings up the password dialog, but it isn't active. It correctly 00667 * activates the password dialog but then processes an old activate 00668 * event activating the icon, so the password dialog is not active. 00669 */ 00670 RemoveEventMessage(ptiCurrent->pq, QEVENT_ACTIVATE, QEVENT_DEACTIVATE); 00671 00672 xxxMakeWindowForegroundWithState(NULL, 0); 00673 00674 pwndActivePrev = ptiCurrent->pq->spwndActivePrev; 00675 ThreadLockWithPti(ptiCurrent, pwndActivePrev, &tlpwndActivePrev); 00676 00677 if (TEST_PUSIF(PUSIF_PALETTEDISPLAY) && xxxSendMessage(pwnd, WM_QUERYNEWPALETTE, 0, 0)) { 00678 xxxSendNotifyMessage(PWND_BROADCAST, WM_PALETTEISCHANGING, 00679 (WPARAM)HWq(pwnd), 0); 00680 } 00681 00682 /* 00683 * If the window becoming active is not already the top window in the 00684 * Z-order, then call xxxBringWindowToTop() to do so. 00685 */ 00686 00687 /* 00688 * If this isn't a child window, first check to see if the 00689 * window isn't already 'on top'. If not, then call 00690 * xxxBringWindowToTop(). 00691 */ 00692 if (!(fFlags & ATW_NOZORDER) && !TestWF(pwnd, WFCHILD)) { 00693 00694 /* 00695 * Look for the first visible child of the desktop. 00696 * ScottLu changed this to start looking at the desktop 00697 * window. Since the desktop window was always visible, 00698 * BringWindowToTop was always called regardless of whether 00699 * it was needed or not. No one can remember why this 00700 * change was made, so I'll change it back to the way it 00701 * was in Windows 3.1. - JerrySh 00702 */ 00703 pwndT = PWNDDESKTOP(pwnd)->spwndChild; 00704 00705 while (pwndT && (!TestWF(pwndT, WFVISIBLE))) { 00706 pwndT = pwndT->spwndNext; 00707 } 00708 00709 /* 00710 * If this activation came from an async call (i.e. 00711 * xxxProcessEventMessage), we need to check to see 00712 * if the thread is the foreground-queue. If not, then 00713 * we do not want to bring the window to the top. This 00714 * is because another window could have already been 00715 * place on top w/foreground. Bringing the window to 00716 * the top in this case would result in a top-level window 00717 * without activation. - ChrisWil 00718 * 00719 * Added a check to see if the previous-active window went 00720 * invisible during the deactivation time. This will ensure 00721 * that we bring the new window to the top. Otherwise, we 00722 * could end up skipping over the previous-window from the 00723 * above tests. Office95 apps demonstrate this behaviour by 00724 * turning their windows invisible during the painting of their 00725 * captionbars. By the time we use to get here, we failed to 00726 * bring the new window to top. 00727 */ 00728 if ((pwnd != pwndT) || (pwndActivePrev && !IsVisible(pwndActivePrev))) { 00729 00730 if (!(fAsync && (gpqForeground != ptiCurrent->pq))) { 00731 DWORD dwFlags; 00732 00733 /* 00734 * Bring the window to the top. If we're already 00735 * activating the window, don't reactivate it. 00736 */ 00737 dwFlags = SWP_NOSIZE | SWP_NOMOVE; 00738 if (pwnd == pwndT) 00739 dwFlags |= SWP_NOACTIVATE; 00740 00741 xxxSetWindowPos(pwnd, PWND_TOP, 0, 0, 0, 0, dwFlags); 00742 } 00743 } 00744 } 00745 00746 /* 00747 * If there was no previous active window, or if the 00748 * previously active window belonged to another thread 00749 * send the WM_ACTIVATEAPP messages. The fActivate == FALSE 00750 * case is handled in xxxDeactivate when 'hwndActivePrev == NULL'. 00751 * 00752 * Harvard Graphics/Windows setup calls SetActiveWindow when it 00753 * receives a deactivationg WM_ACTIVATEAPP. The TIF_INACTIVATEAPPMSG 00754 * prevents an activating WM_ACTIVATEAPP(TRUE) from being sent while 00755 * deactivation is occuring. 00756 */ 00757 fSetActivateAppBit = FALSE; 00758 if (!(ptiCurrent->TIF_flags & TIF_INACTIVATEAPPMSG) && 00759 ((pwndActivePrev == NULL) || 00760 (GETPTI(pwndActivePrev) != GETPTI(pwnd)))) { 00761 AAS aas; 00762 00763 /* 00764 * First send the deactivating WM_ACTIVATEAPP if there 00765 * was a previously active window of another thread in 00766 * the current queue. 00767 */ 00768 if (pwndActivePrev != NULL) { 00769 PTHREADINFO ptiPrev = GETPTI(pwndActivePrev); 00770 TL tlptiPrev; 00771 00772 /* 00773 * Ensure that the other thread can't recurse 00774 * and send more WM_ACTIVATEAPP msgs. 00775 */ 00776 ptiPrev->TIF_flags |= TIF_INACTIVATEAPPMSG; 00777 00778 aas.ptiNotify = ptiPrev; 00779 aas.tidActDeact = TIDq(ptiCurrent); 00780 aas.fActivating = FALSE; 00781 aas.fQueueNotify = FALSE; 00782 00783 ThreadLockPti(ptiCurrent, ptiPrev, &tlptiPrev); 00784 ThreadLockWithPti(ptiCurrent, pwndActivePrev->head.rpdesk->pDeskInfo->spwnd->spwndChild, &tlpwndChild); 00785 xxxInternalEnumWindow(pwndActivePrev->head.rpdesk->pDeskInfo->spwnd->spwndChild, 00786 (WNDENUMPROC_PWND)xxxActivateApp, (LPARAM)&aas, BWL_ENUMLIST); 00787 ThreadUnlock(&tlpwndChild); 00788 ptiPrev->TIF_flags &= ~TIF_INACTIVATEAPPMSG; 00789 ThreadUnlockPti(ptiCurrent, &tlptiPrev); 00790 } 00791 00792 /* 00793 * This will ensure that the current thread will not 00794 * send any more WM_ACTIVATEAPP messages until it 00795 * is done performing its activation. 00796 */ 00797 ptiCurrent->TIF_flags |= TIF_INACTIVATEAPPMSG; 00798 fSetActivateAppBit = TRUE; 00799 00800 aas.ptiNotify = GETPTI(pwnd); 00801 aas.tidActDeact = tidLoseForeground; 00802 aas.fActivating = TRUE; 00803 aas.fQueueNotify = FALSE; 00804 00805 ThreadLockWithPti(ptiCurrent, ptiCurrent->rpdesk->pDeskInfo->spwnd->spwndChild, &tlpwndChild); 00806 xxxInternalEnumWindow(ptiCurrent->rpdesk->pDeskInfo->spwnd->spwndChild, 00807 (WNDENUMPROC_PWND)xxxActivateApp, (LPARAM)&aas, BWL_ENUMLIST); 00808 ThreadUnlock(&tlpwndChild); 00809 } 00810 00811 /* 00812 * If this window has already been drawn as active, set the 00813 * flag so that we don't draw it again. 00814 */ 00815 if (TestWF(pwnd, WFFRAMEON)) { 00816 SetWF(pwnd, WFNONCPAINT); 00817 } 00818 00819 /* 00820 * If the window is marked for destruction, don't do 00821 * the lock because xxxFreeWindow has already been called 00822 * and a lock here will result in the window locking itself 00823 * and never being freed. 00824 */ 00825 if (!HMIsMarkDestroy(pwnd)) { 00826 00827 /* 00828 * Set most recently active window in owner/ownee list. 00829 */ 00830 pwndT = pwnd; 00831 while (pwndT->spwndOwner != NULL) { 00832 pwndT = pwndT->spwndOwner; 00833 } 00834 Lock(&pwndT->spwndLastActive, pwnd); 00835 } 00836 00837 00838 xxxSendMessage(pwnd, WM_NCACTIVATE, 00839 MAKELONG(GETPTI(pwnd)->pq == gpqForeground, 00840 ptiCurrent->pq->spwndActive != NULL ? 00841 TestWF(ptiCurrent->pq->spwndActive, WFMINIMIZED) : 0), 00842 (LPARAM)HW(pwndActivePrev)); 00843 00844 if (ptiCurrent->pq->spwndActive != NULL) { 00845 xxxSendMessage(pwnd, WM_ACTIVATE, 00846 MAKELONG((fMouse ? WA_CLICKACTIVE : WA_ACTIVE), 00847 TestWF(ptiCurrent->pq->spwndActive, WFMINIMIZED)), 00848 (LPARAM)HW(pwndActivePrev)); 00849 } else { 00850 xxxSendMessage(pwnd, WM_ACTIVATE, 00851 MAKELONG((fMouse ? WA_CLICKACTIVE : WA_ACTIVE), 0), 00852 (LPARAM)HW(pwndActivePrev)); 00853 } 00854 00855 xxxUpdateTray(pwnd); 00856 00857 ThreadUnlock(&tlpwndActivePrev); 00858 00859 ClrWF(pwnd, WFNONCPAINT); 00860 00861 /* 00862 * If xxxActivateThisWindow() is called from xxxSetFocus() then 00863 * fSetFocus is FALSE. In this case, we don't set the focus since 00864 * xxxSetFocus() will do that for us. Otherwise, we set the focus 00865 * to the newly activated window if the window with the focus is 00866 * not the new active window or one of its children. Normally, 00867 * xxxDefWindowProc() will set the focus. 00868 */ 00869 ThreadLockWithPti(ptiCurrent, ptiCurrent->pq->spwndActive, &tlpwndActive); 00870 00871 /* 00872 * Win3.1 checks spwndFocus != NULL - we check QF_FOCUSNULLSINCEACTIVE, 00873 * which is the win32 equivalent. On win32, 32 bit apps each have their 00874 * own focus. If the app is not foreground, most of the time spwndFocus 00875 * is NULL when the window is being activated and brought to the 00876 * foreground. It wouldn't go through this code in this case. Win3.1 in 00877 * effect is checking if the previous active application had an 00878 * hwndFocus != NULL. Win32 effectively assumes the last window has a 00879 * non-NULL hwndFocus, so win32 instead checks to see if the focus has 00880 * been set to NULL since this application became active (meaning, did 00881 * it purposefully set the focus to NULL). If it did, don't go through 00882 * this codepath (like win3.1). If it didn't, go through this code path 00883 * because the previous application had an hwndFocus != NULL 00884 * (like win3.1). Effectively it is the same check as win3.1, but 00885 * updated to deal with async input. 00886 * 00887 * Case in point: bring up progman, hit f1 (to get win32 help). Click 00888 * history to get a popup (has the focus in a listbox in the client 00889 * area). Activate another app, now click on title bar only of history 00890 * popup. The focus should get set by going through this code path. 00891 * 00892 * Alternate case: Ventura Publisher brings up "Special Effects" 00893 * dialog. If "Bullet" from this dialog was clicked last time the 00894 * dialog was brought up, sending focus messages here when 00895 * hwndFocus == NULL, would reset the focus to "None" incorrectly 00896 * because Ventura does its state setting when it gets the focus 00897 * messages. The real focus messages it is depending on are the 00898 * ones that come from the SetFocus() call in DlgSetFocus() in 00899 * the dialog management code. (In this case, before the dialog 00900 * comes up, focus == active window. When the dialog comes up 00901 * and EnableWindow(hwndOwner, FALSE) is called, EnableWindow() calls 00902 * SetFocus(NULL) (because it is disabling the window that is also 00903 * the focus window). When the dialog comes up it gets activated via 00904 * SwpActivate(), but since the focus is NULL vpwin does not expect 00905 * to go through this code path.) 00906 * 00907 * - scottlu 00908 */ 00909 #if 0 00910 // this is what win3.1 does - which won't work for win32 00911 00912 if (fSetFocus && ptiCurrent->pq->spwndFocus != NULL && ptiCurrent->pq->spwndActive != 00913 GetTopLevelWindow(ptiCurrent->pq->spwndFocus)) 00914 #else 00915 if (fSetFocus && !(ptiCurrent->pq->QF_flags & QF_FOCUSNULLSINCEACTIVE) && 00916 ptiCurrent->pq->spwndActive != GetTopLevelWindow(ptiCurrent->pq->spwndFocus)) { 00917 #endif 00918 00919 xxxSendFocusMessages(ptiCurrent, 00920 (ptiCurrent->pq->spwndActive != NULL && 00921 TestWF(ptiCurrent->pq->spwndActive, WFMINIMIZED)) ? 00922 NULL : ptiCurrent->pq->spwndActive); 00923 } 00924 00925 ThreadUnlock(&tlpwndActive); 00926 00927 /* 00928 * This flag is examined in the menu loop code so that we exit from 00929 * menu mode if another window was activated while we were tracking 00930 * menus. 00931 */ 00932 ptiCurrent->pq->QF_flags |= QF_ACTIVATIONCHANGE; 00933 00934 if (gppiScreenSaver == NULL) { 00935 00936 /* 00937 * Activation has occurred, update our last idle time counter if 00938 * we're on the input desktop. 00939 */ 00940 if (ptiCurrent->rpdesk == grpdeskRitInput) { 00941 glinp.timeLastInputMessage = NtGetTickCount(); 00942 } 00943 00944 } else { 00945 00946 if (GETPTI(pwnd)->ppi != gppiScreenSaver) { 00947 /* 00948 * Activation ocurred by an app other than the screen saver. 00949 * Update the idle time counter and mark our screen saver as 00950 * active (so it can quit). 00951 */ 00952 00953 #if 0 00954 // LATER 00955 if (ptiCurrent->rpdesk != gppiScreenSaver->rpdeskStartup) { 00956 /* 00957 * Activation is occurring on different desktops, let WinLogon decide 00958 * if it wants to switch. 00959 */ 00960 } 00961 #endif 00962 00963 glinp.timeLastInputMessage = NtGetTickCount(); 00964 gppiScreenSaver->W32PF_Flags &= ~W32PF_IDLESCREENSAVER; 00965 SetForegroundPriorityProcess(gppiScreenSaver, gppiScreenSaver->ptiMainThread, TRUE); 00966 } 00967 } 00968 00969 /* 00970 * If WM_ACTIVATEAPP messages were sent, it is now 00971 * safe to allow them to be sent again. 00972 */ 00973 if (fSetActivateAppBit) 00974 ptiCurrent->TIF_flags &= ~TIF_INACTIVATEAPPMSG; 00975 00976 00977 } else { 00978 #if DBG 00979 if (TestWF(pwnd, WFBEINGACTIVATED)) { 00980 RIPMSG1(RIP_WARNING, "xxxActivateThisWindow recursing on pwnd %#p\n", pwnd); 00981 } 00982 #endif 00983 ptiCurrent->pq->QF_flags &= ~QF_EVENTDEACTIVATEREMOVED; 00984 if (TEST_PUSIF(PUSIF_PALETTEDISPLAY) && xxxSendMessage(pwnd, WM_QUERYNEWPALETTE, 0, 0)) { 00985 xxxSendNotifyMessage(PWND_BROADCAST, WM_PALETTEISCHANGING, 00986 (WPARAM)HWq(pwnd), 0); 00987 } 00988 } 00989 00990 ClrWF(pwnd, WFBEINGACTIVATED); 00991 return ptiCurrent->pq->spwndActive == pwnd; 00992 }

BOOL xxxActivateWindow PWND  pwnd,
UINT  cmd
 

Definition at line 2060 of file focusact.c.

References ATW_MOUSE, ATW_SETFOCUS, AW_SKIP, AW_SKIP2, AW_TRY, AW_TRY2, AW_USE, AW_USE2, BOOL, CheckLock, tagTHREADINFO::cVisWindows, DWORD, FAllowForegroundActivate(), FALSE, FBadWindow(), GETPTI, gpqForeground, gpqForegroundPrev, NextTopWindow(), NTW_IGNORETOOLWINDOW, NULL, tagTHREADINFO::pq, PtiCurrent, tagQ::spwndActivePrev, tagWND::spwndLastActive, tagWND::spwndOwner, TestWF, TestwndChild, TestwndPopup, ThreadLockAlwaysWithPti, ThreadUnlock, TIF_ALLOWFOREGROUNDACTIVATE, tagTHREADINFO::TIF_flags, TRUE, WFBOTTOMMOST, xxxActivateThisWindow(), and xxxSetForegroundWindow().

Referenced by xxxDestroyWindow(), xxxHandleNCMouseGuys(), xxxMenuWindowProc(), xxxMinMaximize(), xxxMouseActivate(), xxxSetActiveWindow(), xxxSetForegroundWindow(), xxxShowWindow(), and xxxSwpActivate().

02063 { 02064 DWORD fFlags = ATW_SETFOCUS; 02065 PTHREADINFO ptiCurrent = PtiCurrent(); 02066 TL tlpwnd; 02067 BOOL fSuccess; 02068 BOOL fAllowForeground, fSetForegroundRight; 02069 02070 CheckLock(pwnd); 02071 02072 02073 if (pwnd != NULL) { 02074 02075 /* 02076 * See if this window is OK to activate 02077 * (Cannot activate child windows). 02078 */ 02079 if (TestwndChild(pwnd)) 02080 return FALSE; 02081 02082 } else { 02083 cmd = AW_SKIP2; 02084 } 02085 02086 switch (cmd) { 02087 02088 case AW_TRY2: 02089 fFlags |= ATW_MOUSE; 02090 02091 /* 02092 *** FALL THRU ** 02093 */ 02094 case AW_TRY: 02095 02096 /* 02097 * See if this window is OK to activate. 02098 */ 02099 if (!FBadWindow(pwnd)) { 02100 break; 02101 } 02102 02103 /* 02104 * If pwnd can not be activated, drop into the AW_SKIP case. 02105 */ 02106 case AW_SKIP: 02107 02108 /* 02109 * Try the owner of this popup. 02110 */ 02111 if (TestwndPopup(pwnd) && !FBadWindow(pwnd->spwndOwner)) { 02112 pwnd = pwnd->spwndOwner; 02113 break; 02114 } 02115 02116 /* 02117 * fall through 02118 */ 02119 02120 case AW_SKIP2: 02121 02122 /* 02123 * Try the previously active window but don't activate a shell window 02124 */ 02125 if ((gpqForegroundPrev != NULL) 02126 && !FBadWindow(gpqForegroundPrev->spwndActivePrev) 02127 /* 02128 * Bug 290129 - joejo 02129 * 02130 * Test for WFBOTTOMMOST as opposed to WEFTOOLWINDOW to fix 02131 * issue with Office2000 assistant and balloon help. 02132 */ 02133 && !TestWF(gpqForegroundPrev->spwndActivePrev, WFBOTTOMMOST)) { 02134 02135 pwnd = gpqForegroundPrev->spwndActivePrev; 02136 break; 02137 } 02138 02139 { 02140 PWND pwndSave = pwnd; 02141 DWORD flags = NTW_IGNORETOOLWINDOW; 02142 02143 TryAgain: 02144 /* 02145 * Find a new active window from the top-level window list, 02146 * skip tool windows the first time through. 02147 */ 02148 pwnd = NextTopWindow(ptiCurrent, pwndSave, (cmd == AW_SKIP ? pwndSave : NULL), 02149 flags); 02150 02151 if (pwnd) { 02152 if (!FBadWindow(pwnd->spwndLastActive)) 02153 pwnd = pwnd->spwndLastActive; 02154 } else { 02155 if (flags == NTW_IGNORETOOLWINDOW) { 02156 flags = 0; 02157 goto TryAgain; 02158 } 02159 } 02160 } 02161 02162 02163 case AW_USE: 02164 break; 02165 02166 case AW_USE2: 02167 fFlags |= ATW_MOUSE; 02168 break; 02169 02170 default: 02171 return FALSE; 02172 } 02173 02174 if (pwnd == NULL) 02175 return FALSE; 02176 02177 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd); 02178 02179 if (GETPTI(pwnd)->pq == ptiCurrent->pq) { 02180 /* 02181 * Activation is within this queue. Usually this means just do 02182 * all the normal message sending. But if this queue isn't the 02183 * foreground queue, check to see if it is allowed to become 02184 * foreground. 02185 */ 02186 02187 /* 02188 * Sometimes processes are granted the right to foreground 02189 * activate themselves, if they aren't foreground, like 02190 * when starting up (there are other cases). Grant this if 02191 * this process is allowed. 02192 */ 02193 02194 /* 02195 * Removed the first clause from the following if statement 02196 * if (pti->pq == gpqForeground || !FAllowForegroundActivate(pti->pq)) { 02197 * This fixes the problem where foreground app A activates app B 02198 * the user switches to app C, then B does something to activate A 02199 * (like destroy an owned window). A now comes to the foreground 02200 * unexpectedly. This clause is not in Win95 code and was added in 02201 * 3.51 code to fix some test script hang (Bug 7461) 02202 */ 02203 02204 if (!FAllowForegroundActivate(ptiCurrent->pq, pwnd)) { 02205 fSuccess = xxxActivateThisWindow(pwnd, 0, fFlags); 02206 ThreadUnlock(&tlpwnd); 02207 return fSuccess; 02208 } 02209 02210 fAllowForeground = TRUE; 02211 /* 02212 * If this thread doesn't have any top-level non-minimized visible windows, 02213 * let it keep the right since it's probably not done with activation yet. 02214 * Bug 274383 - joejo 02215 */ 02216 fSetForegroundRight = (ptiCurrent->cVisWindows == 0); 02217 02218 } else { 02219 /* 02220 * If the caller is in the foreground, it has the right to change 02221 * the foreground itself. 02222 */ 02223 fAllowForeground = (gpqForeground == ptiCurrent->pq) 02224 || (gpqForeground == NULL); 02225 /* 02226 * Give the right to change the foreground to this thread only if it already 02227 * has it, it has more visible windows or this is an explicit request to 02228 * activate the given window. 02229 * When an app destroys/hides the active (foreground) window, we choose a new 02230 * active window and will probably hit this code. We don't want to give them the 02231 * right to change the foreground in this case since it's us making the activation 02232 * (See comments below). We let them keep the right so apps destroying their last 02233 * visible window (ie a splash initialization window) can take the foreground again 02234 * when they create another window (the main window). 02235 */ 02236 if (fAllowForeground) { 02237 fSetForegroundRight = ((ptiCurrent->TIF_flags & TIF_ALLOWFOREGROUNDACTIVATE) 02238 || (ptiCurrent->cVisWindows != 0) 02239 || (cmd == AW_USE)); 02240 } else { 02241 fSetForegroundRight = FALSE; 02242 } 02243 } 02244 02245 fSuccess = FALSE; 02246 if (fAllowForeground) { 02247 /* 02248 * Hack! Temporarily give this thread a foreground right to make sure 02249 * this call succeds. 02250 */ 02251 ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; 02252 TAGMSG1(DBGTAG_FOREGROUND, "xxxActivateWindow temporarly set TIF %#p", ptiCurrent); 02253 fSuccess = xxxSetForegroundWindow(pwnd, (cmd == AW_USE)); 02254 02255 if (fSetForegroundRight) { 02256 /* 02257 * We activated some other app on purpose. If so that means this 02258 * thread is probably controlling this window and will probably want 02259 * to set itself active and foreground really soon again (for example, 02260 * a setup program doing dde to progman). A real live case: wingz - 02261 * bring up page setup..., options..., ok, ok. Under Win3.1 the 02262 * activation goes somewhere strange and then wingz calls 02263 * SetActiveWindow() to bring it back. This'll make sure that works. 02264 * 02265 * We used to set this before calling xxxSetForegeroundWindow above. 02266 * This would cause callers doing an intra-queue activation to 02267 * retain their foreground right eventhough it is supposed to be 02268 * a one shot deal (that's why FAllowForeground clears the bits). 02269 * In addtion, xxxSetForegroundWindow might clear the bits (it didnt' 02270 * used to); so we do it here, and only if we did an inter-queue 02271 * activation 02272 */ 02273 ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; 02274 TAGMSG1(DBGTAG_FOREGROUND, "xxxActivateWindow set TIF %#p", ptiCurrent); 02275 } else { 02276 /* 02277 * Make sure to remove the temporary right. 02278 */ 02279 ptiCurrent->TIF_flags &= ~TIF_ALLOWFOREGROUNDACTIVATE; 02280 TAGMSG1(DBGTAG_FOREGROUND, "xxxActivateWindow clear TIF %#p", ptiCurrent); 02281 } 02282 } 02283 02284 ThreadUnlock(&tlpwnd); 02285 return fSuccess; 02286 }

BOOL xxxAllowSetForegroundWindow DWORD  dwProcessId  ) 
 

Definition at line 1101 of file focusact.c.

References BOOL, CanForceForeground(), DWORD, EnterCrit, FALSE, glinp, LeaveCrit, LockProcessByClientId(), NT_SUCCESS, NTSTATUS(), NULL, pep, PpiCurrent, PpiFromProcess, tagLASTINPUT::ptiLastWoken, tagPROCESSINFO::ptiList, Status, TRUE, and UnlockProcess.

01103 { 01104 DWORD dwError; 01105 PEPROCESS pep; 01106 NTSTATUS Status; 01107 PPROCESSINFO ppi; 01108 /* 01109 * Get the ppi for dwProcessId 01110 * ASFW_ANY NULLs out the input owner so any process can take the foreground 01111 */ 01112 if (dwProcessId != ASFW_ANY) { 01113 LeaveCrit(); 01114 Status = LockProcessByClientId((HANDLE)LongToHandle( dwProcessId ), &pep); 01115 EnterCrit(); 01116 if (!NT_SUCCESS(Status)) { 01117 RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, ""); 01118 return FALSE; 01119 } 01120 ppi = PpiFromProcess(pep); 01121 if (ppi == NULL) { 01122 dwError = ERROR_INVALID_PARAMETER; 01123 goto UnlockAndFail; 01124 } 01125 } 01126 /* 01127 * Do nothing if the current process cannot force a foreground change. 01128 * We could have checked this upfront but we didn't since we had to 01129 * leave the crit section and the state could have changed. 01130 */ 01131 if (!CanForceForeground(PpiCurrent())) { 01132 dwError = ERROR_ACCESS_DENIED; 01133 goto UnlockAndFail; 01134 } 01135 /* 01136 * Let's make a thread (if any) of this process be the last input owner 01137 */ 01138 if (dwProcessId != ASFW_ANY) { 01139 TAGMSG2(DBGTAG_FOREGROUND, "xxxAllowSetForegroundWindow by %#p to %#p", PpiCurrent(), ppi); 01140 glinp.ptiLastWoken = ppi->ptiList; 01141 UnlockProcess(pep); 01142 } else { 01143 TAGMSG1(DBGTAG_FOREGROUND, "xxxAllowSetForegroundWindow by %#p to ANY", PpiCurrent()); 01144 glinp.ptiLastWoken = NULL; 01145 } 01146 return TRUE; 01147 01148 UnlockAndFail: 01149 if (dwProcessId != ASFW_ANY) { 01150 UnlockProcess(pep); 01151 } 01152 RIPERR0(dwError, RIP_VERBOSE, ""); 01153 return FALSE; 01154 }

void xxxCheckFocus PWND  pwnd  ) 
 

Definition at line 2549 of file focusact.c.

References tagQ::caret, CheckLock, NULL, tagTHREADINFO::pq, PtiCurrent, tagCARET::spwnd, tagQ::spwndFocus, tagWND::spwndParent, TestwndChild, ThreadLockWithPti, ThreadUnlock, xxxSetFocus(), and zzzDestroyCaret().

Referenced by xxxDW_SendDestroyMessages(), and xxxShowWindow().

02551 { 02552 TL tlpwndParent; 02553 PTHREADINFO pti; 02554 02555 CheckLock(pwnd); 02556 02557 pti = PtiCurrent(); 02558 02559 if (pwnd == pti->pq->spwndFocus) { 02560 02561 /* 02562 * Set focus to parent of child window. 02563 */ 02564 if (TestwndChild(pwnd)) { 02565 ThreadLockWithPti(pti, pwnd->spwndParent, &tlpwndParent); 02566 xxxSetFocus(pwnd->spwndParent); 02567 ThreadUnlock(&tlpwndParent); 02568 } else { 02569 xxxSetFocus(NULL); 02570 } 02571 } 02572 02573 if (pwnd == pti->pq->caret.spwnd) { 02574 zzzDestroyCaret(); 02575 } 02576 }

void xxxDeactivate PTHREADINFO  pti,
DWORD  tidSetForeground
 

Definition at line 34 of file focusact.c.

References AAS, BOOL, BWL_ENUMLIST, ClrWF, tagAAS::fActivating, FALSE, tagAAS::fQueueNotify, GETPTI, IS_IME_ENABLED, Lock, NULL, tagDESKTOP::pDeskInfo, tagTHREADINFO::pq, PtiCurrent, tagAAS::ptiNotify, tagTHREADINFO::rpdesk, SetWakeBit(), tagDESKTOPINFO::spwnd, tagQ::spwndActive, tagQ::spwndActivePrev, tagQ::spwndCapture, tagWND::spwndChild, tagQ::spwndFocus, TestWF, ThreadLockAlwaysWithPti, ThreadLockPti, ThreadLockWithPti, ThreadUnlock, ThreadUnlockPti, tagAAS::tidActDeact, tagTHREADINFO::TIF_flags, TIF_INACTIVATEAPPMSG, TIF_INCLEANUP, TRUE, Unlock, WFFRAMEON, WFMINIMIZED, WNDENUMPROC_PWND, xxxActivateApp(), xxxFocusSetInputContext(), xxxInternalEnumWindow(), and xxxSendMessage().

Referenced by xxxProcessEventMessage(), and xxxSetForegroundWindow2().

00037 { 00038 PWND pwndLose; 00039 AAS aas; 00040 TL tlpwndCapture; 00041 TL tlpwndChild; 00042 TL tlpwndLose; 00043 TL tlpti; 00044 TL tlptiLose; 00045 WPARAM wParam; 00046 PTHREADINFO ptiLose; 00047 PTHREADINFO ptiCurrent = PtiCurrent(); 00048 BOOL fSetActivateAppBit = FALSE; 00049 00050 /* 00051 * If we're not active, we have nothing to deactivate, so just return. 00052 * If we don't return, we'll send redundant WM_ACTIVATEAPP messages. 00053 * Micrografx Draw, for example, calls FreeProcInstance() twice when 00054 * this occurs, thereby crashing. 00055 */ 00056 if (pti->pq->spwndActive == NULL) 00057 return; 00058 00059 /* 00060 * If pti != ptiCurrent, thread lock pti because we may leave 00061 * the critical section. 00062 */ 00063 if (pti != ptiCurrent) 00064 ThreadLockPti(ptiCurrent, pti, &tlpti); 00065 00066 /* 00067 * Prevent an activating WM_ACTIVATEAPP from being sent 00068 * while we're processing this event. 00069 */ 00070 if (!(pti->TIF_flags & TIF_INACTIVATEAPPMSG)) { 00071 pti->TIF_flags |= TIF_INACTIVATEAPPMSG; 00072 fSetActivateAppBit = TRUE; 00073 } 00074 00075 /* 00076 * Cancel any modes like move/size and menu tracking. 00077 */ 00078 if (pti->pq->spwndCapture != NULL) { 00079 ThreadLockAlwaysWithPti(ptiCurrent, pti->pq->spwndCapture, &tlpwndCapture); 00080 xxxSendMessage(pti->pq->spwndCapture, WM_CANCELMODE, 0, 0); 00081 ThreadUnlock(&tlpwndCapture); 00082 00083 /* 00084 * Set QS_MOUSEMOVE so any sleeping modal loops, 00085 * like the move/size code, will wake up and figure 00086 * out that it should abort. 00087 */ 00088 SetWakeBit(pti, QS_MOUSEMOVE); 00089 } 00090 00091 /* 00092 * See the comments in xxxActivateThisWindow about Harvard Graphics. 00093 * WinWord's Equation editor does some games when it gets the WM_ACTIVATE 00094 * so we have to remember to send the WM_ACTIVATEAPP to ptiLose. 22510 00095 */ 00096 if (pti->pq->spwndActive != NULL) { 00097 pwndLose = pti->pq->spwndActive; 00098 ptiLose = GETPTI(pwndLose); 00099 00100 ThreadLockPti(ptiCurrent, ptiLose, &tlptiLose); 00101 ThreadLockAlwaysWithPti(ptiCurrent, pwndLose, &tlpwndLose); 00102 wParam = MAKELONG(WA_INACTIVE, TestWF(pwndLose, WFMINIMIZED)); 00103 if (!xxxSendMessage(pwndLose, WM_NCACTIVATE, WA_INACTIVE, 0)) { 00104 ThreadUnlock(&tlpwndLose); 00105 ThreadUnlockPti(ptiCurrent, &tlptiLose); 00106 goto Exit; 00107 } 00108 xxxSendMessage(pwndLose, WM_ACTIVATE, wParam, 0); 00109 00110 /* 00111 * Only update the queue's active windows if they weren't 00112 * changed while we were off calling SendMessage. 00113 */ 00114 if (pti->pq->spwndActive == pwndLose) { 00115 Lock(&pti->pq->spwndActivePrev, pti->pq->spwndActive); 00116 Unlock(&pti->pq->spwndActive); 00117 } 00118 00119 /* 00120 * The flag WFFRAMEON is cleared in the default processing of 00121 * WM_NCACTIVATE message. 00122 * We want to clear this flag again here since it might of been 00123 * set in xxxSendNCPaint. 00124 * Pbrush calls DrawMenuBar when it gets the WM_ACTIVATE message 00125 * sent above and this causes xxxSendNCPaint to get called and the 00126 * WFFRAMEON flag gets reset. 00127 */ 00128 ClrWF(pwndLose, WFFRAMEON); 00129 ThreadUnlock(&tlpwndLose); 00130 00131 /* 00132 * Revalidate ptiLose because the thread may have gone away 00133 * when the activation messages were sent above. 00134 */ 00135 aas.ptiNotify = (ptiLose->TIF_flags & TIF_INCLEANUP) ? NULL : ptiLose; 00136 ThreadUnlockPti(ptiCurrent, &tlptiLose); 00137 } else { 00138 00139 /* 00140 * Use a non-NULL special value for the test after 00141 * the xxxActivateApp calls. 00142 */ 00143 pwndLose = (PWND)-1; 00144 aas.ptiNotify = pti; 00145 } 00146 00147 if (aas.ptiNotify) { 00148 aas.tidActDeact = tidSetForeground; 00149 aas.fActivating = FALSE; 00150 aas.fQueueNotify = FALSE; 00151 00152 ThreadLockWithPti(ptiCurrent, 00153 pti->rpdesk->pDeskInfo->spwnd->spwndChild, &tlpwndChild); 00154 xxxInternalEnumWindow(pti->rpdesk->pDeskInfo->spwnd->spwndChild, 00155 (WNDENUMPROC_PWND)xxxActivateApp, (LPARAM)&aas, BWL_ENUMLIST); 00156 ThreadUnlock(&tlpwndChild); 00157 } 00158 00159 /* 00160 * If an app (i.e. Harvard Graphics/Windows Install) tries to 00161 * reactivate itself during a deactivating WM_ACTIVATEAPP 00162 * message, force deactivation. 00163 */ 00164 if (pti->pq->spwndActive == pwndLose) { 00165 00166 ThreadLockWithPti(ptiCurrent, pwndLose, &tlpwndLose); 00167 if (!xxxSendMessage(pwndLose, WM_NCACTIVATE, WA_INACTIVE, 0)) { 00168 ThreadUnlock(&tlpwndLose); 00169 goto Exit; 00170 } 00171 xxxSendMessage(pwndLose, WM_ACTIVATE, WA_INACTIVE, 0); 00172 ThreadUnlock(&tlpwndLose); 00173 00174 /* 00175 * Only update the queue's active windows if they weren't 00176 * changed while we were off calling SendMessage. 00177 */ 00178 if (pti->pq->spwndActive == pwndLose) { 00179 Lock(&pti->pq->spwndActivePrev, pti->pq->spwndActive); 00180 Unlock(&pti->pq->spwndActive); 00181 } 00182 } 00183 00184 if (pti->pq->spwndFocus != NULL) { 00185 pwndLose = Unlock(&pti->pq->spwndFocus); 00186 if (pwndLose != NULL) { 00187 ThreadLockAlwaysWithPti(ptiCurrent, pwndLose, &tlpwndLose); 00188 xxxSendMessage(pwndLose, WM_KILLFOCUS, 0, 0); 00189 #ifdef FE_IME 00190 if (IS_IME_ENABLED()) { 00191 xxxFocusSetInputContext(pwndLose, FALSE, FALSE); 00192 } 00193 #endif 00194 ThreadUnlock(&tlpwndLose); 00195 } 00196 } 00197 00198 Exit: 00199 if (fSetActivateAppBit) { 00200 pti->TIF_flags &= ~TIF_INACTIVATEAPPMSG; 00201 } 00202 if (pti != ptiCurrent) 00203 ThreadUnlockPti(ptiCurrent, &tlpti); 00204 }

void xxxSendFocusMessages PTHREADINFO  pti,
PWND  pwndReceive
 

Definition at line 220 of file focusact.c.

References CheckLock, FALSE, FWINABLE, GETPTI, gpqForeground, HW, HWq, IS_IME_ENABLED, Lock, NULL, tagTHREADINFO::pq, tagQ::QF_flags, QF_FOCUSNULLSINCEACTIVE, SetForegroundThread(), tagQ::spwndActive, tagQ::spwndFocus, TestWF, ThreadLockWithPti, ThreadUnlock, TRUE, WFDESTROYED, xxxFocusSetInputContext(), xxxSendMessage(), and xxxWindowEvent().

Referenced by xxxActivateThisWindow(), and xxxSetFocus().

00223 { 00224 PWND pwndLose; 00225 TL tlpwndLose; 00226 00227 CheckLock(pwndReceive); 00228 00229 /* 00230 * Remember if this app set the focus to NULL on purpose after it was 00231 * activated (needed in ActivateThisWindow()). 00232 */ 00233 pti->pq->QF_flags &= ~QF_FOCUSNULLSINCEACTIVE; 00234 if (pwndReceive == NULL && pti->pq->spwndActive != NULL) 00235 pti->pq->QF_flags |= QF_FOCUSNULLSINCEACTIVE; 00236 00237 pwndLose = pti->pq->spwndFocus; 00238 ThreadLockWithPti(pti, pwndLose, &tlpwndLose); 00239 00240 /* 00241 * We shouldn't be locking a valid pwnd from another queue. 00242 */ 00243 UserAssert((pwndReceive == NULL) 00244 || TestWF(pwndReceive, WFDESTROYED) 00245 || (pti->pq == GETPTI(pwndReceive)->pq)); 00246 Lock(&pti->pq->spwndFocus, pwndReceive); 00247 00248 if (pwndReceive == NULL) { 00249 if (pwndLose != NULL) { 00250 /* 00251 * Tell the client that nobody is gaining focus. 00252 */ 00253 if (FWINABLE()) { 00254 xxxWindowEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, INDEXID_OBJECT, 0); 00255 } 00256 xxxSendMessage(pwndLose, WM_KILLFOCUS, 0, 0); 00257 #ifdef FE_IME 00258 if (IS_IME_ENABLED()) { 00259 xxxFocusSetInputContext(pwndLose, FALSE, FALSE); 00260 } 00261 #endif 00262 } 00263 } else { 00264 00265 /* 00266 * Make this thread foreground so its base 00267 * priority get set higher. 00268 */ 00269 if (pti->pq == gpqForeground) 00270 SetForegroundThread(GETPTI(pwndReceive)); 00271 00272 if (pwndLose != NULL) { 00273 xxxSendMessage(pwndLose, WM_KILLFOCUS, (WPARAM)HWq(pwndReceive), 0); 00274 #ifdef FE_IME 00275 if (IS_IME_ENABLED()) { 00276 xxxFocusSetInputContext(pwndLose, FALSE, FALSE); 00277 } 00278 #endif 00279 } 00280 00281 /* 00282 * Send the WM_SETFOCUS message, but only if the window we're 00283 * setting the focus to still has the focus! This allows apps 00284 * to prevent themselves from losing the focus by catching 00285 * the WM_NCACTIVATE message and returning FALSE or by calling 00286 * SetFocus() inside their WM_KILLFOCUS handler. 00287 */ 00288 if (pwndReceive == pti->pq->spwndFocus) { 00289 #ifdef FE_IME 00290 if (IS_IME_ENABLED()) { 00291 xxxFocusSetInputContext(pwndReceive, TRUE, FALSE); 00292 } 00293 #endif 00294 /* 00295 * We have to do this BEFORE sending the WM_SETFOCUS message. 00296 * The app, upon receiving it, very well may turn around and 00297 * SetFocus() to a child window. 00298 */ 00299 if (FWINABLE()) { 00300 xxxWindowEvent(EVENT_OBJECT_FOCUS, pwndReceive, OBJID_CLIENT, 00301 INDEXID_OBJECT, 0); 00302 } 00303 xxxSendMessage(pwndReceive, WM_SETFOCUS, (WPARAM)HW(pwndLose), 0); 00304 } 00305 } 00306 00307 ThreadUnlock(&tlpwndLose); 00308 }

PWND xxxSetActiveWindow PWND  pwnd  ) 
 

Definition at line 1990 of file focusact.c.

References AW_USE, CheckLock, GETPTI, HW, NULL, tagTHREADINFO::pq, PtiCurrent, RevalidateHwnd, tagQ::spwndActive, TIF_16BIT, tagTHREADINFO::TIF_flags, and xxxActivateWindow().

Referenced by NtUserSetActiveWindow(), and xxxDWP_SetCursor().

01992 { 01993 HWND hwndActiveOld; 01994 PTHREADINFO pti; 01995 01996 CheckLock(pwnd); 01997 01998 pti = PtiCurrent(); 01999 02000 /* 02001 * 32 bit apps must call SetForegroundWindow (to be NT 3.1 compatible) 02002 * but 16 bit apps that are foreground can make other apps foreground. 02003 * xxxActivateWindow makes sure an app is foreground. 02004 */ 02005 if (!(pti->TIF_flags & TIF_16BIT) && (pwnd != NULL) && (GETPTI(pwnd)->pq != pti->pq)) { 02006 return NULL; 02007 } 02008 02009 hwndActiveOld = HW(pti->pq->spwndActive); 02010 02011 xxxActivateWindow(pwnd, AW_USE); 02012 02013 return RevalidateHwnd(hwndActiveOld); 02014 }

PWND xxxSetFocus PWND  pwnd  ) 
 

Definition at line 1815 of file focusact.c.

References CheckLock, FAllowForegroundActivate(), GETPTI, gLCIDSentToShell, gpqForeground, tagKL::hkl, HW, HWq, IsHooked, NULL, tagTHREADINFO::ppi, tagTHREADINFO::pq, PtiCurrent, RevalidateHwnd, SFW_SETFOCUS, tagTHREADINFO::spklActive, tagQ::spwndActive, tagQ::spwndFocus, tagWND::spwndParent, TestWF, TestwndChild, ThreadLockWithPti, ThreadUnlock, WFDISABLED, WFMINIMIZED, WFVISIBLE, WHF_CBT, WHF_SHELL, xxxActivateThisWindow(), xxxCallHook(), xxxSendFocusMessages(), and xxxSetForegroundWindow2().

Referenced by NtUserSetFocus(), xxxCheckFocus(), xxxDefWindowProc(), xxxDWP_ProcessVirtKey(), xxxEnableWindow(), xxxMinMaximize(), and xxxSBWndProc().

01817 { 01818 HWND hwndTemp; 01819 PTHREADINFO ptiCurrent = PtiCurrent(); 01820 PTHREADINFO ptiActiveKL; 01821 PWND pwndTemp = NULL; 01822 TL tlpwndTemp; 01823 01824 CheckLock(pwnd); 01825 /* 01826 * Special case if we are setting the focus to a null window. 01827 */ 01828 if (pwnd == NULL) { 01829 if (IsHooked(ptiCurrent, WHF_CBT) && xxxCallHook(HCBT_SETFOCUS, 0, 01830 (LPARAM)HW(ptiCurrent->pq->spwndFocus), WH_CBT)) { 01831 return NULL; 01832 } 01833 01834 /* 01835 * Save old focus so that we can return it. 01836 */ 01837 hwndTemp = HW(ptiCurrent->pq->spwndFocus); 01838 xxxSendFocusMessages(ptiCurrent, pwnd); 01839 return RevalidateHwnd(hwndTemp); 01840 } 01841 01842 /* 01843 * We no longer allow inter-thread set focuses. 01844 */ 01845 if (GETPTI(pwnd)->pq != ptiCurrent->pq) { 01846 return NULL; 01847 } 01848 01849 /* 01850 * If the window recieving the focus or any of its ancestors is either 01851 * minimized or disabled, don't set the focus. 01852 */ 01853 for (pwndTemp = pwnd; pwndTemp != NULL; pwndTemp = pwndTemp->spwndParent) { 01854 if (TestWF(pwndTemp, WFMINIMIZED) || TestWF(pwndTemp, WFDISABLED)) { 01855 01856 /* 01857 * Don't change the focus if going to a minimized or disabled 01858 * window. 01859 */ 01860 return NULL; 01861 } 01862 01863 if (!TestwndChild(pwndTemp)) { 01864 break; 01865 } 01866 } 01867 UserAssert(pwndTemp != NULL); 01868 01869 /* 01870 * pwndTemp should now be the top level ancestor of pwnd. 01871 */ 01872 ThreadLockWithPti(ptiCurrent, pwndTemp, &tlpwndTemp); 01873 if (pwnd != ptiCurrent->pq->spwndFocus) { 01874 if (IsHooked(ptiCurrent, WHF_CBT) && xxxCallHook(HCBT_SETFOCUS, (WPARAM)HWq(pwnd), 01875 (LPARAM)HW(ptiCurrent->pq->spwndFocus), WH_CBT)) { 01876 ThreadUnlock(&tlpwndTemp); 01877 return NULL; 01878 } 01879 01880 /* 01881 * Activation must follow the focus. That is, setting the focus to 01882 * a particualr window means that the top-level parent of this window 01883 * must be the active window (top-level parent is determined by 01884 * following the parent chain until you hit a top-level guy). So, 01885 * we must activate this top-level parent if it is different than 01886 * the current active window. 01887 * 01888 * Only change activation if top-level parent is not the currently 01889 * active window. 01890 */ 01891 if (pwndTemp != ptiCurrent->pq->spwndActive) { 01892 01893 /* 01894 * If this app is not in the foreground, see if foreground 01895 * activation is allowed. 01896 */ 01897 if (ptiCurrent->pq != gpqForeground && FAllowForegroundActivate(ptiCurrent->pq, pwndTemp)) { 01898 /* 01899 * If the process lost the foreground activation right by giving 01900 * focus to a hidden window, then give it the right back. See 01901 * bug #401932 for how this might affect an app 01902 */ 01903 if (!TestWF(pwndTemp, WFVISIBLE)){ 01904 ptiCurrent->ppi->W32PF_Flags |= W32PF_ALLOWFOREGROUNDACTIVATE; 01905 } 01906 if (!xxxSetForegroundWindow2(pwndTemp, ptiCurrent, SFW_SETFOCUS)) { 01907 ThreadUnlock(&tlpwndTemp); 01908 return NULL; 01909 } 01910 } 01911 01912 /* 01913 * This will return FALSE if something goes wrong. 01914 */ 01915 if (pwndTemp != ptiCurrent->pq->spwndActive) { 01916 if (!xxxActivateThisWindow(pwndTemp, 0, 0)) { 01917 ThreadUnlock(&tlpwndTemp); 01918 return NULL; 01919 } 01920 } 01921 } 01922 01923 /* 01924 * Save current pwndFocus since we must return this. 01925 */ 01926 pwndTemp = ptiCurrent->pq->spwndFocus; 01927 ThreadUnlock(&tlpwndTemp); 01928 ThreadLockWithPti(ptiCurrent, pwndTemp, &tlpwndTemp); 01929 01930 /* 01931 * Change the global pwndFocus and send the WM_{SET/KILL}FOCUS 01932 * messages. 01933 */ 01934 xxxSendFocusMessages(ptiCurrent, pwnd); 01935 01936 } else { 01937 pwndTemp = ptiCurrent->pq->spwndFocus; 01938 } 01939 01940 if (ptiCurrent->pq->spwndFocus) { 01941 /* 01942 * For the shell notification hook, we should use the pti->spkl 01943 * of the window with the focus. This could be a different thread, 01944 * (or even different process) when the queue is attached. The typical 01945 * case would be OLE out-of-process server. 01946 * #352877 01947 */ 01948 ptiActiveKL = GETPTI(ptiCurrent->pq->spwndFocus); 01949 } else { 01950 /* 01951 * Preserving the NT4 behavior, otherwise. 01952 */ 01953 ptiActiveKL = ptiCurrent; 01954 } 01955 UserAssert(ptiActiveKL); 01956 01957 /* 01958 * Update the keyboard icon on the tray if the layout changed during focus change. 01959 * Before winlogon loads kbd layouts, pti->spkActive is NULL. #99321 01960 */ 01961 if (ptiActiveKL->spklActive) { 01962 HKL hklActive = ptiActiveKL->spklActive->hkl; 01963 01964 if ((gLCIDSentToShell != hklActive) && IsHooked(ptiCurrent, WHF_SHELL)) { 01965 gLCIDSentToShell = hklActive; 01966 xxxCallHook(HSHELL_LANGUAGE, (WPARAM)NULL, (LPARAM)hklActive, WH_SHELL); 01967 } 01968 } 01969 01970 hwndTemp = HW(pwndTemp); 01971 ThreadUnlock(&tlpwndTemp); 01972 01973 /* 01974 * Return the pwnd of the window that lost the focus. 01975 * Return the validated hwndTemp: since we locked/unlocked pwndTemp, 01976 * it may be gone. 01977 */ 01978 return RevalidateHwnd(hwndTemp); 01979 }

BOOL xxxSetForegroundWindow PWND  pwnd,
BOOL  fFlash
 

Definition at line 1235 of file focusact.c.

References AW_USE, BOOL, CanForceForeground(), CheckLock, DSW_GetTopLevelCreatorWindow(), DWORD, FALSE, FRemoveForegroundActivate(), GETPTI, GetTopLevelWindow(), GiveUpForeground(), gppiInputProvider, gppiWantForegroundPriority, gpqForeground, HWq, IsForegroundLocked(), IsTrayWindow(), NULL, PostEventMessage(), tagTHREADINFO::ppi, tagTHREADINFO::pq, PtiCurrent, QEVENT_ACTIVATE, ThreadLockAlways, ThreadUnlock, TIF_ALLOWFOREGROUNDACTIVATE, TIF_CSRSSTHREAD, tagTHREADINFO::TIF_flags, TIF_SYSTEMTHREAD, TRUE, UP, xxxActivateWindow(), xxxFlashWindow(), and xxxSetForegroundWindow2().

Referenced by xxxActivateOnMinimize(), xxxActivateWindow(), xxxDefWindowProc(), xxxMenuWindowProc(), xxxOldNextWindow(), xxxStubSetForegroundWindow(), xxxSwitchToThisWindow(), and xxxSysCommand().

01238 { 01239 BOOL fNiceCall = TRUE; 01240 BOOL fSyncActivate, fActive; 01241 DWORD dwFlashFlags; 01242 PTHREADINFO ptiCurrent = PtiCurrent(); 01243 PWND pwndFlash; 01244 TL tlpwndFlash; 01245 01246 CheckLock(pwnd); 01247 01248 /* 01249 * If we're trying to set a window on our own thread to the foreground, 01250 * and we're already in the foreground, treat it just like a call to 01251 * SetActiveWindow(). 01252 */ 01253 if ((pwnd != NULL) && (GETPTI(pwnd)->pq == gpqForeground)) { 01254 fSyncActivate = (gpqForeground == ptiCurrent->pq); 01255 if (fSyncActivate) { 01256 gppiWantForegroundPriority = ptiCurrent->ppi; 01257 } else { 01258 gppiWantForegroundPriority = GETPTI(pwnd)->ppi; 01259 } 01260 01261 goto JustActivateIt; 01262 } 01263 /* 01264 * If the foregrond is not locked 01265 * and this thread has the right to changethe foreground, 01266 * then remove the activation right (it's a one-shot deal) 01267 * and do it. 01268 */ 01269 01270 /* 01271 * Bug 247768 - joejo 01272 * Add compatibility hack for foreground activation problems. 01273 * 01274 * To Fix Winstone99, ignore the foreground lock if the input 01275 * provider is making this call. GerardoB. 01276 * 01277 */ 01278 01279 if ((!IsForegroundLocked() || (ptiCurrent->ppi == gppiInputProvider)) 01280 && (ptiCurrent->TIF_flags & (TIF_ALLOWFOREGROUNDACTIVATE | TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD) 01281 || CanForceForeground(ptiCurrent->ppi) 01282 || GiveUpForeground())) { 01283 01284 TAGMSG1(DBGTAG_FOREGROUND, "xxxSetForegroundWindow FRemoveForegroundActivate %#p", ptiCurrent); 01285 01286 FRemoveForegroundActivate(ptiCurrent); 01287 return xxxSetForegroundWindow2(pwnd, ptiCurrent, 0); 01288 } 01289 fNiceCall = FALSE; 01290 TAGMSG3(DBGTAG_FOREGROUND, "xxxSetForegroundWindow: rude call by %#p to %#p-%#p", 01291 ptiCurrent, pwnd, (pwnd != NULL ? GETPTI(pwnd) : NULL)); 01292 if (pwnd == NULL) { 01293 return FALSE; 01294 } 01295 /* 01296 * Notify the user that this pwnd wants to come to the foreground. 01297 * Try to flash a tray button only; otherwise, flash pwnd 01298 */ 01299 if (fFlash) { 01300 pwndFlash = DSW_GetTopLevelCreatorWindow(GetTopLevelWindow(pwnd)); 01301 if (IsTrayWindow(pwndFlash)) { 01302 dwFlashFlags = FLASHW_TRAY; 01303 } else { 01304 pwndFlash = pwnd; 01305 dwFlashFlags = FLASHW_ALL; 01306 } 01307 ThreadLockAlways(pwndFlash, &tlpwndFlash); 01308 xxxFlashWindow(pwndFlash, 01309 MAKELONG(dwFlashFlags | FLASHW_TIMERNOFG, UP(FOREGROUNDFLASHCOUNT)), 01310 0); 01311 ThreadUnlock(&tlpwndFlash); 01312 } 01313 /* 01314 * Activate the window. 01315 */ 01316 fSyncActivate = (ptiCurrent->pq == GETPTI(pwnd)->pq); 01317 01318 JustActivateIt: 01319 01320 if (fSyncActivate) { 01321 fActive = xxxActivateWindow(pwnd, AW_USE); 01322 } else if (pwnd == GETPTI(pwnd)->pq->spwndActive) { 01323 fActive = TRUE; 01324 } else { 01325 fActive = PostEventMessage(GETPTI(pwnd), GETPTI(pwnd)->pq, 01326 QEVENT_ACTIVATE, NULL, 0, 01327 0, (LPARAM)HWq(pwnd)) ; 01328 } 01329 01330 /* 01331 * Return FALSE if we failed the set foreground request. 01332 */ 01333 return fNiceCall && fActive; 01334 }

BOOL xxxSetForegroundWindow2 PWND  pwnd,
PTHREADINFO  pti,
DWORD  fFlags
 

Definition at line 1342 of file focusact.c.

References AllocQEntry(), ATW_SETFOCUS, BOOL, CheckLock, CMSHUNGAPPTIMEOUT, tagQ::cThreads, DWORD, FALSE, FHungApp(), GETPTI, gppiLockSFW, gppiWantForegroundPriority, gpqForeground, gpqForegroundPrev, gptiForeground, grpdeskRitInput, tagWND::head, HMIsMarkDestroy, HW, LockWindowUpdate2(), tagQ::mlInput, NULL, PEM_ACTIVATE_NOZORDER, PEM_ACTIVATE_RESTORE, tagTHREADINFO::pq, PtiCurrent, tagQ::ptiKeyboard, tagQ::ptiMouse, PWND_TOP, QEVENT_ACTIVATE, QEVENT_DEACTIVATE, QF_EVENTDEACTIVATEREMOVED, tagQ::QF_flags, RemoveEventMessage(), tagTHREADINFO::rpdesk, SetForegroundThread(), SetHungFlag(), SetWakeBit(), SFW_ACTIVATERESTORE, SFW_NOZORDER, SFW_SETFOCUS, SFW_STARTUP, SFW_SWITCH, tagQ::spwndActive, StoreQMessage(), StoreQMessagePti(), TestUP, ThreadLockAlwaysWithPti, ThreadLockPti, ThreadUnlock, ThreadUnlockPti, TID, TIDq, tagTHREADINFO::TIF_flags, TIF_INCLEANUP, TRUE, UINT, WFREDRAWFRAMEIFHUNG, xxxActivateThisWindow(), xxxCancelTracking(), xxxDeactivate(), xxxMakeWindowForegroundWithState(), xxxRedrawHungWindowFrame(), xxxSendMessage(), xxxSetWindowPos(), xxxUpdateTray(), zzzActiveCursorTracking(), and zzzClipCursor().

Referenced by xxxActiveWindowTracking(), xxxButtonEvent(), xxxDoHotKeyStuff(), xxxKeyEvent(), xxxMinMaximize(), xxxNextWindow(), xxxProcessEventMessage(), xxxSetFocus(), xxxSetForegroundWindow(), xxxSetThreadDesktop(), and xxxSwitchDesktop().

01346 { 01347 PTHREADINFO ptiForegroundOld; 01348 PTHREADINFO ptiForegroundNew; 01349 PQ pqForegroundOld, pqForegroundNew, pqCurrent; 01350 HWND hwnd; 01351 PQMSG pqmsgDeactivate, pqmsgActivate; 01352 BOOL bRemovedEvent; 01353 PTHREADINFO ptiCurrent = PtiCurrent(); 01354 BOOL retval = TRUE; 01355 UINT uMsg; 01356 CheckLock(pwnd); 01357 01358 /* 01359 * Queue pointers and threadinfo pointers can go away when calling xxx 01360 * calls. Also, queues can get recalced via AttachThreadInput() during 01361 * xxx calls - so we want to reference the application becoming foreground. 01362 * PQs cannot be refcount locked (either thread locked or structure locked) 01363 * so must (re)calculate them after returning from xxx calls. 01364 * 01365 * NOTE: gpqForeground and gpqForegroundPrev are always current and don't 01366 * need special handling. 01367 */ 01368 01369 /* 01370 * Don't allow the foreground to be set to a window that is not 01371 * on the current desktop. 01372 */ 01373 if (pwnd != NULL && (pwnd->head.rpdesk != grpdeskRitInput || 01374 HMIsMarkDestroy(pwnd))) { 01375 return FALSE; 01376 } 01377 01378 /* 01379 * Unlock SetForegroundWindow (if someone had it locked) 01380 */ 01381 gppiLockSFW = NULL; 01382 TAGMSG3(DBGTAG_FOREGROUND, "xxxSetForegroundWindow2 by %#p to %#p-%#p", 01383 ptiCurrent, pwnd, (pwnd != NULL ? GETPTI(pwnd) : NULL)); 01384 01385 /* 01386 * Calculate who is becoming foreground. Also, remember who we want 01387 * foreground (for priority setting reasons). 01388 */ 01389 if ((gptiForeground != NULL) && !(gptiForeground->TIF_flags & TIF_INCLEANUP)) { 01390 ptiForegroundOld = gptiForeground; 01391 } else { 01392 ptiForegroundOld = NULL; 01393 } 01394 pqForegroundOld = NULL; 01395 pqForegroundNew = NULL; 01396 pqCurrent = NULL; 01397 01398 gpqForegroundPrev = gpqForeground; 01399 01400 if (pwnd != NULL) { 01401 ptiForegroundNew = GETPTI(pwnd); 01402 UserAssert(ptiForegroundNew->rpdesk == grpdeskRitInput); 01403 gppiWantForegroundPriority = GETPTI(pwnd)->ppi; 01404 gpqForeground = GETPTI(pwnd)->pq; 01405 UserAssert(gpqForeground->cThreads != 0); 01406 UserAssert(gpqForeground->ptiMouse->rpdesk == grpdeskRitInput); 01407 // Assert to catch AV in xxxNextWindow doing Alt-Esc: If we have a non-NULL 01408 // gpqForeground, its kbd input thread better have an rpdesk! -IanJa 01409 UserAssert(!gpqForeground || (gpqForeground->ptiKeyboard && gpqForeground->ptiKeyboard->rpdesk)); 01410 SetForegroundThread(GETPTI(pwnd)); 01411 } else { 01412 ptiForegroundNew = NULL; 01413 gppiWantForegroundPriority = NULL; 01414 gpqForeground = NULL; 01415 SetForegroundThread(NULL); 01416 } 01417 01418 /* 01419 * Are we switching the foreground queue? 01420 */ 01421 if (gpqForeground != gpqForegroundPrev) { 01422 TL tlptiForegroundOld; 01423 TL tlptiForegroundNew; 01424 TL tlpti; 01425 01426 ThreadLockPti(ptiCurrent, ptiForegroundOld, &tlptiForegroundOld); 01427 ThreadLockPti(ptiCurrent, ptiForegroundNew, &tlptiForegroundNew); 01428 ThreadLockPti(ptiCurrent, pti, &tlpti); 01429 01430 /* 01431 * If this call didn't come from the RIT, cancel tracking 01432 * and other global states. 01433 */ 01434 if (pti != NULL) { 01435 01436 /* 01437 * Clear any visible tracking going on in system. 01438 */ 01439 xxxCancelTracking(); 01440 01441 /* 01442 * Remove the clip cursor rectangle - it is a global mode that 01443 * gets removed when switching. Also remove any LockWindowUpdate() 01444 * that's still around. 01445 */ 01446 zzzClipCursor(NULL); 01447 LockWindowUpdate2(NULL, TRUE); 01448 01449 /* 01450 * Make sure the desktop of the newly activated window is the 01451 * foreground fullscreen window 01452 */ 01453 xxxMakeWindowForegroundWithState(NULL, 0); 01454 } 01455 01456 /* 01457 * We've potentially done callbacks. Calculate pqForegroundOld 01458 * based on our locked local variable ptiForegroundOld. 01459 */ 01460 pqForegroundOld = NULL; 01461 if (ptiForegroundOld && !(ptiForegroundOld->TIF_flags & TIF_INCLEANUP)) { 01462 pqForegroundOld = ptiForegroundOld->pq; 01463 } 01464 01465 pqCurrent = NULL; 01466 if (pti != NULL) 01467 pqCurrent = pti->pq; 01468 01469 /* 01470 * Now allocate message for the deactivation 01471 */ 01472 pqmsgDeactivate = pqmsgActivate = NULL; 01473 01474 if ((pqForegroundOld != NULL) && (pqForegroundOld != pqCurrent)) { 01475 if ((pqmsgDeactivate = AllocQEntry(&pqForegroundOld->mlInput)) == 01476 NULL) { 01477 retval = FALSE; 01478 goto Exit; 01479 } 01480 } 01481 01482 /* 01483 * Do any appropriate deactivation. 01484 */ 01485 if (pqForegroundOld != NULL) { 01486 01487 /* 01488 * If we're already on the foreground queue we'll call 01489 * xxxDeactivate() directly later in this routine since 01490 * it'll cause us to leave the critical section. 01491 */ 01492 if (pqForegroundOld != pqCurrent) { 01493 StoreQMessage(pqmsgDeactivate, NULL, 0, 01494 gptiForeground != NULL ? (WPARAM)gptiForeground->pEThread->Cid.UniqueThread : 0, 01495 0, 0, QEVENT_DEACTIVATE, 0); 01496 01497 /* 01498 * If there was an old foreground thread, make it perform 01499 * the deactivation. Otherwise, any thread on the queue 01500 * can perform the deactivation. 01501 */ 01502 if (ptiForegroundOld != NULL) { 01503 SetWakeBit(ptiForegroundOld, QS_EVENTSET); 01504 01505 StoreQMessagePti(pqmsgDeactivate, ptiForegroundOld); 01506 01507 } 01508 01509 if (pqForegroundOld->spwndActive != NULL) { 01510 if (ptiForegroundOld != NULL && FHungApp(ptiForegroundOld, CMSHUNGAPPTIMEOUT)) { 01511 TL tlpwnd; 01512 ThreadLockAlwaysWithPti(ptiCurrent, pqForegroundOld->spwndActive, &tlpwnd); 01513 xxxRedrawHungWindowFrame(pqForegroundOld->spwndActive, FALSE); 01514 ThreadUnlock(&tlpwnd); 01515 } else { 01516 SetHungFlag(pqForegroundOld->spwndActive, WFREDRAWFRAMEIFHUNG); 01517 } 01518 } 01519 } 01520 } 01521 01522 /* 01523 * We've potentially done callbacks. Calculate pqForegroundNew 01524 * based on our locked local variable ptiForegroundNew. 01525 */ 01526 pqForegroundNew = NULL; 01527 if (ptiForegroundNew && !(ptiForegroundNew->TIF_flags & TIF_INCLEANUP)) { 01528 pqForegroundNew = ptiForegroundNew->pq; 01529 } 01530 01531 /* 01532 * Update pqCurrent since we may have made an xxx call, 01533 * and this variable may be invalid. 01534 */ 01535 pqCurrent = NULL; 01536 if (pti != NULL) { 01537 pqCurrent = pti->pq; 01538 } 01539 01540 if ((pqForegroundNew != NULL) && (pqForegroundNew != pqCurrent)) { 01541 pqmsgActivate = AllocQEntry(&pqForegroundNew->mlInput); 01542 if (pqmsgActivate == NULL) { 01543 retval = FALSE; 01544 goto Exit; 01545 } 01546 } 01547 01548 /* 01549 * Do any appropriate activation. 01550 */ 01551 if (pqForegroundNew != NULL) { 01552 /* 01553 * We're going to activate (synchronously or async with an activate 01554 * event). We want to remove the last deactivate event if there is 01555 * one because this is new state. If we don't, then 1> we could 01556 * synchronously activate and then asynchronously deactivate, 01557 * thereby processing these events out of order, or 2> we could 01558 * pile up a chain of deactivate / activate events which would 01559 * make the titlebar flash alot if the app wasn't responding to 01560 * input for awhile (in this case, it doesn't matter if we 01561 * put a redundant activate in the queue, since the app is already 01562 * active. Remove all deactivate events because this app is 01563 * setting a state that is not meant to be synchronized with 01564 * existing queued input. 01565 * 01566 * Case: run setup, switch away (it gets deactivate event). setup 01567 * is not reading messages so it hasn't go it yet. It finally 01568 * comes up, calls SetForegroundWindow(). It's synchronous, 01569 * it activates ok and sets foreground. Then the app calls 01570 * GetMessage() and gets the deactivate. Now it isn't active. 01571 */ 01572 bRemovedEvent = RemoveEventMessage(pqForegroundNew, QEVENT_DEACTIVATE, (DWORD)-1); 01573 01574 /* 01575 * Now do any appropriate activation. See comment below 01576 * for special cases. If we're already on the foreground 01577 * queue we'll call xxxActivateThisWindow() directly. 01578 */ 01579 if (pqForegroundNew != pqCurrent) { 01580 01581 /* 01582 * We do the 'pqCurrent == NULL' test to see if we're being 01583 * called from the RIT. In this case we pass NULL for the 01584 * HWND which will check to see if there is already an active 01585 * window for the thread and redraw its frame as truly active 01586 * since it's in the foreground now. It will also cancel any 01587 * global state like LockWindowUpdate() and ClipRect(). 01588 */ 01589 if ((pqCurrent == NULL) && (!(fFlags & SFW_SWITCH))) { 01590 hwnd = NULL; 01591 } else { 01592 hwnd = HW(pwnd); 01593 } 01594 01595 if (bRemovedEvent) { 01596 pqForegroundNew->QF_flags |= QF_EVENTDEACTIVATEREMOVED; 01597 } 01598 /* 01599 * MSMail relies on a specific order to how win3.1 does 01600 * fast switch alt-tab activation. On win3.1, it essentially 01601 * activates the window, then restores it. MsMail gets confused 01602 * if it isn't active when it gets restored, so this logic 01603 * will make sure msmail gets restore after it gets activated. 01604 * 01605 * Click on a message line in the in-box, minimize msmail, 01606 * alt-tab to it. The same line should have the focus if msmail 01607 * got restored after it got activated. 01608 * 01609 * This is the history behind SFW_ACTIVATERESTORE. 01610 */ 01611 if (fFlags & SFW_ACTIVATERESTORE) { 01612 uMsg = PEM_ACTIVATE_RESTORE; 01613 } else { 01614 uMsg = 0; 01615 } 01616 01617 if (fFlags & SFW_NOZORDER) { 01618 uMsg |= PEM_ACTIVATE_NOZORDER; 01619 } 01620 01621 StoreQMessage(pqmsgActivate, NULL, uMsg, 01622 (fFlags & SFW_STARTUP) ? 0 : (WPARAM)TID(ptiForegroundOld), 01623 (LPARAM)hwnd, 0, QEVENT_ACTIVATE, 0); 01624 01625 01626 /* 01627 * Signal the window's thread to perform activation. We 01628 * know that ptiForegroundNew is valid because pqForegroundNew 01629 * is not NULL. 01630 */ 01631 01632 StoreQMessagePti(pqmsgActivate, ptiForegroundNew); 01633 01634 SetWakeBit(ptiForegroundNew, QS_EVENTSET); 01635 01636 if (pqForegroundNew->spwndActive != NULL) { 01637 if (FHungApp(ptiForegroundNew, CMSHUNGAPPTIMEOUT)) { 01638 TL tlpwnd; 01639 ThreadLockAlwaysWithPti(ptiCurrent, pqForegroundNew->spwndActive, &tlpwnd); 01640 xxxRedrawHungWindowFrame(pqForegroundNew->spwndActive, TRUE); 01641 ThreadUnlock(&tlpwnd); 01642 } else { 01643 SetHungFlag(pqForegroundNew->spwndActive, WFREDRAWFRAMEIFHUNG); 01644 } 01645 } 01646 01647 } else { 01648 if (pwnd != pqCurrent->spwndActive) { 01649 if (!(fFlags & SFW_STARTUP)) { 01650 retval = xxxActivateThisWindow(pwnd, TID(ptiForegroundOld), 01651 ((fFlags & SFW_SETFOCUS) ? 0 : ATW_SETFOCUS)); 01652 01653 /* 01654 * Make sure the mouse is on this window. 01655 */ 01656 if (retval && TestUP(ACTIVEWINDOWTRACKING)) { 01657 zzzActiveCursorTracking(pwnd); 01658 } 01659 goto Exit; 01660 } 01661 01662 } else { 01663 01664 /* 01665 * If pwnd is already the active window, just make sure 01666 * it's drawn active and on top (if requested). 01667 */ 01668 xxxSendMessage(pwnd, WM_NCACTIVATE, 01669 TRUE, 01670 (LPARAM)HW(pwnd)); 01671 xxxUpdateTray(pwnd); 01672 if (!(fFlags & SFW_NOZORDER)) { 01673 xxxSetWindowPos(pwnd, PWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 01674 } 01675 } 01676 } 01677 01678 01679 } /* if (pqForegroundNew != NULL) */ 01680 01681 /* 01682 * First update pqForegroundOld and pqCurrent since we may have 01683 * made an xxx call, and these variables may be invalid. 01684 */ 01685 pqForegroundOld = NULL; 01686 if (ptiForegroundOld && !(ptiForegroundOld->TIF_flags & TIF_INCLEANUP)) { 01687 pqForegroundOld = ptiForegroundOld->pq; 01688 } 01689 01690 pqCurrent = NULL; 01691 if (pti != NULL) 01692 pqCurrent = pti->pq; 01693 01694 /* 01695 * Now check to see if we needed to do any 'local' deactivation. 01696 * (ie. were we on the queue that is being deactivated by this 01697 * SetForegroundWindow() call?) 01698 */ 01699 if ((pqForegroundOld != NULL) && (pqForegroundOld == pqCurrent)) { 01700 xxxDeactivate(pti, (pwnd != NULL) ? TIDq(GETPTI(pwnd)) : 0); 01701 } 01702 Exit: 01703 ThreadUnlockPti(ptiCurrent, &tlpti); 01704 ThreadUnlockPti(ptiCurrent, &tlptiForegroundNew); 01705 ThreadUnlockPti(ptiCurrent, &tlptiForegroundOld); 01706 } 01707 01708 return retval; 01709 }

BOOL xxxStubSetForegroundWindow PWND  pwnd  ) 
 

Definition at line 1230 of file focusact.c.

References BOOL, TRUE, and xxxSetForegroundWindow().

01232 { 01233 return xxxSetForegroundWindow(pwnd, TRUE); 01234 }

void xxxUpdateTray PWND  pwnd  ) 
 

Definition at line 374 of file focusact.c.

References BOOL, CheckLock, FALSE, FCallHookTray, FDoTray, FHas31TrayStyles, FPostTray, FTopLevel, GETPTI, gpqForeground, tagWND::head, Is31TrayWindow(), IsTrayWindow(), NULL, tagWND::spwndLastActive, tagWND::spwndOwner, TestWF, ThreadLock, ThreadUnlock, TRUE, WEFTOOLWINDOW, WFVISIBLE, WFWIN40COMPAT, and xxxSetTrayWindow().

Referenced by xxxActivateThisWindow(), xxxProcessEventMessage(), and xxxSetForegroundWindow2().

00375 { 00376 PWND pwndT; 00377 00378 CheckLock(pwnd); 00379 if (!TestWF(pwnd, WFVISIBLE)) { 00380 return; 00381 } 00382 00383 for (pwndT = pwnd; pwndT->spwndOwner; pwndT = pwndT->spwndOwner) { 00384 } 00385 00386 // Notify the shell hook about this activation change 00387 if ( GETPTI(pwndT)->pq == gpqForeground && 00388 FDoTray() && 00389 (FCallHookTray() || FPostTray(pwndT->head.rpdesk)) && 00390 FTopLevel(pwndT) && 00391 TestWF(pwndT, WFVISIBLE)) 00392 { 00393 BOOL fFirstTry; 00394 BOOL fTryAgain; 00395 PWND pwndArg; 00396 TL tlpwndArg; 00397 00398 fFirstTry = TRUE; 00399 do { 00400 fTryAgain = FALSE; 00401 if (TestWF(pwndT, WFWIN40COMPAT)) { 00402 if (TestWF(pwnd, WFWIN40COMPAT) && IsTrayWindow(pwnd)) { 00403 pwndArg = pwnd; 00404 } else { 00405 pwndArg = IsTrayWindow(pwndT) ? pwndT : NULL; 00406 } 00407 } else { 00408 if (TestWF(pwndT, WEFTOOLWINDOW)) { 00409 pwndArg = NULL; 00410 } else if (FHas31TrayStyles(pwndT)) { 00411 pwndArg = Is31TrayWindow(pwndT) ? pwndT : NULL; 00412 } else if (fFirstTry && (pwndT = pwndT->spwndLastActive)) { 00413 fFirstTry = FALSE; 00414 fTryAgain = TRUE; 00415 } else { 00416 return; 00417 } 00418 } 00419 } while (fTryAgain); 00420 00421 ThreadLock(pwndArg, &tlpwndArg); 00422 xxxSetTrayWindow( 00423 (pwndArg) ? pwndArg->head.rpdesk : pwndT->head.rpdesk, 00424 pwndArg, 00425 NULL); 00426 00427 ThreadUnlock(&tlpwndArg); 00428 } 00429 }


Generated on Sat May 15 19:43:44 2004 for test by doxygen 1.3.7