Added a missing LeaveCriticalSection.
[wine.git] / windows / focus.c
bloba0cfb57e9666532b23d9229a164315da2fbf6f6b
1 /*
2 * Focus functions
4 * Copyright 1993 David Metcalfe
5 * 1994 Alexandre Julliard
6 * 1995 Alex Korobka
8 */
10 #include "win.h"
11 #include "winpos.h"
12 #include "hook.h"
13 #include "message.h"
14 #include "task.h"
15 #include "debug.h"
17 DEFAULT_DEBUG_CHANNEL(win)
20 /*****************************************************************
21 * FOCUS_SwitchFocus
22 * pMsgQ is the queue whose perQData focus is to be modified
24 void FOCUS_SwitchFocus( MESSAGEQUEUE *pMsgQ, HWND hFocusFrom, HWND hFocusTo )
26 WND *pFocusTo = WIN_FindWndPtr( hFocusTo );
28 PERQDATA_SetFocusWnd( pMsgQ->pQData, hFocusTo );
30 #if 0
31 if (hFocusFrom) SendMessageA( hFocusFrom, WM_KILLFOCUS, hFocusTo, 0 );
32 #else
33 /* FIXME: must be SendMessage16() because 32A doesn't do
34 * intertask at this time */
35 if (hFocusFrom) SendMessage16( hFocusFrom, WM_KILLFOCUS, hFocusTo, 0 );
36 #endif
38 if( !pFocusTo || hFocusTo != PERQDATA_GetFocusWnd( pMsgQ->pQData ) )
40 WIN_ReleaseWndPtr(pFocusTo);
41 return;
44 /* According to API docs, the WM_SETFOCUS message is sent AFTER the window
45 has received the keyboard focus. */
47 pFocusTo->pDriver->pSetFocus(pFocusTo);
49 WIN_ReleaseWndPtr(pFocusTo);
50 #if 0
51 SendMessageA( hFocusTo, WM_SETFOCUS, hFocusFrom, 0 );
52 #else
53 SendMessage16( hFocusTo, WM_SETFOCUS, hFocusFrom, 0 );
54 #endif
58 /*****************************************************************
59 * SetFocus16 (USER.22)
61 HWND16 WINAPI SetFocus16( HWND16 hwnd )
63 return (HWND16)SetFocus( hwnd );
67 /*****************************************************************
68 * SetFocus32 (USER32.481)
70 HWND WINAPI SetFocus( HWND hwnd )
72 HWND hWndFocus = 0, hwndTop = hwnd;
73 WND *wndPtr = WIN_FindWndPtr( hwnd );
74 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
75 BOOL16 bRet = 0;
77 /* Get the messageQ for the current thread */
78 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
80 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
81 goto CLEANUP;
84 if (wndPtr)
86 /* Check if we can set the focus to this window */
88 while ( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
90 if ( wndPtr->dwStyle & ( WS_MINIMIZE | WS_DISABLED) )
91 goto CLEANUP;
92 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
93 if (!wndPtr) goto CLEANUP;
94 hwndTop = wndPtr->hwndSelf;
97 /* Retrieve the message queue associated with this window */
98 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
99 if ( !pMsgQ )
101 WARN( win, "\tMessage queue not found. Exiting!\n" );
102 goto CLEANUP;
105 /* Make sure that message queue for the window we are setting focus to
106 * shares the same perQ data as the current threads message queue.
107 * In other words you can't set focus to a window owned by a different
108 * thread unless AttachThreadInput has been called previously.
109 * (see AttachThreadInput and SetFocus docs)
111 if ( pCurMsgQ->pQData != pMsgQ->pQData )
112 goto CLEANUP;
114 /* Get the current focus window from the perQ data */
115 hWndFocus = PERQDATA_GetFocusWnd( pMsgQ->pQData );
117 if( hwnd == hWndFocus )
119 bRet = 1; /* Success */
120 goto CLEANUP; /* Nothing to do */
123 /* call hooks */
124 if( HOOK_CallHooks16( WH_CBT, HCBT_SETFOCUS, (WPARAM16)hwnd,
125 (LPARAM)hWndFocus) )
126 goto CLEANUP;
128 /* activate hwndTop if needed. */
129 if (hwndTop != GetActiveWindow())
131 if (!WINPOS_SetActiveWindow(hwndTop, 0, 0)) goto CLEANUP;
133 if (!IsWindow( hwnd )) goto CLEANUP; /* Abort if window destroyed */
136 /* Get the current focus window from the perQ data */
137 hWndFocus = PERQDATA_GetFocusWnd( pMsgQ->pQData );
139 /* Change focus and send messages */
140 FOCUS_SwitchFocus( pMsgQ, hWndFocus, hwnd );
142 else /* NULL hwnd passed in */
144 if( HOOK_CallHooks16( WH_CBT, HCBT_SETFOCUS, 0, (LPARAM)hWndFocus ) )
145 goto CLEANUP;
147 /* Get the current focus from the perQ data of the current message Q */
148 hWndFocus = PERQDATA_GetFocusWnd( pCurMsgQ->pQData );
150 /* Change focus and send messages */
151 FOCUS_SwitchFocus( pCurMsgQ, hWndFocus, hwnd );
154 bRet = 1; /* Success */
156 CLEANUP:
158 /* Unlock the queues before returning */
159 if ( pMsgQ )
160 QUEUE_Unlock( pMsgQ );
161 if ( pCurMsgQ )
162 QUEUE_Unlock( pCurMsgQ );
164 WIN_ReleaseWndPtr(wndPtr);
165 return bRet ? hWndFocus : 0;
169 /*****************************************************************
170 * GetFocus16 (USER.23)
172 HWND16 WINAPI GetFocus16(void)
174 return (HWND16)GetFocus();
178 /*****************************************************************
179 * GetFocus32 (USER32.240)
181 HWND WINAPI GetFocus(void)
183 MESSAGEQUEUE *pCurMsgQ = 0;
184 HWND hwndFocus = 0;
186 /* Get the messageQ for the current thread */
187 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
189 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
190 return 0;
193 /* Get the current focus from the perQ data of the current message Q */
194 hwndFocus = PERQDATA_GetFocusWnd( pCurMsgQ->pQData );
196 QUEUE_Unlock( pCurMsgQ );
198 return hwndFocus;