[Win32k]
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / focus.c
1 /*
2 * ReactOS Win32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
21 #include <win32k.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 HWND FASTCALL
27 IntGetCaptureWindow(VOID)
28 {
29 PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
30 return ForegroundQueue != NULL ? ForegroundQueue->CaptureWindow : 0;
31 }
32
33 HWND FASTCALL
34 IntGetFocusWindow(VOID)
35 {
36 PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
37 return ForegroundQueue != NULL ? ForegroundQueue->FocusWindow : 0;
38 }
39
40 HWND FASTCALL
41 IntGetThreadFocusWindow(VOID)
42 {
43 PTHREADINFO pti;
44 PUSER_MESSAGE_QUEUE ThreadQueue;
45
46 pti = PsGetCurrentThreadWin32Thread();
47 ThreadQueue = pti->MessageQueue;
48 return ThreadQueue != NULL ? ThreadQueue->FocusWindow : 0;
49 }
50
51 VOID FASTCALL
52 co_IntSendDeactivateMessages(HWND hWndPrev, HWND hWnd)
53 {
54 PWND WndPrev ;
55
56 if (hWndPrev && (WndPrev = UserGetWindowObject(hWndPrev)))
57 {
58 co_IntSendMessageNoWait(hWndPrev, WM_NCACTIVATE, FALSE, 0);
59 co_IntSendMessageNoWait(hWndPrev, WM_ACTIVATE,
60 MAKEWPARAM(WA_INACTIVE, WndPrev->style & WS_MINIMIZE),
61 (LPARAM)hWnd);
62 }
63 }
64
65 VOID FASTCALL
66 co_IntSendActivateMessages(HWND hWndPrev, HWND hWnd, BOOL MouseActivate)
67 {
68 USER_REFERENCE_ENTRY Ref, RefPrev;
69 PWND Window, WindowPrev = NULL;
70
71 if ((Window = UserGetWindowObject(hWnd)))
72 {
73 UserRefObjectCo(Window, &Ref);
74
75 WindowPrev = UserGetWindowObject(hWndPrev);
76
77 if (WindowPrev) UserRefObjectCo(WindowPrev, &RefPrev);
78
79 /* Send palette messages */
80 if (co_IntPostOrSendMessage(hWnd, WM_QUERYNEWPALETTE, 0, 0))
81 {
82 UserSendNotifyMessage( HWND_BROADCAST,
83 WM_PALETTEISCHANGING,
84 (WPARAM)hWnd,
85 0);
86 }
87
88 if (Window->spwndPrev != NULL)
89 co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0,
90 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
91
92 if (!Window->spwndOwner && !IntGetParent(Window))
93 {
94 co_IntShellHookNotify(HSHELL_WINDOWACTIVATED, (LPARAM) hWnd);
95 }
96
97 if (Window)
98 { // Set last active for window and it's owner.
99 Window->hWndLastActive = hWnd;
100 if (Window->spwndOwner)
101 Window->spwndOwner->hWndLastActive = hWnd;
102 Window->state |= WNDS_ACTIVEFRAME;
103 }
104
105 if (WindowPrev)
106 WindowPrev->state &= ~WNDS_ACTIVEFRAME;
107
108 if (Window && WindowPrev)
109 {
110 PWND cWindow;
111 HWND *List, *phWnd;
112 HANDLE OldTID = IntGetWndThreadId(WindowPrev);
113 HANDLE NewTID = IntGetWndThreadId(Window);
114
115 DPRINT("SendActiveMessage Old -> %x, New -> %x\n", OldTID, NewTID);
116 if (Window->style & WS_MINIMIZE)
117 {
118 DPRINT("Widow was minimized\n");
119 }
120
121 if (OldTID != NewTID)
122 {
123 List = IntWinListChildren(UserGetWindowObject(IntGetDesktopWindow()));
124 if (List)
125 {
126 for (phWnd = List; *phWnd; ++phWnd)
127 {
128 cWindow = UserGetWindowObject(*phWnd);
129
130 if (cWindow && (IntGetWndThreadId(cWindow) == OldTID))
131 { // FALSE if the window is being deactivated,
132 // ThreadId that owns the window being activated.
133 co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, FALSE, (LPARAM)NewTID);
134 }
135 }
136 for (phWnd = List; *phWnd; ++phWnd)
137 {
138 cWindow = UserGetWindowObject(*phWnd);
139 if (cWindow && (IntGetWndThreadId(cWindow) == NewTID))
140 { // TRUE if the window is being activated,
141 // ThreadId that owns the window being deactivated.
142 co_IntSendMessageNoWait(*phWnd, WM_ACTIVATEAPP, TRUE, (LPARAM)OldTID);
143 }
144 }
145 ExFreePool(List);
146 }
147 }
148 UserDerefObjectCo(WindowPrev); // Now allow the previous window to die.
149 }
150
151 UserDerefObjectCo(Window);
152
153 /* FIXME: IntIsWindow */
154 co_IntSendMessageNoWait(hWnd, WM_NCACTIVATE, (WPARAM)(hWnd == UserGetForegroundWindow()), 0);
155 /* FIXME: WA_CLICKACTIVE */
156 co_IntSendMessageNoWait(hWnd, WM_ACTIVATE,
157 MAKEWPARAM(MouseActivate ? WA_CLICKACTIVE : WA_ACTIVE,
158 Window->style & WS_MINIMIZE),
159 (LPARAM)hWndPrev);
160 }
161 }
162
163 VOID FASTCALL
164 co_IntSendKillFocusMessages(HWND hWndPrev, HWND hWnd)
165 {
166 if (hWndPrev)
167 {
168 IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
169 co_IntPostOrSendMessage(hWndPrev, WM_KILLFOCUS, (WPARAM)hWnd, 0);
170 }
171 }
172
173 VOID FASTCALL
174 co_IntSendSetFocusMessages(HWND hWndPrev, HWND hWnd)
175 {
176 if (hWnd)
177 {
178 PWND pWnd = UserGetWindowObject(hWnd);
179 IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0);
180 co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0);
181 }
182 }
183
184 HWND FASTCALL
185 IntFindChildWindowToOwner(PWND Root, PWND Owner)
186 {
187 HWND Ret;
188 PWND Child, OwnerWnd;
189
190 for(Child = Root->spwndChild; Child; Child = Child->spwndNext)
191 {
192 OwnerWnd = Child->spwndOwner;
193 if(!OwnerWnd)
194 continue;
195
196 if(OwnerWnd == Owner)
197 {
198 Ret = Child->head.h;
199 return Ret;
200 }
201 }
202
203 return NULL;
204 }
205
206 static BOOL FASTCALL
207 co_IntSetForegroundAndFocusWindow(PWND Wnd, PWND FocusWindow, BOOL MouseActivate)
208 {
209 HWND hWnd = Wnd->head.h;
210 HWND hWndPrev = NULL;
211 HWND hWndFocus = FocusWindow->head.h;
212 HWND hWndFocusPrev = NULL;
213 PUSER_MESSAGE_QUEUE PrevForegroundQueue;
214
215 ASSERT_REFS_CO(Wnd);
216
217 DPRINT("IntSetForegroundAndFocusWindow(%x, %x, %s)\n", hWnd, hWndFocus, MouseActivate ? "TRUE" : "FALSE");
218
219 if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
220 {
221 DPRINT("Failed - Child\n");
222 return FALSE;
223 }
224
225 if (0 == (Wnd->style & WS_VISIBLE) &&
226 Wnd->head.pti->pEThread->ThreadsProcess != CsrProcess)
227 {
228 DPRINT("Failed - Invisible\n");
229 return FALSE;
230 }
231
232 PrevForegroundQueue = IntGetFocusMessageQueue();
233 if (PrevForegroundQueue != 0)
234 {
235 hWndPrev = PrevForegroundQueue->ActiveWindow;
236 hWndFocusPrev = PrevForegroundQueue->FocusWindow;
237 }
238
239 if (hWndPrev == hWnd)
240 {
241 DPRINT("Failed - Same\n");
242 return TRUE;
243 }
244
245 /* FIXME: Call hooks. */
246
247 co_IntSendDeactivateMessages(hWndPrev, hWnd);
248 co_IntSendKillFocusMessages(hWndFocusPrev, hWndFocus);
249
250
251 IntSetFocusMessageQueue(Wnd->head.pti->MessageQueue);
252
253 if (Wnd->head.pti->MessageQueue)
254 {
255 Wnd->head.pti->MessageQueue->ActiveWindow = hWnd;
256 }
257
258 if (FocusWindow->head.pti->MessageQueue)
259 {
260 FocusWindow->head.pti->MessageQueue->FocusWindow = hWndFocus;
261 }
262
263 if (PrevForegroundQueue != Wnd->head.pti->MessageQueue)
264 {
265 /* FIXME: Send WM_ACTIVATEAPP to all thread windows. */
266 }
267
268 co_IntSendSetFocusMessages(hWndFocusPrev, hWndFocus);
269 co_IntSendActivateMessages(hWndPrev, hWnd, MouseActivate);
270
271 return TRUE;
272 }
273
274 BOOL FASTCALL
275 co_IntSetForegroundWindow(PWND Window)//FIXME: can Window be NULL??
276 {
277 /*if (Window)*/ ASSERT_REFS_CO(Window);
278
279 return co_IntSetForegroundAndFocusWindow(Window, Window, FALSE);
280 }
281
282 BOOL FASTCALL
283 co_IntMouseActivateWindow(PWND Wnd)
284 {
285 HWND Top;
286 PWND TopWindow;
287 USER_REFERENCE_ENTRY Ref;
288
289 ASSERT_REFS_CO(Wnd);
290
291 if(Wnd->style & WS_DISABLED)
292 {
293 BOOL Ret;
294 PWND TopWnd;
295 PWND DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
296 if(DesktopWindow)
297 {
298 Top = IntFindChildWindowToOwner(DesktopWindow, Wnd);
299 if((TopWnd = UserGetWindowObject(Top)))
300 {
301 UserRefObjectCo(TopWnd, &Ref);
302 Ret = co_IntMouseActivateWindow(TopWnd);
303 UserDerefObjectCo(TopWnd);
304
305 return Ret;
306 }
307 }
308 return FALSE;
309 }
310
311
312 TopWindow = UserGetAncestor(Wnd, GA_ROOT);
313 if (!TopWindow) return FALSE;
314
315 /* TMN: Check return valud from this function? */
316 UserRefObjectCo(TopWindow, &Ref);
317
318 co_IntSetForegroundAndFocusWindow(TopWindow, Wnd, TRUE);
319
320 UserDerefObjectCo(TopWindow);
321
322 return TRUE;
323 }
324
325 HWND FASTCALL
326 co_IntSetActiveWindow(PWND Wnd OPTIONAL)
327 {
328 PTHREADINFO pti;
329 PUSER_MESSAGE_QUEUE ThreadQueue;
330 HWND hWndPrev;
331 HWND hWnd = 0;
332 CBTACTIVATESTRUCT cbt;
333
334 if (Wnd)
335 ASSERT_REFS_CO(Wnd);
336
337 pti = PsGetCurrentThreadWin32Thread();
338 ThreadQueue = pti->MessageQueue;
339 ASSERT(ThreadQueue != 0);
340
341 if (Wnd != 0)
342 {
343 if ((!(Wnd->style & WS_VISIBLE) &&
344 Wnd->head.pti->pEThread->ThreadsProcess != CsrProcess) ||
345 (Wnd->style & (WS_POPUP | WS_CHILD)) == WS_CHILD)
346 {
347 return ThreadQueue ? 0 : ThreadQueue->ActiveWindow;
348 }
349 hWnd = Wnd->head.h;
350 }
351
352 hWndPrev = ThreadQueue->ActiveWindow;
353 if (hWndPrev == hWnd)
354 {
355 return hWndPrev;
356 }
357
358 /* call CBT hook chain */
359 cbt.fMouse = FALSE;
360 cbt.hWndActive = hWndPrev;
361 if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt))
362 {
363 DPRINT1("SetActiveWindow WH_CBT Call Hook return!\n");
364 return 0;
365 }
366 ThreadQueue->ActiveWindow = hWnd;
367
368 co_IntSendDeactivateMessages(hWndPrev, hWnd);
369 co_IntSendActivateMessages(hWndPrev, hWnd, FALSE);
370
371 /* FIXME */
372 /* return IntIsWindow(hWndPrev) ? hWndPrev : 0;*/
373 return hWndPrev;
374 }
375
376 static
377 HWND FASTCALL
378 co_IntSetFocusWindow(PWND Window OPTIONAL)
379 {
380 HWND hWndPrev = 0;
381 PTHREADINFO pti;
382 PUSER_MESSAGE_QUEUE ThreadQueue;
383
384 if (Window)
385 ASSERT_REFS_CO(Window);
386
387 pti = PsGetCurrentThreadWin32Thread();
388 ThreadQueue = pti->MessageQueue;
389 ASSERT(ThreadQueue != 0);
390
391 hWndPrev = ThreadQueue->FocusWindow;
392
393 if (Window != 0)
394 {
395 if (hWndPrev == Window->head.h)
396 {
397 return hWndPrev;
398 }
399
400 if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev))
401 {
402 DPRINT1("SetFocusWindow 1 WH_CBT Call Hook return!\n");
403 return 0;
404 }
405 ThreadQueue->FocusWindow = Window->head.h;
406
407 co_IntSendKillFocusMessages(hWndPrev, Window->head.h);
408 co_IntSendSetFocusMessages(hWndPrev, Window->head.h);
409 }
410 else
411 {
412 ThreadQueue->FocusWindow = 0;
413 if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
414 {
415 DPRINT1("SetFocusWindow 2 WH_CBT Call Hook return!\n");
416 return 0;
417 }
418
419 co_IntSendKillFocusMessages(hWndPrev, 0);
420 }
421 return hWndPrev;
422 }
423
424
425 /*
426 * @implemented
427 */
428 HWND FASTCALL
429 UserGetForegroundWindow(VOID)
430 {
431 PUSER_MESSAGE_QUEUE ForegroundQueue;
432
433 ForegroundQueue = IntGetFocusMessageQueue();
434 return( ForegroundQueue != NULL ? ForegroundQueue->ActiveWindow : 0);
435 }
436
437
438 /*
439 * @implemented
440 */
441 HWND APIENTRY
442 NtUserGetForegroundWindow(VOID)
443 {
444 DECLARE_RETURN(HWND);
445
446 DPRINT("Enter NtUserGetForegroundWindow\n");
447 UserEnterExclusive();
448
449 RETURN( UserGetForegroundWindow());
450
451 CLEANUP:
452 DPRINT("Leave NtUserGetForegroundWindow, ret=%i\n",_ret_);
453 UserLeave();
454 END_CLEANUP;
455 }
456
457
458 HWND FASTCALL UserGetActiveWindow(VOID)
459 {
460 PTHREADINFO pti;
461 PUSER_MESSAGE_QUEUE ThreadQueue;
462
463 pti = PsGetCurrentThreadWin32Thread();
464 ThreadQueue = pti->MessageQueue;
465 return( ThreadQueue ? ThreadQueue->ActiveWindow : 0);
466 }
467
468
469 HWND APIENTRY
470 NtUserSetActiveWindow(HWND hWnd)
471 {
472 USER_REFERENCE_ENTRY Ref;
473 DECLARE_RETURN(HWND);
474
475 DPRINT("Enter NtUserSetActiveWindow(%x)\n", hWnd);
476 UserEnterExclusive();
477
478 if (hWnd)
479 {
480 PWND Window;
481 PTHREADINFO pti;
482 PUSER_MESSAGE_QUEUE ThreadQueue;
483 HWND hWndPrev;
484
485 if (!(Window = UserGetWindowObject(hWnd)))
486 {
487 RETURN( 0);
488 }
489
490 pti = PsGetCurrentThreadWin32Thread();
491 ThreadQueue = pti->MessageQueue;
492
493 if (Window->head.pti->MessageQueue != ThreadQueue)
494 {
495 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
496 RETURN( 0);
497 }
498
499 UserRefObjectCo(Window, &Ref);
500 hWndPrev = co_IntSetActiveWindow(Window);
501 UserDerefObjectCo(Window);
502
503 RETURN( hWndPrev);
504 }
505 else
506 {
507 RETURN( co_IntSetActiveWindow(0));
508 }
509
510 CLEANUP:
511 DPRINT("Leave NtUserSetActiveWindow, ret=%i\n",_ret_);
512 UserLeave();
513 END_CLEANUP;
514 }
515
516 /*
517 * @implemented
518 */
519 HWND APIENTRY
520 IntGetCapture(VOID)
521 {
522 PTHREADINFO pti;
523 PUSER_MESSAGE_QUEUE ThreadQueue;
524 DECLARE_RETURN(HWND);
525
526 DPRINT("Enter IntGetCapture\n");
527
528 pti = PsGetCurrentThreadWin32Thread();
529 ThreadQueue = pti->MessageQueue;
530 RETURN( ThreadQueue ? ThreadQueue->CaptureWindow : 0);
531
532 CLEANUP:
533 DPRINT("Leave IntGetCapture, ret=%i\n",_ret_);
534 END_CLEANUP;
535 }
536
537
538 HWND FASTCALL
539 co_UserSetCapture(HWND hWnd)
540 {
541 PTHREADINFO pti;
542 PUSER_MESSAGE_QUEUE ThreadQueue;
543 PWND Window, pWnd;
544 HWND hWndPrev;
545
546 pti = PsGetCurrentThreadWin32Thread();
547 ThreadQueue = pti->MessageQueue;
548
549 if (ThreadQueue->QF_flags & QF_CAPTURELOCKED)
550 return NULL;
551
552 if ((Window = UserGetWindowObject(hWnd)))
553 {
554 if (Window->head.pti->MessageQueue != ThreadQueue)
555 {
556 return NULL;
557 }
558 }
559
560 hWndPrev = MsqSetStateWindow(ThreadQueue, MSQ_STATE_CAPTURE, hWnd);
561
562 if (hWndPrev)
563 {
564 pWnd = UserGetWindowObject(hWndPrev);
565 if (pWnd)
566 IntNotifyWinEvent(EVENT_SYSTEM_CAPTUREEND, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
567 }
568
569 if (Window)
570 IntNotifyWinEvent(EVENT_SYSTEM_CAPTURESTART, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
571
572 if (hWndPrev && hWndPrev != hWnd)
573 {
574 if (ThreadQueue->MenuOwner && Window) ThreadQueue->QF_flags |= QF_CAPTURELOCKED;
575
576 co_IntPostOrSendMessage(hWndPrev, WM_CAPTURECHANGED, 0, (LPARAM)hWnd);
577
578 ThreadQueue->QF_flags &= ~QF_CAPTURELOCKED;
579 }
580
581 ThreadQueue->CaptureWindow = hWnd;
582
583 if (hWnd == NULL) // Release mode.
584 {
585 MOUSEINPUT mi;
586 /// These are hacks!
587 /* also remove other windows if not capturing anymore */
588 MsqSetStateWindow(ThreadQueue, MSQ_STATE_MENUOWNER, NULL);
589 MsqSetStateWindow(ThreadQueue, MSQ_STATE_MOVESIZE, NULL);
590 ///
591 /* Somebody may have missed some mouse movements */
592 mi.dx = 0;
593 mi.dy = 0;
594 mi.mouseData = 0;
595 mi.dwFlags = MOUSEEVENTF_MOVE;
596 mi.time = 0;
597 mi.dwExtraInfo = 0;
598 IntMouseInput(&mi,FALSE);
599 }
600 return hWndPrev;
601 }
602
603 BOOL
604 FASTCALL
605 IntReleaseCapture(VOID)
606 {
607 PTHREADINFO pti;
608 PUSER_MESSAGE_QUEUE ThreadQueue;
609
610 pti = PsGetCurrentThreadWin32Thread();
611 ThreadQueue = pti->MessageQueue;
612
613 // Can not release inside WM_CAPTURECHANGED!!
614 if (ThreadQueue->QF_flags & QF_CAPTURELOCKED) return FALSE;
615
616 co_UserSetCapture(NULL);
617
618 return TRUE;
619 }
620
621 /*
622 * @implemented
623 */
624 HWND APIENTRY
625 NtUserSetCapture(HWND hWnd)
626 {
627 DECLARE_RETURN(HWND);
628
629 DPRINT("Enter NtUserSetCapture(%x)\n", hWnd);
630 UserEnterExclusive();
631
632 RETURN( co_UserSetCapture(hWnd));
633
634 CLEANUP:
635 DPRINT("Leave NtUserSetCapture, ret=%i\n",_ret_);
636 UserLeave();
637 END_CLEANUP;
638 }
639
640
641
642 HWND FASTCALL co_UserSetFocus(PWND Wnd OPTIONAL)
643 {
644 if (Wnd)
645 {
646 PTHREADINFO pti;
647 PUSER_MESSAGE_QUEUE ThreadQueue;
648 HWND hWndPrev;
649 PWND TopWnd;
650 USER_REFERENCE_ENTRY Ref;
651
652 ASSERT_REFS_CO(Wnd);
653
654 pti = PsGetCurrentThreadWin32Thread();
655 ThreadQueue = pti->MessageQueue;
656
657 if (Wnd->style & (WS_MINIMIZE | WS_DISABLED))
658 {
659 return( (ThreadQueue ? ThreadQueue->FocusWindow : 0));
660 }
661
662 if (Wnd->head.pti->MessageQueue != ThreadQueue)
663 {
664 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
665 return( 0);
666 }
667
668 TopWnd = UserGetAncestor(Wnd, GA_ROOT);
669 if (TopWnd && TopWnd->head.h != UserGetActiveWindow())
670 {
671 // PWND WndTops = UserGetWindowObject(hWndTop);
672 UserRefObjectCo(TopWnd, &Ref);
673 co_IntSetActiveWindow(TopWnd);
674 UserDerefObjectCo(TopWnd);
675 }
676
677 hWndPrev = co_IntSetFocusWindow(Wnd);
678
679 return( hWndPrev);
680 }
681 else
682 {
683 return( co_IntSetFocusWindow(NULL));
684 }
685
686 }
687
688
689 /*
690 * @implemented
691 */
692 HWND APIENTRY
693 NtUserSetFocus(HWND hWnd)
694 {
695 PWND Window;
696 USER_REFERENCE_ENTRY Ref;
697 DECLARE_RETURN(HWND);
698 HWND ret;
699
700 DPRINT("Enter NtUserSetFocus(%x)\n", hWnd);
701 UserEnterExclusive();
702
703 if (hWnd)
704 {
705 if (!(Window = UserGetWindowObject(hWnd)))
706 {
707 RETURN(NULL);
708 }
709
710 UserRefObjectCo(Window, &Ref);
711 ret = co_UserSetFocus(Window);
712 UserDerefObjectCo(Window);
713
714 RETURN(ret);
715 }
716 else
717 {
718 RETURN( co_UserSetFocus(0));
719 }
720
721 CLEANUP:
722 DPRINT("Leave NtUserSetFocus, ret=%i\n",_ret_);
723 UserLeave();
724 END_CLEANUP;
725 }
726
727 /* EOF */