[Win32k]
authorJames Tabor <james.tabor@reactos.org>
Fri, 18 Mar 2011 22:41:22 +0000 (22:41 +0000)
committerJames Tabor <james.tabor@reactos.org>
Fri, 18 Mar 2011 22:41:22 +0000 (22:41 +0000)
- Implement the set of DeferWindowPos functions. Regedit (one of many application) uses it and allocated three when it should be four. This was a good test to verify the batch list growing routine. Instead of drawing per DeferWindowPos call, now a real list is created and run down as a batch.
- ReactOS should handle this the correct way and a good test case is located here: http://bugs.winehq.org/show_bug.cgi?id=23187
- The code is from wine and modified for the use in ReactOS.

svn path=/trunk/; revision=51089

reactos/dll/win32/user32/windows/window.c
reactos/include/reactos/win32k/ntuser.h
reactos/subsystems/win32/win32k/include/winpos.h
reactos/subsystems/win32/win32k/ntuser/ntstubs.c
reactos/subsystems/win32/win32k/ntuser/object.c
reactos/subsystems/win32/win32k/ntuser/simplecall.c
reactos/subsystems/win32/win32k/ntuser/winpos.c

index 2025d81..4cc757f 100644 (file)
@@ -65,17 +65,7 @@ AllowSetForegroundWindow(DWORD dwProcessId)
 HDWP WINAPI
 BeginDeferWindowPos(int nNumWindows)
 {
-    if (nNumWindows < 0)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return 0;
-    }
-#if 0
-    UNIMPLEMENTED;
-    return (HDWP)0;
-#else
-    return (HDWP)1;
-#endif
+    return (HDWP)NtUserCallOneParam((DWORD_PTR)nNumWindows, ONEPARAM_ROUTINE_BEGINDEFERWNDPOS);
 }
 
 
@@ -567,12 +557,7 @@ DeferWindowPos(HDWP hWinPosInfo,
                int cy,
                UINT uFlags)
 {
-#if 0
     return NtUserDeferWindowPos(hWinPosInfo, hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
-#else
-    SetWindowPos(hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
-    return hWinPosInfo;
-#endif
 }
 
 
@@ -582,12 +567,7 @@ DeferWindowPos(HDWP hWinPosInfo,
 BOOL WINAPI
 EndDeferWindowPos(HDWP hWinPosInfo)
 {
-#if 0
-    UNIMPLEMENTED;
-    return FALSE;
-#else
-    return TRUE;
-#endif
+    return NtUserEndDeferWindowPosEx(hWinPosInfo, 0);
 }
 
 
index d9f28d6..484a3a4 100644 (file)
@@ -1631,10 +1631,10 @@ NtUserEnableScrollBar(
   UINT wSBflags,
   UINT wArrows);
 
-DWORD
+BOOL
 NTAPI
 NtUserEndDeferWindowPosEx(
-  DWORD Unknown0,
+  HDWP WinPosInfo,
   DWORD Unknown1);
 
 BOOL NTAPI
index 7f1c52a..a230972 100644 (file)
@@ -1,5 +1,32 @@
 #pragma once
 
+typedef struct _CVR // Tag Ussw
+{
+  WINDOWPOS   pos;
+  LONG        xClientNew;
+  LONG        yClientNew;
+  LONG        cxClientNew;
+  LONG        cyClientNew;
+  RECT        rcBlt;
+  LONG        dxBlt;
+  LONG        dyBlt;
+  UINT        fsRE;
+  HRGN        hrgnVisOld;
+  PTHREADINFO pti;
+  HRGN        hrgnClip;
+  HRGN        hrgnInterMonitor;
+} CVR, *PCVR;
+
+typedef struct _SMWP
+{
+  HEAD head;
+  UINT bShellNotify:1;
+  UINT bHandle:1;
+  INT  ccvr;
+  INT  ccvrAlloc;
+  PCVR acvr;
+} SMWP, *PSMWP;
+
 #define IntPtInWindow(WndObject,x,y) \
   ((x) >= (WndObject)->rcWindow.left && \
    (x) < (WndObject)->rcWindow.right && \
@@ -36,3 +63,5 @@ VOID FASTCALL co_WinPosActivateOtherWindow(PWND Window);
 
 VOID FASTCALL WinPosInitInternalPos(PWND WindowObject,
                                     POINT *pt, RECTL *RestoreRect);
+BOOL FASTCALL IntEndDeferWindowPosEx(HDWP);
+HDWP FASTCALL IntDeferWindowPos(HDWP,HWND,HWND,INT,INT,INT,INT,UINT);
index 7d40582..774ee67 100644 (file)
@@ -1168,18 +1168,6 @@ NtUserDrawMenuBarTemp(
    return 0;
 }
 
-/*
- * @unimplemented
- */
-DWORD APIENTRY
-NtUserEndDeferWindowPosEx(DWORD Unknown0,
-                          DWORD Unknown1)
-{
-   UNIMPLEMENTED
-
-   return 0;
-}
-
 /*
  * FillWindow: Called from User; Dialog, Edit and ListBox procs during a WM_ERASEBKGND.
  */
@@ -1205,7 +1193,7 @@ NtUserFlashWindowEx(IN PFLASHWINFO pfwi)
 {
    UNIMPLEMENTED
 
-   return 0;
+   return 1;
 }
 
 /*
@@ -1305,25 +1293,6 @@ NtUserWindowFromPhysicalPoint(POINT Point)
    return NULL;
 }
 
-/*
- * @unimplemented
- */
-HDWP APIENTRY
-NtUserDeferWindowPos(HDWP WinPosInfo,
-                     HWND Wnd,
-                     HWND WndInsertAfter,
-                     int x,
-                     int y,
-                     int cx,
-                     int cy,
-                     UINT Flags)
-{
-   UNIMPLEMENTED
-
-   return 0;
-}
-
-
 /*
  * NtUserResolveDesktopForWOW
  *
index 8376f0b..4df5c8f 100644 (file)
@@ -177,6 +177,7 @@ UserHandleOwnerByType(USER_OBJECT_TYPE type)
         case otHook:
         case otCallProc:
         case otAccel:
+        case otSMWP:
             pi = GetW32ProcessInfo();
             break;
 
index 2c4844f..1e74111 100644 (file)
@@ -157,6 +157,38 @@ NtUserCallOneParam(
                 MsqPostQuitMessage(pti->MessageQueue, Param);
                 RETURN(TRUE);
           }
+
+      case ONEPARAM_ROUTINE_BEGINDEFERWNDPOS:
+         {
+             PSMWP psmwp;
+             HDWP hDwp = NULL;
+             if (Param < 0)
+             {
+                EngSetLastError(ERROR_INVALID_PARAMETER);
+                RETURN(0);
+             }
+             /* Windows allows zero count, in which case it allocates context for 8 moves */
+             if (Param == 0) Param = 8;
+
+             psmwp = (PSMWP) UserCreateObject( gHandleTable,
+                                               NULL,
+                                              (PHANDLE)&hDwp,
+                                               otSMWP,
+                                               sizeof(SMWP));
+             if (!psmwp) RETURN(0);
+             psmwp->acvr = ExAllocatePoolWithTag(PagedPool, Param * sizeof(CVR), USERTAG_SWP);
+             if (!psmwp->acvr)
+             {
+                UserDeleteObject(hDwp, otSMWP);
+                RETURN(0);
+             }
+             RtlZeroMemory(psmwp->acvr, Param * sizeof(CVR));
+             psmwp->bHandle = TRUE;
+             psmwp->ccvr = 0;          // actualCount
+             psmwp->ccvrAlloc = Param; // suggestedCount             
+             RETURN((DWORD_PTR)hDwp);
+         }
+
       case ONEPARAM_ROUTINE_SHOWCURSOR:
          RETURN( (DWORD_PTR)UserShowCursor((BOOL)Param) );
 
index 6a9dfd2..0d6b268 100644 (file)
@@ -1673,6 +1673,204 @@ co_WinPosWindowFromPoint(PWND ScopeWin, POINT *WinPoint, USHORT* HitTest)
    return Window;
 }
 
+HDWP
+FASTCALL
+IntDeferWindowPos( HDWP hdwp,
+                   HWND hwnd,
+                   HWND hwndAfter,
+                   INT x,
+                   INT y,
+                   INT cx,
+                   INT cy,
+                   UINT flags )
+{
+    PSMWP pDWP;
+    int i;
+    HDWP retvalue = hdwp;
+
+    DPRINT("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
+          hdwp, hwnd, hwndAfter, x, y, cx, cy, flags);
+
+    if (flags & ~(SWP_NOSIZE | SWP_NOMOVE |
+                  SWP_NOZORDER | SWP_NOREDRAW |
+                  SWP_NOACTIVATE | SWP_NOCOPYBITS |
+                  SWP_NOOWNERZORDER|SWP_SHOWWINDOW |
+                  SWP_HIDEWINDOW | SWP_FRAMECHANGED))
+    {
+       EngSetLastError(ERROR_INVALID_PARAMETER);
+       return NULL;    
+    }
+
+    if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, otSMWP)))
+    {
+       EngSetLastError(ERROR_INVALID_DWP_HANDLE);
+       return NULL;
+    }
+
+    for (i = 0; i < pDWP->ccvr; i++)
+    {
+        if (pDWP->acvr[i].pos.hwnd == hwnd)
+        {
+              /* Merge with the other changes */
+            if (!(flags & SWP_NOZORDER))
+            {
+                pDWP->acvr[i].pos.hwndInsertAfter = hwndAfter;
+            }
+            if (!(flags & SWP_NOMOVE))
+            {
+                pDWP->acvr[i].pos.x = x;
+                pDWP->acvr[i].pos.y = y;
+            }
+            if (!(flags & SWP_NOSIZE))
+            {
+                pDWP->acvr[i].pos.cx = cx;
+                pDWP->acvr[i].pos.cy = cy;
+            }
+            pDWP->acvr[i].pos.flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
+                                               SWP_NOZORDER | SWP_NOREDRAW |
+                                               SWP_NOACTIVATE | SWP_NOCOPYBITS|
+                                               SWP_NOOWNERZORDER);
+            pDWP->acvr[i].pos.flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
+                                              SWP_FRAMECHANGED);
+            goto END;
+        }
+    }
+    if (pDWP->ccvr >= pDWP->ccvrAlloc)
+    {
+        PCVR newpos = ExAllocatePoolWithTag(PagedPool, pDWP->ccvrAlloc * 2 * sizeof(CVR), USERTAG_SWP);
+        if (!newpos)
+        {
+            retvalue = NULL;
+            goto END;
+        }
+        RtlZeroMemory(newpos, pDWP->ccvrAlloc * 2 * sizeof(CVR));
+        RtlCopyMemory(newpos, pDWP->acvr, pDWP->ccvrAlloc * sizeof(CVR));
+        ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP);
+        pDWP->ccvrAlloc *= 2;
+        pDWP->acvr = newpos;
+    }
+    pDWP->acvr[pDWP->ccvr].pos.hwnd = hwnd;
+    pDWP->acvr[pDWP->ccvr].pos.hwndInsertAfter = hwndAfter;
+    pDWP->acvr[pDWP->ccvr].pos.x = x;
+    pDWP->acvr[pDWP->ccvr].pos.y = y;
+    pDWP->acvr[pDWP->ccvr].pos.cx = cx;
+    pDWP->acvr[pDWP->ccvr].pos.cy = cy;
+    pDWP->acvr[pDWP->ccvr].pos.flags = flags;
+    pDWP->acvr[pDWP->ccvr].hrgnClip = NULL; 
+    pDWP->acvr[pDWP->ccvr].hrgnInterMonitor = NULL;
+    pDWP->ccvr++;
+END:
+    return retvalue;
+}
+
+BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp )
+{
+    PSMWP pDWP;
+    PCVR winpos;
+    BOOL res = TRUE;
+    int i;
+
+    DPRINT("%p\n", hdwp);
+
+    if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, otSMWP)))
+    {
+       EngSetLastError(ERROR_INVALID_DWP_HANDLE);
+       return FALSE;
+    }
+
+    for (i = 0, winpos = pDWP->acvr; res && i < pDWP->ccvr; i++, winpos++)
+    {
+        DPRINT("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
+               winpos->pos.hwnd, winpos->pos.hwndInsertAfter, winpos->pos.x, winpos->pos.y,
+               winpos->pos.cx, winpos->pos.cy, winpos->pos.flags);
+
+        res = co_WinPosSetWindowPos( UserGetWindowObject(winpos->pos.hwnd),
+                                     winpos->pos.hwndInsertAfter,
+                                     winpos->pos.x,
+                                     winpos->pos.y,
+                                     winpos->pos.cx,
+                                     winpos->pos.cy,
+                                     winpos->pos.flags);
+    }
+    ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP);
+    UserDeleteObject(hdwp, otSMWP);
+    return res;
+}
+
+/*
+ * @implemented
+ */
+BOOL APIENTRY
+NtUserEndDeferWindowPosEx(HDWP WinPosInfo,
+                          DWORD Unknown1)
+{
+   BOOL Ret;
+   DPRINT("Enter NtUserEndDeferWindowPosEx\n");
+   UserEnterExclusive();
+   Ret = IntEndDeferWindowPosEx(WinPosInfo);
+   DPRINT("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret);
+   UserLeave();
+   return Ret;
+}
+
+/*
+ * @implemented
+ */
+HDWP APIENTRY
+NtUserDeferWindowPos(HDWP WinPosInfo,
+                     HWND Wnd,
+                     HWND WndInsertAfter,
+                     int x,
+                     int y,
+                     int cx,
+                     int cy,
+                     UINT Flags)
+{
+   PWND pWnd, pWndIA;
+   HDWP Ret = NULL;
+   UINT Tmp = ~(SWP_ASYNCWINDOWPOS|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_NOREPOSITION|
+                SWP_NOCOPYBITS|SWP_HIDEWINDOW|SWP_SHOWWINDOW|SWP_FRAMECHANGED|
+                SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE);
+
+   DPRINT("Enter NtUsereferWindowPos\n");
+   UserEnterExclusive();
+
+   if ( Flags & Tmp )
+   {
+      EngSetLastError(ERROR_INVALID_FLAGS);
+      goto Exit;
+   }
+
+   pWnd = UserGetWindowObject(Wnd);
+   if ( !pWnd ||
+         pWnd == IntGetDesktopWindow() ||
+         pWnd == IntGetMessageWindow() )
+   {
+      goto Exit;
+   }
+
+   if ( WndInsertAfter &&
+        WndInsertAfter != HWND_BOTTOM &&
+        WndInsertAfter != HWND_TOPMOST && 
+        WndInsertAfter != HWND_NOTOPMOST )
+   {
+      pWndIA = UserGetWindowObject(WndInsertAfter);
+      if ( !pWndIA ||
+            pWndIA == IntGetDesktopWindow() ||
+            pWndIA == IntGetMessageWindow() )
+      {
+         goto Exit;
+      }
+   }
+
+   Ret = IntDeferWindowPos(WinPosInfo, Wnd, WndInsertAfter, x, y, cx, cy, Flags);
+
+Exit:
+   DPRINT("Leave NtUserDeferWindowPos, ret=%i\n", Ret);
+   UserLeave();
+   return Ret;   
+}
+
 BOOL
 APIENTRY
 NtUserGetMinMaxInfo(