From: Rémi Bernon rbernon@codeweavers.com
Setting a __wine_x11_focus_time window property to indicate the time of the last NormalState, -1 if the window is temporarily unmapping itself, or 0 if the window is not in a NormalState. --- dlls/winex11.drv/event.c | 6 +++--- dlls/winex11.drv/window.c | 13 ++++++++++++- dlls/winex11.drv/x11drv.h | 3 ++- 3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index ec714d144fb..3a57e3ea256 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -757,7 +757,7 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event ) { HWND last_focus = x11drv_thread_data()->last_focus, foreground = NtUserGetForegroundWindow();
- if (window_has_pending_wm_state( hwnd, -1 )) + if (window_has_pending_wm_state( hwnd, -1 ) || (hwnd != foreground && !window_should_take_focus( foreground, event_time ))) { WARN( "Ignoring window %p/%lx WM_TAKE_FOCUS serial %lu, event_time %ld, foreground %p during WM_STATE change\n", hwnd, event->window, event->serial, event_time, foreground ); @@ -1231,7 +1231,7 @@ static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event )
if (!(data = get_win_data( hwnd ))) return; if (event->state == PropertyNewValue) value = get_window_wm_state( event->display, event->window ); - window_wm_state_notify( data, event->serial, value ); + window_wm_state_notify( data, event->serial, value, event->time ); release_win_data( data );
NtUserPostMessage( hwnd, WM_WINE_WINDOW_STATE_CHANGED, 0, 0 ); @@ -1244,7 +1244,7 @@ static void handle_xembed_info_notify( HWND hwnd, XPropertyEvent *event )
if (!(data = get_win_data( hwnd ))) return; if (event->state == PropertyNewValue) value = get_window_xembed_info( event->display, event->window ); - window_wm_state_notify( data, event->serial, value ? NormalState : WithdrawnState ); + window_wm_state_notify( data, event->serial, value ? NormalState : WithdrawnState, event->time ); release_win_data( data ); }
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 0d90707eb1c..fca59bc0680 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -108,6 +108,8 @@ static const WCHAR whole_window_prop[] = {'_','_','w','i','n','e','_','x','1','1','_','w','h','o','l','e','_','w','i','n','d','o','w',0}; static const WCHAR clip_window_prop[] = {'_','_','w','i','n','e','_','x','1','1','_','c','l','i','p','_','w','i','n','d','o','w',0}; +static const WCHAR focus_time_prop[] = + {'_','_','w','i','n','e','_','x','1','1','_','f','o','c','u','s','_','t','i','m','e',0};
static pthread_mutex_t win_data_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -1609,7 +1611,7 @@ BOOL X11DRV_GetWindowStateUpdates( HWND hwnd, UINT *state_cmd, UINT *config_cmd, return *state_cmd || *config_cmd; }
-void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ) +void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value, Time time ) { UINT *desired = &data->desired_state.wm_state, *pending = &data->pending_state.wm_state, *current = &data->current_state.wm_state; unsigned long *expect_serial = &data->wm_state_serial; @@ -1646,6 +1648,9 @@ void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, window_set_wm_state( data, data->desired_state.wm_state ); window_set_net_wm_state( data, data->desired_state.net_wm_state ); window_set_config( data, &data->desired_state.rect, FALSE ); + + if (data->current_state.wm_state == NormalState) NtUserSetProp( data->hwnd, focus_time_prop, (HANDLE)time ); + else if (!data->wm_state_serial) NtUserRemoveProp( data->hwnd, focus_time_prop ); }
void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ) @@ -1730,6 +1735,12 @@ BOOL window_has_pending_wm_state( HWND hwnd, UINT state ) return pending; }
+BOOL window_should_take_focus( HWND hwnd, Time time ) +{ + Time focus_time = (UINT_PTR)NtUserGetProp( hwnd, focus_time_prop ); + return !focus_time || (int)(focus_time - time) < 0; +} + /*********************************************************************** * make_window_embedded */ diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 0f4e33dd9c0..9cd471d547a 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -661,8 +661,9 @@ extern void set_gl_drawable_parent( HWND hwnd, HWND parent ); extern void destroy_gl_drawable( HWND hwnd ); extern void destroy_vk_surface( HWND hwnd );
+extern BOOL window_should_take_focus( HWND hwnd, Time time ); extern BOOL window_has_pending_wm_state( HWND hwnd, UINT state ); -extern void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ); +extern void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value, Time time ); 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 BOOL get_window_state_updates( HWND hwnd, UINT *state_cmd, UINT *config_cmd, RECT *rect );