From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 12 ++++++++++ dlls/winex11.drv/window.c | 49 ++++++++++++++++++++++++++++++++++----- dlls/winex11.drv/x11drv.h | 3 +++ 3 files changed, 58 insertions(+), 6 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index dc7030ea04a..de9d9e21abf 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1307,6 +1307,17 @@ static void handle_xembed_info_notify( HWND hwnd, XPropertyEvent *event ) release_win_data( data ); }
+static void handle_net_wm_state_notify( HWND hwnd, XPropertyEvent *event ) +{ + struct x11drv_win_data *data; + UINT value = 0; + + if (!(data = get_win_data( hwnd ))) return; + if (event->state == PropertyNewValue) value = get_window_net_wm_state( event->display, event->window ); + window_net_wm_state_notify( data, event->serial, value ); + release_win_data( data ); +} + /*********************************************************************** * X11DRV_PropertyNotify */ @@ -1317,6 +1328,7 @@ static BOOL X11DRV_PropertyNotify( HWND hwnd, XEvent *xev ) if (!hwnd) return FALSE; if (event->atom == x11drv_atom(WM_STATE)) handle_wm_state_notify( hwnd, event, TRUE ); 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 ); return TRUE; }
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 7e5495df391..c6c44bcb59a 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1222,12 +1222,15 @@ static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_stat for (i = count = 0; i < NB_NET_WM_STATES; i++) { if (!(new_state & (1 << i))) continue; - TRACE( "setting wm state %u for unmapped window %p/%lx\n", - i, data->hwnd, data->whole_window ); atoms[count++] = X11DRV_Atoms[net_wm_state_atoms[i] - FIRST_XATOM]; if (net_wm_state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT) atoms[count++] = x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ); } + + data->pending_state.net_wm_state = new_state; + data->net_wm_state_serial = NextRequest( data->display ); + TRACE( "window %p/%lx, requesting _NET_WM_STATE %#x serial %lu\n", data->hwnd, data->whole_window, + data->pending_state.net_wm_state, data->net_wm_state_serial ); XChangeProperty( data->display, data->whole_window, x11drv_atom(_NET_WM_STATE), XA_ATOM, 32, PropModeReplace, (unsigned char *)atoms, count ); } @@ -1247,14 +1250,15 @@ static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_stat
for (i = 0; i < NB_NET_WM_STATES; i++) { - TRACE( "setting wm state %u for window %p/%lx to %u prev %u\n", - i, data->hwnd, data->whole_window, - (new_state & (1 << i)) != 0, (data->net_wm_state & (1 << i)) != 0 ); - xev.xclient.data.l[0] = (new_state & (1 << i)) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; xev.xclient.data.l[1] = X11DRV_Atoms[net_wm_state_atoms[i] - FIRST_XATOM]; xev.xclient.data.l[2] = ((net_wm_state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT) ? x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ) : 0); + + data->pending_state.net_wm_state = new_state; + data->net_wm_state_serial = NextRequest( data->display ); + TRACE( "window %p/%lx, requesting _NET_WM_STATE %#x serial %lu\n", data->hwnd, data->whole_window, + data->pending_state.net_wm_state, data->net_wm_state_serial ); XSendEvent( data->display, root_window, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev ); } @@ -1478,6 +1482,38 @@ void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, *expect_serial = 0; }
+void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ) +{ + UINT *pending = &data->pending_state.net_wm_state, *current = &data->current_state.net_wm_state; + unsigned long *expect_serial = &data->net_wm_state_serial; + const char *reason = NULL, *expected, *received; + + received = wine_dbg_sprintf( "_NET_WM_STATE %#x/%lu", value, serial ); + expected = *expect_serial ? wine_dbg_sprintf( ", expected %#x/%lu", *pending, *expect_serial ) : ""; + + if (serial < *expect_serial) reason = "old "; + else if (!*expect_serial && *current == value) reason = "no-op "; + + if (reason) + { + WARN( "Ignoring window %p/%lx %s%s%s\n", data->hwnd, data->whole_window, reason, received, expected ); + return; + } + + if (!*expect_serial) reason = "unexpected "; + else if (*pending != value) reason = "mismatch "; + + if (!reason) TRACE( "window %p/%lx, %s%s\n", data->hwnd, data->whole_window, received, expected ); + else + { + WARN( "window %p/%lx, %s%s%s\n", data->hwnd, data->whole_window, reason, received, expected ); + *pending = value; /* avoid requesting the same state again */ + } + + *current = value; + *expect_serial = 0; +} + /*********************************************************************** * make_window_embedded */ @@ -1934,6 +1970,7 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des memset( &data->pending_state, 0, sizeof(data->pending_state) ); memset( &data->current_state, 0, sizeof(data->current_state) ); data->wm_state_serial = 0; + data->net_wm_state_serial = 0;
if (data->xic) { diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 53fb5cc30e1..05c8115d2e3 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -605,6 +605,7 @@ enum x11drv_net_wm_state struct window_state { UINT wm_state; + UINT net_wm_state; };
/* x11drv private window data */ @@ -643,6 +644,7 @@ struct x11drv_win_data struct window_state pending_state; /* window state tracking the pending / requested state */ struct window_state current_state; /* window state tracking the current X11 state */ unsigned long wm_state_serial; /* serial of last pending WM_STATE request */ + unsigned long net_wm_state_serial; /* serial of last pending _NET_WM_STATE request */ };
extern struct x11drv_win_data *get_win_data( HWND hwnd ); @@ -657,6 +659,7 @@ extern void destroy_gl_drawable( HWND hwnd ); extern void destroy_vk_surface( HWND hwnd );
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 wait_for_withdrawn_state( HWND hwnd, BOOL set ); extern Window init_clip_window(void); extern void update_user_time( Time time );