From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 9 +++++ dlls/winex11.drv/window.c | 68 ++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 15 +++++++- dlls/winex11.drv/x11drv_main.c | 2 + 4 files changed, 93 insertions(+), 1 deletion(-)
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 ffd08655690..ea16ff3ceae 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -250,6 +250,30 @@ void host_window_set_parent( struct host_window *win, Window parent ) host_window_reparent( &win->parent, parent, win->window ); }
+/* 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 = 0, desktop = NtUserGetDesktopWindow(); + unsigned long count, remaining; + unsigned long *xhwnd; + int format; + Atom type; + + if (!window) return 0; + if (window == root_window) return desktop; + if (!XFindContext( display, window, winContext, (char **)&hwnd )) return hwnd; + + hwnd = desktop; + X11DRV_expect_error( display, host_window_error, NULL ); + if (!XGetWindowProperty( display, window, x11drv_atom(_WINE_HWND), 0, 65536, False, XA_CARDINAL, + &type, &format, &count, &remaining, (unsigned char **)&xhwnd )) + { + if (type == XA_CARDINAL && format == 32) hwnd = ULongToHandle(*xhwnd); + XFree( xhwnd ); + } + if (X11DRV_check_error()) return desktop; + return hwnd; +}
/*********************************************************************** * http://standards.freedesktop.org/startup-notification-spec @@ -1750,6 +1774,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 7425385ce84..c83c8aadece 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, @@ -667,8 +678,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); diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 6baff60481e..fba19699f00 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", @@ -756,6 +757,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; }