From: Rémi Bernon rbernon@codeweavers.com
When supported, instead of tracking window focus only. --- dlls/winex11.drv/event.c | 29 +++++++++++++++----------- dlls/winex11.drv/window.c | 44 ++++++++++++++++++++++++++++++++++++++- dlls/winex11.drv/x11drv.h | 2 ++ 3 files changed, 62 insertions(+), 13 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index e0d15e55f26..4ccd77fcb37 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -640,23 +640,25 @@ static void set_input_focus( struct x11drv_win_data *data ) /********************************************************************** * set_focus */ -static void set_focus( Display *display, HWND hwnd, Time time ) +static void set_focus( Display *display, HWND focus, Time time ) { - HWND focus; Window win; GUITHREADINFO threadinfo;
- TRACE( "setting foreground window to %p\n", hwnd ); - NtUserSetForegroundWindow( hwnd ); + TRACE( "setting foreground window to %p\n", focus );
- threadinfo.cbSize = sizeof(threadinfo); - NtUserGetGUIThreadInfo( 0, &threadinfo ); - focus = threadinfo.hwndFocus; - if (!focus) focus = threadinfo.hwndActive; - if (focus) focus = NtUserGetAncestor( focus, GA_ROOT ); - win = X11DRV_get_whole_window(focus); + if (!is_netwm_supported( x11drv_atom(_NET_ACTIVE_WINDOW) )) + { + NtUserSetForegroundWindow( focus ); + + threadinfo.cbSize = sizeof(threadinfo); + NtUserGetGUIThreadInfo( 0, &threadinfo ); + focus = threadinfo.hwndFocus; + if (!focus) focus = threadinfo.hwndActive; + if (focus) focus = NtUserGetAncestor( focus, GA_ROOT ); + }
- if (win) + if ((win = X11DRV_get_whole_window( focus ))) { TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time ); XSetInputFocus( display, win, RevertToParent, time ); @@ -901,7 +903,7 @@ static void focus_out( Display *display , HWND hwnd ) /* don't reset the foreground window, if the window which is getting the focus is a Wine window */
- if (!is_current_process_focused()) + if (!is_netwm_supported( x11drv_atom(_NET_ACTIVE_WINDOW) ) && !is_current_process_focused()) { /* Abey : 6-Oct-99. Check again if the focus out window is the Foreground window, because in most cases the messages sent @@ -1315,6 +1317,9 @@ static BOOL X11DRV_PropertyNotify( HWND hwnd, XEvent *xev ) void X11DRV_ActivateWindow( HWND hwnd, HWND previous ) { struct x11drv_win_data *data; + + set_net_active_window( hwnd, previous ); + if (!(data = get_win_data( hwnd ))) return; if (!data->managed || data->embedder) set_input_focus( data ); release_win_data( data ); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 0b4c55f134f..7e69aadcff3 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1657,11 +1657,21 @@ static UINT window_update_client_config( struct x11drv_win_data *data ) */ BOOL X11DRV_GetWindowStateUpdates( HWND hwnd, UINT *state_cmd, UINT *config_cmd, RECT *rect, HWND *foreground ) { + struct x11drv_thread_data *thread_data = x11drv_thread_data(); struct x11drv_win_data *data; + Window window;
*state_cmd = *config_cmd = 0; *foreground = 0;
+ if (NtUserGetWindowThread( NtUserGetForegroundWindow(), NULL ) == GetCurrentThreadId() && + !thread_data->net_active_window_serial && (window = thread_data->current_net_active_window)) + { + *foreground = hwnd_from_window( thread_data->display, window ); + if (*foreground == (HWND)-1) *foreground = NtUserGetDesktopWindow(); + if (*foreground == NtUserGetForegroundWindow()) *foreground = 0; + } + if ((data = get_win_data( hwnd ))) { *state_cmd = window_update_client_state( data ); @@ -1778,6 +1788,38 @@ void net_active_window_notify( unsigned long serial, Window value, Time time ) TRACE( "_NET_ACTIVE_WINDOW changed to %p/%lx\n", hwnd_from_window( data->display, value ), value ); }
+void set_net_active_window( HWND hwnd, HWND previous ) +{ + struct x11drv_thread_data *data = x11drv_thread_data(); + Window window; + XEvent xev; + + if (hwnd == NtUserGetDesktopWindow()) return; + if (!is_netwm_supported( x11drv_atom(_NET_ACTIVE_WINDOW) )) return; + if (!(window = X11DRV_get_whole_window( hwnd ))) return; + if (data->pending_net_active_window == window) return; + + xev.xclient.type = ClientMessage; + xev.xclient.window = window; + xev.xclient.message_type = x11drv_atom(_NET_ACTIVE_WINDOW); + xev.xclient.serial = 0; + xev.xclient.display = data->display; + xev.xclient.send_event = True; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 2; /* source: pager */ + xev.xclient.data.l[1] = 0; /* timestamp */ + xev.xclient.data.l[2] = X11DRV_get_whole_window( previous ); /* current active */ + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + + data->pending_net_active_window = window; + data->net_active_window_serial = NextRequest( data->display ); + TRACE( "requesting _NET_ACTIVE_WINDOW %p/%lx serial %lu\n", hwnd, window, data->net_active_window_serial ); + XSendEvent( data->display, DefaultRootWindow( data->display ), False, + SubstructureRedirectMask | SubstructureNotifyMask, &xev ); + XFlush( data->display ); +} + BOOL window_has_pending_wm_state( HWND hwnd, UINT state ) { struct x11drv_win_data *data; @@ -3322,7 +3364,7 @@ LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) /*********************************************************************** * is_netwm_supported */ -static BOOL is_netwm_supported( Atom atom ) +BOOL is_netwm_supported( Atom atom ) { struct x11drv_thread_data *data = x11drv_thread_data(); BOOL supported; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index c9c5fae3636..d67f85d9103 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -674,8 +674,10 @@ extern void window_wm_state_notify( struct x11drv_win_data *data, unsigned long extern void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ); extern void window_configure_notify( struct x11drv_win_data *data, unsigned long serial, const RECT *rect );
+extern void set_net_active_window( HWND hwnd, HWND previous ); extern void net_active_window_notify( unsigned long serial, Window window, Time time ); extern void net_supported_init( struct x11drv_thread_data *data ); +extern BOOL is_netwm_supported( Atom atom );
extern Window init_clip_window(void); extern void update_user_time( Time time );