2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Focus functions
5 * FILE: win32ss/user/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 Get capture window via foreground Queue.
32 IntGetCaptureWindow(VOID
)
34 PUSER_MESSAGE_QUEUE ForegroundQueue
= IntGetFocusMessageQueue();
35 return ( ForegroundQueue
? (ForegroundQueue
->spwndCapture
? UserHMGetHandle(ForegroundQueue
->spwndCapture
) : 0) : 0);
39 IntGetThreadFocusWindow(VOID
)
42 PUSER_MESSAGE_QUEUE ThreadQueue
;
44 pti
= PsGetCurrentThreadWin32Thread();
45 ThreadQueue
= pti
->MessageQueue
;
48 return ThreadQueue
->spwndFocus
? UserHMGetHandle(ThreadQueue
->spwndFocus
) : 0;
52 UpdateShellHook(PWND Window
)
54 if ( Window
->spwndParent
== UserGetDesktopWindow() &&
55 (!(Window
->ExStyle
& WS_EX_TOOLWINDOW
) ||
56 (Window
->ExStyle
& WS_EX_APPWINDOW
)))
58 // FIXME lParam; The value is TRUE if the window is in full-screen mode, or FALSE otherwise.
59 co_IntShellHookNotify(HSHELL_WINDOWACTIVATED
, (WPARAM
) UserHMGetHandle(Window
), FALSE
);
63 co_IntShellHookNotify(HSHELL_WINDOWACTIVATED
, 0, FALSE
);
68 co_IntSendDeactivateMessages(HWND hWndPrev
, HWND hWnd
, BOOL Clear
)
70 USER_REFERENCE_ENTRY RefPrev
;
73 LPARAM lParam
= hWnd
? (LPARAM
)hWnd
: 0;
75 if (hWndPrev
&& (WndPrev
= ValidateHwndNoErr(hWndPrev
)))
77 UserRefObjectCo(WndPrev
, &RefPrev
);
79 if (co_IntSendMessage(hWndPrev
, WM_NCACTIVATE
, FALSE
, lParam
))
81 co_IntSendMessage(hWndPrev
, WM_ACTIVATE
,
82 MAKEWPARAM(WA_INACTIVE
, (WndPrev
->style
& WS_MINIMIZE
) != 0),
86 WndPrev
->state
&= ~(WNDS_ACTIVEFRAME
|WNDS_HASCAPTION
);
90 ERR("Application is keeping itself Active to prevent the change!\n");
94 UserDerefObjectCo(WndPrev
);
100 // Deactivating the foreground message queue.
102 // Release Active, Capture and Focus Windows associated with this message queue.
105 IntDeactivateWindow(PTHREADINFO pti
, HANDLE tid
)
107 USER_REFERENCE_ENTRY Ref
;
111 PTHREADINFO ptiCurrent
= PsGetCurrentThreadWin32Thread();
113 if ( !pti
->MessageQueue
->spwndActive
)
115 TRACE("IDAW E : Nothing to do, Active is NULL! pti 0x%p tid 0x%p\n",pti
,tid
);
119 TRACE("IDAW : pti 0x%p tid 0x%p\n",pti
,tid
);
121 if (ptiCurrent
!= pti
)
123 IntReferenceThreadInfo(pti
);
124 IntReferenceThreadInfo(ptiCurrent
);
127 if (!(pti
->TIF_flags
& TIF_INACTIVATEAPPMSG
) )
129 pti
->TIF_flags
|= TIF_INACTIVATEAPPMSG
;
134 // Check for Capture and release it.
136 if ( pti
->MessageQueue
->spwndCapture
)
139 PWND pwndCapture
= pti
->MessageQueue
->spwndCapture
;
141 UserRefObjectCo(pwndCapture
, &Ref
);
142 co_IntSendMessage(UserHMGetHandle(pwndCapture
), WM_CANCELMODE
, 0, 0);
143 UserDerefObjectCo(pwndCapture
);
145 /* Generate mouse move message */
146 msg
.message
= WM_MOUSEMOVE
;
147 msg
.wParam
= UserGetMouseButtonsState();
148 msg
.lParam
= MAKELPARAM(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
149 msg
.pt
= gpsi
->ptCursor
;
150 co_MsqInsertMouseMessage(&msg
, 0, 0, TRUE
);
154 // Check for Active and release it.
156 if ( pti
->MessageQueue
->spwndActive
)
158 pwndPrev
= pti
->MessageQueue
->spwndActive
;
159 ptiPrev
= pwndPrev
->head
.pti
;
161 if (!co_IntSendDeactivateMessages(UserHMGetHandle(pwndPrev
), 0, TRUE
))
163 if (InAAPM
) pti
->TIF_flags
&= ~TIF_INACTIVATEAPPMSG
;
164 if (ptiCurrent
!= pti
)
166 IntDereferenceThreadInfo(pti
);
167 IntDereferenceThreadInfo(ptiCurrent
);
172 if ( pti
->MessageQueue
->spwndActive
== pwndPrev
)
174 pti
->MessageQueue
->spwndActivePrev
= pwndPrev
;
175 pti
->MessageQueue
->spwndActive
= NULL
;
178 if (ptiPrev
->TIF_flags
& TIF_INCLEANUP
) ptiPrev
= NULL
;
183 pwndPrev
= (PWND
)-1; // Avoid zero Active window.
188 HANDLE OldTID
= PsGetThreadId(ptiPrev
->pEThread
);
192 List
= IntWinListChildren(UserGetDesktopWindow());
197 for (phWnd
= List
; *phWnd
; ++phWnd
)
199 cWindow
= ValidateHwndNoErr(*phWnd
);
200 if ( cWindow
&& cWindow
->head
.pti
== ptiPrev
)
201 { // FALSE if the window is being deactivated,
202 // ThreadId that owns the window being activated.
203 //ERR("IDW : WM_ACTIVATEAPP(0) hwnd %p tid Old %p New %p\n",UserHMGetHandle(cWindow),OldTID,tid);
204 UserRefObjectCo(cWindow
, &Ref
);
205 co_IntSendMessage(*phWnd
, WM_ACTIVATEAPP
, FALSE
, (LPARAM
)tid
);
206 UserDerefObjectCo(cWindow
);
210 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
215 // Now check for a change (Bounce), if Active same as previous window, release it too.
217 if ( pti
->MessageQueue
->spwndActive
== pwndPrev
)
219 if (!co_IntSendDeactivateMessages(UserHMGetHandle(pwndPrev
), 0, FALSE
))
221 if (InAAPM
) pti
->TIF_flags
&= ~TIF_INACTIVATEAPPMSG
;
222 if (ptiCurrent
!= pti
)
224 IntDereferenceThreadInfo(pti
);
225 IntDereferenceThreadInfo(ptiCurrent
);
230 if ( pti
->MessageQueue
->spwndActive
== pwndPrev
)
232 pti
->MessageQueue
->spwndActivePrev
= pwndPrev
;
233 pti
->MessageQueue
->spwndActive
= NULL
;
238 // Check for Focus and release it.
240 if ( pti
->MessageQueue
->spwndFocus
)
242 PWND pwndFocus
= pti
->MessageQueue
->spwndFocus
;
245 // Fix win.c:test_SetForegroundWindow:SetActiveWindow(0)!
247 pti
->MessageQueue
->spwndFocus
= NULL
; // Null out Focus.
249 UserRefObjectCo(pwndFocus
, &Ref
);
250 co_IntSendMessage(UserHMGetHandle(pwndFocus
), WM_KILLFOCUS
, 0, 0);
251 UserDerefObjectCo(pwndFocus
);
254 if (InAAPM
) pti
->TIF_flags
&= ~TIF_INACTIVATEAPPMSG
;
255 if (ptiCurrent
!= pti
)
257 IntDereferenceThreadInfo(pti
);
258 IntDereferenceThreadInfo(ptiCurrent
);
264 // Activating another threads foreground window after a switch.
267 IntActivateWindow(PWND Wnd
, PTHREADINFO pti
, HANDLE tid
, DWORD Type
)
269 USER_REFERENCE_ENTRY Ref
;
270 PUSER_MESSAGE_QUEUE pmq
= pti
->MessageQueue
;
274 Wnd
= VerifyWnd(Wnd
);
278 UserRefObjectCo(Wnd
, &Ref
);
282 // No foreground queue set.
283 co_IntSetForegroundMessageQueue( Wnd
, pti
, (BOOL
)Type
, 0);
287 // Same Active and Wnd.
288 if ( pmq
->spwndActive
== Wnd
)
290 WPARAM wParam
= (Wnd
->head
.pti
->MessageQueue
== gpqForeground
);
292 co_IntSendMessage( UserHMGetHandle(Wnd
), WM_NCACTIVATE
, wParam
, 0);
296 UpdateShellHook(Wnd
);
298 co_WinPosSetWindowPos(Wnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
301 else // Not the same, set the active Wnd.
303 co_IntSetActiveWindow(Wnd
,(BOOL
)Type
,TRUE
,TRUE
);
306 UserDerefObjectCo(Wnd
);
308 else // Handle no Wnd!
311 pmq
->spwndActive
&& // Active WND not zero,
312 gpqForeground
== pmq
) // Same message queues.
314 Wnd
= pmq
->spwndActive
; // Use active window from current queue.
316 UserRefObjectCo(Wnd
, &Ref
);
318 co_IntSendMessage( UserHMGetHandle(Wnd
), WM_NCACTIVATE
, TRUE
, 0);
320 UpdateShellHook(Wnd
);
322 co_WinPosSetWindowPos(Wnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
324 UserDerefObjectCo(Wnd
);
326 else if (gpqForeground
!= pmq
)
328 // Not the same message queue so clear flags for foreground switching.
329 pti
->TIF_flags
&= ~TIF_ALLOWFOREGROUNDACTIVATE
;
330 pti
->ppi
->W32PF_flags
&= ~W32PF_ALLOWFOREGROUNDACTIVATE
;
336 co_IntMakeWindowActive(PWND Window
)
339 if (VerifyWnd(Window
))
340 { // Set last active for window and it's owner.
342 while (spwndOwner
->spwndOwner
)
344 spwndOwner
= spwndOwner
->spwndOwner
;
346 spwndOwner
->spwndLastActive
= Window
;
349 ERR("MakeWindowActive Failed!\n");
354 co_IntSendActivateMessages(PWND WindowPrev
, PWND Window
, BOOL MouseActivate
, BOOL Async
)
356 USER_REFERENCE_ENTRY Ref
, RefPrev
, RefCall
;
357 HANDLE OldTID
, NewTID
;
358 PTHREADINFO pti
, ptiOld
, ptiNew
;
361 //ERR("SendActivateMessages\n");
363 pti
= PsGetCurrentThreadWin32Thread();
367 UserRefObjectCo(Window
, &Ref
);
369 if (WindowPrev
) UserRefObjectCo(WindowPrev
, &RefPrev
);
371 pti
->MessageQueue
->QF_flags
&= ~QF_EVENTDEACTIVATEREMOVED
;
373 /* Send palette messages */
374 if (gpsi
->PUSIFlags
& PUSIF_PALETTEDISPLAY
&&
375 //co_IntPostOrSendMessage(UserHMGetHandle(Window), WM_QUERYNEWPALETTE, 0, 0))
376 co_IntSendMessage(UserHMGetHandle(Window
), WM_QUERYNEWPALETTE
, 0, 0))
378 UserSendNotifyMessage( HWND_BROADCAST
,
379 WM_PALETTEISCHANGING
,
380 (WPARAM
)UserHMGetHandle(Window
),
383 //// Fixes CORE-6434.
384 if (!(Window
->style
& WS_CHILD
))
386 PWND pwndTemp
= co_GetDesktopWindow(Window
)->spwndChild
;
388 while (pwndTemp
&& !(pwndTemp
->style
& WS_VISIBLE
)) pwndTemp
= pwndTemp
->spwndNext
;
390 if (Window
!= pwndTemp
|| (WindowPrev
&& !IntIsWindowVisible(WindowPrev
)))
392 if (!Async
|| pti
->MessageQueue
== gpqForeground
)
394 UINT flags
= SWP_NOSIZE
| SWP_NOMOVE
;
395 if (Window
== pwndTemp
) flags
|= SWP_NOACTIVATE
;
396 //ERR("co_IntSendActivateMessages SetWindowPos! Async %d pti Q == FGQ %d\n",Async,pti->MessageQueue == gpqForeground);
397 co_WinPosSetWindowPos(Window
, HWND_TOP
, 0, 0, 0, 0, flags
);
402 //// CORE-1161 and CORE-6651
403 if (Window
->spwndPrev
)
405 HWND
*phwndTopLevel
, *phwndCurrent
;
406 PWND pwndCurrent
, pwndDesktop
;
408 pwndDesktop
= co_GetDesktopWindow(Window
);//UserGetDesktopWindow();
409 if (Window
->spwndParent
== pwndDesktop
)
411 phwndTopLevel
= IntWinListChildren(pwndDesktop
);
412 phwndCurrent
= phwndTopLevel
;
415 pwndCurrent
= UserGetWindowObject(*phwndCurrent
);
417 if (pwndCurrent
&& pwndCurrent
->spwndOwner
== Window
)
419 co_WinPosSetWindowPos(pwndCurrent
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
|SWP_NOACTIVATE
);
423 ExFreePoolWithTag(phwndTopLevel
, USERTAG_WINDOWLIST
);
429 OldTID
= WindowPrev
? IntGetWndThreadId(WindowPrev
) : NULL
;
430 NewTID
= Window
? IntGetWndThreadId(Window
) : NULL
;
431 ptiOld
= WindowPrev
? WindowPrev
->head
.pti
: NULL
;
432 ptiNew
= Window
? Window
->head
.pti
: NULL
;
434 //ERR("SendActivateMessage Old -> %x, New -> %x\n", OldTID, NewTID);
436 if (!(pti
->TIF_flags
& TIF_INACTIVATEAPPMSG
) &&
442 List
= IntWinListChildren(UserGetDesktopWindow());
447 ptiOld
->TIF_flags
|= TIF_INACTIVATEAPPMSG
;
448 // Note: Do not set pci flags, this does crash!
449 for (phWnd
= List
; *phWnd
; ++phWnd
)
451 cWindow
= ValidateHwndNoErr(*phWnd
);
452 if (cWindow
&& cWindow
->head
.pti
== ptiOld
)
453 { // FALSE if the window is being deactivated,
454 // ThreadId that owns the window being activated.
455 //ERR("SAM : WM_ACTIVATEAPP(0) tid Old %p New %p\n",OldTID,NewTID);
456 UserRefObjectCo(cWindow
, &RefCall
);
457 co_IntSendMessage(*phWnd
, WM_ACTIVATEAPP
, FALSE
, (LPARAM
)NewTID
);
458 UserDerefObjectCo(cWindow
);
461 ptiOld
->TIF_flags
&= ~TIF_INACTIVATEAPPMSG
;
464 { //// Prevents a resource crash due to reentrance!
466 pti
->TIF_flags
|= TIF_INACTIVATEAPPMSG
;
468 for (phWnd
= List
; *phWnd
; ++phWnd
)
470 cWindow
= ValidateHwndNoErr(*phWnd
);
471 if (cWindow
&& cWindow
->head
.pti
== ptiNew
)
472 { // TRUE if the window is being activated,
473 // ThreadId that owns the window being deactivated.
474 //ERR("SAM : WM_ACTIVATEAPP(1) hwnd %p tid New %p Old %p\n",UserHMGetHandle(cWindow),NewTID,OldTID);
475 UserRefObjectCo(cWindow
, &RefCall
);
476 co_IntSendMessage(*phWnd
, WM_ACTIVATEAPP
, TRUE
, (LPARAM
)OldTID
);
477 UserDerefObjectCo(cWindow
);
481 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
488 UserDerefObjectCo(WindowPrev
); // Now allow the previous window to die.
490 if (Window
->state
& WNDS_ACTIVEFRAME
)
491 { // If already active frame do not allow NCPaint.
492 //ERR("SendActivateMessage Is Active Frame!\n");
493 Window
->state
|= WNDS_NONCPAINT
;
496 if (Window
->style
& WS_MINIMIZE
)
498 TRACE("Widow was minimized\n");
501 co_IntMakeWindowActive(Window
);
503 co_IntSendMessage( UserHMGetHandle(Window
),
505 (WPARAM
)(Window
== (gpqForeground
? gpqForeground
->spwndActive
: NULL
)),
508 co_IntSendMessage( UserHMGetHandle(Window
),
510 MAKEWPARAM(MouseActivate
? WA_CLICKACTIVE
: WA_ACTIVE
, (Window
->style
& WS_MINIMIZE
) != 0),
511 (LPARAM
)(WindowPrev
? UserHMGetHandle(WindowPrev
) : 0));
513 if (Window
->style
& WS_VISIBLE
)
514 UpdateShellHook(Window
);
516 Window
->state
&= ~WNDS_NONCPAINT
;
518 UserDerefObjectCo(Window
);
524 IntSendFocusMessages( PTHREADINFO pti
, PWND pWnd
)
527 PUSER_MESSAGE_QUEUE ThreadQueue
= pti
->MessageQueue
; // Queue can change...
529 ThreadQueue
->QF_flags
&= ~QF_FOCUSNULLSINCEACTIVE
;
530 if (!pWnd
&& ThreadQueue
->spwndActive
)
532 ThreadQueue
->QF_flags
|= QF_FOCUSNULLSINCEACTIVE
;
535 pWndPrev
= ThreadQueue
->spwndFocus
;
537 /* check if the specified window can be set in the input data of a given queue */
538 if (!pWnd
|| ThreadQueue
== pWnd
->head
.pti
->MessageQueue
)
539 /* set the current thread focus window */
540 ThreadQueue
->spwndFocus
= pWnd
;
546 co_IntSendMessage(UserHMGetHandle(pWndPrev
), WM_KILLFOCUS
, (WPARAM
)UserHMGetHandle(pWnd
), 0);
548 if (ThreadQueue
->spwndFocus
== pWnd
)
550 IntNotifyWinEvent(EVENT_OBJECT_FOCUS
, pWnd
, OBJID_CLIENT
, CHILDID_SELF
, 0);
552 co_IntSendMessage(UserHMGetHandle(pWnd
), WM_SETFOCUS
, (WPARAM
)(pWndPrev
? UserHMGetHandle(pWndPrev
) : NULL
), 0);
559 IntNotifyWinEvent(EVENT_OBJECT_FOCUS
, NULL
, OBJID_CLIENT
, CHILDID_SELF
, 0);
561 co_IntSendMessage(UserHMGetHandle(pWndPrev
), WM_KILLFOCUS
, 0, 0);
567 FindRemoveEventMsg(PTHREADINFO pti
, DWORD Event
, DWORD EventLast
)
569 PUSER_MESSAGE Message
;
573 Entry
= pti
->PostedMessagesListHead
.Flink
;
574 while (Entry
!= &pti
->PostedMessagesListHead
)
576 // Scan posted queue messages to see if we received async messages.
577 Message
= CONTAINING_RECORD(Entry
, USER_MESSAGE
, ListEntry
);
578 Entry
= Entry
->Flink
;
580 if (Message
->dwQEvent
== EventLast
)
582 //ERR("Event D/SAW: Last Activate/Deactivate %d\n", EventLast);
586 if (Message
->dwQEvent
== Event
)
588 //ERR("Event D/SAW: Found one in the Post Msg Queue! Activate/Deactivate %d\n", Event);
589 ClearMsgBitsMask(pti
, Message
->QS_Flags
);
590 MsqDestroyMessage(Message
);
598 ToggleFGActivate(PTHREADINFO pti
)
601 PPROCESSINFO ppi
= pti
->ppi
;
603 Ret
= !!(pti
->TIF_flags
& TIF_ALLOWFOREGROUNDACTIVATE
);
606 pti
->TIF_flags
&= ~TIF_ALLOWFOREGROUNDACTIVATE
;
609 Ret
= !!(ppi
->W32PF_flags
& W32PF_ALLOWFOREGROUNDACTIVATE
);
612 ppi
->W32PF_flags
&= ~W32PF_ALLOWFOREGROUNDACTIVATE
;
613 //ERR("ToggleFGActivate is %d\n",Ret);
618 IsAllowedFGActive(PTHREADINFO pti
, PWND Wnd
)
620 // Not allowed if one or more,,
621 if (!ToggleFGActivate(pti
) || // bits not set,
622 pti
->rpdesk
!= gpdeskInputDesktop
|| // not current Desktop,
623 pti
->MessageQueue
== gpqForeground
|| // if already the queue foreground,
624 IsFGLocked() || // foreground is locked,
625 Wnd
->ExStyle
& WS_EX_NOACTIVATE
) // or,,, does not become the foreground window when the user clicks it.
629 //ERR("IsAllowedFGActive is TRUE\n");
634 Can the system force foreground from one or more conditions.
637 CanForceFG(PPROCESSINFO ppi
)
640 ptiLastInput
->ppi
== ppi
||
642 gptiForeground
->ppi
== ppi
||
643 ppi
->W32PF_flags
& (W32PF_ALLOWFOREGROUNDACTIVATE
| W32PF_SETFOREGROUNDALLOWED
) ||
644 gppiInputProvider
== ppi
||
647 //ERR("CanForceFG is FALSE\n");
652 // Switching out foreground message queues.
655 co_IntSetForegroundMessageQueue(
657 _In_ PTHREADINFO pti
,
658 _In_ BOOL MouseActivate
,
661 PTHREADINFO ptiChg
, ptiPrev
;
662 PUSER_MESSAGE_QUEUE pumq
, pumqChg
, pumqPrev
;
663 BOOL Removed
, Ret
= TRUE
;
665 if (Wnd
&& !VerifyWnd(Wnd
))
670 if ( !gptiForeground
|| gptiForeground
->TIF_flags
& TIF_INCLEANUP
)
673 ptiPrev
= gptiForeground
;
677 ptiChg
= Wnd
->head
.pti
;
678 IntSetFocusMessageQueue(Wnd
->head
.pti
->MessageQueue
);
679 gptiForeground
= Wnd
->head
.pti
;
680 //ERR("Set Foreground pti 0x%p Q 0x%p hWnd 0x%p\n",Wnd->head.pti, Wnd->head.pti->MessageQueue,Wnd->head.h);
685 IntSetFocusMessageQueue(NULL
);
686 gptiForeground
= NULL
;
687 //ERR("Set Foreground pti 0x0 Q 0x0 hWnd 0x0\n");
691 // Process the changing out of the message queues.
693 if (gpqForegroundPrev
!= gpqForeground
)
696 if ( ptiPrev
&& !(ptiPrev
->TIF_flags
& TIF_INCLEANUP
) )
698 pumqPrev
= ptiPrev
->MessageQueue
;
701 pumq
= pti
? pti
->MessageQueue
: NULL
;
703 // Deactivate the previous message queue.
706 if ( pumq
!= pumqPrev
)
709 HWND hWndPrev
= pumqPrev
->spwndActive
? UserHMGetHandle(pumqPrev
->spwndActive
) : NULL
;
710 HANDLE tid
= gptiForeground
? PsGetThreadId(gptiForeground
->pEThread
) : NULL
; // TID from changing Window PTI.
712 Msg
.message
= WM_ASYNC_SETACTIVEWINDOW
;
714 Msg
.wParam
= (WPARAM
)pumqPrev
->spwndActive
;
717 //ERR("SFWAMQ : DAW P pti 0x%p tid 0x%p hWndPrev 0x%p\n",ptiPrev,tid,hWndPrev);
718 MsqPostMessage(ptiPrev
, &Msg
, FALSE
, QS_EVENT
, POSTEVENT_DAW
, (LONG_PTR
)tid
);
723 if ( ptiChg
&& !(ptiChg
->TIF_flags
& TIF_INCLEANUP
) )
725 pumqChg
= ptiChg
->MessageQueue
;
728 pumq
= pti
? pti
->MessageQueue
: NULL
;
730 // Activate changing message queue.
735 What happens is that we get the WM_WINE_SETACTIVEWINDOW message sent by the
736 other thread after we already changed the foreground window back to our own
739 //ERR("SFWAMQ : 1\n");
740 Removed
= FindRemoveEventMsg(ptiChg
, POSTEVENT_DAW
, POSTEVENT_NONE
);
745 HWND hWnd
= Wnd
? UserHMGetHandle(Wnd
) : NULL
;
746 HANDLE tid
= ptiPrev
? PsGetThreadId(ptiPrev
->pEThread
) : NULL
;
748 if (Removed
) pumqChg
->QF_flags
|= QF_EVENTDEACTIVATEREMOVED
;
750 Msg
.message
= WM_ASYNC_SETACTIVEWINDOW
;
752 Msg
.wParam
= (WPARAM
)Wnd
;
753 Msg
.lParam
= (LPARAM
)tid
; //// Fixme! Type flags?
755 //ERR("SFWAMQ : SAW P pti 0x%p tid 0x%p hWnd 0x%p\n",ptiChg,tid,hWnd);
756 MsqPostMessage(ptiChg
, &Msg
, FALSE
, QS_EVENT
, POSTEVENT_SAW
, (LONG_PTR
)Type
|MouseActivate
);
758 else // Current message queue same as changed message queue.
760 if (pumq
->spwndActive
== Wnd
)
762 co_IntSendMessage( UserHMGetHandle(Wnd
), WM_NCACTIVATE
, TRUE
, (LPARAM
)UserHMGetHandle(Wnd
));
764 UpdateShellHook(Wnd
);
766 co_WinPosSetWindowPos(Wnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
770 //ERR("SFWAMQ : SAW I pti 0x%p hWnd 0x%p\n",ptiChg,Wnd->head.h);
771 Ret
= co_IntSetActiveWindow(Wnd
, MouseActivate
, TRUE
/*Type*/, FALSE
);
772 //if (!Ret) ERR("SFWAMQ : ISAW : return error\n");
778 // Handle same message queue after switch out.
780 if ( ptiPrev
&& !(ptiPrev
->TIF_flags
& TIF_INCLEANUP
) )
782 pumqPrev
= ptiPrev
->MessageQueue
;
784 pumq
= pti
? pti
->MessageQueue
: NULL
;
786 if ( pumqPrev
&& pumq
== pumqPrev
)
788 HANDLE tid
= Wnd
? PsGetThreadId(Wnd
->head
.pti
->pEThread
) : NULL
;
789 //ERR("SFWAMQ : DAW I pti 0x%p tid 0x%p hWnd 0x%p\n",ptiPrev,tid,Wnd ? Wnd->head.h : 0);
790 IntDeactivateWindow(pti
, tid
);
798 The system restricts which processes can set the foreground window. A process
799 can set the foreground window only if one of the following conditions is true:
801 * The process is the foreground process.
802 * The process was started by the foreground process.
803 * The process received the last input event.
804 * There is no foreground process.
805 * The foreground process is being debugged.
806 * The foreground is not locked (see LockSetForegroundWindow).
807 * The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
808 * No menus are active.
812 co_IntSetForegroundAndFocusWindow(
814 _In_ BOOL MouseActivate
,
817 HWND hWnd
= Wnd
? UserHMGetHandle(Wnd
) : NULL
;
818 PUSER_MESSAGE_QUEUE PrevForegroundQueue
;
822 if (Wnd
) ASSERT_REFS_CO(Wnd
);
824 TRACE("SetForegroundAndFocusWindow(%x, %s)\n", hWnd
, (MouseActivate
? "TRUE" : "FALSE"));
826 PrevForegroundQueue
= IntGetFocusMessageQueue(); // Use this active desktop.
827 pti
= PsGetCurrentThreadWin32Thread();
829 if (Wnd
&& PrevForegroundQueue
)
830 { // Same Window Q as foreground just do active.
831 if (Wnd
->head
.pti
->MessageQueue
== PrevForegroundQueue
)
833 //ERR("Same Window Q as foreground just do active.\n");
834 if (pti
->MessageQueue
== PrevForegroundQueue
)
835 { // Same WQ and TQ go active.
836 //ERR("Same WQ and TQ go active.\n");
837 Ret
= IntUserSetActiveWindow(Wnd
, MouseActivate
, TRUE
, FALSE
);
839 else if (Wnd
->head
.pti
->MessageQueue
->spwndActive
== Wnd
)
840 { // Same WQ and it is active.
841 //ERR("Same WQ and it is active.\n");
845 { // Same WQ as FG but not the same TQ send active.
846 //ERR("Same WQ as FG but not the same TQ send active.\n");
848 PTHREADINFO ptiNew
= Wnd
->head
.pti
;
850 Msg
.message
= WM_ASYNC_SETACTIVEWINDOW
;
852 Msg
.wParam
= (WPARAM
)Wnd
;
855 //ERR("SFAFW 1 : SAW P pti 0x%p hWnd 0x%p\n",ptiNew,hWnd);
856 MsqPostMessage(ptiNew
, &Msg
, FALSE
, QS_EVENT
, POSTEVENT_SAW
, (LONG_PTR
)MouseActivate
);
864 if ( (( !IsFGLocked() || pti
->ppi
== gppiInputProvider
) &&
865 ( CanForceFG(pti
->ppi
) || pti
->TIF_flags
& (TIF_SYSTEMTHREAD
|TIF_CSRSSTHREAD
|TIF_ALLOWFOREGROUNDACTIVATE
) )) ||
866 pti
->ppi
== ppiScrnSaver
870 ToggleFGActivate(pti
);
872 return co_IntSetForegroundMessageQueue( Wnd
, pti
, MouseActivate
, 0 );
875 if (!Wnd
) return FALSE
; // No window, always return FALSE.
877 //// if (bFlash) FIXME : handle flash!!!
879 if (pti
->MessageQueue
== Wnd
->head
.pti
->MessageQueue
)
881 //ERR("Same PQ and WQ go active.\n");
882 Ret
= IntUserSetActiveWindow(Wnd
, MouseActivate
, TRUE
, FALSE
);
883 //if (!Ret) ERR("ISFAFW : IUSAW : return error\n");
885 else if (Wnd
->head
.pti
->MessageQueue
->spwndActive
== Wnd
)
887 TRACE("Same Active and Wnd.\n"); // Leave this for now.
891 //ERR("Activate Not same PQ and WQ and Wnd.\n");
892 //// CORE-10785 fix hang, ROSTESTS-208 allows test to run.
894 PTHREADINFO ptiNew
= Wnd
->head
.pti
;
896 Msg
.message
= WM_ASYNC_SETACTIVEWINDOW
;
898 Msg
.wParam
= (WPARAM
)Wnd
;
901 //ERR("SFAFW 2 : SAW P pti 0x%p hWnd 0x%p\n",ptiNew,hWnd);
902 MsqPostMessage(ptiNew
, &Msg
, FALSE
, QS_EVENT
, POSTEVENT_SAW
, (LONG_PTR
)MouseActivate
);
904 // Always return FALSE.
909 // Set the Active Window.
912 co_IntSetActiveWindow(
919 PUSER_MESSAGE_QUEUE ThreadQueue
;
920 PWND pWndChg
, WndPrev
; // State changes.
924 CBTACTIVATESTRUCT cbt
;
926 //ERR("co_IntSetActiveWindow 1\n");
928 pti
= PsGetCurrentThreadWin32Thread();
929 ThreadQueue
= pti
->MessageQueue
;
930 ASSERT(ThreadQueue
!= 0);
932 hWndPrev
= ThreadQueue
->spwndActive
? UserHMGetHandle(ThreadQueue
->spwndActive
) : NULL
;
934 pWndChg
= ThreadQueue
->spwndActive
; // Keep to notify of a preemptive switch.
936 if ( !Wnd
|| Wnd
== UserGetDesktopWindow() )
938 //ERR("ISAW : NULL %p\n",Wnd);
943 hWnd
= UserHMGetHandle(Wnd
);
944 //ERR("co_IntSetActiveWindow 2 hWnd 0x%p\n",hWnd);
946 /* check if the specified window can be set in the input data of a given queue */
947 if ( ThreadQueue
!= Wnd
->head
.pti
->MessageQueue
)
949 //ERR("ISAW : Must have the same Message Queue\n");
955 //ERR("ISAW : Window is in Destroy!\n");
959 if ( Wnd
== pWndChg
)
961 //ERR("ISAW : Nothing to do\n");
962 return TRUE
; // Fix CORE-8780 and CORE-11979. See CORE-11324 for breakage.
965 if ( Wnd
->state
& WNDS_BEINGACTIVATED
) return TRUE
;
967 /* Call CBT hook chain */
969 cbt
.hWndActive
= hWndPrev
;
970 if (co_HOOK_CallHooks( WH_CBT
, HCBT_ACTIVATE
, (WPARAM
)hWnd
, (LPARAM
)&cbt
))
972 ERR("SetActiveWindow: WH_CBT Call Hook return!\n");
976 ThreadQueue
->QF_flags
&= ~QF_EVENTDEACTIVATEREMOVED
;
978 if ( ThreadQueue
->spwndActive
&& ThreadQueue
->spwndActive
->state
& WNDS_DESTROYED
)
979 ThreadQueue
->spwndActive
= NULL
;
981 ThreadQueue
->spwndActivePrev
= ThreadQueue
->spwndActive
;
983 WndPrev
= ThreadQueue
->spwndActive
; // Keep to save changing active.
987 if (ThreadQueue
== gpqForeground
) gpqForegroundPrev
= ThreadQueue
;
988 if (!co_IntSendDeactivateMessages(UserHMGetHandle(WndPrev
), hWnd
, TRUE
)) return FALSE
;
991 WndPrev
= ThreadQueue
->spwndActive
; // Again keep to save changing active.
993 // While in calling message proc or hook:
994 // Fail if a preemptive switch was made, current active not made previous,
995 // focus window is dead or no longer the same thread queue.
996 if ( ThreadQueue
->spwndActivePrev
!= ThreadQueue
->spwndActive
||
997 pWndChg
!= WndPrev
||
998 (Wnd
&& !VerifyWnd(Wnd
)) ||
999 ThreadQueue
!= pti
->MessageQueue
)
1001 ERR("SetActiveWindow: Summary ERROR, active state changed!\n");
1005 if (!WndPrev
) ThreadQueue
->QF_flags
&= ~QF_FOCUSNULLSINCEACTIVE
;
1007 /* set the current thread active window */
1008 ThreadQueue
->spwndActive
= Wnd
;
1010 // Set state flag to prevent recursions.
1011 Wnd
->state
|= WNDS_BEINGACTIVATED
;
1013 IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND
, Wnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1015 // Clear out activate EVENT messages.
1016 FindRemoveEventMsg(pti
, POSTEVENT_SAW
, POSTEVENT_DAW
);
1018 WndPrev
= VerifyWnd(ThreadQueue
->spwndActivePrev
); // Now should be set but verify it again.
1020 InAAPM
= co_IntSendActivateMessages(WndPrev
, Wnd
, bMouse
, Async
);
1022 /* now change focus if necessary */
1023 //// Fixes CORE-6452 allows setting focus on window.
1024 if (bFocus
&& !(ThreadQueue
->QF_flags
& QF_FOCUSNULLSINCEACTIVE
))
1026 /* Do not change focus if the window is no longer active */
1027 if (pti
->MessageQueue
->spwndActive
!= IntGetNonChildAncestor(pti
->MessageQueue
->spwndFocus
))
1029 PWND pWndSend
= pti
->MessageQueue
->spwndActive
;
1030 // Clear focus if the active window is minimized.
1031 if (pWndSend
&& pti
->MessageQueue
->spwndActive
->style
& WS_MINIMIZE
) pWndSend
= NULL
;
1032 // Send focus messages and if so, set the focus.
1033 IntSendFocusMessages( pti
, pWndSend
);
1039 pti
->TIF_flags
&= ~TIF_INACTIVATEAPPMSG
;
1042 // Checked in MENU_TrackMenu
1043 ThreadQueue
->QF_flags
|= QF_ACTIVATIONCHANGE
;
1045 //ERR("co_IntSetActiveWindow Exit\n");
1046 Wnd
->state
&= ~WNDS_BEINGACTIVATED
;
1047 return (ThreadQueue
->spwndActive
== Wnd
);
1051 // Set the Active Window.
1053 // Window is not optional!
1056 IntUserSetActiveWindow(
1063 PUSER_MESSAGE_QUEUE ThreadQueue
;
1065 //ERR("IntUserSetActiveWindow 1\n");
1066 ASSERT_REFS_CO(Wnd
);
1067 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
1068 //ERR("IntUserSetActiveWindow 1a hWnd 0x%p\n",UserHMGetHandle(Wnd));
1070 //ERR("IntUserSetActiveWindow 2\n");
1071 pti
= PsGetCurrentThreadWin32Thread();
1072 ThreadQueue
= pti
->MessageQueue
;
1073 ASSERT(ThreadQueue
!= 0);
1077 BOOL Ret
, DoFG
, AllowFG
;
1079 if (ThreadQueue
== Wnd
->head
.pti
->MessageQueue
)
1081 if (IsAllowedFGActive(pti
, Wnd
))
1087 //ERR("IntUserSetActiveWindow 3 Go Out!\n");
1090 AllowFG
= !pti
->cVisWindows
; // Nothing is visable.
1091 //ERR("IntUserSetActiveWindow 3a DoFG = %d AllowFG = %d\n",DoFG,AllowFG);
1093 else //if (ThreadQueue != Wnd->head.pti->MessageQueue)
1095 //PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
1096 // Rule 1 & 4, We are foreground so set this FG window or NULL foreground....
1097 if (!gpqForeground
|| gpqForeground
== ThreadQueue
)
1105 if (pti
->TIF_flags
& TIF_ALLOWFOREGROUNDACTIVATE
|| pti
->cVisWindows
)
1112 //ERR("IntUserSetActiveWindow 3b DoFG = %d AllowFG = %d\n",DoFG,AllowFG);
1117 pti
->TIF_flags
|= TIF_ALLOWFOREGROUNDACTIVATE
;
1118 //ERR("IntUserSetActiveWindow 3c FG set\n");
1119 Ret
= co_IntSetForegroundAndFocusWindow(Wnd
, bMouse
, TRUE
);
1122 pti
->TIF_flags
|= TIF_ALLOWFOREGROUNDACTIVATE
;
1126 pti
->TIF_flags
&= ~TIF_ALLOWFOREGROUNDACTIVATE
;
1132 return co_IntSetActiveWindow(Wnd
, bMouse
, bFocus
, Async
);
1136 co_IntMouseActivateWindow(PWND Wnd
)
1138 TRACE("Mouse Active\n");
1139 return co_IntSetForegroundAndFocusWindow(Wnd
, TRUE
, TRUE
);
1143 UserSetActiveWindow( _In_opt_ PWND Wnd
)
1145 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1149 if ((Wnd
->style
& (WS_POPUP
|WS_CHILD
)) == WS_CHILD
) return FALSE
;
1151 return IntUserSetActiveWindow(Wnd
, FALSE
, TRUE
, FALSE
);
1154 Yes your eye are not deceiving you~!
1156 First part of wines Win.c test_SetActiveWindow:
1158 flush_events( TRUE );
1159 ShowWindow(hwnd, SW_HIDE);
1162 check_wnd_state(0, 0, 0, 0); <-- This should pass if ShowWindow does it's job!!! As of 10/28/2012 it does!
1164 Now Handle wines Msg.c test_SetActiveWindow( 0 )...
1166 TRACE("USAW: Previous active window\n");
1167 if ( gpqForegroundPrev
&&
1168 gpqForegroundPrev
->spwndActivePrev
&&
1169 (gpqForegroundPrev
->spwndActivePrev
->style
& (WS_VISIBLE
|WS_DISABLED
)) == WS_VISIBLE
&&
1170 !(gpqForegroundPrev
->spwndActivePrev
->state2
& WNDS2_BOTTOMMOST
) &&
1171 (Wnd
= VerifyWnd(gpqForegroundPrev
->spwndActivePrev
)) != NULL
)
1173 TRACE("USAW:PAW hwnd %p\n",Wnd
?Wnd
->head
.h
:NULL
);
1174 return IntUserSetActiveWindow(Wnd
, FALSE
, TRUE
, FALSE
);
1177 // Activate anyone but the active window.
1178 if ( pti
->MessageQueue
->spwndActive
&&
1179 (Wnd
= VerifyWnd(pti
->MessageQueue
->spwndActive
)) != NULL
)
1181 //ERR("USAW:AOWM hwnd %p\n",Wnd?Wnd->head.h:NULL);
1182 if (!ActivateOtherWindowMin(Wnd
))
1184 // Okay, now go find someone else to play with!
1185 //ERR("USAW: Going to WPAOW\n");
1186 co_WinPosActivateOtherWindow(Wnd
);
1191 TRACE("USAW: Nothing\n");
1196 co_UserSetFocus(PWND Window
)
1201 PUSER_MESSAGE_QUEUE ThreadQueue
;
1204 ASSERT_REFS_CO(Window
);
1206 pti
= PsGetCurrentThreadWin32Thread();
1207 ThreadQueue
= pti
->MessageQueue
;
1208 ASSERT(ThreadQueue
!= 0);
1210 TRACE("Enter SetFocus hWnd 0x%p pti 0x%p\n",Window
? UserHMGetHandle(Window
) : 0, pti
);
1212 hWndPrev
= ThreadQueue
->spwndFocus
? UserHMGetHandle(ThreadQueue
->spwndFocus
) : 0;
1216 if (hWndPrev
== UserHMGetHandle(Window
))
1218 return hWndPrev
? (IntIsWindow(hWndPrev
) ? hWndPrev
: 0) : 0; /* Nothing to do */
1221 if (Window
->head
.pti
->MessageQueue
!= ThreadQueue
)
1223 ERR("SetFocus Must have the same Q!\n");
1227 /* Check if we can set the focus to this window */
1228 //// Fixes wine win test_SetParent both "todo" line 3710 and 3720...
1229 for (pwndTop
= Window
; pwndTop
; pwndTop
= pwndTop
->spwndParent
)
1231 if (pwndTop
->style
& (WS_MINIMIZED
|WS_DISABLED
)) return 0;
1232 if ((pwndTop
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
) break;
1233 if (pwndTop
->spwndParent
== NULL
) break;
1236 if (co_HOOK_CallHooks( WH_CBT
, HCBT_SETFOCUS
, (WPARAM
)Window
->head
.h
, (LPARAM
)hWndPrev
))
1238 ERR("SetFocus 1 WH_CBT Call Hook return!\n");
1242 /* Activate pwndTop if needed. */
1243 if (pwndTop
!= ThreadQueue
->spwndActive
)
1245 PUSER_MESSAGE_QUEUE ForegroundQueue
= IntGetFocusMessageQueue(); // Keep it based on desktop.
1246 if (ThreadQueue
!= ForegroundQueue
&& IsAllowedFGActive(pti
, pwndTop
)) // Rule 2 & 3.
1248 //ERR("SetFocus: Set Foreground!\n");
1249 if (!(pwndTop
->style
& WS_VISIBLE
))
1251 pti
->ppi
->W32PF_flags
|= W32PF_ALLOWFOREGROUNDACTIVATE
;
1253 if (!co_IntSetForegroundAndFocusWindow(pwndTop
, FALSE
, TRUE
))
1255 ERR("SetFocus: Set Foreground and Focus Failed!\n");
1260 /* Set Active when it is needed. */
1261 if (pwndTop
!= ThreadQueue
->spwndActive
)
1263 //ERR("SetFocus: Set Active! %p\n",pwndTop?UserHMGetHandle(pwndTop):0);
1264 if (!co_IntSetActiveWindow(pwndTop
, FALSE
, FALSE
, FALSE
))
1266 ERR("SetFocus: Set Active Failed!\n");
1271 /* Abort if window destroyed */
1272 if (Window
->state2
& WNDS2_INDESTROY
) return 0;
1273 /* Do not change focus if the window is no longer active */
1274 if (pwndTop
!= ThreadQueue
->spwndActive
)
1276 ERR("SetFocus: Top window did not go active!\n");
1281 // Check again! SetActiveWindow could have set the focus via WM_ACTIVATE.
1282 hWndPrev
= ThreadQueue
->spwndFocus
? UserHMGetHandle(ThreadQueue
->spwndFocus
) : 0;
1284 IntSendFocusMessages( pti
, Window
);
1286 TRACE("Focus: %p -> %p\n", hWndPrev
, Window
->head
.h
);
1288 else /* NULL hwnd passed in */
1290 if (co_HOOK_CallHooks( WH_CBT
, HCBT_SETFOCUS
, (WPARAM
)0, (LPARAM
)hWndPrev
))
1292 ERR("SetFocus: 2 WH_CBT Call Hook return!\n");
1295 //ERR("SetFocus: Set Focus NULL\n");
1296 /* set the current thread focus window null */
1297 IntSendFocusMessages( pti
, NULL
);
1299 return hWndPrev
? (IntIsWindow(hWndPrev
) ? hWndPrev
: 0) : 0;
1303 UserGetForegroundWindow(VOID
)
1305 PUSER_MESSAGE_QUEUE ForegroundQueue
;
1307 ForegroundQueue
= IntGetFocusMessageQueue();
1308 return( ForegroundQueue
? (ForegroundQueue
->spwndActive
? UserHMGetHandle(ForegroundQueue
->spwndActive
) : 0) : 0);
1311 HWND FASTCALL
UserGetActiveWindow(VOID
)
1314 PUSER_MESSAGE_QUEUE ThreadQueue
;
1316 pti
= PsGetCurrentThreadWin32Thread();
1317 ThreadQueue
= pti
->MessageQueue
;
1318 return( ThreadQueue
? (ThreadQueue
->spwndActive
? UserHMGetHandle(ThreadQueue
->spwndActive
) : 0) : 0);
1325 PUSER_MESSAGE_QUEUE ThreadQueue
;
1326 DECLARE_RETURN(HWND
);
1328 TRACE("Enter IntGetCapture\n");
1330 pti
= PsGetCurrentThreadWin32Thread();
1331 ThreadQueue
= pti
->MessageQueue
;
1332 RETURN( ThreadQueue
? (ThreadQueue
->spwndCapture
? UserHMGetHandle(ThreadQueue
->spwndCapture
) : 0) : 0);
1335 TRACE("Leave IntGetCapture, ret=%p\n", _ret_
);
1340 co_UserSetCapture(HWND hWnd
)
1343 PUSER_MESSAGE_QUEUE ThreadQueue
;
1344 PWND pWnd
, Window
= NULL
;
1347 pti
= PsGetCurrentThreadWin32Thread();
1348 ThreadQueue
= pti
->MessageQueue
;
1350 if (ThreadQueue
->QF_flags
& QF_CAPTURELOCKED
)
1353 if (hWnd
&& (Window
= UserGetWindowObject(hWnd
)))
1355 if (Window
->head
.pti
->MessageQueue
!= ThreadQueue
)
1357 ERR("Window Thread does not match Current!\n");
1362 hWndPrev
= MsqSetStateWindow(pti
, MSQ_STATE_CAPTURE
, hWnd
);
1366 pWnd
= UserGetWindowObject(hWndPrev
);
1368 IntNotifyWinEvent(EVENT_SYSTEM_CAPTUREEND
, pWnd
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1372 IntNotifyWinEvent(EVENT_SYSTEM_CAPTURESTART
, Window
, OBJID_WINDOW
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1375 // Only send the message if we have a previous Window!
1376 // Fix msg_menu tracking popup menu and win test_capture_4!!!!
1380 if (ThreadQueue
->MenuOwner
&& Window
) ThreadQueue
->QF_flags
|= QF_CAPTURELOCKED
;
1382 co_IntSendMessage(hWndPrev
, WM_CAPTURECHANGED
, 0, (LPARAM
)hWnd
);
1384 ThreadQueue
->QF_flags
&= ~QF_CAPTURELOCKED
;
1387 if (hWnd
== NULL
) // Release mode.
1390 /// These are HACKS!
1391 /* Also remove other windows if not capturing anymore */
1392 MsqSetStateWindow(pti
, MSQ_STATE_MENUOWNER
, NULL
);
1393 MsqSetStateWindow(pti
, MSQ_STATE_MOVESIZE
, NULL
);
1395 /* Somebody may have missed some mouse movements */
1399 mi
.dwFlags
= MOUSEEVENTF_MOVE
;
1402 UserSendMouseInput(&mi
, FALSE
);
1412 IntReleaseCapture(VOID
)
1415 PUSER_MESSAGE_QUEUE ThreadQueue
;
1417 pti
= PsGetCurrentThreadWin32Thread();
1418 ThreadQueue
= pti
->MessageQueue
;
1420 // Can not release inside WM_CAPTURECHANGED!!
1421 if (ThreadQueue
->QF_flags
& QF_CAPTURELOCKED
) return FALSE
;
1423 co_UserSetCapture(NULL
);
1432 co_IntSetForegroundWindow(PWND Window
)
1434 if (Window
) ASSERT_REFS_CO(Window
);
1436 return co_IntSetForegroundAndFocusWindow(Window
, FALSE
, TRUE
);
1443 co_IntSetForegroundWindowMouse(PWND Window
)
1445 if (Window
) ASSERT_REFS_CO(Window
);
1447 return co_IntSetForegroundAndFocusWindow(Window
, TRUE
, FALSE
);
1454 IntLockSetForegroundWindow(UINT uLockCode
)
1456 ULONG Err
= ERROR_ACCESS_DENIED
;
1457 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
1461 if ( CanForceFG(ppi
) && !gppiLockSFW
)
1468 if ( gppiLockSFW
== ppi
)
1475 Err
= ERROR_INVALID_PARAMETER
;
1477 EngSetLastError(Err
);
1485 IntAllowSetForegroundWindow(DWORD dwProcessId
)
1487 PPROCESSINFO ppi
, ppiCur
;
1488 PEPROCESS Process
= NULL
;
1491 if (dwProcessId
!= ASFW_ANY
)
1493 if (!NT_SUCCESS(PsLookupProcessByProcessId(UlongToHandle(dwProcessId
), &Process
)))
1495 EngSetLastError(ERROR_INVALID_PARAMETER
);
1498 ppi
= PsGetProcessWin32Process(Process
);
1501 ObDereferenceObject(Process
);
1505 ppiCur
= PsGetCurrentProcessWin32Process();
1506 if (!CanForceFG(ppiCur
))
1508 if (Process
) ObDereferenceObject(Process
);
1509 EngSetLastError(ERROR_ACCESS_DENIED
);
1512 if (dwProcessId
== ASFW_ANY
)
1513 { // All processes will be enabled to set the foreground window.
1514 //ERR("ptiLastInput is CLEARED!!\n");
1515 ptiLastInput
= NULL
;
1518 { // Rule #3, last input event in force.
1519 ERR("ptiLastInput is SET!!\n");
1520 //ptiLastInput = ppi->ptiList; // See CORE-6384 & CORE-7030.
1521 ObDereferenceObject(Process
);
1530 NtUserGetForegroundWindow(VOID
)
1532 DECLARE_RETURN(HWND
);
1534 TRACE("Enter NtUserGetForegroundWindow\n");
1535 UserEnterExclusive();
1537 RETURN( UserGetForegroundWindow());
1540 TRACE("Leave NtUserGetForegroundWindow, ret=%p\n",_ret_
);
1546 NtUserSetActiveWindow(HWND hWnd
)
1548 USER_REFERENCE_ENTRY Ref
;
1551 DECLARE_RETURN(HWND
);
1553 TRACE("Enter NtUserSetActiveWindow(%p)\n", hWnd
);
1554 UserEnterExclusive();
1559 if (!(Window
= UserGetWindowObject(hWnd
)))
1561 ERR("NtUserSetActiveWindow: Invalid handle 0x%p!\n",hWnd
);
1567 Window
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
1569 hWndPrev
= gptiCurrent
->MessageQueue
->spwndActive
? UserHMGetHandle(gptiCurrent
->MessageQueue
->spwndActive
) : NULL
;
1570 if (Window
) UserRefObjectCo(Window
, &Ref
);
1571 UserSetActiveWindow(Window
);
1572 if (Window
) UserDerefObjectCo(Window
);
1573 RETURN( hWndPrev
? (IntIsWindow(hWndPrev
) ? hWndPrev
: 0) : 0 );
1578 TRACE("Leave NtUserSetActiveWindow, ret=%p\n",_ret_
);
1587 NtUserSetCapture(HWND hWnd
)
1589 DECLARE_RETURN(HWND
);
1591 TRACE("Enter NtUserSetCapture(%p)\n", hWnd
);
1592 UserEnterExclusive();
1594 RETURN( co_UserSetCapture(hWnd
));
1597 TRACE("Leave NtUserSetCapture, ret=%p\n", _ret_
);
1606 NtUserSetFocus(HWND hWnd
)
1609 USER_REFERENCE_ENTRY Ref
;
1610 DECLARE_RETURN(HWND
);
1613 TRACE("Enter NtUserSetFocus(%p)\n", hWnd
);
1614 UserEnterExclusive();
1618 if (!(Window
= UserGetWindowObject(hWnd
)))
1620 ERR("NtUserSetFocus: Invalid handle 0x%p!\n",hWnd
);
1624 UserRefObjectCo(Window
, &Ref
);
1625 ret
= co_UserSetFocus(Window
);
1626 UserDerefObjectCo(Window
);
1632 RETURN( co_UserSetFocus(0));
1636 TRACE("Leave NtUserSetFocus, ret=%p\n",_ret_
);