2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Focus functions
5 * FILE: subsystems/win32/win32k/ntuser/focus.c
6 * PROGRAMER: ReactOS Team
10 DBG_DEFAULT_CHANNEL(UserFocus
);
12 PUSER_MESSAGE_QUEUE gpqForeground
= NULL
;
13 PUSER_MESSAGE_QUEUE gpqForegroundPrev
= NULL
;
14 PTHREADINFO gptiForeground
= NULL
;
15 PPROCESSINFO gppiLockSFW
= NULL
;
16 ULONG guSFWLockCount
= 0; // Rule #8, No menus are active. So should be zero.
17 PTHREADINFO ptiLastInput
= NULL
;
20 Check locking of a process or one or more menus are active.
25 return (gppiLockSFW
|| guSFWLockCount
);
29 IntGetCaptureWindow(VOID
)
31 PUSER_MESSAGE_QUEUE ForegroundQueue
= IntGetFocusMessageQueue();
32 return ForegroundQueue
!= NULL
? ForegroundQueue
->CaptureWindow
: 0;
36 IntGetThreadFocusWindow(VOID
)
39 PUSER_MESSAGE_QUEUE ThreadQueue
;
41 pti
= PsGetCurrentThreadWin32Thread();
42 ThreadQueue
= pti
->MessageQueue
;
45 return ThreadQueue
->spwndFocus
? UserHMGetHandle(ThreadQueue
->spwndFocus
) : 0;
49 co_IntSendDeactivateMessages(HWND hWndPrev
, HWND hWnd
)
53 if (hWndPrev
&& (WndPrev
= UserGetWindowObject(hWndPrev
)))
55 co_IntSendMessageNoWait(hWndPrev
, WM_NCACTIVATE
, FALSE
, 0);
56 co_IntSendMessageNoWait(hWndPrev
, WM_ACTIVATE
,
57 MAKEWPARAM(WA_INACTIVE
, WndPrev
->style
& WS_MINIMIZE
),
63 co_IntMakeWindowActive(PWND Window
)
67 { // Set last active for window and it's owner.
68 Window
->spwndLastActive
= Window
;
69 spwndOwner
= Window
->spwndOwner
;
72 spwndOwner
->spwndLastActive
= Window
;
73 spwndOwner
= spwndOwner
->spwndOwner
;
77 ERR("MakeWindowActive Failed!\n");
82 co_IntSendActivateMessages(HWND hWndPrev
, HWND hWnd
, BOOL MouseActivate
)
84 USER_REFERENCE_ENTRY Ref
, RefPrev
;
85 PWND Window
, WindowPrev
= NULL
;
86 HANDLE OldTID
, NewTID
;
87 PTHREADINFO ptiOld
, ptiNew
;
89 if ((Window
= UserGetWindowObject(hWnd
)))
91 UserRefObjectCo(Window
, &Ref
);
93 WindowPrev
= UserGetWindowObject(hWndPrev
);
95 if (WindowPrev
) UserRefObjectCo(WindowPrev
, &RefPrev
);
97 /* Send palette messages */
98 if (gpsi
->PUSIFlags
& PUSIF_PALETTEDISPLAY
&&
99 co_IntPostOrSendMessage(hWnd
, WM_QUERYNEWPALETTE
, 0, 0))
101 UserSendNotifyMessage( HWND_BROADCAST
,
102 WM_PALETTEISCHANGING
,
107 if (Window
->spwndPrev
!= NULL
)
108 co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0,
109 SWP_NOSIZE
| SWP_NOMOVE
);
111 if (!Window
->spwndOwner
&& !IntGetParent(Window
))
113 co_IntShellHookNotify(HSHELL_WINDOWACTIVATED
, (LPARAM
) hWnd
);
118 Window
->state
|= WNDS_ACTIVEFRAME
;
120 if (Window
->style
& WS_MINIMIZE
)
122 TRACE("Widow was minimized\n");
127 WindowPrev
->state
&= ~WNDS_ACTIVEFRAME
;
129 OldTID
= WindowPrev
? IntGetWndThreadId(WindowPrev
) : NULL
;
130 NewTID
= Window
? IntGetWndThreadId(Window
) : NULL
;
131 ptiOld
= WindowPrev
? WindowPrev
->head
.pti
: NULL
;
132 ptiNew
= Window
? Window
->head
.pti
: NULL
;
134 TRACE("SendActiveMessage Old -> %x, New -> %x\n", OldTID
, NewTID
);
136 if (OldTID
!= NewTID
)
141 List
= IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow()));
146 for (phWnd
= List
; *phWnd
; ++phWnd
)
148 cWindow
= UserGetWindowObject(*phWnd
);
149 if (cWindow
&& cWindow
->head
.pti
== ptiOld
)
150 { // FALSE if the window is being deactivated,
151 // ThreadId that owns the window being activated.
152 co_IntSendMessageNoWait(*phWnd
, WM_ACTIVATEAPP
, FALSE
, (LPARAM
)NewTID
);
158 for (phWnd
= List
; *phWnd
; ++phWnd
)
160 cWindow
= UserGetWindowObject(*phWnd
);
161 if (cWindow
&& cWindow
->head
.pti
== ptiNew
)
162 { // TRUE if the window is being activated,
163 // ThreadId that owns the window being deactivated.
164 co_IntSendMessageNoWait(*phWnd
, WM_ACTIVATEAPP
, TRUE
, (LPARAM
)OldTID
);
172 UserDerefObjectCo(WindowPrev
); // Now allow the previous window to die.
174 UserDerefObjectCo(Window
);
176 /* FIXME: IntIsWindow */
177 co_IntSendMessageNoWait(hWnd
, WM_NCACTIVATE
, (WPARAM
)(hWnd
== UserGetForegroundWindow()), 0);
178 /* FIXME: WA_CLICKACTIVE */
179 co_IntSendMessageNoWait(hWnd
, WM_ACTIVATE
,
180 MAKEWPARAM(MouseActivate
? WA_CLICKACTIVE
: WA_ACTIVE
,
181 Window
->style
& WS_MINIMIZE
),
187 co_IntSendKillFocusMessages(HWND hWndPrev
, HWND hWnd
)
191 IntNotifyWinEvent(EVENT_OBJECT_FOCUS
, NULL
, OBJID_CLIENT
, CHILDID_SELF
, 0);
192 co_IntPostOrSendMessage(hWndPrev
, WM_KILLFOCUS
, (WPARAM
)hWnd
, 0);
197 co_IntSendSetFocusMessages(HWND hWndPrev
, HWND hWnd
)
201 PWND pWnd
= UserGetWindowObject(hWnd
);
204 IntNotifyWinEvent(EVENT_OBJECT_FOCUS
, pWnd
, OBJID_CLIENT
, CHILDID_SELF
, 0);
205 co_IntPostOrSendMessage(hWnd
, WM_SETFOCUS
, (WPARAM
)hWndPrev
, 0);
211 IntFindChildWindowToOwner(PWND Root
, PWND Owner
)
214 PWND Child
, OwnerWnd
;
216 for(Child
= Root
->spwndChild
; Child
; Child
= Child
->spwndNext
)
218 OwnerWnd
= Child
->spwndOwner
;
222 if(OwnerWnd
== Owner
)
233 FindRemoveAsyncMsg(PWND Wnd
)
235 PUSER_MESSAGE_QUEUE MessageQueue
;
236 PUSER_SENT_MESSAGE Message
;
241 MessageQueue
= Wnd
->head
.pti
->MessageQueue
;
243 if (!IsListEmpty(&MessageQueue
->SentMessagesListHead
))
245 // Scan sent queue messages to see if we received async messages.
246 Entry
= MessageQueue
->SentMessagesListHead
.Flink
;
247 Message
= CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, ListEntry
);
250 if (Message
->Msg
.message
== WM_ASYNC_SETACTIVEWINDOW
&&
251 Message
->Msg
.hwnd
== UserHMGetHandle(Wnd
) &&
252 Message
->Msg
.wParam
== 0 )
254 TRACE("ASYNC SAW: Found one in the Sent Msg Queue! %p\n", Message
->Msg
.hwnd
);
255 RemoveEntryList(Entry
); // Purge the entry.
257 Entry
= Message
->ListEntry
.Flink
;
258 Message
= CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, ListEntry
);
260 while (Entry
!= &MessageQueue
->SentMessagesListHead
);
265 Can the system force foreground from one or more conditions.
268 CanForceFG(PPROCESSINFO ppi
)
271 ptiLastInput
->ppi
== ppi
||
273 gptiForeground
->ppi
== ppi
||
274 ppi
->W32PF_flags
& (W32PF_ALLOWFOREGROUNDACTIVATE
| W32PF_SETFOREGROUNDALLOWED
) ||
275 gppiInputProvider
== ppi
||
283 The system restricts which processes can set the foreground window. A process
284 can set the foreground window only if one of the following conditions is true:
286 * The process is the foreground process.
287 * The process was started by the foreground process.
288 * The process received the last input event.
289 * There is no foreground process.
290 * The foreground process is being debugged.
291 * The foreground is not locked (see LockSetForegroundWindow).
292 * The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
293 * No menus are active.
297 co_IntSetForegroundAndFocusWindow(PWND Wnd
, BOOL MouseActivate
)
299 HWND hWnd
= UserHMGetHandle(Wnd
);
300 HWND hWndPrev
= NULL
;
301 PUSER_MESSAGE_QUEUE PrevForegroundQueue
;
303 BOOL fgRet
= FALSE
, Ret
= FALSE
;
307 TRACE("SetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd
, MouseActivate
? "TRUE" : "FALSE");
309 PrevForegroundQueue
= IntGetFocusMessageQueue(); // Use this active desktop.
310 pti
= PsGetCurrentThreadWin32Thread();
312 if (PrevForegroundQueue
)
313 { // Same Window Q as foreground just do active.
314 if (Wnd
&& Wnd
->head
.pti
->MessageQueue
== PrevForegroundQueue
)
316 if (pti
->MessageQueue
== PrevForegroundQueue
)
317 { // Same WQ and TQ go active.
318 Ret
= co_IntSetActiveWindow(Wnd
, NULL
, MouseActivate
, TRUE
);
320 else if (Wnd
->head
.pti
->MessageQueue
->spwndActive
== Wnd
)
321 { // Same WQ and it is active.
325 { // Same WQ as FG but not the same TQ send active.
326 co_IntSendMessageNoWait(hWnd
, WM_ASYNC_SETACTIVEWINDOW
, (WPARAM
)Wnd
, (LPARAM
)MouseActivate
);
332 hWndPrev
= PrevForegroundQueue
->spwndActive
? UserHMGetHandle(PrevForegroundQueue
->spwndActive
) : 0;
335 if ( (( !IsFGLocked() || pti
->ppi
== gppiInputProvider
) &&
336 ( CanForceFG(pti
->ppi
) || pti
->TIF_flags
& (TIF_SYSTEMTHREAD
|TIF_CSRSSTHREAD
|TIF_ALLOWFOREGROUNDACTIVATE
) )) ||
337 pti
->ppi
== ppiScrnSaver
340 IntSetFocusMessageQueue(Wnd
->head
.pti
->MessageQueue
);
341 gptiForeground
= Wnd
->head
.pti
;
344 What happens is that we get the WM_WINE_SETACTIVEWINDOW message sent by the
345 other thread after we already changed the foreground window back to our own
348 FindRemoveAsyncMsg(Wnd
); // Do this to fix test_SFW todos!
352 // Fix FG Bounce with regedit.
353 if (hWndPrev
!= hWnd
)
355 if (PrevForegroundQueue
&&
357 Wnd
->head
.pti
->MessageQueue
!= PrevForegroundQueue
&&
358 PrevForegroundQueue
->spwndActive
)
360 //ERR("SFGW: Send NULL to 0x%x\n",hWndPrev);
361 if (pti
->MessageQueue
== PrevForegroundQueue
)
363 //ERR("SFGW: TI same as Prev TI\n");
364 co_IntSetActiveWindow(NULL
, NULL
, FALSE
, TRUE
);
367 co_IntSendMessageNoWait(hWndPrev
, WM_ASYNC_SETACTIVEWINDOW
, 0, 0 );
371 if (pti
->MessageQueue
== Wnd
->head
.pti
->MessageQueue
)
373 Ret
= co_IntSetActiveWindow(Wnd
, NULL
, MouseActivate
, TRUE
);
375 else if (Wnd
->head
.pti
->MessageQueue
->spwndActive
== Wnd
)
381 co_IntSendMessageNoWait(hWnd
, WM_ASYNC_SETACTIVEWINDOW
, (WPARAM
)Wnd
, (LPARAM
)MouseActivate
);
389 co_IntMouseActivateWindow(PWND Wnd
)
393 USER_REFERENCE_ENTRY Ref
;
397 if (Wnd
->style
& WS_DISABLED
)
401 PWND DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
404 Top
= IntFindChildWindowToOwner(DesktopWindow
, Wnd
);
405 if ((TopWnd
= UserGetWindowObject(Top
)))
407 UserRefObjectCo(TopWnd
, &Ref
);
408 Ret
= co_IntMouseActivateWindow(TopWnd
);
409 UserDerefObjectCo(TopWnd
);
417 TopWindow
= UserGetAncestor(Wnd
, GA_ROOT
);
418 if (!TopWindow
) return FALSE
;
420 /* TMN: Check return valud from this function? */
421 UserRefObjectCo(TopWindow
, &Ref
);
423 co_IntSetForegroundAndFocusWindow(TopWindow
, TRUE
);
425 UserDerefObjectCo(TopWindow
);
431 co_IntSetActiveWindow(PWND Wnd OPTIONAL
, HWND
* Prev
, BOOL bMouse
, BOOL bFocus
)
434 PUSER_MESSAGE_QUEUE ThreadQueue
;
437 CBTACTIVATESTRUCT cbt
;
442 hWnd
= UserHMGetHandle(Wnd
);
445 pti
= PsGetCurrentThreadWin32Thread();
446 ThreadQueue
= pti
->MessageQueue
;
447 ASSERT(ThreadQueue
!= 0);
449 hWndPrev
= ThreadQueue
->spwndActive
? UserHMGetHandle(ThreadQueue
->spwndActive
) : NULL
;
450 if (Prev
) *Prev
= hWndPrev
;
451 if (hWndPrev
== hWnd
) return TRUE
;
455 if (ThreadQueue
!= Wnd
->head
.pti
->MessageQueue
)
457 PUSER_MESSAGE_QUEUE ForegroundQueue
= IntGetFocusMessageQueue();
458 // Rule 1 & 4, We are foreground so set this FG window or NULL foreground....
459 if (!ForegroundQueue
|| ForegroundQueue
== ThreadQueue
)
461 return co_IntSetForegroundAndFocusWindow(Wnd
, bMouse
);
465 if (Wnd
->state
& WNDS_BEINGACTIVATED
) return TRUE
;
468 /* Call CBT hook chain */
470 cbt
.hWndActive
= hWndPrev
;
471 if (co_HOOK_CallHooks( WH_CBT
, HCBT_ACTIVATE
, (WPARAM
)hWnd
, (LPARAM
)&cbt
))
473 ERR("SetActiveWindow WH_CBT Call Hook return!\n");
477 co_IntSendDeactivateMessages(hWndPrev
, hWnd
);
479 if (Wnd
) Wnd
->state
|= WNDS_BEINGACTIVATED
;
481 IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
483 /* check if the specified window can be set in the input data of a given queue */
484 if ( !Wnd
|| ThreadQueue
== Wnd
->head
.pti
->MessageQueue
)
486 /* set the current thread active window */
487 if (!Wnd
|| co_IntMakeWindowActive(Wnd
))
489 ThreadQueue
->spwndActivePrev
= ThreadQueue
->spwndActive
;
490 ThreadQueue
->spwndActive
= Wnd
;
494 co_IntSendActivateMessages(hWndPrev
, hWnd
, bMouse
);
496 /* now change focus if necessary */
499 /* Do not change focus if the window is no longer active */
500 if (ThreadQueue
->spwndActive
== Wnd
)
502 if (!ThreadQueue
->spwndFocus
||
504 UserGetAncestor(ThreadQueue
->spwndFocus
, GA_ROOT
) != Wnd
)
506 co_UserSetFocus(Wnd
);
511 if (Wnd
) Wnd
->state
&= ~WNDS_BEINGACTIVATED
;
516 co_UserSetFocus(PWND Window
)
521 PUSER_MESSAGE_QUEUE ThreadQueue
;
524 ASSERT_REFS_CO(Window
);
526 pti
= PsGetCurrentThreadWin32Thread();
527 ThreadQueue
= pti
->MessageQueue
;
528 ASSERT(ThreadQueue
!= 0);
530 hWndPrev
= ThreadQueue
->spwndFocus
? UserHMGetHandle(ThreadQueue
->spwndFocus
) : 0;
534 if (hWndPrev
== UserHMGetHandle(Window
))
536 return hWndPrev
; /* Nothing to do */
539 if (Window
->head
.pti
->MessageQueue
!= ThreadQueue
)
541 ERR("SetFocus Must have the same Q!\n");
545 /* Check if we can set the focus to this window */
549 if (pwndTop
->style
& (WS_MINIMIZED
|WS_DISABLED
)) return 0;
550 if (!pwndTop
->spwndParent
|| pwndTop
->spwndParent
== UserGetDesktopWindow())
552 if ((pwndTop
->style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return 0;
555 if (pwndTop
->spwndParent
== UserGetMessageWindow()) return 0;
556 pwndTop
= pwndTop
->spwndParent
;
559 if (co_HOOK_CallHooks( WH_CBT
, HCBT_SETFOCUS
, (WPARAM
)Window
->head
.h
, (LPARAM
)hWndPrev
))
561 ERR("SetFocus 1 WH_CBT Call Hook return!\n");
565 /* Activate pwndTop if needed. */
566 if (pwndTop
!= ThreadQueue
->spwndActive
)
568 PUSER_MESSAGE_QUEUE ForegroundQueue
= IntGetFocusMessageQueue(); // Keep it based on desktop.
569 if (ThreadQueue
!= ForegroundQueue
) // HACK see rule 2 & 3.
571 if (!co_IntSetForegroundAndFocusWindow(pwndTop
, FALSE
))
573 ERR("SetFocus Set Foreground and Focus Failed!\n");
578 /* Set Active when it is needed. */
579 if (pwndTop
!= ThreadQueue
->spwndActive
)
581 if (!co_IntSetActiveWindow(pwndTop
, NULL
, FALSE
, FALSE
))
583 ERR("SetFocus Set Active Failed!\n");
588 /* Abort if window destroyed */
589 if (Window
->state2
& WNDS2_INDESTROY
) return 0;
590 /* Do not change focus if the window is no longer active */
591 if (pwndTop
!= ThreadQueue
->spwndActive
)
593 ERR("SetFocus Top window did not go active!\n");
598 // Check again! SetActiveWindow could have set the focus via WM_ACTIVATE.
599 if (ThreadQueue
->spwndFocus
&& ThreadQueue
->spwndFocus
== Window
)
601 hWndPrev
= UserHMGetHandle(ThreadQueue
->spwndFocus
);
604 /* check if the specified window can be set in the input data of a given queue */
605 if (ThreadQueue
== Window
->head
.pti
->MessageQueue
)
606 /* set the current thread focus window */
607 ThreadQueue
->spwndFocus
= Window
;
609 TRACE("Focus: %d -> %d\n", hWndPrev
, Window
->head
.h
);
611 co_IntSendKillFocusMessages(hWndPrev
, Window
->head
.h
);
612 co_IntSendSetFocusMessages(hWndPrev
, Window
->head
.h
);
614 else /* NULL hwnd passed in */
616 if (!hWndPrev
) return 0; /* nothing to do */
617 if (co_HOOK_CallHooks( WH_CBT
, HCBT_SETFOCUS
, (WPARAM
)0, (LPARAM
)hWndPrev
))
619 ERR("SetFocusWindow 2 WH_CBT Call Hook return!\n");
623 /* set the current thread focus window null */
624 ThreadQueue
->spwndFocus
= 0;
626 co_IntSendKillFocusMessages(hWndPrev
, 0);
628 return hWndPrev
? (IntIsWindow(hWndPrev
) ? hWndPrev
: 0) : 0;
632 UserGetForegroundWindow(VOID
)
634 PUSER_MESSAGE_QUEUE ForegroundQueue
;
636 ForegroundQueue
= IntGetFocusMessageQueue();
637 return( ForegroundQueue
? (ForegroundQueue
->spwndActive
? UserHMGetHandle(ForegroundQueue
->spwndActive
) : 0) : 0);
640 HWND FASTCALL
UserGetActiveWindow(VOID
)
643 PUSER_MESSAGE_QUEUE ThreadQueue
;
645 pti
= PsGetCurrentThreadWin32Thread();
646 ThreadQueue
= pti
->MessageQueue
;
647 return( ThreadQueue
? (ThreadQueue
->spwndActive
? UserHMGetHandle(ThreadQueue
->spwndActive
) : 0) : 0);
654 PUSER_MESSAGE_QUEUE ThreadQueue
;
655 DECLARE_RETURN(HWND
);
657 TRACE("Enter IntGetCapture\n");
659 pti
= PsGetCurrentThreadWin32Thread();
660 ThreadQueue
= pti
->MessageQueue
;
661 RETURN( ThreadQueue
? ThreadQueue
->CaptureWindow
: 0);
664 TRACE("Leave IntGetCapture, ret=%i\n",_ret_
);
669 co_UserSetCapture(HWND hWnd
)
672 PUSER_MESSAGE_QUEUE ThreadQueue
;
676 pti
= PsGetCurrentThreadWin32Thread();
677 ThreadQueue
= pti
->MessageQueue
;
679 if (ThreadQueue
->QF_flags
& QF_CAPTURELOCKED
)
682 if ((Window
= UserGetWindowObject(hWnd
)))
684 if (Window
->head
.pti
->MessageQueue
!= ThreadQueue
)
690 hWndPrev
= MsqSetStateWindow(ThreadQueue
, MSQ_STATE_CAPTURE
, hWnd
);
694 pWnd
= UserGetWindowObject(hWndPrev
);
696 IntNotifyWinEvent(EVENT_SYSTEM_CAPTUREEND
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
700 IntNotifyWinEvent(EVENT_SYSTEM_CAPTURESTART
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
702 if (hWndPrev
&& hWndPrev
!= hWnd
)
704 if (ThreadQueue
->MenuOwner
&& Window
) ThreadQueue
->QF_flags
|= QF_CAPTURELOCKED
;
706 co_IntPostOrSendMessage(hWndPrev
, WM_CAPTURECHANGED
, 0, (LPARAM
)hWnd
);
708 ThreadQueue
->QF_flags
&= ~QF_CAPTURELOCKED
;
711 ThreadQueue
->CaptureWindow
= hWnd
;
713 if (hWnd
== NULL
) // Release mode.
717 /* Also remove other windows if not capturing anymore */
718 MsqSetStateWindow(ThreadQueue
, MSQ_STATE_MENUOWNER
, NULL
);
719 MsqSetStateWindow(ThreadQueue
, MSQ_STATE_MOVESIZE
, NULL
);
721 /* Somebody may have missed some mouse movements */
725 mi
.dwFlags
= MOUSEEVENTF_MOVE
;
728 UserSendMouseInput(&mi
, FALSE
);
738 IntReleaseCapture(VOID
)
741 PUSER_MESSAGE_QUEUE ThreadQueue
;
743 pti
= PsGetCurrentThreadWin32Thread();
744 ThreadQueue
= pti
->MessageQueue
;
746 // Can not release inside WM_CAPTURECHANGED!!
747 if (ThreadQueue
->QF_flags
& QF_CAPTURELOCKED
) return FALSE
;
749 co_UserSetCapture(NULL
);
758 co_IntSetForegroundWindow(PWND Window
)
760 ASSERT_REFS_CO(Window
);
762 return co_IntSetForegroundAndFocusWindow(Window
, FALSE
);
769 IntLockSetForegroundWindow(UINT uLockCode
)
771 ULONG Err
= ERROR_ACCESS_DENIED
;
772 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
776 if ( CanForceFG(ppi
) && !gppiLockSFW
)
783 if ( gppiLockSFW
== ppi
)
790 Err
= ERROR_INVALID_PARAMETER
;
792 EngSetLastError(Err
);
800 IntAllowSetForegroundWindow(DWORD dwProcessId
)
802 PPROCESSINFO ppi
, ppiCur
;
803 PEPROCESS Process
= NULL
;
806 if (dwProcessId
!= ASFW_ANY
)
808 if (!NT_SUCCESS(PsLookupProcessByProcessId((HANDLE
)dwProcessId
, &Process
)))
810 EngSetLastError(ERROR_INVALID_PARAMETER
);
813 ppi
= PsGetProcessWin32Process(Process
);
816 ObDereferenceObject(Process
);
820 ppiCur
= PsGetCurrentProcessWin32Process();
821 if (!CanForceFG(ppiCur
))
823 if (Process
) ObDereferenceObject(Process
);
824 EngSetLastError(ERROR_ACCESS_DENIED
);
827 if (dwProcessId
== ASFW_ANY
)
828 { // All processes will be enabled to set the foreground window.
832 { // Rule #3, last input event in force.
833 ptiLastInput
= ppi
->ptiList
;
834 ObDereferenceObject(Process
);
843 NtUserGetForegroundWindow(VOID
)
845 DECLARE_RETURN(HWND
);
847 TRACE("Enter NtUserGetForegroundWindow\n");
848 UserEnterExclusive();
850 RETURN( UserGetForegroundWindow());
853 TRACE("Leave NtUserGetForegroundWindow, ret=%i\n",_ret_
);
859 NtUserSetActiveWindow(HWND hWnd
)
861 USER_REFERENCE_ENTRY Ref
;
864 DECLARE_RETURN(HWND
);
866 TRACE("Enter NtUserSetActiveWindow(%x)\n", hWnd
);
867 UserEnterExclusive();
872 if (!(Window
= UserGetWindowObject(hWnd
)))
879 Window
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
881 if (Window
) UserRefObjectCo(Window
, &Ref
);
882 if (!co_IntSetActiveWindow(Window
, &hWndPrev
, FALSE
, TRUE
)) hWndPrev
= NULL
;
883 if (Window
) UserDerefObjectCo(Window
);
888 RETURN( hWndPrev
? (IntIsWindow(hWndPrev
) ? hWndPrev
: 0) : 0 );
891 TRACE("Leave NtUserSetActiveWindow, ret=%i\n",_ret_
);
900 NtUserSetCapture(HWND hWnd
)
902 DECLARE_RETURN(HWND
);
904 TRACE("Enter NtUserSetCapture(%x)\n", hWnd
);
905 UserEnterExclusive();
907 RETURN( co_UserSetCapture(hWnd
));
910 TRACE("Leave NtUserSetCapture, ret=%i\n",_ret_
);
919 NtUserSetFocus(HWND hWnd
)
922 USER_REFERENCE_ENTRY Ref
;
923 DECLARE_RETURN(HWND
);
926 TRACE("Enter NtUserSetFocus(%x)\n", hWnd
);
927 UserEnterExclusive();
931 if (!(Window
= UserGetWindowObject(hWnd
)))
936 UserRefObjectCo(Window
, &Ref
);
937 ret
= co_UserSetFocus(Window
);
938 UserDerefObjectCo(Window
);
944 RETURN( co_UserSetFocus(0));
948 TRACE("Leave NtUserSetFocus, ret=%i\n",_ret_
);