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

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jul 2 07:18:08 CDT 2015


Module: wine
Branch: master
Commit: 3d8353fe182f3e7742cd7dab3420635e45ace129
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3d8353fe182f3e7742cd7dab3420635e45ace129

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Wed Jul  1 13:43:48 2015 -0500

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.

---

 dlls/winex11.drv/event.c  | 35 +++----------------------
 dlls/winex11.drv/window.c | 67 ++++++++++++++++++++++++++++++++++++++---------
 dlls/winex11.drv/x11drv.h |  1 +
 3 files changed, 59 insertions(+), 44 deletions(-)

diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index a1abfe7..ee30259 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -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))
             {
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 69f6446..50c3290 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -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
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 213f610..cb4b0bb 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -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;




More information about the wine-cvs mailing list