winex11.drv: Track external changes to _NET_WM_STATE in net_wm_state.

In some cases, WM's will modify the _NET_WM_STATE of our own windows.
Most notably, this can happen when the WM maximizes our window, but
mutter has been known to alter the fullscreen state as well. If we
want to reconfigure our window later, we'll probably have to remove
these states, which means we need to remember that they were set.
This commit is contained in:
Vincent Povirk 2015-07-01 13:43:48 -05:00 committed by Alexandre Julliard
parent 396dd9d141
commit 3d8353fe18
3 changed files with 59 additions and 44 deletions

View File

@ -948,35 +948,6 @@ static void X11DRV_UnmapNotify( HWND hwnd, XEvent *event )
}
/***********************************************************************
* is_net_wm_state_maximized
*/
static BOOL is_net_wm_state_maximized( Display *display, struct x11drv_win_data *data )
{
Atom type, *state;
int format, ret = 0;
unsigned long i, count, remaining;
if (!data->whole_window) return FALSE;
if (!XGetWindowProperty( display, data->whole_window, x11drv_atom(_NET_WM_STATE), 0,
65536/sizeof(CARD32), False, XA_ATOM, &type, &format, &count,
&remaining, (unsigned char **)&state ))
{
if (type == XA_ATOM && format == 32)
{
for (i = 0; i < count; i++)
{
if (state[i] == x11drv_atom(_NET_WM_STATE_MAXIMIZED_VERT) ||
state[i] == x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ))
ret++;
}
}
XFree( state );
}
return (ret == 2);
}
/***********************************************************************
* reparent_notify
*/
@ -1132,7 +1103,8 @@ void X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev )
style = GetWindowLongW( data->hwnd, GWL_STYLE );
if ((style & WS_CAPTION) == WS_CAPTION)
{
if (is_net_wm_state_maximized( event->display, data ))
read_net_wm_states( event->display, data );
if ((data->net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)))
{
if (!(style & WS_MAXIMIZE))
{
@ -1267,7 +1239,8 @@ static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL updat
if (data->iconic && data->wm_state == NormalState) /* restore window */
{
data->iconic = FALSE;
if ((style & WS_CAPTION) == WS_CAPTION && is_net_wm_state_maximized( event->display, data ))
read_net_wm_states( event->display, data );
if ((style & WS_CAPTION) == WS_CAPTION && (data->net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)))
{
if ((style & WS_MAXIMIZEBOX) && !(style & WS_DISABLED))
{

View File

@ -65,6 +65,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
#define _NET_WM_STATE_ADD 1
#define _NET_WM_STATE_TOGGLE 2
static const unsigned int net_wm_state_atoms[NB_NET_WM_STATES] =
{
XATOM__NET_WM_STATE_FULLSCREEN,
XATOM__NET_WM_STATE_ABOVE,
XATOM__NET_WM_STATE_MAXIMIZED_VERT,
XATOM__NET_WM_STATE_SKIP_PAGER,
XATOM__NET_WM_STATE_SKIP_TASKBAR
};
#define SWP_AGG_NOPOSCHANGE (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER)
/* is cursor clipping active? */
@ -960,15 +969,6 @@ void update_user_time( Time time )
*/
void update_net_wm_states( struct x11drv_win_data *data )
{
static const unsigned int state_atoms[NB_NET_WM_STATES] =
{
XATOM__NET_WM_STATE_FULLSCREEN,
XATOM__NET_WM_STATE_ABOVE,
XATOM__NET_WM_STATE_MAXIMIZED_VERT,
XATOM__NET_WM_STATE_SKIP_PAGER,
XATOM__NET_WM_STATE_SKIP_TASKBAR
};
DWORD i, style, ex_style, new_state = 0;
if (!data->managed) return;
@ -1005,8 +1005,8 @@ void update_net_wm_states( struct x11drv_win_data *data )
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[state_atoms[i] - FIRST_XATOM];
if (state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT)
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);
}
XChangeProperty( data->display, data->whole_window, x11drv_atom(_NET_WM_STATE), XA_ATOM,
@ -1034,8 +1034,8 @@ void update_net_wm_states( struct x11drv_win_data *data )
(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[state_atoms[i] - FIRST_XATOM];
xev.xclient.data.l[2] = ((state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT) ?
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);
XSendEvent( data->display, root_window, False,
SubstructureRedirectMask | SubstructureNotifyMask, &xev );
@ -1044,6 +1044,47 @@ void update_net_wm_states( struct x11drv_win_data *data )
data->net_wm_state = new_state;
}
/***********************************************************************
* read_net_wm_states
*/
void read_net_wm_states( Display* display, struct x11drv_win_data *data )
{
Atom type, *state;
int format;
unsigned long i, j, count, remaining;
DWORD new_state = 0;
BOOL maximized_horz = FALSE;
if (!data->whole_window) return;
if (!XGetWindowProperty( display, data->whole_window, x11drv_atom(_NET_WM_STATE), 0,
65536/sizeof(CARD32), False, XA_ATOM, &type, &format, &count,
&remaining, (unsigned char **)&state ))
{
if (type == XA_ATOM && format == 32)
{
for (i = 0; i < count; i++)
{
if (state[i] == x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ))
maximized_horz = TRUE;
for (j=0; j < NB_NET_WM_STATES; j++)
{
if (state[i] == X11DRV_Atoms[net_wm_state_atoms[j] - FIRST_XATOM])
{
new_state |= 1 << j;
}
}
}
}
XFree( state );
}
if (!maximized_horz)
new_state &= ~(1 << NET_WM_STATE_MAXIMIZED);
data->net_wm_state = new_state;
}
/***********************************************************************
* set_xembed_flags

View File

@ -576,6 +576,7 @@ extern void destroy_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN;
extern void wait_for_withdrawn_state( HWND hwnd, BOOL set ) DECLSPEC_HIDDEN;
extern Window init_clip_window(void) DECLSPEC_HIDDEN;
extern void update_user_time( Time time ) DECLSPEC_HIDDEN;
extern void read_net_wm_states( Display *display, struct x11drv_win_data *data ) DECLSPEC_HIDDEN;
extern void update_net_wm_states( struct x11drv_win_data *data ) DECLSPEC_HIDDEN;
extern void make_window_embedded( struct x11drv_win_data *data ) DECLSPEC_HIDDEN;
extern Window create_client_window( struct x11drv_win_data *data, const XVisualInfo *visual ) DECLSPEC_HIDDEN;