- 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
This commit is contained in:
James Tabor 2011-03-18 22:41:22 +00:00
parent f5912e7155
commit 115d07d686
7 changed files with 265 additions and 56 deletions

View 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);
}

View file

@ -1631,10 +1631,10 @@ NtUserEnableScrollBar(
UINT wSBflags,
UINT wArrows);
DWORD
BOOL
NTAPI
NtUserEndDeferWindowPosEx(
DWORD Unknown0,
HDWP WinPosInfo,
DWORD Unknown1);
BOOL NTAPI

View 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);

View 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
*

View file

@ -177,6 +177,7 @@ UserHandleOwnerByType(USER_OBJECT_TYPE type)
case otHook:
case otCallProc:
case otAccel:
case otSMWP:
pi = GetW32ProcessInfo();
break;

View 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) );

View 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(