Reimplemented Get/SetActiveWindow, Get/SetFocus and
Get/SetForegroundWindow by storing the information in the server. Implemented correct inter-process window activation.
This commit is contained in:
parent
00ea0868ba
commit
5030bda77c
|
@ -31,7 +31,6 @@ C_SRCS = \
|
|||
$(TOPOBJDIR)/windows/defwnd.c \
|
||||
$(TOPOBJDIR)/windows/dialog.c \
|
||||
$(TOPOBJDIR)/windows/driver.c \
|
||||
$(TOPOBJDIR)/windows/focus.c \
|
||||
$(TOPOBJDIR)/windows/hook.c \
|
||||
$(TOPOBJDIR)/windows/input.c \
|
||||
$(TOPOBJDIR)/windows/keyboard.c \
|
||||
|
@ -63,6 +62,7 @@ C_SRCS = \
|
|||
dde/server.c \
|
||||
display.c \
|
||||
exticon.c \
|
||||
focus.c \
|
||||
lstr.c \
|
||||
message.c \
|
||||
misc.c \
|
||||
|
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
* Focus and activation functions
|
||||
*
|
||||
* Copyright 1993 David Metcalfe
|
||||
* Copyright 1995 Alex Korobka
|
||||
* Copyright 1994, 2002 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "winerror.h"
|
||||
#include "win.h"
|
||||
#include "hook.h"
|
||||
#include "message.h"
|
||||
#include "user.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(win);
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* set_focus_window
|
||||
*
|
||||
* Change the focus window, sending the WM_SETFOCUS and WM_KILLFOCUS messages
|
||||
*/
|
||||
static HWND set_focus_window( HWND hwnd )
|
||||
{
|
||||
HWND previous = 0;
|
||||
BOOL ret;
|
||||
|
||||
SERVER_START_REQ( set_focus_window )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if ((ret = !wine_server_call_err( req ))) previous = reply->previous;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!ret) return 0;
|
||||
if (previous == hwnd) return previous;
|
||||
|
||||
if (previous)
|
||||
{
|
||||
SendMessageW( previous, WM_KILLFOCUS, (WPARAM)hwnd, 0 );
|
||||
if (hwnd != GetFocus()) return previous; /* changed by the message */
|
||||
}
|
||||
if (IsWindow(hwnd))
|
||||
{
|
||||
if (USER_Driver.pSetFocus) USER_Driver.pSetFocus(hwnd);
|
||||
SendMessageW( hwnd, WM_SETFOCUS, (WPARAM)previous, 0 );
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* set_active_window
|
||||
*/
|
||||
static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus )
|
||||
{
|
||||
HWND previous = GetActiveWindow();
|
||||
BOOL ret;
|
||||
DWORD old_thread, new_thread;
|
||||
|
||||
if (previous == hwnd)
|
||||
{
|
||||
if (prev) *prev = hwnd;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* call CBT hook chain */
|
||||
if (HOOK_IsHooked( WH_CBT ))
|
||||
{
|
||||
CBTACTIVATESTRUCT cbt;
|
||||
cbt.fMouse = mouse;
|
||||
cbt.hWndActive = previous;
|
||||
if (HOOK_CallHooksW( WH_CBT, HCBT_ACTIVATE, (WPARAM)hwnd, (LPARAM)&cbt )) return FALSE;
|
||||
}
|
||||
|
||||
if (IsWindow(previous))
|
||||
{
|
||||
SendMessageW( previous, WM_NCACTIVATE, FALSE, 0 );
|
||||
SendMessageW( previous, WM_ACTIVATE,
|
||||
MAKEWPARAM( WA_INACTIVE, IsIconic(previous) ), (LPARAM)hwnd );
|
||||
}
|
||||
|
||||
SERVER_START_REQ( set_active_window )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if ((ret = !wine_server_call_err( req ))) previous = reply->previous;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!ret) return FALSE;
|
||||
if (prev) *prev = previous;
|
||||
if (previous == hwnd) return TRUE;
|
||||
|
||||
if (hwnd)
|
||||
{
|
||||
/* send palette messages */
|
||||
if (SendMessageW( hwnd, WM_QUERYNEWPALETTE, 0, 0 ))
|
||||
SendMessageW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0 );
|
||||
|
||||
if (!(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MANAGED))
|
||||
SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
|
||||
|
||||
if (!IsWindow(hwnd)) return FALSE;
|
||||
}
|
||||
|
||||
old_thread = previous ? GetWindowThreadProcessId( previous, NULL ) : 0;
|
||||
new_thread = hwnd ? GetWindowThreadProcessId( hwnd, NULL ) : 0;
|
||||
|
||||
if (old_thread != new_thread)
|
||||
{
|
||||
HWND *list, *phwnd;
|
||||
|
||||
if ((list = WIN_ListChildren( GetDesktopWindow() )))
|
||||
{
|
||||
if (old_thread)
|
||||
{
|
||||
for (phwnd = list; *phwnd; phwnd++)
|
||||
{
|
||||
if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread)
|
||||
SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread );
|
||||
}
|
||||
}
|
||||
if (new_thread)
|
||||
{
|
||||
for (phwnd = list; *phwnd; phwnd++)
|
||||
{
|
||||
if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread)
|
||||
SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread );
|
||||
}
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
}
|
||||
}
|
||||
|
||||
if (IsWindow(hwnd))
|
||||
{
|
||||
SendMessageW( hwnd, WM_NCACTIVATE, (hwnd == GetForegroundWindow()), 0 );
|
||||
SendMessageW( hwnd, WM_ACTIVATE,
|
||||
MAKEWPARAM( mouse ? WA_CLICKACTIVE : WA_ACTIVE, IsIconic(hwnd) ),
|
||||
(LPARAM)previous );
|
||||
}
|
||||
|
||||
/* now change focus if necessary */
|
||||
if (focus)
|
||||
{
|
||||
HWND curfocus = GetFocus();
|
||||
if (!curfocus || !hwnd || GetAncestor( curfocus, GA_ROOT ) != hwnd)
|
||||
set_focus_window( hwnd );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* set_foreground_window
|
||||
*/
|
||||
static BOOL set_foreground_window( HWND hwnd, BOOL mouse )
|
||||
{
|
||||
BOOL ret, send_msg_old = FALSE, send_msg_new = FALSE;
|
||||
HWND previous = 0;
|
||||
|
||||
SERVER_START_REQ( set_foreground_window )
|
||||
{
|
||||
req->handle = hwnd;
|
||||
if ((ret = !wine_server_call_err( req )))
|
||||
{
|
||||
previous = reply->previous;
|
||||
send_msg_old = reply->send_msg_old;
|
||||
send_msg_new = reply->send_msg_new;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (ret)
|
||||
{
|
||||
if (send_msg_old) /* old window belongs to other thread */
|
||||
SendNotifyMessageW( previous, WM_WINE_SETACTIVEWINDOW, 0, 0 );
|
||||
else if (send_msg_new) /* old window belongs to us but new one to other thread */
|
||||
ret = set_active_window( 0, NULL, mouse, TRUE );
|
||||
|
||||
if (send_msg_new) /* new window belongs to other thread */
|
||||
SendNotifyMessageW( hwnd, WM_WINE_SETACTIVEWINDOW, hwnd, 0 );
|
||||
else /* new window belongs to us */
|
||||
ret = set_active_window( hwnd, NULL, mouse, TRUE );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* FOCUS_MouseActivate
|
||||
*
|
||||
* Activate a window as a result of a mouse click
|
||||
*/
|
||||
BOOL FOCUS_MouseActivate( HWND hwnd )
|
||||
{
|
||||
return set_foreground_window( hwnd, TRUE );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* SetActiveWindow (USER32.@)
|
||||
*/
|
||||
HWND WINAPI SetActiveWindow( HWND hwnd )
|
||||
{
|
||||
HWND prev;
|
||||
|
||||
TRACE( "%x\n", hwnd );
|
||||
|
||||
if (hwnd)
|
||||
{
|
||||
LONG style = GetWindowLongW( hwnd, GWL_STYLE );
|
||||
|
||||
if (!(style & WS_VISIBLE) || (style & (WS_POPUP|WS_CHILD)) == WS_CHILD)
|
||||
return GetActiveWindow(); /* Windows doesn't seem to return an error here */
|
||||
|
||||
hwnd = WIN_GetFullHandle( hwnd );
|
||||
}
|
||||
|
||||
if (!set_active_window( hwnd, &prev, FALSE, TRUE )) return 0;
|
||||
return prev;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* SetFocus (USER32.@)
|
||||
*/
|
||||
HWND WINAPI SetFocus( HWND hwnd )
|
||||
{
|
||||
HWND hwndTop = hwnd;
|
||||
HWND previous = GetFocus();
|
||||
|
||||
TRACE( "%x prev %x\n", hwnd, previous );
|
||||
|
||||
if (hwnd)
|
||||
{
|
||||
/* Check if we can set the focus to this window */
|
||||
hwnd = WIN_GetFullHandle( hwnd );
|
||||
if (hwnd == previous) return previous; /* nothing to do */
|
||||
for (;;)
|
||||
{
|
||||
HWND parent;
|
||||
LONG style = GetWindowLongW( hwndTop, GWL_STYLE );
|
||||
if (style & (WS_MINIMIZE | WS_DISABLED)) return 0;
|
||||
parent = GetAncestor( hwndTop, GA_PARENT );
|
||||
if (!parent || parent == GetDesktopWindow()) break;
|
||||
hwndTop = parent;
|
||||
}
|
||||
|
||||
/* call hooks */
|
||||
if (HOOK_CallHooksW( WH_CBT, HCBT_SETFOCUS, (WPARAM)hwnd, (LPARAM)previous )) return 0;
|
||||
|
||||
/* activate hwndTop if needed. */
|
||||
if (hwndTop != GetActiveWindow())
|
||||
{
|
||||
if (!set_active_window( hwndTop, NULL, FALSE, FALSE )) return 0;
|
||||
if (!IsWindow( hwnd )) return 0; /* Abort if window destroyed */
|
||||
}
|
||||
}
|
||||
else /* NULL hwnd passed in */
|
||||
{
|
||||
if (!previous) return 0; /* nothing to do */
|
||||
if( HOOK_CallHooksW( WH_CBT, HCBT_SETFOCUS, 0, (LPARAM)previous ) )
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* change focus and send messages */
|
||||
return set_focus_window( hwnd );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* SetForegroundWindow (USER32.@)
|
||||
*/
|
||||
BOOL WINAPI SetForegroundWindow( HWND hwnd )
|
||||
{
|
||||
TRACE( "%x\n", hwnd );
|
||||
if (hwnd) hwnd = WIN_GetFullHandle( hwnd );
|
||||
return set_foreground_window( hwnd, FALSE );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* GetActiveWindow (USER32.@)
|
||||
*/
|
||||
HWND WINAPI GetActiveWindow(void)
|
||||
{
|
||||
HWND ret = 0;
|
||||
|
||||
SERVER_START_REQ( get_thread_input )
|
||||
{
|
||||
req->tid = GetCurrentThreadId();
|
||||
if (!wine_server_call_err( req )) ret = reply->active;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* GetFocus (USER32.@)
|
||||
*/
|
||||
HWND WINAPI GetFocus(void)
|
||||
{
|
||||
HWND ret = 0;
|
||||
|
||||
SERVER_START_REQ( get_thread_input )
|
||||
{
|
||||
req->tid = GetCurrentThreadId();
|
||||
if (!wine_server_call_err( req )) ret = reply->focus;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* GetForegroundWindow (USER32.@)
|
||||
*/
|
||||
HWND WINAPI GetForegroundWindow(void)
|
||||
{
|
||||
HWND ret = 0;
|
||||
|
||||
SERVER_START_REQ( get_thread_input )
|
||||
{
|
||||
req->tid = 0;
|
||||
if (!wine_server_call_err( req )) ret = reply->foreground;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
|
@ -1060,6 +1060,8 @@ static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPAR
|
|||
return (LRESULT)SetWindowLongW( hwnd, wparam, lparam );
|
||||
case WM_WINE_ENABLEWINDOW:
|
||||
return EnableWindow( hwnd, wparam );
|
||||
case WM_WINE_SETACTIVEWINDOW:
|
||||
return SetActiveWindow( (HWND)wparam );
|
||||
default:
|
||||
FIXME( "unknown internal message %x\n", msg );
|
||||
return 0;
|
||||
|
|
|
@ -364,6 +364,20 @@ static void EVENT_ProcessEvent( XEvent *event )
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* can_activate_window
|
||||
*
|
||||
* Check if we can activate the specified window.
|
||||
*/
|
||||
inline static BOOL can_activate_window( HWND hwnd )
|
||||
{
|
||||
LONG style = GetWindowLongW( hwnd, GWL_STYLE );
|
||||
if (!(style & WS_VISIBLE)) return FALSE;
|
||||
if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
|
||||
return !(style & WS_DISABLED);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* set_focus_error_handler
|
||||
*
|
||||
|
@ -380,16 +394,12 @@ static int set_focus_error_handler( Display *display, XErrorEvent *event, void *
|
|||
*/
|
||||
static void set_focus( HWND hwnd, Time time )
|
||||
{
|
||||
HWND focus = GetFocus();
|
||||
HWND focus;
|
||||
Window win;
|
||||
|
||||
if (hwnd != focus && !IsChild( hwnd, focus ))
|
||||
{
|
||||
TRACE( "changing window focus to %x\n", hwnd );
|
||||
SetFocus( hwnd );
|
||||
}
|
||||
TRACE( "setting foreground window to %x\n", hwnd );
|
||||
SetForegroundWindow( hwnd );
|
||||
|
||||
/* focus window might be changed by the above SetFocus() call */
|
||||
focus = GetFocus();
|
||||
win = X11DRV_get_whole_window(focus);
|
||||
|
||||
|
@ -430,7 +440,7 @@ static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
|
|||
hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
|
||||
GetForegroundWindow(), last_focus );
|
||||
|
||||
if (IsWindowEnabled(hwnd))
|
||||
if (can_activate_window(hwnd))
|
||||
{
|
||||
/* simulate a mouse click on the caption to find out
|
||||
* whether the window wants to be activated */
|
||||
|
@ -445,7 +455,7 @@ static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
|
|||
hwnd = GetFocus();
|
||||
if (!hwnd) hwnd = GetActiveWindow();
|
||||
if (!hwnd) hwnd = last_focus;
|
||||
if (hwnd && IsWindowEnabled(hwnd)) set_focus( hwnd, event_time );
|
||||
if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -475,17 +485,14 @@ static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
|
|||
if (wmTakeFocus) return; /* ignore FocusIn if we are using take focus */
|
||||
if (event->detail == NotifyPointer) return;
|
||||
|
||||
if (!IsWindowEnabled(hwnd))
|
||||
if (!can_activate_window(hwnd))
|
||||
{
|
||||
HWND hwnd = GetFocus();
|
||||
if (!hwnd) hwnd = GetActiveWindow();
|
||||
if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
|
||||
if (hwnd && IsWindowEnabled(hwnd)) set_focus( hwnd, CurrentTime );
|
||||
}
|
||||
else if (hwnd != GetForegroundWindow())
|
||||
{
|
||||
SetForegroundWindow( hwnd );
|
||||
if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
|
||||
}
|
||||
else SetForegroundWindow( hwnd );
|
||||
}
|
||||
|
||||
|
||||
|
@ -503,6 +510,7 @@ static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
|
|||
TRACE( "win %x xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
|
||||
|
||||
if (event->detail == NotifyPointer) return;
|
||||
x11drv_thread_data()->last_focus = hwnd;
|
||||
if (hwnd != GetForegroundWindow()) return;
|
||||
SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
|
||||
|
||||
|
@ -527,7 +535,6 @@ static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
|
|||
if (hwnd == GetForegroundWindow())
|
||||
{
|
||||
TRACE( "lost focus, setting fg to 0\n" );
|
||||
x11drv_thread_data()->last_focus = hwnd;
|
||||
SetForegroundWindow( 0 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1025,7 +1025,7 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos )
|
|||
if ((GetWindowLongW( winpos->hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD)
|
||||
SendMessageA( winpos->hwnd, WM_CHILDACTIVATE, 0, 0 );
|
||||
else
|
||||
SetActiveWindow( winpos->hwnd );
|
||||
SetForegroundWindow( winpos->hwnd );
|
||||
}
|
||||
|
||||
/* And last, send the WM_WINDOWPOSCHANGED message */
|
||||
|
|
|
@ -57,7 +57,8 @@ enum wine_internal_message
|
|||
WM_WINE_SHOWWINDOW,
|
||||
WM_WINE_SETPARENT,
|
||||
WM_WINE_SETWINDOWLONG,
|
||||
WM_WINE_ENABLEWINDOW
|
||||
WM_WINE_ENABLEWINDOW,
|
||||
WM_WINE_SETACTIVEWINDOW
|
||||
};
|
||||
|
||||
/* internal SendInput codes (FIXME) */
|
||||
|
|
|
@ -143,6 +143,8 @@ extern void CARET_GetRect(LPRECT lprc); /* windows/caret.c */
|
|||
|
||||
extern HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType ); /* windows/defwnd.c */
|
||||
|
||||
extern BOOL FOCUS_MouseActivate( HWND hwnd );
|
||||
|
||||
/* Classes functions */
|
||||
struct tagCLASS; /* opaque structure */
|
||||
struct builtin_class_descr;
|
||||
|
@ -153,7 +155,4 @@ extern struct tagCLASS *CLASS_AddWindow( ATOM atom, HINSTANCE inst, WINDOWPROCTY
|
|||
extern void CLASS_RemoveWindow( struct tagCLASS *cls );
|
||||
extern void CLASS_FreeModuleClasses( HMODULE16 hModule );
|
||||
|
||||
/* windows/focus.c */
|
||||
extern void FOCUS_SwitchFocus( struct tagMESSAGEQUEUE *pMsgQ, HWND , HWND );
|
||||
|
||||
#endif /* __WINE_WIN_H */
|
||||
|
|
|
@ -2507,6 +2507,7 @@ struct get_window_info_reply
|
|||
{
|
||||
struct reply_header __header;
|
||||
user_handle_t full_handle;
|
||||
user_handle_t last_active;
|
||||
process_id_t pid;
|
||||
thread_id_t tid;
|
||||
atom_t atom;
|
||||
|
@ -2763,6 +2764,44 @@ struct get_thread_input_reply
|
|||
};
|
||||
|
||||
|
||||
struct set_foreground_window_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t handle;
|
||||
};
|
||||
struct set_foreground_window_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
user_handle_t previous;
|
||||
int send_msg_old;
|
||||
int send_msg_new;
|
||||
};
|
||||
|
||||
|
||||
struct set_focus_window_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t handle;
|
||||
};
|
||||
struct set_focus_window_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
user_handle_t previous;
|
||||
};
|
||||
|
||||
|
||||
struct set_active_window_request
|
||||
{
|
||||
struct request_header __header;
|
||||
user_handle_t handle;
|
||||
};
|
||||
struct set_active_window_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
user_handle_t previous;
|
||||
};
|
||||
|
||||
|
||||
enum request
|
||||
{
|
||||
REQ_new_process,
|
||||
|
@ -2923,6 +2962,9 @@ enum request
|
|||
REQ_get_window_properties,
|
||||
REQ_attach_thread_input,
|
||||
REQ_get_thread_input,
|
||||
REQ_set_foreground_window,
|
||||
REQ_set_focus_window,
|
||||
REQ_set_active_window,
|
||||
REQ_NB_REQUESTS
|
||||
};
|
||||
|
||||
|
@ -3088,6 +3130,9 @@ union generic_request
|
|||
struct get_window_properties_request get_window_properties_request;
|
||||
struct attach_thread_input_request attach_thread_input_request;
|
||||
struct get_thread_input_request get_thread_input_request;
|
||||
struct set_foreground_window_request set_foreground_window_request;
|
||||
struct set_focus_window_request set_focus_window_request;
|
||||
struct set_active_window_request set_active_window_request;
|
||||
};
|
||||
union generic_reply
|
||||
{
|
||||
|
@ -3251,8 +3296,11 @@ union generic_reply
|
|||
struct get_window_properties_reply get_window_properties_reply;
|
||||
struct attach_thread_input_reply attach_thread_input_reply;
|
||||
struct get_thread_input_reply get_thread_input_reply;
|
||||
struct set_foreground_window_reply set_foreground_window_reply;
|
||||
struct set_focus_window_reply set_focus_window_reply;
|
||||
struct set_active_window_reply set_active_window_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 85
|
||||
#define SERVER_PROTOCOL_VERSION 86
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -39,8 +39,6 @@ extern BOOL WINPOS_RedrawIconTitle( HWND hWnd );
|
|||
extern BOOL WINPOS_ShowIconTitle( HWND hwnd, BOOL bShow );
|
||||
extern void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos, POINT *minTrack,
|
||||
POINT *maxTrack );
|
||||
extern BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse,
|
||||
BOOL fChangeFocus );
|
||||
extern LONG WINPOS_HandleWindowPosChanging16(HWND hwnd, struct tagWINDOWPOS16 *winpos);
|
||||
extern LONG WINPOS_HandleWindowPosChanging(HWND hwnd, WINDOWPOS *winpos);
|
||||
extern HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest );
|
||||
|
|
|
@ -1762,6 +1762,7 @@ enum message_type
|
|||
user_handle_t handle; /* handle to the window */
|
||||
@REPLY
|
||||
user_handle_t full_handle; /* full 32-bit handle */
|
||||
user_handle_t last_active; /* last active popup */
|
||||
process_id_t pid; /* process owning the window */
|
||||
thread_id_t tid; /* thread owning the window */
|
||||
atom_t atom; /* class atom */
|
||||
|
@ -1931,3 +1932,26 @@ enum message_type
|
|||
user_handle_t caret; /* handle to the caret window */
|
||||
rectangle_t rect; /* caret rectangle */
|
||||
@END
|
||||
|
||||
/* Set the system foreground window */
|
||||
@REQ(set_foreground_window)
|
||||
user_handle_t handle; /* handle to the foreground window */
|
||||
@REPLY
|
||||
user_handle_t previous; /* handle to the previous foreground window */
|
||||
int send_msg_old; /* whether we have to send a msg to the old window */
|
||||
int send_msg_new; /* whether we have to send a msg to the new window */
|
||||
@END
|
||||
|
||||
/* Set the current thread focus window */
|
||||
@REQ(set_focus_window)
|
||||
user_handle_t handle; /* handle to the focus window */
|
||||
@REPLY
|
||||
user_handle_t previous; /* handle to the previous focus window */
|
||||
@END
|
||||
|
||||
/* Set the current thread active window */
|
||||
@REQ(set_active_window)
|
||||
user_handle_t handle; /* handle to the active window */
|
||||
@REPLY
|
||||
user_handle_t previous; /* handle to the previous active window */
|
||||
@END
|
||||
|
|
|
@ -621,6 +621,25 @@ inline static void thread_input_cleanup_window( struct msg_queue *queue, user_ha
|
|||
if (window == input->caret) input->caret = 0;
|
||||
}
|
||||
|
||||
/* check if the specified window can be set in the input data of a given queue */
|
||||
static int check_queue_input_window( struct msg_queue *queue, user_handle_t window )
|
||||
{
|
||||
struct thread *thread;
|
||||
int ret = 0;
|
||||
|
||||
if (!window) return 1; /* we can always clear the data */
|
||||
|
||||
if ((thread = get_window_thread( window )))
|
||||
{
|
||||
ret = (queue->input == thread->queue->input);
|
||||
if (!ret) set_error( STATUS_ACCESS_DENIED );
|
||||
release_object( thread );
|
||||
}
|
||||
else set_error( STATUS_INVALID_HANDLE );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* attach two thread input data structures */
|
||||
int attach_thread_input( struct thread *thread_from, struct thread *thread_to )
|
||||
{
|
||||
|
@ -1292,3 +1311,61 @@ DECL_HANDLER(get_thread_input)
|
|||
reply->foreground = foreground_input ? foreground_input->active : 0;
|
||||
if (thread) release_object( thread );
|
||||
}
|
||||
|
||||
|
||||
/* set the system foreground window */
|
||||
DECL_HANDLER(set_foreground_window)
|
||||
{
|
||||
struct msg_queue *queue = get_current_queue();
|
||||
|
||||
reply->previous = foreground_input ? foreground_input->active : 0;
|
||||
reply->send_msg_old = (reply->previous && foreground_input != queue->input);
|
||||
reply->send_msg_new = FALSE;
|
||||
|
||||
if (req->handle)
|
||||
{
|
||||
struct thread *thread;
|
||||
|
||||
if (is_top_level_window( req->handle ) &&
|
||||
((thread = get_window_thread( req->handle ))))
|
||||
{
|
||||
foreground_input = thread->queue->input;
|
||||
reply->send_msg_new = (foreground_input != queue->input);
|
||||
release_object( thread );
|
||||
}
|
||||
else set_error( STATUS_INVALID_HANDLE );
|
||||
}
|
||||
else foreground_input = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* set the current thread focus window */
|
||||
DECL_HANDLER(set_focus_window)
|
||||
{
|
||||
struct msg_queue *queue = get_current_queue();
|
||||
|
||||
reply->previous = 0;
|
||||
if (queue && check_queue_input_window( queue, req->handle ))
|
||||
{
|
||||
reply->previous = queue->input->focus;
|
||||
queue->input->focus = get_user_full_handle( req->handle );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* set the current thread active window */
|
||||
DECL_HANDLER(set_active_window)
|
||||
{
|
||||
struct msg_queue *queue = get_current_queue();
|
||||
|
||||
reply->previous = 0;
|
||||
if (queue && check_queue_input_window( queue, req->handle ))
|
||||
{
|
||||
if (!req->handle || make_window_active( req->handle ))
|
||||
{
|
||||
reply->previous = queue->input->active;
|
||||
queue->input->active = get_user_full_handle( req->handle );
|
||||
}
|
||||
else set_error( STATUS_INVALID_HANDLE );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -261,6 +261,9 @@ DECL_HANDLER(get_window_property);
|
|||
DECL_HANDLER(get_window_properties);
|
||||
DECL_HANDLER(attach_thread_input);
|
||||
DECL_HANDLER(get_thread_input);
|
||||
DECL_HANDLER(set_foreground_window);
|
||||
DECL_HANDLER(set_focus_window);
|
||||
DECL_HANDLER(set_active_window);
|
||||
|
||||
#ifdef WANT_REQUEST_HANDLERS
|
||||
|
||||
|
@ -425,6 +428,9 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_get_window_properties,
|
||||
(req_handler)req_attach_thread_input,
|
||||
(req_handler)req_get_thread_input,
|
||||
(req_handler)req_set_foreground_window,
|
||||
(req_handler)req_set_focus_window,
|
||||
(req_handler)req_set_active_window,
|
||||
};
|
||||
#endif /* WANT_REQUEST_HANDLERS */
|
||||
|
||||
|
|
|
@ -2005,6 +2005,7 @@ static void dump_get_window_info_request( const struct get_window_info_request *
|
|||
static void dump_get_window_info_reply( const struct get_window_info_reply *req )
|
||||
{
|
||||
fprintf( stderr, " full_handle=%08x,", req->full_handle );
|
||||
fprintf( stderr, " last_active=%08x,", req->last_active );
|
||||
fprintf( stderr, " pid=%08x,", req->pid );
|
||||
fprintf( stderr, " tid=%08x,", req->tid );
|
||||
fprintf( stderr, " atom=%04x", req->atom );
|
||||
|
@ -2200,6 +2201,38 @@ static void dump_get_thread_input_reply( const struct get_thread_input_reply *re
|
|||
dump_rectangle( &req->rect );
|
||||
}
|
||||
|
||||
static void dump_set_foreground_window_request( const struct set_foreground_window_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%08x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_set_foreground_window_reply( const struct set_foreground_window_reply *req )
|
||||
{
|
||||
fprintf( stderr, " previous=%08x,", req->previous );
|
||||
fprintf( stderr, " send_msg_old=%d,", req->send_msg_old );
|
||||
fprintf( stderr, " send_msg_new=%d", req->send_msg_new );
|
||||
}
|
||||
|
||||
static void dump_set_focus_window_request( const struct set_focus_window_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%08x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_set_focus_window_reply( const struct set_focus_window_reply *req )
|
||||
{
|
||||
fprintf( stderr, " previous=%08x", req->previous );
|
||||
}
|
||||
|
||||
static void dump_set_active_window_request( const struct set_active_window_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%08x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_set_active_window_reply( const struct set_active_window_reply *req )
|
||||
{
|
||||
fprintf( stderr, " previous=%08x", req->previous );
|
||||
}
|
||||
|
||||
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||
(dump_func)dump_new_process_request,
|
||||
(dump_func)dump_get_new_process_info_request,
|
||||
|
@ -2359,6 +2392,9 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_get_window_properties_request,
|
||||
(dump_func)dump_attach_thread_input_request,
|
||||
(dump_func)dump_get_thread_input_request,
|
||||
(dump_func)dump_set_foreground_window_request,
|
||||
(dump_func)dump_set_focus_window_request,
|
||||
(dump_func)dump_set_active_window_request,
|
||||
};
|
||||
|
||||
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||
|
@ -2520,6 +2556,9 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_get_window_properties_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_thread_input_reply,
|
||||
(dump_func)dump_set_foreground_window_reply,
|
||||
(dump_func)dump_set_focus_window_reply,
|
||||
(dump_func)dump_set_active_window_reply,
|
||||
};
|
||||
|
||||
static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||
|
@ -2681,6 +2720,9 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"get_window_properties",
|
||||
"attach_thread_input",
|
||||
"get_thread_input",
|
||||
"set_foreground_window",
|
||||
"set_focus_window",
|
||||
"set_active_window",
|
||||
};
|
||||
|
||||
/* ### make_requests end ### */
|
||||
|
|
|
@ -54,6 +54,8 @@ extern void post_message( user_handle_t win, unsigned int message,
|
|||
|
||||
extern void destroy_thread_windows( struct thread *thread );
|
||||
extern int is_child_window( user_handle_t parent, user_handle_t child );
|
||||
extern int is_top_level_window( user_handle_t window );
|
||||
extern int make_window_active( user_handle_t window );
|
||||
extern struct thread *get_window_thread( user_handle_t handle );
|
||||
extern user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread );
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ struct window
|
|||
user_handle_t handle; /* full handle for this window */
|
||||
struct thread *thread; /* thread owning the window */
|
||||
atom_t atom; /* class atom */
|
||||
user_handle_t last_active; /* last active popup */
|
||||
rectangle_t window_rect; /* window rectangle */
|
||||
rectangle_t client_rect; /* client rectangle */
|
||||
unsigned int style; /* window style */
|
||||
|
@ -268,6 +269,7 @@ static struct window *create_window( struct window *parent, struct window *owner
|
|||
win->first_unlinked = NULL;
|
||||
win->thread = current;
|
||||
win->atom = atom;
|
||||
win->last_active = win->handle;
|
||||
win->style = 0;
|
||||
win->ex_style = 0;
|
||||
win->id = 0;
|
||||
|
@ -321,6 +323,27 @@ int is_child_window( user_handle_t parent, user_handle_t child )
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* check whether window is a top-level window */
|
||||
int is_top_level_window( user_handle_t window )
|
||||
{
|
||||
struct window *win = get_user_object( window, USER_WINDOW );
|
||||
return (win && win->parent == top_window);
|
||||
}
|
||||
|
||||
/* make a window active if possible */
|
||||
int make_window_active( user_handle_t window )
|
||||
{
|
||||
struct window *owner, *win = get_window( window );
|
||||
|
||||
if (!win) return 0;
|
||||
|
||||
/* set last active for window and its owner */
|
||||
win->last_active = win->handle;
|
||||
if ((owner = get_user_object( win->owner, USER_WINDOW ))) owner->last_active = win->handle;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* return the thread owning a window */
|
||||
struct thread *get_window_thread( user_handle_t handle )
|
||||
{
|
||||
|
@ -478,6 +501,8 @@ DECL_HANDLER(get_window_info)
|
|||
if (win)
|
||||
{
|
||||
reply->full_handle = win->handle;
|
||||
reply->last_active = win->handle;
|
||||
if (get_user_object( win->last_active, USER_WINDOW )) reply->last_active = win->last_active;
|
||||
if (win->thread)
|
||||
{
|
||||
reply->tid = get_thread_id( win->thread );
|
||||
|
|
180
windows/focus.c
180
windows/focus.c
|
@ -1,180 +0,0 @@
|
|||
/*
|
||||
* Focus functions
|
||||
*
|
||||
* Copyright 1993 David Metcalfe
|
||||
* 1994 Alexandre Julliard
|
||||
* 1995 Alex Korobka
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "windef.h"
|
||||
#include "wingdi.h"
|
||||
#include "wine/winuser16.h"
|
||||
#include "win.h"
|
||||
#include "winpos.h"
|
||||
#include "hook.h"
|
||||
#include "message.h"
|
||||
#include "queue.h"
|
||||
#include "user.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(win);
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* FOCUS_SwitchFocus
|
||||
* pMsgQ is the queue whose perQData focus is to be modified
|
||||
*/
|
||||
void FOCUS_SwitchFocus( MESSAGEQUEUE *pMsgQ, HWND hFocusFrom, HWND hFocusTo )
|
||||
{
|
||||
PERQDATA_SetFocusWnd( pMsgQ->pQData, hFocusTo );
|
||||
|
||||
if (hFocusFrom)
|
||||
SendNotifyMessageA( hFocusFrom, WM_KILLFOCUS, (WPARAM)hFocusTo, 0 );
|
||||
|
||||
if( !hFocusTo || hFocusTo != PERQDATA_GetFocusWnd( pMsgQ->pQData ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* According to API docs, the WM_SETFOCUS message is sent AFTER the window
|
||||
has received the keyboard focus. */
|
||||
if (USER_Driver.pSetFocus) USER_Driver.pSetFocus(hFocusTo);
|
||||
|
||||
SendMessageA( hFocusTo, WM_SETFOCUS, (WPARAM)hFocusFrom, 0 );
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* SetFocus (USER32.@)
|
||||
*/
|
||||
HWND WINAPI SetFocus( HWND hwnd )
|
||||
{
|
||||
HWND hWndFocus = 0, hwndTop = hwnd;
|
||||
MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
|
||||
BOOL bRet = 0;
|
||||
|
||||
/* Get the messageQ for the current thread */
|
||||
if (!(pCurMsgQ = QUEUE_Current()))
|
||||
{
|
||||
WARN("\tCurrent message queue not found. Exiting!\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hwnd)
|
||||
{
|
||||
/* Check if we can set the focus to this window */
|
||||
WND *wndPtr;
|
||||
|
||||
hwnd = WIN_GetFullHandle( hwnd );
|
||||
for (;;)
|
||||
{
|
||||
HWND parent;
|
||||
LONG style = GetWindowLongW( hwndTop, GWL_STYLE );
|
||||
if (style & (WS_MINIMIZE | WS_DISABLED)) return 0;
|
||||
parent = GetAncestor( hwndTop, GA_PARENT );
|
||||
if (!parent || parent == GetDesktopWindow()) break;
|
||||
hwndTop = parent;
|
||||
}
|
||||
|
||||
if (!(wndPtr = WIN_FindWndPtr( hwndTop ))) return 0;
|
||||
|
||||
/* Retrieve the message queue associated with this window */
|
||||
pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
|
||||
WIN_ReleaseWndPtr( wndPtr );
|
||||
if ( !pMsgQ )
|
||||
{
|
||||
WARN("\tMessage queue not found. Exiting!\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure that message queue for the window we are setting focus to
|
||||
* shares the same perQ data as the current threads message queue.
|
||||
* In other words you can't set focus to a window owned by a different
|
||||
* thread unless AttachThreadInput has been called previously.
|
||||
* (see AttachThreadInput and SetFocus docs)
|
||||
*/
|
||||
if ( pCurMsgQ->pQData != pMsgQ->pQData )
|
||||
goto CLEANUP;
|
||||
|
||||
/* Get the current focus window from the perQ data */
|
||||
hWndFocus = PERQDATA_GetFocusWnd( pMsgQ->pQData );
|
||||
|
||||
if( hwnd == hWndFocus )
|
||||
{
|
||||
bRet = 1; /* Success */
|
||||
goto CLEANUP; /* Nothing to do */
|
||||
}
|
||||
|
||||
/* call hooks */
|
||||
if( HOOK_CallHooksA( WH_CBT, HCBT_SETFOCUS, (WPARAM)hwnd, (LPARAM)hWndFocus) )
|
||||
goto CLEANUP;
|
||||
|
||||
/* activate hwndTop if needed. */
|
||||
if (hwndTop != GetActiveWindow())
|
||||
{
|
||||
if (!WINPOS_SetActiveWindow(hwndTop, 0, 0)) goto CLEANUP;
|
||||
|
||||
if (!IsWindow( hwnd )) goto CLEANUP; /* Abort if window destroyed */
|
||||
}
|
||||
|
||||
/* Get the current focus window from the perQ data */
|
||||
hWndFocus = PERQDATA_GetFocusWnd( pMsgQ->pQData );
|
||||
|
||||
/* Change focus and send messages */
|
||||
FOCUS_SwitchFocus( pMsgQ, hWndFocus, hwnd );
|
||||
}
|
||||
else /* NULL hwnd passed in */
|
||||
{
|
||||
if( HOOK_CallHooksA( WH_CBT, HCBT_SETFOCUS, 0, (LPARAM)hWndFocus ) )
|
||||
return 0;
|
||||
|
||||
/* Get the current focus from the perQ data of the current message Q */
|
||||
hWndFocus = PERQDATA_GetFocusWnd( pCurMsgQ->pQData );
|
||||
|
||||
/* Change focus and send messages */
|
||||
FOCUS_SwitchFocus( pCurMsgQ, hWndFocus, hwnd );
|
||||
}
|
||||
|
||||
bRet = 1; /* Success */
|
||||
|
||||
CLEANUP:
|
||||
|
||||
/* Unlock the queues before returning */
|
||||
if ( pMsgQ )
|
||||
QUEUE_Unlock( pMsgQ );
|
||||
|
||||
return bRet ? hWndFocus : 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* GetFocus (USER32.@)
|
||||
*/
|
||||
HWND WINAPI GetFocus(void)
|
||||
{
|
||||
MESSAGEQUEUE *pCurMsgQ = 0;
|
||||
|
||||
/* Get the messageQ for the current thread */
|
||||
if (!(pCurMsgQ = QUEUE_Current()))
|
||||
{
|
||||
WARN("\tCurrent message queue not found. Exiting!\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the current focus from the perQ data of the current message Q */
|
||||
return PERQDATA_GetFocusWnd( pCurMsgQ->pQData );
|
||||
}
|
|
@ -512,8 +512,6 @@ static BOOL process_cooked_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL r
|
|||
(raw_message == WM_RBUTTONDOWN) ||
|
||||
(raw_message == WM_MBUTTONDOWN))
|
||||
{
|
||||
HWND hwndTop = GetAncestor( msg->hwnd, GA_ROOT );
|
||||
|
||||
/* Send the WM_PARENTNOTIFY,
|
||||
* note that even for double/nonclient clicks
|
||||
* notification message is still WM_L/M/RBUTTONDOWN.
|
||||
|
@ -522,11 +520,19 @@ static BOOL process_cooked_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL r
|
|||
|
||||
/* Activate the window if needed */
|
||||
|
||||
if (msg->hwnd != GetActiveWindow() && hwndTop != GetDesktopWindow())
|
||||
if (msg->hwnd != GetActiveWindow())
|
||||
{
|
||||
HWND hwndTop = msg->hwnd;
|
||||
while (hwndTop)
|
||||
{
|
||||
if ((GetWindowLongW( hwndTop, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) != WS_CHILD) break;
|
||||
hwndTop = GetParent( hwndTop );
|
||||
}
|
||||
|
||||
if (hwndTop && hwndTop != GetDesktopWindow())
|
||||
{
|
||||
LONG ret = SendMessageA( msg->hwnd, WM_MOUSEACTIVATE, (WPARAM)hwndTop,
|
||||
MAKELONG( hittest, raw_message ) );
|
||||
|
||||
switch(ret)
|
||||
{
|
||||
case MA_NOACTIVATEANDEAT:
|
||||
|
@ -539,11 +545,7 @@ static BOOL process_cooked_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL r
|
|||
/* fall through */
|
||||
case MA_ACTIVATE:
|
||||
case 0:
|
||||
if (hwndTop != GetForegroundWindow() )
|
||||
{
|
||||
if (!WINPOS_SetActiveWindow( hwndTop, TRUE , TRUE ))
|
||||
eatMsg = TRUE;
|
||||
}
|
||||
if (!FOCUS_MouseActivate( hwndTop )) eatMsg = TRUE;
|
||||
break;
|
||||
default:
|
||||
WARN( "unknown WM_MOUSEACTIVATE code %ld\n", ret );
|
||||
|
@ -551,6 +553,7 @@ static BOOL process_cooked_mouse_message( MSG *msg, ULONG_PTR extra_info, BOOL r
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* send the WM_SETCURSOR message */
|
||||
|
||||
|
|
|
@ -1999,7 +1999,7 @@ LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
|
|||
{
|
||||
HWND top = GetAncestor( hwnd, GA_ROOT );
|
||||
|
||||
if( WINPOS_SetActiveWindow(top, TRUE, TRUE) || (GetActiveWindow() == top) )
|
||||
if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
|
||||
SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1479,7 +1479,10 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
|
|||
|
||||
/* Hide the window */
|
||||
|
||||
ShowWindow( hwnd, SW_HIDE );
|
||||
if (!ShowWindow( hwnd, SW_HIDE ))
|
||||
{
|
||||
if (hwnd == GetActiveWindow()) WINPOS_ActivateOtherWindow( hwnd );
|
||||
}
|
||||
if (!IsWindow(hwnd)) return TRUE;
|
||||
|
||||
/* Recursively destroy owned windows */
|
||||
|
@ -1510,8 +1513,6 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
|
|||
if (!got_one) break;
|
||||
}
|
||||
|
||||
WINPOS_ActivateOtherWindow( hwnd );
|
||||
|
||||
if ((owner = GetWindow( hwnd, GW_OWNER )))
|
||||
{
|
||||
WND *ptr = WIN_FindWndPtr( owner );
|
||||
|
@ -3109,7 +3110,7 @@ BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
|
|||
{
|
||||
WPARAM16 wparam;
|
||||
if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
|
||||
else wparam = (hWnd == GetActiveWindow());
|
||||
else wparam = (hWnd == GetForegroundWindow());
|
||||
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
|
||||
|
|
432
windows/winpos.c
432
windows/winpos.c
|
@ -69,14 +69,12 @@ typedef struct
|
|||
|
||||
/* ----- internal variables ----- */
|
||||
|
||||
static HWND hwndPrevActive = 0; /* Previously active window */
|
||||
static HWND hGlobalShellWindow=0; /*the shell*/
|
||||
static HWND hGlobalTaskmanWindow=0;
|
||||
static HWND hGlobalProgmanWindow=0;
|
||||
|
||||
static LPCSTR atomInternalPos;
|
||||
|
||||
extern HQUEUE16 hActiveQueue;
|
||||
|
||||
/***********************************************************************
|
||||
* WINPOS_CreateInternalPosAtom
|
||||
|
@ -95,30 +93,7 @@ BOOL WINPOS_CreateInternalPosAtom()
|
|||
*/
|
||||
void WINPOS_CheckInternalPos( HWND hwnd )
|
||||
{
|
||||
LPINTERNALPOS lpPos;
|
||||
MESSAGEQUEUE *pMsgQ = 0;
|
||||
WND *wndPtr = WIN_GetPtr( hwnd );
|
||||
|
||||
if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return;
|
||||
|
||||
lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
|
||||
|
||||
/* Retrieve the message queue associated with this window */
|
||||
pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
|
||||
if ( !pMsgQ )
|
||||
{
|
||||
WARN("\tMessage queue not found. Exiting!\n" );
|
||||
WIN_ReleasePtr( wndPtr );
|
||||
return;
|
||||
}
|
||||
|
||||
if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
|
||||
|
||||
if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
|
||||
{
|
||||
PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
|
||||
WARN("\tattempt to activate destroyed window!\n");
|
||||
}
|
||||
LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
|
||||
|
||||
if( lpPos )
|
||||
{
|
||||
|
@ -126,9 +101,6 @@ void WINPOS_CheckInternalPos( HWND hwnd )
|
|||
DestroyWindow( lpPos->hwndIconTitle );
|
||||
HeapFree( GetProcessHeap(), 0, lpPos );
|
||||
}
|
||||
|
||||
QUEUE_Unlock( pMsgQ );
|
||||
WIN_ReleasePtr( wndPtr );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -640,132 +612,6 @@ BOOL WINAPI IsZoomed(HWND hWnd)
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* GetActiveWindow (USER32.@)
|
||||
*/
|
||||
HWND WINAPI GetActiveWindow(void)
|
||||
{
|
||||
MESSAGEQUEUE *pCurMsgQ = 0;
|
||||
|
||||
/* Get the messageQ for the current thread */
|
||||
if (!(pCurMsgQ = QUEUE_Current()))
|
||||
{
|
||||
WARN("\tCurrent message queue not found. Exiting!\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the current active window from the perQ data of the current message Q */
|
||||
return PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* WINPOS_CanActivate
|
||||
*/
|
||||
static BOOL WINPOS_CanActivate(HWND hwnd)
|
||||
{
|
||||
if (!hwnd) return FALSE;
|
||||
return ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_DISABLED|WS_CHILD)) == 0);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* WINPOS_IsVisible
|
||||
*/
|
||||
static BOOL WINPOS_IsVisible(HWND hwnd)
|
||||
{
|
||||
if (!hwnd) return FALSE;
|
||||
return ((GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE) == WS_VISIBLE);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* SetActiveWindow (USER32.@)
|
||||
*/
|
||||
HWND WINAPI SetActiveWindow( HWND hwnd )
|
||||
{
|
||||
HWND prev = 0;
|
||||
WND *wndPtr = WIN_FindWndPtr( hwnd );
|
||||
MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
|
||||
|
||||
if (!wndPtr) return 0;
|
||||
|
||||
if (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)) goto error;
|
||||
|
||||
/* Get the messageQ for the current thread */
|
||||
if (!(pCurMsgQ = QUEUE_Current()))
|
||||
{
|
||||
WARN("\tCurrent message queue not found. Exiting!\n" );
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Retrieve the message queue associated with this window */
|
||||
pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
|
||||
if ( !pMsgQ )
|
||||
{
|
||||
WARN("\tWindow message queue not found. Exiting!\n" );
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Make sure that the window is associated with the calling threads
|
||||
* message queue. It must share the same perQ data.
|
||||
*/
|
||||
if ( pCurMsgQ->pQData != pMsgQ->pQData )
|
||||
{
|
||||
QUEUE_Unlock( pMsgQ );
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Save current active window */
|
||||
prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
|
||||
QUEUE_Unlock( pMsgQ );
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
WINPOS_SetActiveWindow( hwnd, FALSE, TRUE );
|
||||
return prev;
|
||||
|
||||
error:
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* GetForegroundWindow (USER32.@)
|
||||
*/
|
||||
HWND WINAPI GetForegroundWindow(void)
|
||||
{
|
||||
HWND hwndActive = 0;
|
||||
|
||||
/* Get the foreground window (active window of hActiveQueue) */
|
||||
if ( hActiveQueue )
|
||||
{
|
||||
MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
|
||||
if ( pActiveQueue )
|
||||
hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
|
||||
|
||||
QUEUE_Unlock( pActiveQueue );
|
||||
}
|
||||
|
||||
return hwndActive;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* SetForegroundWindow (USER32.@)
|
||||
*/
|
||||
BOOL WINAPI SetForegroundWindow( HWND hwnd )
|
||||
{
|
||||
if (!hwnd) return WINPOS_SetActiveWindow( 0, FALSE, TRUE );
|
||||
|
||||
/* child windows get WM_CHILDACTIVATE message */
|
||||
if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD)
|
||||
return SendMessageA( hwnd, WM_CHILDACTIVATE, 0, 0 );
|
||||
|
||||
hwnd = WIN_GetFullHandle( hwnd );
|
||||
if( hwnd == GetForegroundWindow() ) return FALSE;
|
||||
|
||||
return WINPOS_SetActiveWindow( hwnd, FALSE, TRUE );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* AllowSetForegroundWindow (USER32.@)
|
||||
*/
|
||||
|
@ -1191,221 +1037,24 @@ void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* WINPOS_SetActiveWindow
|
||||
* can_activate_window
|
||||
*
|
||||
* SetActiveWindow() back-end. This is the only function that
|
||||
* can assign active status to a window. It must be called only
|
||||
* for the top level windows.
|
||||
* Check if we can activate the specified window.
|
||||
*/
|
||||
BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
|
||||
static BOOL can_activate_window( HWND hwnd )
|
||||
{
|
||||
WND* wndPtr=0, *wndTemp;
|
||||
HQUEUE16 hOldActiveQueue, hNewActiveQueue;
|
||||
MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
|
||||
WORD wIconized = 0;
|
||||
HWND hwndActive = 0;
|
||||
BOOL bRet = 0;
|
||||
LONG style;
|
||||
|
||||
TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
|
||||
|
||||
/* Get current active window from the active queue */
|
||||
if ( hActiveQueue )
|
||||
{
|
||||
pOldActiveQueue = QUEUE_Lock( hActiveQueue );
|
||||
if ( pOldActiveQueue )
|
||||
hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
|
||||
}
|
||||
|
||||
if ((wndPtr = WIN_FindWndPtr(hWnd)))
|
||||
hWnd = wndPtr->hwndSelf; /* make it a full handle */
|
||||
|
||||
/* paranoid checks */
|
||||
if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
|
||||
goto CLEANUP_END;
|
||||
|
||||
/* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
|
||||
* return 0;
|
||||
*/
|
||||
hOldActiveQueue = hActiveQueue;
|
||||
|
||||
if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
|
||||
{
|
||||
wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
|
||||
WIN_ReleaseWndPtr(wndTemp);
|
||||
}
|
||||
else
|
||||
TRACE("no current active window.\n");
|
||||
|
||||
/* call CBT hook chain */
|
||||
if (HOOK_IsHooked( WH_CBT ))
|
||||
{
|
||||
CBTACTIVATESTRUCT cbt;
|
||||
cbt.fMouse = fMouse;
|
||||
cbt.hWndActive = hwndActive;
|
||||
if (HOOK_CallHooksA( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt )) goto CLEANUP_END;
|
||||
}
|
||||
|
||||
/* set prev active wnd to current active wnd and send notification */
|
||||
if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
|
||||
{
|
||||
MESSAGEQUEUE *pTempActiveQueue = 0;
|
||||
|
||||
SendNotifyMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 );
|
||||
SendNotifyMessageA( hwndPrevActive, WM_ACTIVATE,
|
||||
MAKEWPARAM( WA_INACTIVE, wIconized ),
|
||||
(LPARAM)hWnd );
|
||||
|
||||
/* check if something happened during message processing
|
||||
* (global active queue may have changed)
|
||||
*/
|
||||
pTempActiveQueue = QUEUE_Lock( hActiveQueue );
|
||||
if(!pTempActiveQueue)
|
||||
goto CLEANUP_END;
|
||||
|
||||
hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
|
||||
QUEUE_Unlock( pTempActiveQueue );
|
||||
if( hwndPrevActive != hwndActive )
|
||||
goto CLEANUP_END;
|
||||
}
|
||||
|
||||
/* Set new active window in the message queue */
|
||||
hwndActive = hWnd;
|
||||
if ( wndPtr )
|
||||
{
|
||||
pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
|
||||
if ( pNewActiveQueue )
|
||||
PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
|
||||
}
|
||||
else /* have to do this or MDI frame activation goes to hell */
|
||||
if( pOldActiveQueue )
|
||||
PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
|
||||
|
||||
/* send palette messages */
|
||||
if (hWnd && SendMessageW( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
|
||||
SendMessageW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hWnd, 0 );
|
||||
|
||||
/* if prev wnd is minimized redraw icon title */
|
||||
if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
|
||||
|
||||
/* managed windows will get ConfigureNotify event */
|
||||
if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
|
||||
{
|
||||
/* check Z-order and bring hWnd to the top */
|
||||
HWND tmp = GetTopWindow(0);
|
||||
while (tmp && !(GetWindowLongA( tmp, GWL_STYLE ) & WS_VISIBLE))
|
||||
tmp = GetWindow( tmp, GW_HWNDNEXT );
|
||||
|
||||
if( tmp != hWnd )
|
||||
SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
|
||||
if (!IsWindow(hWnd))
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Get a handle to the new active queue */
|
||||
hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
|
||||
|
||||
/* send WM_ACTIVATEAPP if necessary */
|
||||
if (hOldActiveQueue != hNewActiveQueue)
|
||||
{
|
||||
HWND *list, *phwnd;
|
||||
DWORD old_thread = GetWindowThreadProcessId( hwndPrevActive, NULL );
|
||||
DWORD new_thread = GetWindowThreadProcessId( hwndActive, NULL );
|
||||
|
||||
if ((list = WIN_ListChildren( GetDesktopWindow() )))
|
||||
{
|
||||
for (phwnd = list; *phwnd; phwnd++)
|
||||
{
|
||||
if (!IsWindow( *phwnd )) continue;
|
||||
if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread)
|
||||
SendNotifyMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread );
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
}
|
||||
|
||||
hActiveQueue = hNewActiveQueue;
|
||||
|
||||
if ((list = WIN_ListChildren( GetDesktopWindow() )))
|
||||
{
|
||||
for (phwnd = list; *phwnd; phwnd++)
|
||||
{
|
||||
if (!IsWindow( *phwnd )) continue;
|
||||
if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread)
|
||||
SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread );
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
}
|
||||
|
||||
if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
|
||||
}
|
||||
|
||||
if (hWnd)
|
||||
{
|
||||
/* walk up to the first unowned window */
|
||||
HWND tmp = GetAncestor( hWnd, GA_ROOTOWNER );
|
||||
if ((wndTemp = WIN_FindWndPtr( tmp )))
|
||||
{
|
||||
/* and set last active owned popup */
|
||||
wndTemp->hwndLastActive = hWnd;
|
||||
|
||||
wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
|
||||
WIN_ReleaseWndPtr(wndTemp);
|
||||
}
|
||||
SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
|
||||
SendMessageA( hWnd, WM_ACTIVATE,
|
||||
MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
|
||||
(LPARAM)hwndPrevActive );
|
||||
if( !IsWindow(hWnd) ) goto CLEANUP;
|
||||
}
|
||||
|
||||
/* change focus if possible */
|
||||
if ( fChangeFocus )
|
||||
{
|
||||
if ( pNewActiveQueue )
|
||||
{
|
||||
HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
|
||||
|
||||
if ( !hOldFocus || GetAncestor( hOldFocus, GA_ROOT ) != hwndActive )
|
||||
FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
|
||||
(wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
|
||||
0 : hwndActive );
|
||||
}
|
||||
|
||||
if ( pOldActiveQueue &&
|
||||
( !pNewActiveQueue ||
|
||||
pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
|
||||
{
|
||||
HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
|
||||
if ( hOldFocus )
|
||||
FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
if( !hwndPrevActive && wndPtr )
|
||||
{
|
||||
if (USER_Driver.pForceWindowRaise) USER_Driver.pForceWindowRaise( wndPtr->hwndSelf );
|
||||
}
|
||||
|
||||
/* if active wnd is minimized redraw icon title */
|
||||
if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
|
||||
|
||||
bRet = (hWnd == hwndActive); /* Success? */
|
||||
|
||||
CLEANUP: /* Unlock the message queues before returning */
|
||||
|
||||
if ( pNewActiveQueue )
|
||||
QUEUE_Unlock( pNewActiveQueue );
|
||||
|
||||
CLEANUP_END:
|
||||
|
||||
if ( pOldActiveQueue )
|
||||
QUEUE_Unlock( pOldActiveQueue );
|
||||
|
||||
WIN_ReleaseWndPtr(wndPtr);
|
||||
return bRet;
|
||||
if (!hwnd) return FALSE;
|
||||
style = GetWindowLongW( hwnd, GWL_STYLE );
|
||||
if (!(style & WS_VISIBLE)) return FALSE;
|
||||
if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
|
||||
return !(style & WS_DISABLED);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* WINPOS_ActivateOtherWindow
|
||||
*
|
||||
|
@ -1413,54 +1062,29 @@ CLEANUP_END:
|
|||
*/
|
||||
void WINPOS_ActivateOtherWindow(HWND hwnd)
|
||||
{
|
||||
HWND hwndActive = 0;
|
||||
HWND hwndTo = 0;
|
||||
HWND hwndDefaultTo = 0;
|
||||
HWND owner;
|
||||
HWND hwndTo, fg;
|
||||
|
||||
/* Get current active window from the active queue */
|
||||
if ( hActiveQueue )
|
||||
if ((GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) && (hwndTo = GetWindow( hwnd, GW_OWNER )))
|
||||
{
|
||||
MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
|
||||
if ( pActiveQueue )
|
||||
{
|
||||
hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
|
||||
QUEUE_Unlock( pActiveQueue );
|
||||
}
|
||||
hwndTo = GetAncestor( hwndTo, GA_ROOT );
|
||||
if (can_activate_window( hwndTo )) goto done;
|
||||
}
|
||||
|
||||
if (!(hwnd = WIN_IsCurrentThread( hwnd ))) return;
|
||||
|
||||
if( hwnd == hwndPrevActive )
|
||||
hwndPrevActive = 0;
|
||||
|
||||
if( hwndActive != hwnd && (hwndActive || USER_IsExitingThread( GetCurrentThreadId() )))
|
||||
return;
|
||||
|
||||
if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) ||
|
||||
!(owner = GetWindow( hwnd, GW_OWNER )) ||
|
||||
!WINPOS_CanActivate((hwndTo = GetAncestor( owner, GA_ROOT ))) ||
|
||||
!WINPOS_IsVisible(hwndTo))
|
||||
hwndTo = hwnd;
|
||||
for (;;)
|
||||
{
|
||||
HWND tmp = GetAncestor( hwnd, GA_ROOT );
|
||||
hwndTo = hwndPrevActive;
|
||||
|
||||
while( !WINPOS_CanActivate(hwndTo) || !WINPOS_IsVisible(hwndTo))
|
||||
{
|
||||
/* by now owned windows should've been taken care of */
|
||||
if(!hwndDefaultTo && WINPOS_CanActivate(hwndTo))
|
||||
hwndDefaultTo = hwndTo;
|
||||
tmp = hwndTo = GetWindow( tmp, GW_HWNDNEXT );
|
||||
if( !hwndTo )
|
||||
{
|
||||
hwndTo = hwndDefaultTo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(hwndTo = GetWindow( hwndTo, GW_HWNDNEXT ))) break;
|
||||
if (can_activate_window( hwndTo )) break;
|
||||
}
|
||||
|
||||
SetActiveWindow( hwndTo );
|
||||
hwndPrevActive = 0;
|
||||
done:
|
||||
fg = GetForegroundWindow();
|
||||
TRACE("win = %x fg = %x\n", hwndTo, fg);
|
||||
if (!fg || (hwnd == fg))
|
||||
{
|
||||
if (SetForegroundWindow( hwndTo )) return;
|
||||
}
|
||||
if (!SetActiveWindow( hwndTo )) SetActiveWindow(0);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue