Made nt-related types compatible, throw out wine-specific types.
[wine] / windows / focus.c
1 /*
2  * Focus functions
3  *
4  * Copyright 1993 David Metcalfe
5  *           1994 Alexandre Julliard
6  *           1995 Alex Korobka
7  *
8  */
9
10 #include "win.h"
11 #include "winpos.h"
12 #include "hook.h"
13 #include "message.h"
14 #include "task.h"
15 #include "debug.h"
16
17
18 /*****************************************************************
19  *               FOCUS_SwitchFocus 
20  * pMsgQ is the queue whose perQData focus is to be modified
21  */
22 void FOCUS_SwitchFocus( MESSAGEQUEUE *pMsgQ, HWND32 hFocusFrom, HWND32 hFocusTo )
23 {
24     WND *pFocusTo = WIN_FindWndPtr( hFocusTo );
25
26     PERQDATA_SetFocusWnd( pMsgQ->pQData, hFocusTo );
27     
28 #if 0
29     if (hFocusFrom) SendMessage32A( hFocusFrom, WM_KILLFOCUS, hFocusTo, 0 );
30 #else
31     /* FIXME: must be SendMessage16() because 32A doesn't do
32      * intertask at this time */
33     if (hFocusFrom) SendMessage16( hFocusFrom, WM_KILLFOCUS, hFocusTo, 0 );
34 #endif
35
36     if( !pFocusTo || hFocusTo != PERQDATA_GetFocusWnd( pMsgQ->pQData ) )
37         return;
38
39     /* According to API docs, the WM_SETFOCUS message is sent AFTER the window
40        has received the keyboard focus. */
41
42     pFocusTo->pDriver->pSetFocus(pFocusTo);
43
44 #if 0
45     SendMessage32A( hFocusTo, WM_SETFOCUS, hFocusFrom, 0 );
46 #else
47     SendMessage16( hFocusTo, WM_SETFOCUS, hFocusFrom, 0 );
48 #endif
49 }
50
51
52 /*****************************************************************
53  *               SetFocus16   (USER.22)
54  */
55 HWND16 WINAPI SetFocus16( HWND16 hwnd )
56 {
57     return (HWND16)SetFocus32( hwnd );
58 }
59
60
61 /*****************************************************************
62  *               SetFocus32   (USER32.481)
63  */
64 HWND32 WINAPI SetFocus32( HWND32 hwnd )
65 {
66     HWND32 hWndFocus = 0, hwndTop = hwnd;
67     WND *wndPtr = WIN_FindWndPtr( hwnd );
68     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
69     BOOL16 bRet = 0;
70
71     /* Get the messageQ for the current thread */
72     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() )))
73     {
74         WARN( win, "\tCurrent message queue not found. Exiting!\n" );
75         goto CLEANUP;
76     }
77
78     if (wndPtr)
79     {
80           /* Check if we can set the focus to this window */
81
82         while ( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD  )
83         {
84             if ( wndPtr->dwStyle & ( WS_MINIMIZE | WS_DISABLED) )
85                  goto CLEANUP;
86             if (!(wndPtr = wndPtr->parent)) goto CLEANUP;
87             hwndTop = wndPtr->hwndSelf;
88         }
89
90         /* Retrieve the message queue associated with this window */
91         pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
92         if ( !pMsgQ )
93         {
94             WARN( win, "\tMessage queue not found. Exiting!\n" );
95             goto CLEANUP;
96         }
97
98         /* Make sure that message queue for the window we are setting focus to
99          * shares the same perQ data as the current threads message queue.
100          * In other words you can't set focus to a window owned by a different
101          * thread unless AttachThreadInput has been called previously.
102          * (see AttachThreadInput and SetFocus docs)
103          */
104         if ( pCurMsgQ->pQData != pMsgQ->pQData )
105             goto CLEANUP;
106
107         /* Get the current focus window from the perQ data */
108         hWndFocus = PERQDATA_GetFocusWnd( pMsgQ->pQData );
109         
110         if( hwnd == hWndFocus )
111         {
112             bRet = 1;      // Success
113             goto CLEANUP;  // Nothing to do
114         }
115         
116         /* call hooks */
117         if( HOOK_CallHooks16( WH_CBT, HCBT_SETFOCUS, (WPARAM16)hwnd,
118                               (LPARAM)hWndFocus) )
119             goto CLEANUP;
120
121         /* activate hwndTop if needed. */
122         if (hwndTop != GetActiveWindow32())
123         {
124             if (!WINPOS_SetActiveWindow(hwndTop, 0, 0)) goto CLEANUP;
125
126             if (!IsWindow32( hwnd )) goto CLEANUP;  /* Abort if window destroyed */
127         }
128
129         /* Get the current focus window from the perQ data */
130         hWndFocus = PERQDATA_GetFocusWnd( pMsgQ->pQData );
131         
132         /* Change focus and send messages */
133         FOCUS_SwitchFocus( pMsgQ, hWndFocus, hwnd );
134     }
135     else /* NULL hwnd passed in */
136     {
137         if( HOOK_CallHooks16( WH_CBT, HCBT_SETFOCUS, 0, (LPARAM)hWndFocus ) )
138             goto CLEANUP;
139
140         /* Get the current focus from the perQ data of the current message Q */
141         hWndFocus = PERQDATA_GetFocusWnd( pCurMsgQ->pQData );
142
143       /* Change focus and send messages */
144         FOCUS_SwitchFocus( pCurMsgQ, hWndFocus, hwnd );
145     }
146
147     bRet = 1;      // Success
148     
149 CLEANUP:
150
151     /* Unlock the queues before returning */
152     if ( pMsgQ )
153         QUEUE_Unlock( pMsgQ );
154     if ( pCurMsgQ )
155         QUEUE_Unlock( pCurMsgQ );
156
157     return bRet ? hWndFocus : 0;
158 }
159
160
161 /*****************************************************************
162  *               GetFocus16   (USER.23)
163  */
164 HWND16 WINAPI GetFocus16(void)
165 {
166     return (HWND16)GetFocus32();
167 }
168
169
170 /*****************************************************************
171  *               GetFocus32   (USER32.240)
172  */
173 HWND32 WINAPI GetFocus32(void)
174 {
175     MESSAGEQUEUE *pCurMsgQ = 0;
176     HWND32 hwndFocus = 0;
177
178     /* Get the messageQ for the current thread */
179     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() )))
180     {
181         WARN( win, "\tCurrent message queue not found. Exiting!\n" );
182         return 0;
183     }
184
185     /* Get the current focus from the perQ data of the current message Q */
186     hwndFocus = PERQDATA_GetFocusWnd( pCurMsgQ->pQData );
187
188     QUEUE_Unlock( pCurMsgQ );
189
190     return hwndFocus;
191 }