1 /*
2 * Focus and activation functions
3 *
4 * Copyright 1993 David Metcalfe
5 * Copyright 1995 Alex Korobka
6 * Copyright 1994, 2002 Alexandre Julliard
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "win.h"
32 #include "user_private.h"
33 #include "wine/server.h"
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(win);
37
38
39 /*****************************************************************
40 * set_focus_window
41 *
42 * Change the focus window, sending the WM_SETFOCUS and WM_KILLFOCUS messages
43 */
44 static HWND set_focus_window( HWND hwnd )
45 {
46 HWND previous = 0;
47 BOOL ret;
48
49 SERVER_START_REQ( set_focus_window )
50 {
51 req->handle = wine_server_user_handle( hwnd );
52 if ((ret = !wine_server_call_err( req )))
53 previous = wine_server_ptr_handle( reply->previous );
54 }
55 SERVER_END_REQ;
56 if (!ret) return 0;
57 if (previous == hwnd) return previous;
58
59 if (previous)
60 {
61 SendMessageW( previous, WM_KILLFOCUS, (WPARAM)hwnd, 0 );
62 if (hwnd != GetFocus()) return previous; /* changed by the message */
63 }
64 if (IsWindow(hwnd))
65 {
66 USER_Driver->pSetFocus(hwnd);
67 SendMessageW( hwnd, WM_SETFOCUS, (WPARAM)previous, 0 );
68 }
69 return previous;
70 }
71
72
73 /*******************************************************************
74 * set_active_window
75 */
76 static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
77 {
78 HWND previous = GetActiveWindow();
79 BOOL ret;
80 DWORD old_thread, new_thread;
81 CBTACTIVATESTRUCT cbt;
82
83 if (previous == hwnd)
84 {
85 if (prev) *prev = hwnd;
86 return TRUE;
87 }
88
89 /* call CBT hook chain */
90 cbt.fMouse = mouse;
91 cbt.hWndActive = previous;
92 if (HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt, TRUE )) return FALSE;
93
94 if (IsWindow(previous))
95 {
96 SendMessageW( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd );
97 SendMessageW( previous, WM_ACTIVATE,
98 MAKEWPARAM( WA_INACTIVE, IsIconic(previous) ), (LPARAM)hwnd );
99 }
100
101 SERVER_START_REQ( set_active_window )
102 {
103 req->handle = wine_server_user_handle( hwnd );
104 if ((ret = !wine_server_call_err( req )))
105 previous = wine_server_ptr_handle( reply->previous );
106 }
107 SERVER_END_REQ;
108 if (!ret) return FALSE;
109 if (prev) *prev = previous;
110 if (previous == hwnd) return TRUE;
111
112 if (hwnd)
113 {
114 /* send palette messages */
115 if (SendMessageW( hwnd, WM_QUERYNEWPALETTE, 0, 0 ))
116 SendMessageTimeoutW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0,
117 SMTO_ABORTIFHUNG, 2000, NULL );
118 if (!IsWindow(hwnd)) return FALSE;
119 }
120
121 old_thread = previous ? GetWindowThreadProcessId( previous, NULL ) : 0;
122 new_thread = hwnd ? GetWindowThreadProcessId( hwnd, NULL ) : 0;
123
124 if (old_thread != new_thread)
125 {
126 HWND *list, *phwnd;
127
128 if ((list = WIN_ListChildren( GetDesktopWindow() )))
129 {
130 if (old_thread)
131 {
132 for (phwnd = list; *phwnd; phwnd++)
133 {
134 if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread)
135 SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread );
136 }
137 }
138 if (new_thread)
139 {
140 for (phwnd = list; *phwnd; phwnd++)
141 {
142 if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread)
143 SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread );
144 }
145 }
146 HeapFree( GetProcessHeap(), 0, list );
147 }
148 }
149
150 if (IsWindow(hwnd))
151 {
152 SendMessageW( hwnd, WM_NCACTIVATE, (hwnd == GetForegroundWindow()), (LPARAM)previous );
153 SendMessageW( hwnd, WM_ACTIVATE,
154 MAKEWPARAM( mouse ? WA_CLICKACTIVE : WA_ACTIVE, IsIconic(hwnd) ),
155 (LPARAM)previous );
156 }
157
158 /* now change focus if necessary */
159 if (focus)
160 {
161 GUITHREADINFO info;
162
163 GetGUIThreadInfo( GetCurrentThreadId(), &info );
164 /* Do not change focus if the window is no more active */
165 if (hwnd == info.hwndActive)
166 {
167 if (!info.hwndFocus || !hwnd || GetAncestor( info.hwndFocus, GA_ROOT ) != hwnd)
168 set_focus_window( hwnd );
169 }
170 }
171
172 return TRUE;
173 }
174
175
176 /*******************************************************************
177 * set_foreground_window
178 */
179 static BOOL set_foreground_window( HWND hwnd, BOOL mouse )
180 {
181 BOOL ret, send_msg_old = FALSE, send_msg_new = FALSE;
182 HWND previous = 0;
183
184 SERVER_START_REQ( set_foreground_window )
185 {
186 req->handle = wine_server_user_handle( hwnd );
187 if ((ret = !wine_server_call_err( req )))
188 {
189 previous = wine_server_ptr_handle( reply->previous );
190 send_msg_old = reply->send_msg_old;
191 send_msg_new = reply->send_msg_new;
192 }
193 }
194 SERVER_END_REQ;
195
196 if (ret && previous != hwnd)
197 {
198 if (send_msg_old) /* old window belongs to other thread */
199 SendNotifyMessageW( previous, WM_WINE_SETACTIVEWINDOW, 0, 0 );
200 else if (send_msg_new) /* old window belongs to us but new one to other thread */
201 ret = set_active_window( 0, NULL, mouse, TRUE );
202
203 if (send_msg_new) /* new window belongs to other thread */
204 SendNotifyMessageW( hwnd, WM_WINE_SETACTIVEWINDOW, (WPARAM)hwnd, 0 );
205 else /* new window belongs to us */
206 ret = set_active_window( hwnd, NULL, mouse, TRUE );
207 }
208 return ret;
209 }
210
211
212 /*******************************************************************
213 * FOCUS_MouseActivate
214 *
215 * Activate a window as a result of a mouse click
216 */
217 BOOL FOCUS_MouseActivate( HWND hwnd )
218 {
219 return set_foreground_window( hwnd, TRUE );
220 }
221
222
223 /*******************************************************************
224 * SetActiveWindow (USER32.@)
225 */
226 HWND WINAPI SetActiveWindow( HWND hwnd )
227 {
228 HWND prev;
229
230 TRACE( "%p\n", hwnd );
231
232 if (hwnd)
233 {
234 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
235
236 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD)
237 return GetActiveWindow(); /* Windows doesn't seem to return an error here */
238
239 hwnd = WIN_GetFullHandle( hwnd );
240 }
241
242 if (!set_active_window( hwnd, &prev, FALSE, TRUE )) return 0;
243 return prev;
244 }
245
246
247 /*****************************************************************
248 * SetFocus (USER32.@)
249 */
250 HWND WINAPI SetFocus( HWND hwnd )
251 {
252 HWND hwndTop = hwnd;
253 HWND previous = GetFocus();
254
255 TRACE( "%p prev %p\n", hwnd, previous );
256
257 if (hwnd)
258 {
259 /* Check if we can set the focus to this window */
260 hwnd = WIN_GetFullHandle( hwnd );
261 if (hwnd == previous) return previous; /* nothing to do */
262 for (;;)
263 {
264 HWND parent;
265 LONG style = GetWindowLongW( hwndTop, GWL_STYLE );
266 if (style & (WS_MINIMIZE | WS_DISABLED)) return 0;
267 parent = GetAncestor( hwndTop, GA_PARENT );
268 if (!parent || parent == GetDesktopWindow()) break;
269 if (parent == get_hwnd_message_parent()) return 0;
270 hwndTop = parent;
271 }
272
273 /* call hooks */
274 if (HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)hwnd, (LPARAM)previous, TRUE )) return 0;
275
276 /* activate hwndTop if needed. */
277 if (hwndTop != GetActiveWindow())
278 {
279 if (!set_active_window( hwndTop, NULL, FALSE, FALSE )) return 0;
280 if (!IsWindow( hwnd )) return 0; /* Abort if window destroyed */
281
282 /* Do not change focus if the window is no longer active */
283 if (hwndTop != GetActiveWindow()) return 0;
284 }
285 }
286 else /* NULL hwnd passed in */
287 {
288 if (!previous) return 0; /* nothing to do */
289 if (HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, 0, (LPARAM)previous, TRUE )) return 0;
290 }
291
292 /* change focus and send messages */
293 return set_focus_window( hwnd );
294 }
295
296
297 /*******************************************************************
298 * SetForegroundWindow (USER32.@)
299 */
300 BOOL WINAPI SetForegroundWindow( HWND hwnd )
301 {
302 TRACE( "%p\n", hwnd );
303
304 hwnd = WIN_GetFullHandle( hwnd );
305 return set_foreground_window( hwnd, FALSE );
306 }
307
308
309 /*******************************************************************
310 * GetActiveWindow (USER32.@)
311 */
312 HWND WINAPI GetActiveWindow(void)
313 {
314 HWND ret = 0;
315
316 SERVER_START_REQ( get_thread_input )
317 {
318 req->tid = GetCurrentThreadId();
319 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->active );
320 }
321 SERVER_END_REQ;
322 return ret;
323 }
324
325
326 /*****************************************************************
327 * GetFocus (USER32.@)
328 */
329 HWND WINAPI GetFocus(void)
330 {
331 HWND ret = 0;
332
333 SERVER_START_REQ( get_thread_input )
334 {
335 req->tid = GetCurrentThreadId();
336 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->focus );
337 }
338 SERVER_END_REQ;
339 return ret;
340 }
341
342
343 /*******************************************************************
344 * GetForegroundWindow (USER32.@)
345 */
346 HWND WINAPI GetForegroundWindow(void)
347 {
348 HWND ret = 0;
349
350 SERVER_START_REQ( get_thread_input )
351 {
352 req->tid = 0;
353 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->foreground );
354 }
355 SERVER_END_REQ;
356 return ret;
357 }
358
359
360 /***********************************************************************
361 * SetShellWindowEx (USER32.@)
362 * hwndShell = Progman[Program Manager]
363 * |-> SHELLDLL_DefView
364 * hwndListView = | |-> SysListView32
365 * | | |-> tooltips_class32
366 * | |
367 * | |-> SysHeader32
368 * |
369 * |-> ProxyTarget
370 */
371 BOOL WINAPI SetShellWindowEx(HWND hwndShell, HWND hwndListView)
372 {
373 BOOL ret;
374
375 if (GetShellWindow())
376 return FALSE;
377
378 if (GetWindowLongW(hwndShell, GWL_EXSTYLE) & WS_EX_TOPMOST)
379 return FALSE;
380
381 if (hwndListView != hwndShell)
382 if (GetWindowLongW(hwndListView, GWL_EXSTYLE) & WS_EX_TOPMOST)
383 return FALSE;
384
385 if (hwndListView && hwndListView!=hwndShell)
386 SetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
387
388 SetWindowPos(hwndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
389
390 SERVER_START_REQ(set_global_windows)
391 {
392 req->flags = SET_GLOBAL_SHELL_WINDOWS;
393 req->shell_window = wine_server_user_handle( hwndShell );
394 req->shell_listview = wine_server_user_handle( hwndListView );
395 ret = !wine_server_call_err(req);
396 }
397 SERVER_END_REQ;
398
399 return ret;
400 }
401
402
403 /*******************************************************************
404 * SetShellWindow (USER32.@)
405 */
406 BOOL WINAPI SetShellWindow(HWND hwndShell)
407 {
408 return SetShellWindowEx(hwndShell, hwndShell);
409 }
410
411
412 /*******************************************************************
413 * GetShellWindow (USER32.@)
414 */
415 HWND WINAPI GetShellWindow(void)
416 {
417 HWND hwndShell = 0;
418
419 SERVER_START_REQ(set_global_windows)
420 {
421 req->flags = 0;
422 if (!wine_server_call_err(req))
423 hwndShell = wine_server_ptr_handle( reply->old_shell_window );
424 }
425 SERVER_END_REQ;
426
427 return hwndShell;
428 }
429
430
431 /***********************************************************************
432 * SetProgmanWindow (USER32.@)
433 */
434 HWND WINAPI SetProgmanWindow ( HWND hwnd )
435 {
436 SERVER_START_REQ(set_global_windows)
437 {
438 req->flags = SET_GLOBAL_PROGMAN_WINDOW;
439 req->progman_window = wine_server_user_handle( hwnd );
440 if (wine_server_call_err( req )) hwnd = 0;
441 }
442 SERVER_END_REQ;
443 return hwnd;
444 }
445
446
447 /***********************************************************************
448 * GetProgmanWindow (USER32.@)
449 */
450 HWND WINAPI GetProgmanWindow(void)
451 {
452 HWND ret = 0;
453
454 SERVER_START_REQ(set_global_windows)
455 {
456 req->flags = 0;
457 if (!wine_server_call_err(req))
458 ret = wine_server_ptr_handle( reply->old_progman_window );
459 }
460 SERVER_END_REQ;
461 return ret;
462 }
463
464
465 /***********************************************************************
466 * SetTaskmanWindow (USER32.@)
467 * NOTES
468 * hwnd = MSTaskSwWClass
469 * |-> SysTabControl32
470 */
471 HWND WINAPI SetTaskmanWindow ( HWND hwnd )
472 {
473 SERVER_START_REQ(set_global_windows)
474 {
475 req->flags = SET_GLOBAL_TASKMAN_WINDOW;
476 req->taskman_window = wine_server_user_handle( hwnd );
477 if (wine_server_call_err( req )) hwnd = 0;
478 }
479 SERVER_END_REQ;
480 return hwnd;
481 }
482
483 /***********************************************************************
484 * GetTaskmanWindow (USER32.@)
485 */
486 HWND WINAPI GetTaskmanWindow(void)
487 {
488 HWND ret = 0;
489
490 SERVER_START_REQ(set_global_windows)
491 {
492 req->flags = 0;
493 if (!wine_server_call_err(req))
494 ret = wine_server_ptr_handle( reply->old_taskman_window );
495 }
496 SERVER_END_REQ;
497 return ret;
498 }
499
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.