[PATCH 4/4 - try2] user32: Factorization of graphics drivers' SetWindowPos

Pierre d'Herbemont pdherbemont at free.fr
Wed Jan 24 08:01:51 CST 2007


---
  dlls/user32/driver.c       |    6 +-
  dlls/user32/user_private.h |    2 +-
  dlls/user32/winpos.c       |   76 ++++++++++++++++++-
  dlls/winex11.drv/window.c  |    8 +-
  dlls/winex11.drv/winpos.c  |  184 
+++++++++++++++++++++++++-------------------
  dlls/winex11.drv/x11drv.h  |    4 +-
  6 files changed, 191 insertions(+), 89 deletions(-)
-------------- next part --------------
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c
index 90f7a40..0f64eb3 100644
--- a/dlls/user32/driver.c
+++ b/dlls/user32/driver.c
@@ -382,7 +382,7 @@ static void nulldrv_SetParent( HWND hwnd
 }
 
 static BOOL nulldrv_SetWindowPos( HWND hwnd, HWND insert_after, const RECT *rectWindow,
-                                  const RECT *rectClient, UINT swp_flags, const RECT *valid_rects )
+                                  const RECT *rectClient, UINT swp_flags, DWORD new_style )
 {
     return FALSE;
 }
@@ -713,9 +713,9 @@ static void loaderdrv_SetParent( HWND hw
 }
 
 static BOOL loaderdrv_SetWindowPos( HWND hwnd, HWND insert_after, const RECT *rectWindow,
-                                    const RECT *rectClient, UINT swp_flags, const RECT *valid_rects )
+                                    const RECT *rectClient, UINT swp_flags, DWORD new_style )
 {
-    return load_driver()->pSetWindowPos( hwnd, insert_after, rectWindow, rectClient, swp_flags, valid_rects );
+    return load_driver()->pSetWindowPos( hwnd, insert_after, rectWindow, rectClient, swp_flags, new_style );
 }
 
 static int loaderdrv_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index 6522dde..eeb4b27 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -151,7 +151,7 @@ typedef struct tagUSER_DRIVER {
     BOOL   (*pScrollDC)(HDC, INT, INT, const RECT *, const RECT *, HRGN, LPRECT);
     void   (*pSetFocus)(HWND);
     void   (*pSetParent)(HWND,HWND,HWND);
-    BOOL   (*pSetWindowPos)(HWND,HWND,const RECT *,const RECT *,UINT,const RECT *);
+    BOOL   (*pSetWindowPos)(HWND,HWND,const RECT *,const RECT *,UINT,DWORD);
     int    (*pSetWindowRgn)(HWND,HRGN,BOOL);
     void   (*pSetWindowIcon)(HWND,UINT,HICON);
     void   (*pSetWindowStyle)(HWND,DWORD);
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index 46f9a26..a262ec1 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -1546,6 +1546,80 @@ static BOOL fixup_flags( WINDOWPOS *winp
 }
 
 /***********************************************************************
+ *		WINPOS_SetWindowPos
+ *
+ *     User32 internal function
+ */
+BOOL WINPOS_SetWindowPos( HWND hwnd, HWND insert_after, const RECT *rectWindow,
+                                   const RECT *rectClient, UINT swp_flags, const RECT *valid_rects )
+{
+    RECT new_whole_rect;
+    WND *win;
+    DWORD new_style;
+    BOOL ret;
+
+    new_whole_rect = *rectWindow;
+    ret = USER_Driver->pGetVisibleRect( hwnd, &new_whole_rect );
+
+    if (!(win = WIN_GetPtr( hwnd ))) return FALSE;
+    if (win == WND_OTHER_PROCESS)
+    {
+        if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
+        return FALSE;
+    }
+
+    if (!IsRectEmpty( &valid_rects[0] ))
+    {
+        int x_offset = 0, y_offset = 0;
+
+        if (ret)
+        {
+            /* the graphics driver will move the bits for us */
+            x_offset = win->rectWindow.left - rectWindow->left;
+            y_offset = win->rectWindow.top - rectWindow->top;
+        }
+
+        if (x_offset != valid_rects[1].left - valid_rects[0].left ||
+            y_offset != valid_rects[1].top - valid_rects[0].top)
+        {
+            /* FIXME: should copy the window bits here */
+            valid_rects = NULL;
+        }
+    }
+
+    SERVER_START_REQ( set_window_pos )
+    {
+        req->handle        = hwnd;
+        req->previous      = insert_after;
+        req->flags         = swp_flags;
+        req->window.left   = rectWindow->left;
+        req->window.top    = rectWindow->top;
+        req->window.right  = rectWindow->right;
+        req->window.bottom = rectWindow->bottom;
+        req->client.left   = rectClient->left;
+        req->client.top    = rectClient->top;
+        req->client.right  = rectClient->right;
+        req->client.bottom = rectClient->bottom;
+        if (memcmp( rectWindow, &new_whole_rect, sizeof(RECT) ) || !IsRectEmpty( &valid_rects[0] ))
+        {
+            wine_server_add_data( req, &new_whole_rect, sizeof(new_whole_rect) );
+            if (!IsRectEmpty( &valid_rects[0] ))
+                wine_server_add_data( req, valid_rects, 2 * sizeof(*valid_rects) );
+        }
+        ret = !wine_server_call( req );
+        new_style = reply->new_style;
+    }
+    SERVER_END_REQ;
+
+    WIN_ReleasePtr( win );
+
+    if (!ret)
+        return ret;
+
+    return USER_Driver->pSetWindowPos(hwnd, insert_after, rectWindow, rectClient, swp_flags, new_style);
+}
+
+/***********************************************************************
  *		USER_SetWindowPos
  *
  *     User32 internal function
@@ -1588,7 +1662,7 @@ BOOL USER_SetWindowPos( WINDOWPOS * winp
 
     SWP_DoNCCalcSize( winpos, &newWindowRect, &newClientRect, valid_rects );
 
-    if(!USER_Driver->pSetWindowPos( winpos->hwnd, winpos->hwndInsertAfter, 
+    if(!WINPOS_SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter, 
                             &newWindowRect, &newClientRect, orig_flags, valid_rects ))
         return FALSE;
 
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index e9fc4f0..7494285 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -973,7 +973,7 @@ static void get_desktop_xwin( Display *d
         SetPropA( data->hwnd, whole_window_prop, (HANDLE)root_window );
         SetPropA( data->hwnd, visual_id_prop, (HANDLE)visualid );
         data->whole_window = root_window;
-        X11DRV_SetWindowPos( data->hwnd, 0, &virtual_screen_rect, &virtual_screen_rect,
+        X11DRV_WINPOS_SetWindowPos( data->hwnd, 0, &virtual_screen_rect, &virtual_screen_rect,
                                SWP_NOZORDER, NULL );
         if (root_window != DefaultRootWindow( display ))
         {
@@ -1039,7 +1039,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CRE
 
     /* initialize the dimensions before sending WM_GETMINMAXINFO */
     SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
-    X11DRV_SetWindowPos( hwnd, 0, &rect, &rect, SWP_NOZORDER, NULL );
+    X11DRV_WINPOS_SetWindowPos( hwnd, 0, &rect, &rect, SWP_NOZORDER, NULL );
 
     /* create an X window if it's a top level window */
     if (GetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow())
@@ -1083,7 +1083,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CRE
         if (cs->cy < 0) cs->cy = 0;
 
         SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
-        if (!X11DRV_SetWindowPos( hwnd, 0, &rect, &rect, SWP_NOZORDER, NULL )) return FALSE;
+        if (!X11DRV_WINPOS_SetWindowPos( hwnd, 0, &rect, &rect, SWP_NOZORDER, NULL )) return FALSE;
     }
 
     /* send WM_NCCREATE */
@@ -1111,7 +1111,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CRE
     /* yes, even if the CBT hook was called with HWND_TOP */
     insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
 
-    X11DRV_SetWindowPos( hwnd, insert_after, &wndPtr->rectWindow, &rect, 0, NULL );
+    X11DRV_WINPOS_SetWindowPos( hwnd, insert_after, &wndPtr->rectWindow, &rect, 0, NULL );
 
     TRACE( "win %p window %d,%d,%d,%d client %d,%d,%d,%d whole %d,%d,%d,%d X client %d,%d,%d,%d xwin %x\n",
            hwnd, wndPtr->rectWindow.left, wndPtr->rectWindow.top,
diff --git a/dlls/winex11.drv/winpos.c b/dlls/winex11.drv/winpos.c
index ab4f8af..a39438b 100644
--- a/dlls/winex11.drv/winpos.c
+++ b/dlls/winex11.drv/winpos.c
@@ -255,15 +255,17 @@ BOOL X11DRV_GetVisibleRect( HWND hwnd, R
 }
 
 /***********************************************************************
- *		SetWindowPos   (X11DRV.@)
+ *		X11DRV_WINPOS_SetWindowPos
+ *
+ *  FIXME: Temporary function that will disappear as soon as CreateWindow
+ *  will be properly factorized into user32
  */
-BOOL X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, const RECT *rectWindow,
+BOOL X11DRV_WINPOS_SetWindowPos( HWND hwnd, HWND insert_after, const RECT *rectWindow,
                                    const RECT *rectClient, UINT swp_flags, const RECT *valid_rects )
 {
-    struct x11drv_win_data *data;
-    RECT new_whole_rect, old_client_rect, old_screen_rect;
+    RECT new_whole_rect;
     WND *win;
-    DWORD old_style, new_style;
+    DWORD new_style;
     BOOL ret;
 
     new_whole_rect = *rectWindow;
@@ -319,105 +321,129 @@ BOOL X11DRV_SetWindowPos( HWND hwnd, HWN
     }
     SERVER_END_REQ;
 
-    if (!(data = X11DRV_get_win_data( hwnd ))) return FALSE;
+    WIN_ReleasePtr( win );
+
+    if (!ret)
+        return ret;
+
+    return X11DRV_SetWindowPos(hwnd, insert_after, rectWindow, rectClient, swp_flags, new_style);
+}
 
-    old_client_rect = data->client_rect;
+/***********************************************************************
+ *		SetWindowPos   (X11DRV.@)
+ */
+BOOL X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, const RECT *rectWindow,
+                                   const RECT *rectClient, UINT swp_flags, DWORD new_style )
+{
+    RECT new_whole_rect, old_client_rect, old_screen_rect;
+    Display *display = thread_display();
+    struct x11drv_win_data *data;
+    DWORD old_style;
+    WND *win;
 
-    if (win == WND_DESKTOP || data->whole_window == DefaultRootWindow(gdi_display))
+    if (!(win = WIN_GetPtr( hwnd ))) return FALSE;
+    if (win == WND_OTHER_PROCESS)
     {
-        data->whole_rect = data->client_rect = data->window_rect = *rectWindow;
-        if (win != WND_DESKTOP)
-        {
-            win->rectWindow   = *rectWindow;
-            win->rectClient   = *rectClient;
-            win->dwStyle      = new_style;
-            WIN_ReleasePtr( win );
-        }
-        return ret;
+        if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %p\n", hwnd );
+        return FALSE;
     }
 
-    if (ret)
-    {
-        Display *display = thread_display();
+    /* invalidate DCEs */
 
-        /* invalidate DCEs */
+    if ((((swp_flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && (new_style & WS_VISIBLE)) ||
+         (swp_flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)))
+    {
+        RECT rect;
+        UnionRect( &rect, rectWindow, &win->rectWindow );
+        invalidate_dce( hwnd, &rect );
+    }
 
-        if ((((swp_flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) && (new_style & WS_VISIBLE)) ||
-             (swp_flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)))
-        {
-            RECT rect;
-            UnionRect( &rect, rectWindow, &win->rectWindow );
-            invalidate_dce( hwnd, &rect );
-        }
+    old_style = win->dwStyle;
 
+    if (win != WND_DESKTOP)
+    {
         win->rectWindow   = *rectWindow;
         win->rectClient   = *rectClient;
-        old_style         = win->dwStyle;
         win->dwStyle      = new_style;
-        data->window_rect = *rectWindow;
+    }
 
-        TRACE( "win %p window %s client %s style %08x\n",
-               hwnd, wine_dbgstr_rect(rectWindow), wine_dbgstr_rect(rectClient), new_style );
+    if (!(data = X11DRV_get_win_data( hwnd ))) return FALSE;
 
-        /* FIXME: copy the valid bits */
+    if (hwnd == GetDesktopWindow() || data->whole_window == DefaultRootWindow(gdi_display))
+    {
+        data->whole_rect = data->client_rect = data->window_rect = *rectWindow;
+        WIN_ReleasePtr( win );
+        return TRUE;
+    }
+
+    new_whole_rect = *rectWindow;
+    X11DRV_window_to_X_rect( data, &new_whole_rect );
+
+    old_client_rect   = data->client_rect;
 
-        if (data->whole_window && !data->lock_changes)
+    data->window_rect = *rectWindow;
+
+    TRACE( "win %p window %s client %s style %08x\n",
+           hwnd, wine_dbgstr_rect(rectWindow), wine_dbgstr_rect(rectClient), new_style );
+
+    /* FIXME: copy the valid bits */
+
+    if (data->whole_window && !data->lock_changes)
+    {
+        if ((old_style & WS_VISIBLE) && !(new_style & WS_VISIBLE))
+        {
+            /* window got hidden, unmap it */
+            TRACE( "unmapping win %p\n", hwnd );
+            wine_tsx11_lock();
+            XUnmapWindow( display, data->whole_window );
+            wine_tsx11_unlock();
+        }
+        else if ((new_style & WS_VISIBLE) && !X11DRV_is_window_rect_mapped( rectWindow ))
         {
-            if ((old_style & WS_VISIBLE) && !(new_style & WS_VISIBLE))
+            /* resizing to zero size or off screen -> unmap */
+            TRACE( "unmapping zero size or off-screen win %p\n", hwnd );
+            wine_tsx11_lock();
+            XUnmapWindow( display, data->whole_window );
+            wine_tsx11_unlock();
+        }
+    }
+
+    X11DRV_sync_window_position( display, data, swp_flags, rectClient, &new_whole_rect );
+
+    if (data->whole_window && !data->lock_changes)
+    {
+        BOOL new_fs_state, mapped = FALSE;
+
+        if ((new_style & WS_VISIBLE) && !(new_style & WS_MINIMIZE) &&
+            X11DRV_is_window_rect_mapped( rectWindow ))
+        {
+            if (!(old_style & WS_VISIBLE))
             {
-                /* window got hidden, unmap it */
-                TRACE( "unmapping win %p\n", hwnd );
+                /* window got shown, map it */
+                TRACE( "mapping win %p\n", hwnd );
+                X11DRV_sync_window_style( display, data );
+                X11DRV_set_wm_hints( display, data );
                 wine_tsx11_lock();
-                XUnmapWindow( display, data->whole_window );
+                XMapWindow( display, data->whole_window );
                 wine_tsx11_unlock();
+                mapped = TRUE;
             }
-            else if ((new_style & WS_VISIBLE) && !X11DRV_is_window_rect_mapped( rectWindow ))
+            else if ((swp_flags & (SWP_NOSIZE | SWP_NOMOVE)) != (SWP_NOSIZE | SWP_NOMOVE))
             {
-                /* resizing to zero size or off screen -> unmap */
-                TRACE( "unmapping zero size or off-screen win %p\n", hwnd );
+                /* resizing from zero size to non-zero -> map */
+                TRACE( "mapping non zero size or off-screen win %p\n", hwnd );
                 wine_tsx11_lock();
-                XUnmapWindow( display, data->whole_window );
+                XMapWindow( display, data->whole_window );
                 wine_tsx11_unlock();
+                mapped = TRUE;
             }
-        }
-
-        X11DRV_sync_window_position( display, data, swp_flags, rectClient, &new_whole_rect );
-
-        if (data->whole_window && !data->lock_changes)
-        {
-            BOOL new_fs_state, mapped = FALSE;
-
-            if ((new_style & WS_VISIBLE) && !(new_style & WS_MINIMIZE) &&
-                X11DRV_is_window_rect_mapped( rectWindow ))
-            {
-                if (!(old_style & WS_VISIBLE))
-                {
-                    /* window got shown, map it */
-                    TRACE( "mapping win %p\n", hwnd );
-                    X11DRV_sync_window_style( display, data );
-                    X11DRV_set_wm_hints( display, data );
-                    wine_tsx11_lock();
-                    XMapWindow( display, data->whole_window );
-                    wine_tsx11_unlock();
-                    mapped = TRUE;
-                }
-                else if ((swp_flags & (SWP_NOSIZE | SWP_NOMOVE)) != (SWP_NOSIZE | SWP_NOMOVE))
-                {
-                    /* resizing from zero size to non-zero -> map */
-                    TRACE( "mapping non zero size or off-screen win %p\n", hwnd );
-                    wine_tsx11_lock();
-                    XMapWindow( display, data->whole_window );
-                    wine_tsx11_unlock();
-                    mapped = TRUE;
-                }
-                SetRect( &old_screen_rect, 0, 0, screen_width, screen_height );
-                if (fullscreen_state_changed( data, &old_client_rect, &old_screen_rect, &new_fs_state ) || mapped)
-                    update_fullscreen_state( display, data->whole_window, new_fs_state );
-            }
+            SetRect( &old_screen_rect, 0, 0, screen_width, screen_height );
+            if (fullscreen_state_changed( data, &old_client_rect, &old_screen_rect, &new_fs_state ) || mapped)
+                update_fullscreen_state( display, data->whole_window, new_fs_state );
         }
     }
     WIN_ReleasePtr( win );
-    return ret;
+    return TRUE;
 }
 
 
@@ -881,7 +907,7 @@ void X11DRV_handle_desktop_resize( unsig
     xinerama_init();
     TRACE("desktop %p change to (%dx%d)\n", hwnd, width, height);
     data->lock_changes++;
-    X11DRV_SetWindowPos( hwnd, 0, &virtual_screen_rect, &virtual_screen_rect,
+    X11DRV_WINPOS_SetWindowPos( hwnd, 0, &virtual_screen_rect, &virtual_screen_rect,
                            SWP_NOZORDER|SWP_NOMOVE, NULL );
     data->lock_changes--;
     ClipCursor(NULL);
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index dc1d955..4697199 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -685,8 +685,10 @@ extern void X11DRV_sync_window_style( Di
 extern void X11DRV_sync_window_position( Display *display, struct x11drv_win_data *data,
                                          UINT swp_flags, const RECT *new_client_rect,
                                          const RECT *new_whole_rect );
+extern BOOL X11DRV_WINPOS_SetWindowPos( HWND hwnd, HWND insert_after, const RECT *rectWindow,
+                                   const RECT *rectClient, UINT swp_flags, const RECT *valid_rects );
 extern BOOL X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, const RECT *rectWindow,
-                                   const RECT *rectClient, UINT swp_flags, const RECT *validRects );
+                                   const RECT *rectClient, UINT swp_flags, DWORD new_style );
 extern void X11DRV_set_wm_hints( Display *display, struct x11drv_win_data *data );
 extern void xinerama_init(void);
 


More information about the wine-patches mailing list