small range fixes for OSS driver
[wine] / windows / winpos.c
index 99399c0..d714cb4 100644 (file)
@@ -5,8 +5,6 @@
  *                       1995, 1996, 1999 Alex Korobka
  */
 
-#include "x11drv.h"
-
 #include <string.h>
 #include "sysmetrics.h"
 #include "heap.h"
@@ -26,6 +24,8 @@
 #include "local.h"
 #include "ldt.h"
 
+DEFAULT_DEBUG_CHANNEL(win)
+
 #define HAS_DLGFRAME(style,exStyle) \
     (((exStyle) & WS_EX_DLGMODALFRAME) || \
      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
 #define SWP_EX_NOCOPY          0x0001
 #define SWP_EX_PAINTSELF       0x0002
 
+#define MINMAX_NOSWP           0x00010000
+
 /* ----- internal variables ----- */
 
 static HWND hwndPrevActive  = 0;  /* Previously active window */
 static HWND hGlobalShellWindow=0; /*the shell*/
+static HWND hGlobalTaskmanWindow=0;
+static HWND hGlobalProgmanWindow=0;
 
 static LPCSTR atomInternalPos;
 
@@ -1140,16 +1144,20 @@ void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
  * This function assumes that 'cmd' is different from the current window
  * state.
  */
-UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
+UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
 {
-    UINT16 swpFlags = 0;
+    UINT swpFlags = 0;
     POINT pt;
-    POINT size = { wndPtr->rectWindow.left, wndPtr->rectWindow.top };
-    LPINTERNALPOS lpPos = WINPOS_InitInternalPos( wndPtr, size,
-                                                  &wndPtr->rectWindow );
+    POINT size;
+    LPINTERNALPOS lpPos;
 
     TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
 
+    size.x = wndPtr->rectWindow.left;
+    size.y = wndPtr->rectWindow.top;
+
+    lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
+
     if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
     {
        if( wndPtr->dwStyle & WS_MINIMIZE )
@@ -1170,6 +1178,10 @@ UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
                     wndPtr->flags &= ~WIN_RESTORE_MAX;
                 wndPtr->dwStyle |= WS_MINIMIZE;
 
+                if( wndPtr->flags & WIN_NATIVE )
+                    if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
+                        swpFlags |= MINMAX_NOSWP;
+
                 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
 
                 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
@@ -1184,6 +1196,10 @@ UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
 
                 if( wndPtr->dwStyle & WS_MINIMIZE )
                 {
+                    if( wndPtr->flags & WIN_NATIVE )
+                        if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
+                            swpFlags |= MINMAX_NOSWP;
+
                     WINPOS_ShowIconTitle( wndPtr, FALSE );
                     wndPtr->dwStyle &= ~WS_MINIMIZE;
                 }
@@ -1196,8 +1212,13 @@ UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
            case SW_RESTORE:
                 if( wndPtr->dwStyle & WS_MINIMIZE )
                 {
+                    if( wndPtr->flags & WIN_NATIVE )
+                        if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
+                            swpFlags |= MINMAX_NOSWP;
+
                     wndPtr->dwStyle &= ~WS_MINIMIZE;
                     WINPOS_ShowIconTitle( wndPtr, FALSE );
+
                     if( wndPtr->flags & WIN_RESTORE_MAX)
                     {
                         /* Restore to maximized position */
@@ -1255,7 +1276,7 @@ BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
     WND*       wndPtr = WIN_FindWndPtr( hwnd );
     BOOL       wasVisible, showFlag;
     RECT16     newPos = {0, 0, 0, 0};
-    int        swp = 0;
+    UINT       swp = 0;
 
     if (!wndPtr) return FALSE;
 
@@ -1337,8 +1358,9 @@ BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
     {
         /* We can't activate a child window */
         if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
-        SetWindowPos( hwnd, HWND_TOP, 
-                       newPos.left, newPos.top, newPos.right, newPos.bottom, swp );
+       if (!(swp & MINMAX_NOSWP))
+           SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top, 
+                                         newPos.right, newPos.bottom, LOWORD(swp) );
         if (!IsWindow( hwnd )) goto END;
        else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
     }
@@ -1524,12 +1546,19 @@ BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
 {
     if( pwpl32 )
     {
-       WINDOWPLACEMENT16 wpl = { sizeof(WINDOWPLACEMENT16), 
-               pwpl32->flags, pwpl32->showCmd, { pwpl32->ptMinPosition.x,
-               pwpl32->ptMinPosition.y }, { pwpl32->ptMaxPosition.x,
-               pwpl32->ptMaxPosition.y }, { pwpl32->rcNormalPosition.left,
-               pwpl32->rcNormalPosition.top, pwpl32->rcNormalPosition.right,
-               pwpl32->rcNormalPosition.bottom } };
+       WINDOWPLACEMENT16 wpl;
+
+       wpl.length = sizeof(WINDOWPLACEMENT16);
+       wpl.flags = pwpl32->flags;
+       wpl.showCmd = pwpl32->showCmd;
+       wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
+       wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
+       wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
+       wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
+       wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
+       wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
+       wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
+       wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
 
         return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
     }
@@ -1612,8 +1641,8 @@ BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
     HQUEUE16 hOldActiveQueue, hNewActiveQueue;
     MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
     WORD     wIconized = 0;
-    HWND   hwndActive = 0;
-    BOOL   bRet = 0;
+    HWND     hwndActive = 0;
+    BOOL     bRet = 0;
 
     /* Get current active window from the active queue */
     if ( hActiveQueue )
@@ -1624,7 +1653,8 @@ BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
     }
 
     /* paranoid checks */
-    if( hWnd == GetDesktopWindow() || hWnd == hwndActive ) goto CLEANUP;
+    if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
+       goto CLEANUP_END;
 
 /*  if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
  *     return 0;
@@ -1643,20 +1673,12 @@ BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
     /* call CBT hook chain */
     if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
     {
-        LRESULT wRet;
         cbtStruct->fMouse     = fMouse;
         cbtStruct->hWndActive = hwndActive;
-        wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
-                                 (LPARAM)SEGPTR_GET(cbtStruct) );
+        bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
+                                     (LPARAM)SEGPTR_GET(cbtStruct) );
         SEGPTR_FREE(cbtStruct);
-        if (wRet)
-        {
-            /* Unlock the active queue before returning */
-            if ( pOldActiveQueue )
-                QUEUE_Unlock( pOldActiveQueue );
-            WIN_ReleaseWndPtr(wndPtr);
-            return wRet;
-        }
+        if (bRet) goto CLEANUP_END;
     }
 
     /* set prev active wnd to current active wnd and send notification */
@@ -1666,29 +1688,26 @@ BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
         
         if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
         {
-           if (GetSysModalWindow16() != hWnd) goto CLEANUP;
+           if (GetSysModalWindow16() != hWnd) 
+               goto CLEANUP_END;
            /* disregard refusal if hWnd is sysmodal */
         }
 
-#if 1
        SendMessageA( hwndPrevActive, WM_ACTIVATE,
                         MAKEWPARAM( WA_INACTIVE, wIconized ),
                         (LPARAM)hWnd );
-#else
-       /* FIXME: must be SendMessage16() because A doesn't do
-        * intertask at this time */
-       SendMessage16( hwndPrevActive, WM_ACTIVATE, WA_INACTIVE,
-                               MAKELPARAM( (HWND16)hWnd, wIconized ) );
-#endif
 
         /* check if something happened during message processing
          * (global active queue may have changed)
          */
         pTempActiveQueue = QUEUE_Lock( hActiveQueue );
+        if(!pTempActiveQueue)
+            goto CLEANUP_END;
+
         hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
         QUEUE_Unlock( pTempActiveQueue );
         if( hwndPrevActive != hwndActive )
-            goto CLEANUP;
+            goto CLEANUP_END;
     }
 
     /* Set new active window in the message queue */
@@ -1724,7 +1743,8 @@ BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
        if( wndTemp != wndPtr )
            SetWindowPos(hWnd, HWND_TOP, 0,0,0,0, 
                           SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
-        if (!IsWindow(hWnd))  goto CLEANUP;
+        if (!IsWindow(hWnd))  
+           goto CLEANUP;
     }
 
     /* Get a handle to the new active queue */
@@ -1782,15 +1802,9 @@ BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
         wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
         WIN_ReleaseWndPtr(wndTemp);
         SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
-#if 1
         SendMessageA( hWnd, WM_ACTIVATE,
                 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
                 (LPARAM)hwndPrevActive );
-#else
-        SendMessage16(hWnd, WM_ACTIVATE, (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE,
-                      MAKELPARAM( (HWND16)hwndPrevActive, wIconized) );
-#endif
-
         if( !IsWindow(hWnd) ) goto CLEANUP;
     }
 
@@ -1809,17 +1823,20 @@ BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
     /* if active wnd is minimized redraw icon title */
     if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
 
-    bRet = 1;  // Success
+    bRet = (hWnd == hwndActive);  /* Success? */
     
-CLEANUP:
+CLEANUP: /* Unlock the message queues before returning */
 
-    /* Unlock the message queues before returning */
-    if ( pOldActiveQueue )
-        QUEUE_Unlock( pOldActiveQueue );
     if ( pNewActiveQueue )
         QUEUE_Unlock( pNewActiveQueue );
+
+CLEANUP_END:
+
+    if ( pOldActiveQueue )
+        QUEUE_Unlock( pOldActiveQueue );
+
     WIN_ReleaseWndPtr(wndPtr);
-    return bRet ? (hWnd == hwndActive) : 0;
+    return bRet;
 }
 
 /*******************************************************************
@@ -1856,6 +1873,7 @@ BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
   {
       WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
 
+      WIN_ReleaseWndPtr(pWndTo);
       pWndTo = WIN_FindWndPtr(hwndPrevActive);
 
       while( !WINPOS_CanActivate(pWndTo) ) 
@@ -2233,35 +2251,70 @@ nocopy:
 
 /***********************************************************************
  *           SWP_DoSimpleFrameChanged
+ *
+ * NOTE: old and new client rect origins are identical, only
+ *      extents may have changed. Window extents are the same.
  */
-static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pNewClientRect, RECT* pOldClientRect )
+static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
 {
-    WORD wErase = 0;
+    INT         i = 0;
     RECT rect;
+    HRGN hrgn = 0;
 
-    if( pNewClientRect->right > pOldClientRect->right ) /* redraw exposed client area on the right */
+    if( !(swpFlags & SWP_NOCLIENTSIZE) )
     {
-       rect.top = 0; rect.bottom = pNewClientRect->bottom - pNewClientRect->top;
-       rect.left = pOldClientRect->right - pNewClientRect->left;
-       rect.right = pNewClientRect->right - pNewClientRect->left;
-       wErase = 1;
-       PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | 
-                           RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME );
-     }
-     if( pNewClientRect->bottom > pOldClientRect->bottom ) /* redraw exposed client area on the bottom */
-     {
-       rect.left = 0; rect.right = ((wErase)? pOldClientRect->right : pNewClientRect->right) - pNewClientRect->left;
-       rect.top = pOldClientRect->bottom - pNewClientRect->top;
-       rect.bottom = pNewClientRect->bottom - pNewClientRect->top;
-        wErase = 1;
-        PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | 
-                           RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME );
-     }
-     if( !wErase ) /* IMMEDIATELY update the nonclient area */
-     {
-       HRGN h;
-        if( (h = WIN_UpdateNCRgn(wndPtr, TRUE, TRUE)) > 1) DeleteObject( h );
-     }
+       /* FIXME: WVR alignment flags */
+
+       if( wndPtr->rectClient.right >  pOldClientRect->right ) /* right edge */
+       {
+           i++;
+           rect.top = 0; 
+           rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
+           rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
+           if(!(uFlags & SWP_EX_NOCOPY))
+               rect.left = pOldClientRect->right - wndPtr->rectClient.left;
+           else
+           {
+               rect.left = 0;
+               goto redraw;
+           }
+       }
+
+       if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
+       {
+           if( i )
+               hrgn = CreateRectRgnIndirect( &rect );
+           rect.left = 0;
+           rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
+           rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
+           if(!(uFlags & SWP_EX_NOCOPY))
+               rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
+           else
+               rect.top = 0;
+           if( i++ ) 
+               REGION_UnionRectWithRgn( hrgn, &rect );
+       }
+
+       if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
+       {
+           rect = wndPtr->rectWindow;
+           OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
+                              wndPtr->rectWindow.top - wndPtr->rectClient.top );
+           i++;
+       }
+    }
+
+    if( i )
+    {
+redraw:
+       PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
+                           RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
+    }
+    else
+       hrgn = WIN_UpdateNCRgn(wndPtr, TRUE, TRUE);
+
+    if( hrgn > 1 )
+       DeleteObject( hrgn );
 }
 
 /***********************************************************************
@@ -2484,12 +2537,17 @@ Pos:  /* -----------------------------------------------------------------------
 
     /* Common operations */
 
-    SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
+    wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
 
     if(!(winpos.flags & SWP_NOZORDER))
     {
-        WIN_UnlinkWindow( winpos.hwnd );
-        WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
+       /* upon window creation (while processing WM_NCCREATE), wndPtr->parent is set correctly
+       *       but wndPtr is not yet in wndPtr->parent->child list
+       * in those cases (SetWindowPos called while processing WM_NCCREATE),
+       *       do not unlink/link winPtr in parent->child
+       */
+       if ( WIN_UnlinkWindow( winpos.hwnd ) )
+         WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
     }
 
     /* Reset active DCEs */
@@ -2507,6 +2565,23 @@ Pos:  /* -----------------------------------------------------------------------
     oldWindowRect = wndPtr->rectWindow;
     oldClientRect = wndPtr->rectClient;
 
+    /* Find out if we have to redraw the whole client rect */
+
+    if( oldClientRect.bottom - oldClientRect.top ==
+        newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
+
+    if( oldClientRect.right - oldClientRect.left ==
+        newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
+
+    uFlags |=  ((winpos.flags & SWP_NOCOPYBITS) ||
+                (!(winpos.flags & SWP_NOCLIENTSIZE) && 
+                 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS))) ? SWP_EX_NOCOPY : 0;
+
+    /* FIXME: actually do something with WVR_VALIDRECTS */
+
+    wndPtr->rectWindow = newWindowRect;
+    wndPtr->rectClient = newClientRect;
+
     if (wndPtr->flags & WIN_NATIVE)    /* -------------------------------------------- hosted window */
     {
        BOOL bCallDriver = TRUE;
@@ -2514,9 +2589,6 @@ Pos:  /* -----------------------------------------------------------------------
 
         winpos.hwndInsertAfter = hwndInsertAfter;
 
-        wndPtr->rectWindow = newWindowRect;
-        wndPtr->rectClient = newClientRect;
-
        if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
         {
          /* This is the only place where we need to force repainting of the contents
@@ -2535,15 +2607,15 @@ Pos:  /* -----------------------------------------------------------------------
                    winpos.hwndInsertAfter = tempInsertAfter;
                    bCallDriver = FALSE;
 
-                   if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
-                       (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top)   )
-                       SWP_DoSimpleFrameChanged(wndPtr, &newClientRect, &oldClientRect );
+                   if( winpos.flags & SWP_NOCLIENTMOVE )
+                       SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
                    else
                    {
                        /* client area moved but window extents remained the same, copy valid bits */
 
                        visRgn = CreateRectRgn( 0, 0, x, y );
-                       uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect, &oldClientRect, SWP_EX_PAINTSELF);
+                       uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect, 
+                                                   uFlags | SWP_EX_PAINTSELF );
                    }
                }
            }
@@ -2554,9 +2626,14 @@ Pos:  /* -----------------------------------------------------------------------
          if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
          {
            if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
-               (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top)   )
+               (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
+               !(uFlags & SWP_EX_NOCOPY) )
            {
-               if( !(wndPtr->flags & WIN_MANAGED) ) /* force outer frame redraw */
+               /* The origin of the client rect didn't move so we can try to repaint
+                * only the nonclient area by setting bit gravity hint for the host window system.
+                */
+
+               if( !(wndPtr->flags & WIN_MANAGED) )
                {
                    HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
                                                     newWindowRect.bottom - newWindowRect.top);
@@ -2608,20 +2685,11 @@ Pos:  /* -----------------------------------------------------------------------
     }
     else                               /* -------------------------------------------- emulated window */
     {
-        wndPtr->rectWindow = newWindowRect;
-        wndPtr->rectClient = newClientRect;
-
-       if( oldClientRect.bottom - oldClientRect.top ==
-           newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
-
-       if( oldClientRect.right - oldClientRect.left ==
-           newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
-
            if( winpos.flags & SWP_SHOWWINDOW )
            {
                wndPtr->dwStyle |= WS_VISIBLE;
                uFlags |= SWP_EX_PAINTSELF;
-               visRgn = 1;
+               visRgn = 1; /* redraw the whole window */
            }
            else if( !(winpos.flags & SWP_NOREDRAW) )
            {
@@ -2634,16 +2702,15 @@ Pos:  /* -----------------------------------------------------------------------
                }
                else
                {
-                   uFlags |=  ((winpos.flags & SWP_NOCOPYBITS) || 
-                       (wvrFlags >= WVR_HREDRAW && wvrFlags < WVR_VALIDRECTS)) ? SWP_EX_NOCOPY : 0;
-
                    if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
                         uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect, 
                                                            &oldClientRect, uFlags);
                    else
                    {
+                       /* nothing moved, redraw frame if needed */
+                        
                        if( winpos.flags & SWP_FRAMECHANGED )
-                           SWP_DoSimpleFrameChanged( wndPtr, &newClientRect, &oldClientRect );
+                           SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
                        if( visRgn )
                        {
                            DeleteObject( visRgn );
@@ -2671,11 +2738,6 @@ Pos:  /* -----------------------------------------------------------------------
 
     /* ------------------------------------------------------------------------ FINAL */
 
-      /* Activate the window */
-
-    if (!(flags & SWP_NOACTIVATE))
-           WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
-    
     if (wndPtr->flags & WIN_NATIVE)
         EVENT_Synchronize();  /* Synchronize with the host window system */
 
@@ -2684,7 +2746,11 @@ Pos:  /* -----------------------------------------------------------------------
 
     wndTemp = WIN_GetDesktop();
 
-    /* repaint invalidated region (if any) */
+    /* repaint invalidated region (if any) 
+     *
+     * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
+     *        and force update after ChangeActiveWindow() to avoid painting frames twice.
+     */
 
     if( visRgn )
     {
@@ -2709,6 +2775,9 @@ Pos:  /* -----------------------------------------------------------------------
 
     WIN_ReleaseDesktop();
 
+    if (!(flags & SWP_NOACTIVATE))
+            WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
+
       /* And last, send the WM_WINDOWPOSCHANGED message */
 
     TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
@@ -2911,38 +2980,59 @@ void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
 {
     FIXME(win, "(%04x, %d): stub\n", parent, action);
 }
+
 /***********************************************************************
- *           GetProgmanWindow                  [USER32.289]
+ *           SetProgmanWindow                  [USER32.522]
  */
-HRESULT WINAPI GetProgmanWindow ( )
-{      FIXME(win,"stub\n");
-       return 0;
+HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
+{
+       hGlobalProgmanWindow = hwnd;
+       return hGlobalProgmanWindow;
 }
+
 /***********************************************************************
- *           GetTaskmanWindow                  [USER32.304]
+ *           GetProgmanWindow                  [USER32.289]
  */
-HRESULT WINAPI GetTaskmanWindow ( )
-{      FIXME(win,"stub\n");
-       return 0;
+HRESULT WINAPI GetProgmanWindow ( )
+{
+       return hGlobalProgmanWindow;
 }
+
 /***********************************************************************
- *           SetProgmanWindow                  [USER32.522]
+ *           SetShellWindowEx                  [USER32.531]
+ * hwndProgman =  Progman[Program Manager]
+ *                |-> SHELLDLL_DefView
+ * hwndListView = |   |-> SysListView32
+ *                |   |   |-> tooltips_class32
+ *                |   |
+ *                |   |-> SysHeader32
+ *                |   
+ *                |-> ProxyTarget
  */
-HRESULT WINAPI SetProgmanWindow ( DWORD x )
-{      FIXME(win,"0x%08lx stub\n",x);
-       return 0;
+HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
+{
+       FIXME(win,"0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
+       hGlobalShellWindow = hwndProgman;
+       return hGlobalShellWindow;
+
 }
+
 /***********************************************************************
- *           SetShellWindowEx                  [USER32.531]
+ *           SetTaskmanWindow                  [USER32.537]
+ * NOTES
+ *   hwnd = MSTaskSwWClass 
+ *          |-> SysTabControl32
  */
-HRESULT WINAPI SetShellWindowEx ( DWORD x, DWORD y )
-{      FIXME(win,"0x%08lx 0x%08lx stub\n",x,y);
-       return 0;
+HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
+{
+       hGlobalTaskmanWindow = hwnd;
+       return hGlobalTaskmanWindow;
 }
+
 /***********************************************************************
- *           SetTaskmanWindow                  [USER32.537]
+ *           GetTaskmanWindow                  [USER32.304]
  */
-HRESULT WINAPI SetTaskmanWindow ( DWORD x )
-{      FIXME(win,"0x%08lx stub\n",x);
-       return 0;
+HRESULT WINAPI GetTaskmanWindow ( )
+{      
+       return hGlobalTaskmanWindow;
 }