Fix -Wwrite-strings warnings.
[wine/wine64.git] / dlls / user / focus.c
blob64e597b25ff8287ad63eecd1bd2060093b69cf98
1 /*
2 * Focus and activation functions
4 * Copyright 1993 David Metcalfe
5 * Copyright 1995 Alex Korobka
6 * Copyright 1994, 2002 Alexandre Julliard
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winerror.h"
32 #include "win.h"
33 #include "user_private.h"
34 #include "wine/server.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(win);
40 /*****************************************************************
41 * set_focus_window
43 * Change the focus window, sending the WM_SETFOCUS and WM_KILLFOCUS messages
45 static HWND set_focus_window( HWND hwnd )
47 HWND previous = 0;
48 BOOL ret;
50 SERVER_START_REQ( set_focus_window )
52 req->handle = hwnd;
53 if ((ret = !wine_server_call_err( req ))) previous = reply->previous;
55 SERVER_END_REQ;
56 if (!ret) return 0;
57 if (previous == hwnd) return previous;
59 if (previous)
61 SendMessageW( previous, WM_KILLFOCUS, (WPARAM)hwnd, 0 );
62 if (hwnd != GetFocus()) return previous; /* changed by the message */
64 if (IsWindow(hwnd))
66 if (USER_Driver.pSetFocus) USER_Driver.pSetFocus(hwnd);
67 SendMessageW( hwnd, WM_SETFOCUS, (WPARAM)previous, 0 );
69 return previous;
73 /*******************************************************************
74 * set_active_window
76 static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
78 HWND previous = GetActiveWindow();
79 BOOL ret;
80 DWORD old_thread, new_thread;
81 CBTACTIVATESTRUCT cbt;
83 if (previous == hwnd)
85 if (prev) *prev = hwnd;
86 return TRUE;
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;
94 if (IsWindow(previous))
96 SendMessageW( previous, WM_NCACTIVATE, FALSE, (LPARAM)hwnd );
97 SendMessageW( previous, WM_ACTIVATE,
98 MAKEWPARAM( WA_INACTIVE, IsIconic(previous) ), (LPARAM)hwnd );
101 SERVER_START_REQ( set_active_window )
103 req->handle = hwnd;
104 if ((ret = !wine_server_call_err( req ))) previous = reply->previous;
106 SERVER_END_REQ;
107 if (!ret) return FALSE;
108 if (prev) *prev = previous;
109 if (previous == hwnd) return TRUE;
111 if (hwnd)
113 /* send palette messages */
114 if (SendMessageW( hwnd, WM_QUERYNEWPALETTE, 0, 0 ))
115 SendMessageTimeoutW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0,
116 SMTO_ABORTIFHUNG, 2000, NULL );
118 if (!GetPropA( hwnd, "__wine_x11_managed" ))
119 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
121 if (!IsWindow(hwnd)) return FALSE;
124 old_thread = previous ? GetWindowThreadProcessId( previous, NULL ) : 0;
125 new_thread = hwnd ? GetWindowThreadProcessId( hwnd, NULL ) : 0;
127 if (old_thread != new_thread)
129 HWND *list, *phwnd;
131 if ((list = WIN_ListChildren( GetDesktopWindow() )))
133 if (old_thread)
135 for (phwnd = list; *phwnd; phwnd++)
137 if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread)
138 SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread );
141 if (new_thread)
143 for (phwnd = list; *phwnd; phwnd++)
145 if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread)
146 SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread );
149 HeapFree( GetProcessHeap(), 0, list );
153 if (IsWindow(hwnd))
155 SendMessageW( hwnd, WM_NCACTIVATE, (hwnd == GetForegroundWindow()), (LPARAM)previous );
156 SendMessageW( hwnd, WM_ACTIVATE,
157 MAKEWPARAM( mouse ? WA_CLICKACTIVE : WA_ACTIVE, IsIconic(hwnd) ),
158 (LPARAM)previous );
161 /* now change focus if necessary */
162 if (focus)
164 HWND curfocus = GetFocus();
165 if (!curfocus || !hwnd || GetAncestor( curfocus, GA_ROOT ) != hwnd)
166 set_focus_window( hwnd );
169 return TRUE;
173 /*******************************************************************
174 * set_foreground_window
176 static BOOL set_foreground_window( HWND hwnd, BOOL mouse )
178 BOOL ret, send_msg_old = FALSE, send_msg_new = FALSE;
179 HWND previous = 0;
181 SERVER_START_REQ( set_foreground_window )
183 req->handle = hwnd;
184 if ((ret = !wine_server_call_err( req )))
186 previous = reply->previous;
187 send_msg_old = reply->send_msg_old;
188 send_msg_new = reply->send_msg_new;
191 SERVER_END_REQ;
193 if (ret)
195 if (send_msg_old) /* old window belongs to other thread */
196 SendNotifyMessageW( previous, WM_WINE_SETACTIVEWINDOW, 0, 0 );
197 else if (send_msg_new) /* old window belongs to us but new one to other thread */
198 ret = set_active_window( 0, NULL, mouse, TRUE );
200 if (send_msg_new) /* new window belongs to other thread */
201 SendNotifyMessageW( hwnd, WM_WINE_SETACTIVEWINDOW, (WPARAM)hwnd, 0 );
202 else /* new window belongs to us */
203 ret = set_active_window( hwnd, NULL, mouse, TRUE );
205 return ret;
209 /*******************************************************************
210 * FOCUS_MouseActivate
212 * Activate a window as a result of a mouse click
214 BOOL FOCUS_MouseActivate( HWND hwnd )
216 return set_foreground_window( hwnd, TRUE );
220 /*******************************************************************
221 * SetActiveWindow (USER32.@)
223 HWND WINAPI SetActiveWindow( HWND hwnd )
225 HWND prev;
227 TRACE( "%p\n", hwnd );
229 if (hwnd)
231 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
233 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD)
234 return GetActiveWindow(); /* Windows doesn't seem to return an error here */
236 hwnd = WIN_GetFullHandle( hwnd );
239 if (!set_active_window( hwnd, &prev, FALSE, TRUE )) return 0;
240 return prev;
244 /*****************************************************************
245 * SetFocus (USER32.@)
247 HWND WINAPI SetFocus( HWND hwnd )
249 HWND hwndTop = hwnd;
250 HWND previous = GetFocus();
252 TRACE( "%p prev %p\n", hwnd, previous );
254 if (hwnd)
256 /* Check if we can set the focus to this window */
257 hwnd = WIN_GetFullHandle( hwnd );
258 if (hwnd == previous) return previous; /* nothing to do */
259 for (;;)
261 HWND parent;
262 LONG style = GetWindowLongW( hwndTop, GWL_STYLE );
263 if (style & (WS_MINIMIZE | WS_DISABLED)) return 0;
264 parent = GetAncestor( hwndTop, GA_PARENT );
265 if (!parent || parent == GetDesktopWindow()) break;
266 hwndTop = parent;
269 /* call hooks */
270 if (HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)hwnd, (LPARAM)previous, TRUE )) return 0;
272 /* activate hwndTop if needed. */
273 if (hwndTop != GetActiveWindow())
275 if (!set_active_window( hwndTop, NULL, FALSE, FALSE )) return 0;
276 if (!IsWindow( hwnd )) return 0; /* Abort if window destroyed */
279 else /* NULL hwnd passed in */
281 if (!previous) return 0; /* nothing to do */
282 if (HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, 0, (LPARAM)previous, TRUE )) return 0;
285 /* change focus and send messages */
286 return set_focus_window( hwnd );
290 /*******************************************************************
291 * SetForegroundWindow (USER32.@)
293 BOOL WINAPI SetForegroundWindow( HWND hwnd )
295 TRACE( "%p\n", hwnd );
296 if (hwnd) hwnd = WIN_GetFullHandle( hwnd );
297 return set_foreground_window( hwnd, FALSE );
301 /*******************************************************************
302 * GetActiveWindow (USER32.@)
304 HWND WINAPI GetActiveWindow(void)
306 HWND ret = 0;
308 SERVER_START_REQ( get_thread_input )
310 req->tid = GetCurrentThreadId();
311 if (!wine_server_call_err( req )) ret = reply->active;
313 SERVER_END_REQ;
314 return ret;
318 /*****************************************************************
319 * GetFocus (USER32.@)
321 HWND WINAPI GetFocus(void)
323 HWND ret = 0;
325 SERVER_START_REQ( get_thread_input )
327 req->tid = GetCurrentThreadId();
328 if (!wine_server_call_err( req )) ret = reply->focus;
330 SERVER_END_REQ;
331 return ret;
335 /*******************************************************************
336 * GetForegroundWindow (USER32.@)
338 HWND WINAPI GetForegroundWindow(void)
340 HWND ret = 0;
342 SERVER_START_REQ( get_thread_input )
344 req->tid = 0;
345 if (!wine_server_call_err( req )) ret = reply->foreground;
347 SERVER_END_REQ;
348 return ret;
352 /***********************************************************************
353 * SetShellWindowEx (USER32.@)
354 * hwndShell = Progman[Program Manager]
355 * |-> SHELLDLL_DefView
356 * hwndListView = | |-> SysListView32
357 * | | |-> tooltips_class32
358 * | |
359 * | |-> SysHeader32
361 * |-> ProxyTarget
363 BOOL WINAPI SetShellWindowEx(HWND hwndShell, HWND hwndListView)
365 BOOL ret;
367 if (GetShellWindow())
368 return FALSE;
370 if (GetWindowLongW(hwndShell, GWL_EXSTYLE) & WS_EX_TOPMOST)
371 return FALSE;
373 if (hwndListView != hwndShell)
374 if (GetWindowLongW(hwndListView, GWL_EXSTYLE) & WS_EX_TOPMOST)
375 return FALSE;
377 if (hwndListView && hwndListView!=hwndShell)
378 SetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
380 SetWindowPos(hwndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
382 SERVER_START_REQ(set_global_windows)
384 req->flags = SET_GLOBAL_SHELL_WINDOWS;
385 req->shell_window = hwndShell;
386 req->shell_listview = hwndListView;
387 ret = !wine_server_call_err(req);
389 SERVER_END_REQ;
391 return ret;
395 /*******************************************************************
396 * SetShellWindow (USER32.@)
398 BOOL WINAPI SetShellWindow(HWND hwndShell)
400 return SetShellWindowEx(hwndShell, hwndShell);
404 /*******************************************************************
405 * GetShellWindow (USER32.@)
407 HWND WINAPI GetShellWindow(void)
409 HWND hwndShell = 0;
411 SERVER_START_REQ(set_global_windows)
413 req->flags = 0;
414 if (!wine_server_call_err(req))
415 hwndShell = reply->old_shell_window;
417 SERVER_END_REQ;
419 return hwndShell;
423 /***********************************************************************
424 * SetProgmanWindow (USER32.@)
426 HWND WINAPI SetProgmanWindow ( HWND hwnd )
428 SERVER_START_REQ(set_global_windows)
430 req->flags = SET_GLOBAL_PROGMAN_WINDOW;
431 req->progman_window = hwnd;
432 if (wine_server_call_err( req )) hwnd = 0;
434 SERVER_END_REQ;
435 return hwnd;
439 /***********************************************************************
440 * GetProgmanWindow (USER32.@)
442 HWND WINAPI GetProgmanWindow(void)
444 HWND ret = 0;
446 SERVER_START_REQ(set_global_windows)
448 req->flags = 0;
449 if (!wine_server_call_err(req)) ret = reply->old_progman_window;
451 SERVER_END_REQ;
452 return ret;
456 /***********************************************************************
457 * SetTaskmanWindow (USER32.@)
458 * NOTES
459 * hwnd = MSTaskSwWClass
460 * |-> SysTabControl32
462 HWND WINAPI SetTaskmanWindow ( HWND hwnd )
464 SERVER_START_REQ(set_global_windows)
466 req->flags = SET_GLOBAL_TASKMAN_WINDOW;
467 req->taskman_window = hwnd;
468 if (wine_server_call_err( req )) hwnd = 0;
470 SERVER_END_REQ;
471 return hwnd;
474 /***********************************************************************
475 * GetTaskmanWindow (USER32.@)
477 HWND WINAPI GetTaskmanWindow(void)
479 HWND ret = 0;
481 SERVER_START_REQ(set_global_windows)
483 req->flags = 0;
484 if (!wine_server_call_err(req)) ret = reply->old_taskman_window;
486 SERVER_END_REQ;
487 return ret;