Author: jimtabor Date: Fri Mar 18 22:41:22 2011 New Revision: 51089
URL: http://svn.reactos.org/svn/reactos?rev=51089&view=rev Log: [Win32k] - 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.
Modified: trunk/reactos/dll/win32/user32/windows/window.c trunk/reactos/include/reactos/win32k/ntuser.h trunk/reactos/subsystems/win32/win32k/include/winpos.h trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c trunk/reactos/subsystems/win32/win32k/ntuser/object.c trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c
Modified: trunk/reactos/dll/win32/user32/windows/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/wi... ============================================================================== --- trunk/reactos/dll/win32/user32/windows/window.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/user32/windows/window.c [iso-8859-1] Fri Mar 18 22:41:22 2011 @@ -65,17 +65,7 @@ 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 @@ 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 @@ BOOL WINAPI EndDeferWindowPos(HDWP hWinPosInfo) { -#if 0 - UNIMPLEMENTED; - return FALSE; -#else - return TRUE; -#endif + return NtUserEndDeferWindowPosEx(hWinPosInfo, 0); }
Modified: trunk/reactos/include/reactos/win32k/ntuser.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/win32k/ntus... ============================================================================== --- trunk/reactos/include/reactos/win32k/ntuser.h [iso-8859-1] (original) +++ trunk/reactos/include/reactos/win32k/ntuser.h [iso-8859-1] Fri Mar 18 22:41:22 2011 @@ -1631,10 +1631,10 @@ UINT wSBflags, UINT wArrows);
-DWORD +BOOL NTAPI NtUserEndDeferWindowPosEx( - DWORD Unknown0, + HDWP WinPosInfo, DWORD Unknown1);
BOOL NTAPI
Modified: trunk/reactos/subsystems/win32/win32k/include/winpos.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/winpos.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/winpos.h [iso-8859-1] Fri Mar 18 22:41:22 2011 @@ -1,4 +1,31 @@ #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 && \ @@ -36,3 +63,5 @@
VOID FASTCALL WinPosInitInternalPos(PWND WindowObject, POINT *pt, RECTL *RestoreRect); +BOOL FASTCALL IntEndDeferWindowPosEx(HDWP); +HDWP FASTCALL IntDeferWindowPos(HDWP,HWND,HWND,INT,INT,INT,INT,UINT);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c [iso-8859-1] Fri Mar 18 22:41:22 2011 @@ -1169,18 +1169,6 @@ }
/* - * @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 @@ { UNIMPLEMENTED
- return 0; + return 1; }
/* @@ -1306,25 +1294,6 @@ }
/* - * @unimplemented - */ -HDWP APIENTRY -NtUserDeferWindowPos(HDWP WinPosInfo, - HWND Wnd, - HWND WndInsertAfter, - int x, - int y, - int cx, - int cy, - UINT Flags) -{ - UNIMPLEMENTED - - return 0; -} - - -/* * NtUserResolveDesktopForWOW * * Status
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/object.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/object.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/object.c [iso-8859-1] Fri Mar 18 22:41:22 2011 @@ -177,6 +177,7 @@ case otHook: case otCallProc: case otAccel: + case otSMWP: pi = GetW32ProcessInfo(); break;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/simplecall.c [iso-8859-1] Fri Mar 18 22:41:22 2011 @@ -157,6 +157,38 @@ 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) );
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c [iso-8859-1] Fri Mar 18 22:41:22 2011 @@ -1673,6 +1673,204 @@ 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(