blob: ab4ea08619d253c75d358fd0a427f365a0d468bc [file] [log] [blame]
Alexandre Julliard0e607781993-11-03 19:23:37 +00001/*
2 * Focus functions
3 *
4 * Copyright 1993 David Metcalfe
Alexandre Julliardd4719651995-12-12 18:49:11 +00005 * 1994 Alexandre Julliard
6 * 1995 Alex Korobka
Alexandre Julliard234bc241994-12-10 13:02:28 +00007 *
Alexandre Julliardd4719651995-12-12 18:49:11 +00008 */
Alexandre Julliard0e607781993-11-03 19:23:37 +00009
Jeremy Whited3e22d92000-02-10 19:03:02 +000010#include "windef.h"
11#include "wingdi.h"
Michael Veksler9d14a001999-05-08 12:40:24 +000012#include "wine/winuser16.h"
Alexandre Julliard0e607781993-11-03 19:23:37 +000013#include "win.h"
Alexandre Julliardd4719651995-12-12 18:49:11 +000014#include "winpos.h"
15#include "hook.h"
Alexandre Julliardf1aa3031996-08-05 17:42:43 +000016#include "message.h"
Patrik Stridvall6cc47d42000-03-08 18:26:56 +000017#include "queue.h"
Noel Borthwickb4278561999-02-05 10:37:53 +000018#include "task.h"
Alexandre Julliard359f497e1999-07-04 16:02:24 +000019#include "debugtools.h"
Alexandre Julliardd4719651995-12-12 18:49:11 +000020
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000021DEFAULT_DEBUG_CHANNEL(win)
22
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000023
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000024/*****************************************************************
Alexandre Julliardd4719651995-12-12 18:49:11 +000025 * FOCUS_SwitchFocus
Noel Borthwickb4278561999-02-05 10:37:53 +000026 * pMsgQ is the queue whose perQData focus is to be modified
Alexandre Julliardd4719651995-12-12 18:49:11 +000027 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000028void FOCUS_SwitchFocus( MESSAGEQUEUE *pMsgQ, HWND hFocusFrom, HWND hFocusTo )
Alexandre Julliardd4719651995-12-12 18:49:11 +000029{
Patrik Stridvalle35d6361998-12-07 09:13:40 +000030 WND *pFocusTo = WIN_FindWndPtr( hFocusTo );
Alexandre Julliardd4719651995-12-12 18:49:11 +000031
Noel Borthwickb4278561999-02-05 10:37:53 +000032 PERQDATA_SetFocusWnd( pMsgQ->pQData, hFocusTo );
33
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +000034#if 0
Alexandre Julliarda3960291999-02-26 11:11:13 +000035 if (hFocusFrom) SendMessageA( hFocusFrom, WM_KILLFOCUS, hFocusTo, 0 );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +000036#else
37 /* FIXME: must be SendMessage16() because 32A doesn't do
38 * intertask at this time */
39 if (hFocusFrom) SendMessage16( hFocusFrom, WM_KILLFOCUS, hFocusTo, 0 );
40#endif
Noel Borthwickb4278561999-02-05 10:37:53 +000041
42 if( !pFocusTo || hFocusTo != PERQDATA_GetFocusWnd( pMsgQ->pQData ) )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +000043 {
44 WIN_ReleaseWndPtr(pFocusTo);
Alexandre Julliardd4719651995-12-12 18:49:11 +000045 return;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +000046 }
Alexandre Julliardd4719651995-12-12 18:49:11 +000047
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000048 /* According to API docs, the WM_SETFOCUS message is sent AFTER the window
49 has received the keyboard focus. */
Patrik Stridvalle35d6361998-12-07 09:13:40 +000050
51 pFocusTo->pDriver->pSetFocus(pFocusTo);
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000052
Francois Boisvert6b1b41c1999-03-14 17:25:32 +000053 WIN_ReleaseWndPtr(pFocusTo);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +000054#if 0
Alexandre Julliarda3960291999-02-26 11:11:13 +000055 SendMessageA( hFocusTo, WM_SETFOCUS, hFocusFrom, 0 );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +000056#else
57 SendMessage16( hFocusTo, WM_SETFOCUS, hFocusFrom, 0 );
58#endif
Alexandre Julliardd4719651995-12-12 18:49:11 +000059}
60
Alexandre Julliard0e607781993-11-03 19:23:37 +000061
62/*****************************************************************
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000063 * SetFocus16 (USER.22)
Alexandre Julliard0e607781993-11-03 19:23:37 +000064 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +000065HWND16 WINAPI SetFocus16( HWND16 hwnd )
Alexandre Julliard0e607781993-11-03 19:23:37 +000066{
Alexandre Julliarda3960291999-02-26 11:11:13 +000067 return (HWND16)SetFocus( hwnd );
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000068}
69
70
71/*****************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +000072 * SetFocus (USER32.481)
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000073 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000074HWND WINAPI SetFocus( HWND hwnd )
Alexandre Julliard8bbf8181996-09-13 16:50:47 +000075{
Alexandre Julliarda3960291999-02-26 11:11:13 +000076 HWND hWndFocus = 0, hwndTop = hwnd;
Alexandre Julliard59730ae1996-03-24 16:20:51 +000077 WND *wndPtr = WIN_FindWndPtr( hwnd );
Noel Borthwickb4278561999-02-05 10:37:53 +000078 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
79 BOOL16 bRet = 0;
80
81 /* Get the messageQ for the current thread */
Alexandre Julliarda3960291999-02-26 11:11:13 +000082 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
Noel Borthwickb4278561999-02-05 10:37:53 +000083 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +000084 WARN("\tCurrent message queue not found. Exiting!\n" );
Noel Borthwickb4278561999-02-05 10:37:53 +000085 goto CLEANUP;
86 }
Alexandre Julliard0e607781993-11-03 19:23:37 +000087
Alexandre Julliardd4719651995-12-12 18:49:11 +000088 if (wndPtr)
Alexandre Julliard0e607781993-11-03 19:23:37 +000089 {
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000090 /* Check if we can set the focus to this window */
91
Alexandre Julliardd4719651995-12-12 18:49:11 +000092 while ( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
Alexandre Julliardcdd09231994-01-12 11:12:51 +000093 {
Alexandre Julliardd4719651995-12-12 18:49:11 +000094 if ( wndPtr->dwStyle & ( WS_MINIMIZE | WS_DISABLED) )
Noel Borthwickb4278561999-02-05 10:37:53 +000095 goto CLEANUP;
Francois Boisvert3a3cd9f1999-03-28 12:42:52 +000096 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
97 if (!wndPtr) goto CLEANUP;
Alexandre Julliard59730ae1996-03-24 16:20:51 +000098 hwndTop = wndPtr->hwndSelf;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000099 }
100
Adrian Thurston73a26fa1999-10-24 17:23:52 +0000101 /* definitely at the top window now */
102 if ( wndPtr->dwStyle & ( WS_MINIMIZE | WS_DISABLED) ) goto CLEANUP;
103
Noel Borthwickb4278561999-02-05 10:37:53 +0000104 /* Retrieve the message queue associated with this window */
105 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
106 if ( !pMsgQ )
107 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000108 WARN("\tMessage queue not found. Exiting!\n" );
Noel Borthwickb4278561999-02-05 10:37:53 +0000109 goto CLEANUP;
110 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000111
Noel Borthwickb4278561999-02-05 10:37:53 +0000112 /* Make sure that message queue for the window we are setting focus to
113 * shares the same perQ data as the current threads message queue.
114 * In other words you can't set focus to a window owned by a different
115 * thread unless AttachThreadInput has been called previously.
116 * (see AttachThreadInput and SetFocus docs)
117 */
118 if ( pCurMsgQ->pQData != pMsgQ->pQData )
119 goto CLEANUP;
120
121 /* Get the current focus window from the perQ data */
122 hWndFocus = PERQDATA_GetFocusWnd( pMsgQ->pQData );
123
124 if( hwnd == hWndFocus )
125 {
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +0000126 bRet = 1; /* Success */
127 goto CLEANUP; /* Nothing to do */
Noel Borthwickb4278561999-02-05 10:37:53 +0000128 }
129
Alexandre Julliardd4719651995-12-12 18:49:11 +0000130 /* call hooks */
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000131 if( HOOK_CallHooks16( WH_CBT, HCBT_SETFOCUS, (WPARAM16)hwnd,
Noel Borthwickb4278561999-02-05 10:37:53 +0000132 (LPARAM)hWndFocus) )
133 goto CLEANUP;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000134
135 /* activate hwndTop if needed. */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000136 if (hwndTop != GetActiveWindow())
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000137 {
Noel Borthwickb4278561999-02-05 10:37:53 +0000138 if (!WINPOS_SetActiveWindow(hwndTop, 0, 0)) goto CLEANUP;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000139
Alexandre Julliarda3960291999-02-26 11:11:13 +0000140 if (!IsWindow( hwnd )) goto CLEANUP; /* Abort if window destroyed */
Alexandre Julliardcdd09231994-01-12 11:12:51 +0000141 }
Noel Borthwickb4278561999-02-05 10:37:53 +0000142
143 /* Get the current focus window from the perQ data */
144 hWndFocus = PERQDATA_GetFocusWnd( pMsgQ->pQData );
145
146 /* Change focus and send messages */
147 FOCUS_SwitchFocus( pMsgQ, hWndFocus, hwnd );
Alexandre Julliard0e607781993-11-03 19:23:37 +0000148 }
Noel Borthwickb4278561999-02-05 10:37:53 +0000149 else /* NULL hwnd passed in */
150 {
151 if( HOOK_CallHooks16( WH_CBT, HCBT_SETFOCUS, 0, (LPARAM)hWndFocus ) )
152 goto CLEANUP;
153
154 /* Get the current focus from the perQ data of the current message Q */
155 hWndFocus = PERQDATA_GetFocusWnd( pCurMsgQ->pQData );
Alexandre Julliard0e607781993-11-03 19:23:37 +0000156
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000157 /* Change focus and send messages */
Noel Borthwickb4278561999-02-05 10:37:53 +0000158 FOCUS_SwitchFocus( pCurMsgQ, hWndFocus, hwnd );
159 }
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000160
Patrik Stridvall0f8bc5b1999-04-22 16:27:50 +0000161 bRet = 1; /* Success */
Noel Borthwickb4278561999-02-05 10:37:53 +0000162
163CLEANUP:
Alexandre Julliardd4719651995-12-12 18:49:11 +0000164
Noel Borthwickb4278561999-02-05 10:37:53 +0000165 /* Unlock the queues before returning */
166 if ( pMsgQ )
167 QUEUE_Unlock( pMsgQ );
168 if ( pCurMsgQ )
169 QUEUE_Unlock( pCurMsgQ );
170
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000171 WIN_ReleaseWndPtr(wndPtr);
Noel Borthwickb4278561999-02-05 10:37:53 +0000172 return bRet ? hWndFocus : 0;
Alexandre Julliard0e607781993-11-03 19:23:37 +0000173}
174
175
176/*****************************************************************
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000177 * GetFocus16 (USER.23)
Alexandre Julliard0e607781993-11-03 19:23:37 +0000178 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000179HWND16 WINAPI GetFocus16(void)
Alexandre Julliard0e607781993-11-03 19:23:37 +0000180{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000181 return (HWND16)GetFocus();
Alexandre Julliard0e607781993-11-03 19:23:37 +0000182}
183
184
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000185/*****************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000186 * GetFocus (USER32.240)
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000187 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000188HWND WINAPI GetFocus(void)
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000189{
Noel Borthwickb4278561999-02-05 10:37:53 +0000190 MESSAGEQUEUE *pCurMsgQ = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000191 HWND hwndFocus = 0;
Noel Borthwickb4278561999-02-05 10:37:53 +0000192
193 /* Get the messageQ for the current thread */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000194 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
Noel Borthwickb4278561999-02-05 10:37:53 +0000195 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000196 WARN("\tCurrent message queue not found. Exiting!\n" );
Noel Borthwickb4278561999-02-05 10:37:53 +0000197 return 0;
198 }
199
200 /* Get the current focus from the perQ data of the current message Q */
201 hwndFocus = PERQDATA_GetFocusWnd( pCurMsgQ->pQData );
202
203 QUEUE_Unlock( pCurMsgQ );
204
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000205 return hwndFocus;
206}