ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

focus.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:        See COPYING in the top level directory
00003  * PROJECT:          ReactOS Win32k subsystem
00004  * PURPOSE:          Focus functions
00005  * FILE:             subsystems/win32/win32k/ntuser/focus.c
00006  * PROGRAMER:        ReactOS Team
00007  */
00008 
00009 #include <win32k.h>
00010 DBG_DEFAULT_CHANNEL(UserFocus);
00011 
00012 PUSER_MESSAGE_QUEUE gpqForeground = NULL;
00013 PUSER_MESSAGE_QUEUE gpqForegroundPrev = NULL;
00014 PTHREADINFO gptiForeground = NULL;
00015 PPROCESSINFO gppiLockSFW = NULL;
00016 ULONG guSFWLockCount = 0; // Rule #8, No menus are active. So should be zero.
00017 PTHREADINFO ptiLastInput = NULL;
00018 
00019 /*
00020   Check locking of a process or one or more menus are active.
00021 */
00022 BOOL FASTCALL
00023 IsFGLocked(VOID)
00024 {
00025    return (gppiLockSFW || guSFWLockCount);
00026 }
00027 
00028 HWND FASTCALL
00029 IntGetCaptureWindow(VOID)
00030 {
00031    PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
00032    return ForegroundQueue != NULL ? ForegroundQueue->CaptureWindow : 0;
00033 }
00034 
00035 HWND FASTCALL
00036 IntGetThreadFocusWindow(VOID)
00037 {
00038    PTHREADINFO pti;
00039    PUSER_MESSAGE_QUEUE ThreadQueue;
00040 
00041    pti = PsGetCurrentThreadWin32Thread();
00042    ThreadQueue = pti->MessageQueue;
00043    if (!ThreadQueue)
00044      return NULL;
00045    return ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0;
00046 }
00047 
00048 VOID FASTCALL
00049 co_IntSendDeactivateMessages(HWND hWndPrev, HWND hWnd)
00050 {
00051     PWND WndPrev ;
00052 
00053    if (hWndPrev && (WndPrev = UserGetWindowObject(hWndPrev)))
00054    {
00055       co_IntSendMessageNoWait(hWndPrev, WM_NCACTIVATE, FALSE, 0);
00056       co_IntSendMessageNoWait(hWndPrev, WM_ACTIVATE,
00057                  MAKEWPARAM(WA_INACTIVE, WndPrev->style & WS_MINIMIZE),
00058                  (LPARAM)hWnd);
00059    }
00060 }
00061 
00062 BOOL FASTCALL
00063 co_IntMakeWindowActive(PWND Window)
00064 {
00065   PWND spwndOwner;
00066   if (Window)
00067   {  // Set last active for window and it's owner.
00068      Window->spwndLastActive = Window;
00069      spwndOwner = Window->spwndOwner;
00070      while (spwndOwner)
00071      {
00072        spwndOwner->spwndLastActive = Window;
00073        spwndOwner = spwndOwner->spwndOwner;
00074      }
00075      return TRUE;
00076    }
00077    ERR("MakeWindowActive Failed!\n");
00078    return FALSE;
00079 }
00080 
00081 VOID FASTCALL
00082 co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate)
00083 {
00084    USER_REFERENCE_ENTRY Ref, RefPrev;
00085    PWND Window, WindowPrev = NULL;
00086    HANDLE OldTID, NewTID;
00087    PTHREADINFO ptiOld, ptiNew;
00088 
00089    if ((Window = UserGetWindowObject(hWnd)))
00090    { 
00091       UserRefObjectCo(Window, &Ref);
00092 
00093       WindowPrev = UserGetWindowObject(hWndPrev);
00094 
00095       if (WindowPrev) UserRefObjectCo(WindowPrev, &RefPrev);
00096 
00097       /* Send palette messages */
00098       if (gpsi->PUSIFlags & PUSIF_PALETTEDISPLAY &&
00099           co_IntPostOrSendMessage(hWnd, WM_QUERYNEWPALETTE, 0, 0))
00100       {
00101          UserSendNotifyMessage( HWND_BROADCAST,
00102                                 WM_PALETTEISCHANGING,
00103                                (WPARAM)hWnd,
00104                                 0);
00105       }
00106 
00107       if (Window->spwndPrev != NULL)
00108          co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0,
00109                                SWP_NOSIZE | SWP_NOMOVE);
00110 
00111       if (!Window->spwndOwner && !IntGetParent(Window))
00112       {
00113          co_IntShellHookNotify(HSHELL_WINDOWACTIVATED, (LPARAM) hWnd);
00114       }
00115 
00116       if (Window)
00117       {
00118          Window->state |= WNDS_ACTIVEFRAME;
00119 
00120          if (Window->style & WS_MINIMIZE)
00121          {
00122             TRACE("Widow was minimized\n");
00123          }
00124       }
00125 
00126       if (WindowPrev)
00127          WindowPrev->state &= ~WNDS_ACTIVEFRAME;
00128 
00129       OldTID = WindowPrev ? IntGetWndThreadId(WindowPrev) : NULL;
00130       NewTID = Window ? IntGetWndThreadId(Window) : NULL;
00131       ptiOld = WindowPrev ? WindowPrev->head.pti : NULL;
00132       ptiNew = Window ? Window->head.pti : NULL;
00133 
00134       TRACE("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID);
00135 
00136       if (OldTID != NewTID)
00137       {
00138          PWND cWindow;
00139          HWND *List, *phWnd;
00140 
00141          List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow()));
00142          if ( List )
00143          {
00144             if ( OldTID )
00145             {
00146                for (phWnd = List; *phWnd; ++phWnd)
00147                {
00148                   cWindow = UserGetWindowObject(*phWnd);
00149                   if (cWindow && cWindow->head.pti == ptiOld)
00150                   {  // FALSE if the window is being deactivated,
00151                      // ThreadId that owns the window being activated.
00152                     co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID);
00153                   }
00154                }
00155             }
00156             if ( NewTID )
00157             {
00158                for (phWnd = List; *phWnd; ++phWnd)
00159                {
00160                   cWindow = UserGetWindowObject(*phWnd);
00161                   if (cWindow && cWindow->head.pti == ptiNew)
00162                   { // TRUE if the window is being activated,
00163                     // ThreadId that owns the window being deactivated.
00164                     co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID);
00165                   }
00166                }
00167             }
00168             ExFreePool(List);
00169          }
00170       }
00171       if (WindowPrev)
00172          UserDerefObjectCo(WindowPrev); // Now allow the previous window to die.
00173 
00174       UserDerefObjectCo(Window);
00175 
00176       /* FIXME: IntIsWindow */
00177       co_IntSendMessageNoWait(hWnd, WM_NCACTIVATE, (WPARAM)(hWnd == UserGetForegroundWindow()), 0);
00178       /* FIXME: WA_CLICKACTIVE */
00179       co_IntSendMessageNoWait(hWnd, WM_ACTIVATE,
00180                               MAKEWPARAM(MouseActivate ? WA_CLICKACTIVE : WA_ACTIVE,
00181                               Window->style & WS_MINIMIZE),
00182                               (LPARAM)hWndPrev);
00183    }
00184 }
00185 
00186 VOID FASTCALL
00187 co_IntSendKillFocusMessages(HWND hWndPrev, HWND hWnd)
00188 {
00189    if (hWndPrev)
00190    {
00191       IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
00192       co_IntPostOrSendMessage(hWndPrev, WM_KILLFOCUS, (WPARAM)hWnd, 0);
00193    }
00194 }
00195 
00196 VOID FASTCALL
00197 co_IntSendSetFocusMessages(HWND hWndPrev, HWND hWnd)
00198 {
00199    if (hWnd)
00200    {
00201       PWND pWnd = UserGetWindowObject(hWnd);
00202       if (pWnd)
00203       {
00204          IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0);
00205          co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0);
00206       }
00207    }
00208 }
00209 
00210 HWND FASTCALL
00211 IntFindChildWindowToOwner(PWND Root, PWND Owner)
00212 {
00213    HWND Ret;
00214    PWND Child, OwnerWnd;
00215 
00216    for(Child = Root->spwndChild; Child; Child = Child->spwndNext)
00217    {
00218        OwnerWnd = Child->spwndOwner;
00219       if(!OwnerWnd)
00220          continue;
00221 
00222       if(OwnerWnd == Owner)
00223       {
00224          Ret = Child->head.h;
00225          return Ret;
00226       }
00227    }
00228 
00229    return NULL;
00230 }
00231 
00232 VOID FASTCALL
00233 FindRemoveAsyncMsg(PWND Wnd)
00234 {
00235    PUSER_MESSAGE_QUEUE MessageQueue;
00236    PUSER_SENT_MESSAGE Message;
00237    PLIST_ENTRY Entry;
00238 
00239    if (!Wnd) return;
00240 
00241    MessageQueue = Wnd->head.pti->MessageQueue;
00242 
00243    if (!IsListEmpty(&MessageQueue->SentMessagesListHead))
00244    {
00245       // Scan sent queue messages to see if we received async messages.
00246       Entry = MessageQueue->SentMessagesListHead.Flink;
00247       Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
00248       do
00249       {
00250          if (Message->Msg.message == WM_ASYNC_SETACTIVEWINDOW &&
00251              Message->Msg.hwnd == UserHMGetHandle(Wnd) &&
00252              Message->Msg.wParam == 0 )
00253          {
00254              TRACE("ASYNC SAW: Found one in the Sent Msg Queue! %p\n", Message->Msg.hwnd);
00255              RemoveEntryList(Entry); // Purge the entry.
00256          }
00257          Entry = Message->ListEntry.Flink;
00258          Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
00259       }
00260       while (Entry != &MessageQueue->SentMessagesListHead);
00261    }
00262 }
00263 
00264 /*
00265    Can the system force foreground from one or more conditions.
00266  */
00267 BOOL FASTCALL
00268 CanForceFG(PPROCESSINFO ppi)
00269 {
00270    if (!ptiLastInput ||
00271         ptiLastInput->ppi == ppi ||
00272        !gptiForeground ||
00273         gptiForeground->ppi == ppi ||
00274         ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_SETFOREGROUNDALLOWED) ||
00275         gppiInputProvider == ppi ||
00276        !gpqForeground
00277       ) return TRUE;
00278    return FALSE;
00279 }
00280 
00281 /*
00282    MSDN:
00283    The system restricts which processes can set the foreground window. A process
00284    can set the foreground window only if one of the following conditions is true: 
00285 
00286     * The process is the foreground process.
00287     * The process was started by the foreground process.
00288     * The process received the last input event.
00289     * There is no foreground process.
00290     * The foreground process is being debugged.
00291     * The foreground is not locked (see LockSetForegroundWindow).
00292     * The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo). 
00293     * No menus are active.
00294 */
00295 
00296 static BOOL FASTCALL
00297 co_IntSetForegroundAndFocusWindow(PWND Wnd, BOOL MouseActivate)
00298 {
00299    HWND hWnd = UserHMGetHandle(Wnd);
00300    HWND hWndPrev = NULL;
00301    PUSER_MESSAGE_QUEUE PrevForegroundQueue;
00302    PTHREADINFO pti;
00303    BOOL fgRet = FALSE, Ret = FALSE;
00304 
00305    ASSERT_REFS_CO(Wnd);
00306 
00307    TRACE("SetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd, MouseActivate ? "TRUE" : "FALSE");
00308 
00309    PrevForegroundQueue = IntGetFocusMessageQueue(); // Use this active desktop.
00310    pti = PsGetCurrentThreadWin32Thread();
00311 
00312    if (PrevForegroundQueue)
00313    {  // Same Window Q as foreground just do active.
00314       if (Wnd && Wnd->head.pti->MessageQueue == PrevForegroundQueue)
00315       {
00316          if (pti->MessageQueue == PrevForegroundQueue)
00317          { // Same WQ and TQ go active.
00318             Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE);
00319          }
00320          else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd)
00321          { // Same WQ and it is active.
00322             Ret = TRUE;
00323          }
00324          else
00325          { // Same WQ as FG but not the same TQ send active.
00326             co_IntSendMessageNoWait(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate );
00327             Ret = TRUE;
00328          }
00329          return Ret;
00330       }
00331 
00332       hWndPrev = PrevForegroundQueue->spwndActive ? UserHMGetHandle(PrevForegroundQueue->spwndActive) : 0;
00333    }
00334 
00335    if ( (( !IsFGLocked() || pti->ppi == gppiInputProvider ) &&
00336          ( CanForceFG(pti->ppi) || pti->TIF_flags & (TIF_SYSTEMTHREAD|TIF_CSRSSTHREAD|TIF_ALLOWFOREGROUNDACTIVATE) )) ||
00337         pti->ppi == ppiScrnSaver
00338       )
00339    { 
00340       IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue);
00341       gptiForeground = Wnd->head.pti;
00342 /*
00343      Henri Verbeet,
00344      What happens is that we get the WM_WINE_SETACTIVEWINDOW message sent by the
00345      other thread after we already changed the foreground window back to our own
00346      window.
00347  */
00348       FindRemoveAsyncMsg(Wnd); // Do this to fix test_SFW todos!
00349       fgRet = TRUE;
00350    } 
00351 
00352    //  Fix FG Bounce with regedit.
00353    if (hWndPrev != hWnd )
00354    {
00355       if (PrevForegroundQueue &&
00356           fgRet &&
00357           Wnd->head.pti->MessageQueue != PrevForegroundQueue &&
00358           PrevForegroundQueue->spwndActive)
00359       {
00360          //ERR("SFGW: Send NULL to 0x%x\n",hWndPrev);
00361          if (pti->MessageQueue == PrevForegroundQueue)
00362          {
00363             //ERR("SFGW: TI same as Prev TI\n");
00364             co_IntSetActiveWindow(NULL, NULL, FALSE, TRUE);
00365          }
00366          else
00367          co_IntSendMessageNoWait(hWndPrev, WM_ASYNC_SETACTIVEWINDOW, 0, 0 );
00368       }
00369    }
00370 
00371    if (pti->MessageQueue == Wnd->head.pti->MessageQueue)
00372    {
00373        Ret = co_IntSetActiveWindow(Wnd, NULL, MouseActivate, TRUE);
00374    }
00375    else if (Wnd->head.pti->MessageQueue->spwndActive == Wnd)
00376    {
00377        Ret = TRUE;
00378    }
00379    else
00380    {
00381        co_IntSendMessageNoWait(hWnd, WM_ASYNC_SETACTIVEWINDOW, (WPARAM)Wnd, (LPARAM)MouseActivate );
00382        Ret = TRUE;
00383    }
00384 
00385    return Ret && fgRet;
00386 }
00387 
00388 BOOL FASTCALL
00389 co_IntMouseActivateWindow(PWND Wnd)
00390 {
00391    HWND Top;
00392    PWND TopWindow;
00393    USER_REFERENCE_ENTRY Ref;
00394 
00395    ASSERT_REFS_CO(Wnd);
00396 
00397    if (Wnd->style & WS_DISABLED)
00398    {
00399       BOOL Ret;
00400       PWND TopWnd;
00401       PWND DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
00402       if (DesktopWindow)
00403       {
00404          Top = IntFindChildWindowToOwner(DesktopWindow, Wnd);
00405          if ((TopWnd = UserGetWindowObject(Top)))
00406          {
00407             UserRefObjectCo(TopWnd, &Ref);
00408             Ret = co_IntMouseActivateWindow(TopWnd);
00409             UserDerefObjectCo(TopWnd);
00410 
00411             return Ret;
00412          }
00413       }
00414       return FALSE;
00415    }
00416 
00417    TopWindow = UserGetAncestor(Wnd, GA_ROOT);
00418    if (!TopWindow) return FALSE;
00419 
00420    /* TMN: Check return valud from this function? */
00421    UserRefObjectCo(TopWindow, &Ref);
00422 
00423    co_IntSetForegroundAndFocusWindow(TopWindow, TRUE);
00424 
00425    UserDerefObjectCo(TopWindow);
00426 
00427    return TRUE;
00428 }
00429 
00430 BOOL FASTCALL
00431 co_IntSetActiveWindow(PWND Wnd OPTIONAL, HWND * Prev, BOOL bMouse, BOOL bFocus)
00432 {
00433    PTHREADINFO pti;
00434    PUSER_MESSAGE_QUEUE ThreadQueue;
00435    HWND hWndPrev;
00436    HWND hWnd = 0;
00437    CBTACTIVATESTRUCT cbt;
00438 
00439    if (Wnd)
00440    {
00441       ASSERT_REFS_CO(Wnd);
00442       hWnd = UserHMGetHandle(Wnd);
00443    }
00444 
00445    pti = PsGetCurrentThreadWin32Thread();
00446    ThreadQueue = pti->MessageQueue;
00447    ASSERT(ThreadQueue != 0);
00448 
00449    hWndPrev = ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : NULL;
00450    if (Prev) *Prev = hWndPrev;
00451    if (hWndPrev == hWnd) return TRUE;
00452 
00453    if (Wnd)
00454    {
00455       if (ThreadQueue != Wnd->head.pti->MessageQueue)
00456       {
00457          PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
00458          // Rule 1 & 4, We are foreground so set this FG window or NULL foreground....
00459          if (!ForegroundQueue || ForegroundQueue == ThreadQueue)
00460          {
00461             return co_IntSetForegroundAndFocusWindow(Wnd, bMouse);
00462          }
00463       }
00464 
00465       if (Wnd->state & WNDS_BEINGACTIVATED) return TRUE;
00466    }
00467 
00468    /* Call CBT hook chain */
00469    cbt.fMouse     = bMouse;
00470    cbt.hWndActive = hWndPrev;
00471    if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt))
00472    {
00473       ERR("SetActiveWindow WH_CBT Call Hook return!\n");
00474       return FALSE;
00475    }
00476 
00477    co_IntSendDeactivateMessages(hWndPrev, hWnd);
00478 
00479    if (Wnd) Wnd->state |= WNDS_BEINGACTIVATED;
00480 
00481    IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
00482 
00483    /* check if the specified window can be set in the input data of a given queue */
00484    if ( !Wnd || ThreadQueue == Wnd->head.pti->MessageQueue)
00485    {
00486       /* set the current thread active window */
00487       if (!Wnd || co_IntMakeWindowActive(Wnd))
00488       {
00489          ThreadQueue->spwndActivePrev = ThreadQueue->spwndActive;
00490          ThreadQueue->spwndActive = Wnd;
00491       }
00492    }
00493 
00494    co_IntSendActivateMessages(hWndPrev, hWnd, bMouse);
00495 
00496    /* now change focus if necessary */
00497    if (bFocus)
00498    {
00499       /* Do not change focus if the window is no longer active */
00500       if (ThreadQueue->spwndActive == Wnd)
00501       {
00502          if (!ThreadQueue->spwndFocus ||
00503              !Wnd ||
00504               UserGetAncestor(ThreadQueue->spwndFocus, GA_ROOT) != Wnd)
00505          {
00506             co_UserSetFocus(Wnd);
00507          }
00508       }
00509    }
00510 
00511    if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED;
00512    return TRUE;
00513 }
00514 
00515 HWND FASTCALL
00516 co_UserSetFocus(PWND Window)
00517 {
00518    HWND hWndPrev = 0;
00519    PWND pwndTop;
00520    PTHREADINFO pti;
00521    PUSER_MESSAGE_QUEUE ThreadQueue;
00522 
00523    if (Window)
00524       ASSERT_REFS_CO(Window);
00525 
00526    pti = PsGetCurrentThreadWin32Thread();
00527    ThreadQueue = pti->MessageQueue;
00528    ASSERT(ThreadQueue != 0);
00529 
00530    hWndPrev = ThreadQueue->spwndFocus ? UserHMGetHandle(ThreadQueue->spwndFocus) : 0;
00531 
00532    if (Window != 0)
00533    {
00534       if (hWndPrev == UserHMGetHandle(Window))
00535       {
00536          return hWndPrev; /* Nothing to do */
00537       }
00538 
00539       if (Window->head.pti->MessageQueue != ThreadQueue)
00540       {
00541          ERR("SetFocus Must have the same Q!\n");
00542          return 0;
00543       }
00544 
00545       /* Check if we can set the focus to this window */
00546       pwndTop = Window;
00547       for (;;)
00548       {
00549          if (pwndTop->style & (WS_MINIMIZED|WS_DISABLED)) return 0;
00550          if (!pwndTop->spwndParent || pwndTop->spwndParent == UserGetDesktopWindow())
00551          {
00552             if ((pwndTop->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return 0;
00553             break;         
00554          }
00555          if (pwndTop->spwndParent == UserGetMessageWindow()) return 0;
00556          pwndTop = pwndTop->spwndParent;
00557       }
00558 
00559       if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev))
00560       {
00561          ERR("SetFocus 1 WH_CBT Call Hook return!\n");
00562          return 0;
00563       }
00564 
00565       /* Activate pwndTop if needed. */
00566       if (pwndTop != ThreadQueue->spwndActive)
00567       {
00568          PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue(); // Keep it based on desktop.
00569          if (ThreadQueue != ForegroundQueue) // HACK see rule 2 & 3.
00570          {
00571             if (!co_IntSetForegroundAndFocusWindow(pwndTop, FALSE))
00572             {
00573                ERR("SetFocus Set Foreground and Focus Failed!\n");
00574                return 0;
00575             }
00576          }
00577 
00578          /* Set Active when it is needed. */
00579          if (pwndTop != ThreadQueue->spwndActive)
00580          {
00581             if (!co_IntSetActiveWindow(pwndTop, NULL, FALSE, FALSE))
00582             {
00583                ERR("SetFocus Set Active Failed!\n");
00584                return 0;
00585             }
00586          }
00587 
00588          /* Abort if window destroyed */
00589          if (Window->state2 & WNDS2_INDESTROY) return 0;
00590          /* Do not change focus if the window is no longer active */
00591          if (pwndTop != ThreadQueue->spwndActive)
00592          {
00593             ERR("SetFocus Top window did not go active!\n");
00594             return 0;
00595          }
00596       }
00597 
00598       /* check if the specified window can be set in the input data of a given queue */
00599       if ( !Window || ThreadQueue == Window->head.pti->MessageQueue)
00600          /* set the current thread focus window */
00601          ThreadQueue->spwndFocus = Window;
00602 
00603       TRACE("Focus: %d -> %d\n", hWndPrev, Window->head.h);
00604 
00605       co_IntSendKillFocusMessages(hWndPrev, Window->head.h);
00606       co_IntSendSetFocusMessages(hWndPrev, Window->head.h);
00607    }
00608    else /* NULL hwnd passed in */
00609    {
00610       if (!hWndPrev) return 0; /* nothing to do */
00611       if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
00612       {
00613          ERR("SetFocusWindow 2 WH_CBT Call Hook return!\n");
00614          return 0;
00615       }
00616 
00617       /* set the current thread focus window null */
00618       ThreadQueue->spwndFocus = 0;
00619 
00620       co_IntSendKillFocusMessages(hWndPrev, 0);
00621    }
00622    return hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0;
00623 }
00624 
00625 HWND FASTCALL
00626 UserGetForegroundWindow(VOID)
00627 {
00628    PUSER_MESSAGE_QUEUE ForegroundQueue;
00629 
00630    ForegroundQueue = IntGetFocusMessageQueue();
00631    return( ForegroundQueue ? (ForegroundQueue->spwndActive ? UserHMGetHandle(ForegroundQueue->spwndActive) : 0) : 0);
00632 }
00633 
00634 HWND FASTCALL UserGetActiveWindow(VOID)
00635 {
00636    PTHREADINFO pti;
00637    PUSER_MESSAGE_QUEUE ThreadQueue;
00638 
00639    pti = PsGetCurrentThreadWin32Thread();
00640    ThreadQueue = pti->MessageQueue;
00641    return( ThreadQueue ? (ThreadQueue->spwndActive ? UserHMGetHandle(ThreadQueue->spwndActive) : 0) : 0);
00642 }
00643 
00644 HWND APIENTRY
00645 IntGetCapture(VOID)
00646 {
00647    PTHREADINFO pti;
00648    PUSER_MESSAGE_QUEUE ThreadQueue;
00649    DECLARE_RETURN(HWND);
00650 
00651    TRACE("Enter IntGetCapture\n");
00652 
00653    pti = PsGetCurrentThreadWin32Thread();
00654    ThreadQueue = pti->MessageQueue;
00655    RETURN( ThreadQueue ? ThreadQueue->CaptureWindow : 0);
00656 
00657 CLEANUP:
00658    TRACE("Leave IntGetCapture, ret=%i\n",_ret_);
00659    END_CLEANUP;
00660 }
00661 
00662 HWND FASTCALL
00663 co_UserSetCapture(HWND hWnd)
00664 {
00665    PTHREADINFO pti;
00666    PUSER_MESSAGE_QUEUE ThreadQueue;
00667    PWND Window, pWnd;
00668    HWND hWndPrev;
00669 
00670    pti = PsGetCurrentThreadWin32Thread();
00671    ThreadQueue = pti->MessageQueue;
00672 
00673    if (ThreadQueue->QF_flags & QF_CAPTURELOCKED)
00674       return NULL;
00675 
00676    if ((Window = UserGetWindowObject(hWnd)))
00677    {
00678       if (Window->head.pti->MessageQueue != ThreadQueue)
00679       {
00680          return NULL;
00681       }
00682    }
00683    
00684    hWndPrev = MsqSetStateWindow(ThreadQueue, MSQ_STATE_CAPTURE, hWnd);
00685 
00686    if (hWndPrev)
00687    {
00688       pWnd = UserGetWindowObject(hWndPrev);
00689       if (pWnd)
00690          IntNotifyWinEvent(EVENT_SYSTEM_CAPTUREEND, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
00691    }
00692 
00693    if (Window)
00694       IntNotifyWinEvent(EVENT_SYSTEM_CAPTURESTART, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
00695 
00696    if (hWndPrev && hWndPrev != hWnd)
00697    {
00698       if (ThreadQueue->MenuOwner && Window) ThreadQueue->QF_flags |= QF_CAPTURELOCKED;
00699 
00700       co_IntPostOrSendMessage(hWndPrev, WM_CAPTURECHANGED, 0, (LPARAM)hWnd);
00701 
00702       ThreadQueue->QF_flags &= ~QF_CAPTURELOCKED;
00703    }
00704 
00705    ThreadQueue->CaptureWindow = hWnd;
00706 
00707    if (hWnd == NULL) // Release mode.
00708    {
00709       MOUSEINPUT mi;
00711       /* Also remove other windows if not capturing anymore */
00712       MsqSetStateWindow(ThreadQueue, MSQ_STATE_MENUOWNER, NULL);
00713       MsqSetStateWindow(ThreadQueue, MSQ_STATE_MOVESIZE, NULL);
00715       /* Somebody may have missed some mouse movements */
00716       mi.dx = 0;
00717       mi.dy = 0;
00718       mi.mouseData = 0;
00719       mi.dwFlags = MOUSEEVENTF_MOVE;
00720       mi.time = 0;
00721       mi.dwExtraInfo = 0;
00722       UserSendMouseInput(&mi, FALSE);
00723    }
00724    return hWndPrev;
00725 }
00726 
00727 /*
00728   API Call
00729 */
00730 BOOL
00731 FASTCALL
00732 IntReleaseCapture(VOID)
00733 {
00734    PTHREADINFO pti;
00735    PUSER_MESSAGE_QUEUE ThreadQueue;
00736 
00737    pti = PsGetCurrentThreadWin32Thread();
00738    ThreadQueue = pti->MessageQueue;
00739 
00740    // Can not release inside WM_CAPTURECHANGED!!
00741    if (ThreadQueue->QF_flags & QF_CAPTURELOCKED) return FALSE;
00742 
00743    co_UserSetCapture(NULL);
00744 
00745    return TRUE;
00746 }
00747 
00748 /*
00749   API Call
00750 */
00751 BOOL FASTCALL
00752 co_IntSetForegroundWindow(PWND Window)
00753 {
00754    ASSERT_REFS_CO(Window);
00755 
00756    return co_IntSetForegroundAndFocusWindow(Window, FALSE);
00757 }
00758 
00759 /*
00760   API Call
00761 */
00762 BOOL FASTCALL
00763 IntLockSetForegroundWindow(UINT uLockCode)
00764 {
00765    ULONG Err = ERROR_ACCESS_DENIED;
00766    PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
00767    switch (uLockCode)
00768    {
00769       case LSFW_LOCK:
00770          if ( CanForceFG(ppi) && !gppiLockSFW )
00771          {
00772             gppiLockSFW = ppi;
00773             return TRUE;
00774          }
00775          break;
00776       case LSFW_UNLOCK:
00777          if ( gppiLockSFW == ppi)
00778          {
00779             gppiLockSFW = NULL;
00780             return TRUE;
00781          }
00782          break;
00783       default:
00784          Err = ERROR_INVALID_PARAMETER;
00785    }
00786    EngSetLastError(Err);
00787    return FALSE;
00788 }
00789 
00790 /*
00791   API Call
00792 */
00793 BOOL FASTCALL
00794 IntAllowSetForegroundWindow(DWORD dwProcessId)
00795 {
00796    PPROCESSINFO ppi, ppiCur;
00797    PEPROCESS Process = NULL;
00798 
00799    ppi = NULL;
00800    if (dwProcessId != ASFW_ANY)
00801    {
00802       if (!NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)dwProcessId, &Process)))
00803       {
00804          EngSetLastError(ERROR_INVALID_PARAMETER);
00805          return FALSE;
00806       }
00807       ppi = PsGetProcessWin32Process(Process);
00808       if (!ppi)
00809       {
00810          ObDereferenceObject(Process);
00811          return FALSE;
00812       }
00813    }
00814    ppiCur = PsGetCurrentProcessWin32Process();
00815    if (!CanForceFG(ppiCur))
00816    {
00817       if (Process) ObDereferenceObject(Process);
00818       EngSetLastError(ERROR_ACCESS_DENIED);
00819       return FALSE;
00820    }
00821    if (dwProcessId == ASFW_ANY)
00822    {  // All processes will be enabled to set the foreground window.
00823       ptiLastInput = NULL;
00824    }
00825    else
00826    {  // Rule #3, last input event in force.
00827       ptiLastInput = ppi->ptiList;
00828       ObDereferenceObject(Process);
00829    }
00830    return TRUE;
00831 }
00832 
00833 /*
00834  * @implemented
00835  */
00836 HWND APIENTRY
00837 NtUserGetForegroundWindow(VOID)
00838 {
00839    DECLARE_RETURN(HWND);
00840 
00841    TRACE("Enter NtUserGetForegroundWindow\n");
00842    UserEnterExclusive();
00843 
00844    RETURN( UserGetForegroundWindow());
00845 
00846 CLEANUP:
00847    TRACE("Leave NtUserGetForegroundWindow, ret=%i\n",_ret_);
00848    UserLeave();
00849    END_CLEANUP;
00850 }
00851 
00852 HWND APIENTRY
00853 NtUserSetActiveWindow(HWND hWnd)
00854 {
00855    USER_REFERENCE_ENTRY Ref;
00856    HWND hWndPrev;
00857    PWND Window;
00858    DECLARE_RETURN(HWND);
00859 
00860    TRACE("Enter NtUserSetActiveWindow(%x)\n", hWnd);
00861    UserEnterExclusive();
00862 
00863    Window = NULL;
00864    if (hWnd)
00865    {
00866       if (!(Window = UserGetWindowObject(hWnd)))
00867       {
00868          RETURN( 0);
00869       }
00870    }
00871 
00872    if (!Window ||
00873         Window->head.pti->MessageQueue == gptiCurrent->MessageQueue)
00874    {
00875       if (Window) UserRefObjectCo(Window, &Ref);
00876       if (!co_IntSetActiveWindow(Window, &hWndPrev, FALSE, TRUE)) hWndPrev = NULL;
00877       if (Window) UserDerefObjectCo(Window);
00878    }
00879    else
00880       hWndPrev = NULL;
00881 
00882    RETURN( hWndPrev ? (IntIsWindow(hWndPrev) ? hWndPrev : 0) : 0 );
00883 
00884 CLEANUP:
00885    TRACE("Leave NtUserSetActiveWindow, ret=%i\n",_ret_);
00886    UserLeave();
00887    END_CLEANUP;
00888 }
00889 
00890 /*
00891  * @implemented
00892  */
00893 HWND APIENTRY
00894 NtUserSetCapture(HWND hWnd)
00895 {
00896    DECLARE_RETURN(HWND);
00897 
00898    TRACE("Enter NtUserSetCapture(%x)\n", hWnd);
00899    UserEnterExclusive();
00900 
00901    RETURN( co_UserSetCapture(hWnd));
00902 
00903 CLEANUP:
00904    TRACE("Leave NtUserSetCapture, ret=%i\n",_ret_);
00905    UserLeave();
00906    END_CLEANUP;
00907 }
00908 
00909 /*
00910  * @implemented
00911  */
00912 HWND APIENTRY
00913 NtUserSetFocus(HWND hWnd)
00914 {
00915    PWND Window;
00916    USER_REFERENCE_ENTRY Ref;
00917    DECLARE_RETURN(HWND);
00918    HWND ret;
00919 
00920    TRACE("Enter NtUserSetFocus(%x)\n", hWnd);
00921    UserEnterExclusive();
00922 
00923    if (hWnd)
00924    {
00925       if (!(Window = UserGetWindowObject(hWnd)))
00926       {
00927          RETURN(NULL);
00928       }
00929 
00930       UserRefObjectCo(Window, &Ref);
00931       ret = co_UserSetFocus(Window);
00932       UserDerefObjectCo(Window);
00933 
00934       RETURN(ret);
00935    }
00936    else
00937    {
00938       RETURN( co_UserSetFocus(0));
00939    }
00940 
00941 CLEANUP:
00942    TRACE("Leave NtUserSetFocus, ret=%i\n",_ret_);
00943    UserLeave();
00944    END_CLEANUP;
00945 }
00946 
00947 /* EOF */

Generated on Sun May 27 2012 04:38:31 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.