Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfocus.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
1.7.6.1
|