From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 9 +++++ dlls/winex11.drv/window.c | 69 +++++++++++++++++++++++++++++++++- dlls/winex11.drv/x11drv.h | 16 +++++++- dlls/winex11.drv/x11drv_main.c | 2 + 4 files changed, 92 insertions(+), 4 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index b1797cea24a..91a0230107a 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1262,6 +1262,14 @@ static void handle_net_supported_notify( XPropertyEvent *event ) if (event->state == PropertyNewValue) net_supported_init( data ); }
+static void handle_net_active_window( XPropertyEvent *event ) +{ + Window window = 0; + + if (event->state == PropertyNewValue) window = get_net_active_window( event->display ); + net_active_window_notify( event->serial, window, event->time ); +} + /*********************************************************************** * X11DRV_PropertyNotify */ @@ -1274,6 +1282,7 @@ static BOOL X11DRV_PropertyNotify( HWND hwnd, XEvent *xev ) if (event->atom == x11drv_atom(_XEMBED_INFO)) handle_xembed_info_notify( hwnd, event ); if (event->atom == x11drv_atom(_NET_WM_STATE)) handle_net_wm_state_notify( hwnd, event ); if (event->atom == x11drv_atom(_NET_SUPPORTED)) handle_net_supported_notify( event ); + if (event->atom == x11drv_atom(_NET_ACTIVE_WINDOW)) handle_net_active_window( event );
return TRUE; } diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 43e1caac0d3..947d440113f 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -250,7 +250,6 @@ void host_window_set_parent( struct host_window *win, Window parent ) host_window_reparent( &win->parent, parent, win->window ); }
- /*********************************************************************** * http://standards.freedesktop.org/startup-notification-spec */ @@ -316,7 +315,7 @@ static BOOL is_managed( HWND hwnd ) return ret; }
-HWND *build_hwnd_list(void) +static HWND *build_hwnd_list(void) { NTSTATUS status; HWND *list; @@ -351,6 +350,28 @@ static BOOL has_owned_popups( HWND hwnd ) return ret; }
+/* returns the HWND for the X11 window, or the desktop window if it isn't a Wine window */ +static HWND hwnd_from_window( Display *display, Window window ) +{ + HWND hwnd, desktop = NtUserGetDesktopWindow(); + HWND *list; + UINT i; + + if (!window) return 0; + if (window == root_window) return desktop; + if (!XFindContext( display, window, winContext, (char **)&hwnd )) return hwnd; + + if (!(list = build_hwnd_list())) return desktop; + + for (i = 0; list[i] != HWND_BOTTOM; i++) + if (window == X11DRV_get_whole_window( list[i] )) + break; + hwnd = list[i] == HWND_BOTTOM ? desktop : list[i]; + + free( list ); + + return hwnd; +}
/*********************************************************************** * alloc_win_data @@ -1750,6 +1771,50 @@ void window_configure_notify( struct x11drv_win_data *data, unsigned long serial current, expected, prefix, received, NULL ); }
+void net_active_window_notify( unsigned long serial, Window value, Time time ) +{ + struct x11drv_thread_data *data = x11drv_thread_data(); + Window *desired = &data->desired_state.net_active_window, *pending = &data->pending_state.net_active_window, *current = &data->current_state.net_active_window; + unsigned long *expect_serial = &data->net_active_window_serial; + const char *expected, *received; + HWND current_hwnd, pending_hwnd; + + current_hwnd = hwnd_from_window( data->display, value ); + pending_hwnd = hwnd_from_window( data->display, *pending ); + + received = wine_dbg_sprintf( "_NET_ACTIVE_WINDOW %p/%lx serial %lu time %lu", current_hwnd, value, serial, time ); + expected = *expect_serial ? wine_dbg_sprintf( ", expected %p/%lx serial %lu", pending_hwnd, *pending, *expect_serial ) : ""; + handle_state_change( serial, expect_serial, sizeof(value), &value, desired, pending, + current, expected, "", received, NULL ); +} + +Window get_net_active_window( Display *display ) +{ + unsigned long count, remaining; + Window window = None, *value; + int format; + Atom type; + + if (!XGetWindowProperty( display, DefaultRootWindow( display ), x11drv_atom(_NET_ACTIVE_WINDOW), 0, + 65536 / sizeof(Window), False, XA_WINDOW, &type, &format, &count, + &remaining, (unsigned char **)&value )) + { + if (type == XA_WINDOW && format == 32) window = *value; + XFree( value ); + } + + return window; +} + +void net_active_window_init( struct x11drv_thread_data *data ) +{ + Window window = get_net_active_window( data->display ); + + data->desired_state.net_active_window = window; + data->pending_state.net_active_window = window; + data->current_state.net_active_window = window; +} + BOOL window_has_pending_wm_state( HWND hwnd, UINT state ) { struct x11drv_win_data *data; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index a5bab864ad9..51e57c41bec 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -381,6 +381,11 @@ extern RECT host_window_configure_child( struct host_window *win, Window window, extern POINT host_window_map_point( struct host_window *win, int x, int y ); extern struct host_window *get_host_window( Window window, BOOL create );
+struct display_state +{ + Window net_active_window; +}; + struct x11drv_thread_data { Display *display; @@ -403,6 +408,11 @@ struct x11drv_thread_data XIValuatorClassInfo y_valuator; int xinput2_pointer; /* XInput2 master pointer device id */ #endif /* HAVE_X11_EXTENSIONS_XINPUT2_H */ + + struct display_state desired_state; /* display state tracking the desired / win32 state */ + struct display_state pending_state; /* display state tracking the pending / requested state */ + struct display_state current_state; /* display state tracking the current X11 state */ + unsigned long net_active_window_serial; /* serial of last pending _NET_ACTIVE_WINDOW request */ };
extern struct x11drv_thread_data *x11drv_init_thread_data(void); @@ -485,6 +495,7 @@ enum x11drv_atoms XATOM__ICC_PROFILE, XATOM__KDE_NET_WM_STATE_SKIP_SWITCHER, XATOM__MOTIF_WM_HINTS, + XATOM__NET_ACTIVE_WINDOW, XATOM__NET_STARTUP_INFO_BEGIN, XATOM__NET_STARTUP_INFO, XATOM__NET_SUPPORTED, @@ -666,8 +677,10 @@ 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_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 );
+extern Window get_net_active_window( Display *display ); +extern void net_active_window_notify( unsigned long serial, Window window, Time time ); +extern void net_active_window_init( struct x11drv_thread_data *data ); extern void net_supported_init( struct x11drv_thread_data *data );
extern Window init_clip_window(void); @@ -706,7 +719,6 @@ extern void ungrab_clipping_window(void); extern void move_resize_window( HWND hwnd, int dir, POINT pos ); extern void X11DRV_InitKeyboard( Display *display ); extern BOOL X11DRV_ProcessEvents( DWORD mask ); -extern HWND *build_hwnd_list(void);
typedef int (*x11drv_error_callback)( Display *display, XErrorEvent *event, void *arg );
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index e58d3afca63..e27202eb2bf 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -126,6 +126,7 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] = "_ICC_PROFILE", "_KDE_NET_WM_STATE_SKIP_SWITCHER", "_MOTIF_WM_HINTS", + "_NET_ACTIVE_WINDOW", "_NET_STARTUP_INFO_BEGIN", "_NET_STARTUP_INFO", "_NET_SUPPORTED", @@ -755,6 +756,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) if (use_xim) xim_thread_attach( data ); x11drv_xinput2_init( data ); net_supported_init( data ); + net_active_window_init( data );
return data; }