Commit 3d8353fe authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

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.
parent 396dd9d1
......@@ -949,35 +949,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
*/
static void reparent_notify( Display *display, HWND hwnd, Window xparent, int x, int y )
......@@ -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))
{
......
......@@ -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
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment