Author: jimtabor
Date: Mon Aug 22 13:28:02 2016
New Revision: 72429
URL:
http://svn.reactos.org/svn/reactos?rev=72429&view=rev
Log:
[NtUser]
- Defer the changing of the window region while setting the window position.
- Patch based on Stefano Toncich work. See CORE-6897 and possibly CORE-7229.
Modified:
trunk/reactos/win32ss/user/ntuser/winpos.c
Modified: trunk/reactos/win32ss/user/ntuser/winpos.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/winpos…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/winpos.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/winpos.c [iso-8859-1] Mon Aug 22 13:28:02 2016
@@ -31,6 +31,40 @@
VOID FASTCALL IntLinkWindow(PWND Wnd,PWND WndInsertAfter);
/* FUNCTIONS *****************************************************************/
+
+#if DBG
+/***********************************************************************
+ * dump_winpos_flags
+ */
+static void dump_winpos_flags(UINT flags)
+{
+ static const DWORD dumped_flags = (SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
SWP_NOREDRAW |
+ SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_SHOWWINDOW
|
+ SWP_HIDEWINDOW | SWP_NOCOPYBITS |
SWP_NOOWNERZORDER |
+ SWP_NOSENDCHANGING | SWP_DEFERERASE |
SWP_ASYNCWINDOWPOS |
+ SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE |
SWP_STATECHANGED);
+ TRACE("flags:");
+ if(flags & SWP_NOSIZE) TRACE(" SWP_NOSIZE");
+ if(flags & SWP_NOMOVE) TRACE(" SWP_NOMOVE");
+ if(flags & SWP_NOZORDER) TRACE(" SWP_NOZORDER");
+ if(flags & SWP_NOREDRAW) TRACE(" SWP_NOREDRAW");
+ if(flags & SWP_NOACTIVATE) TRACE(" SWP_NOACTIVATE");
+ if(flags & SWP_FRAMECHANGED) TRACE(" SWP_FRAMECHANGED");
+ if(flags & SWP_SHOWWINDOW) TRACE(" SWP_SHOWWINDOW");
+ if(flags & SWP_HIDEWINDOW) TRACE(" SWP_HIDEWINDOW");
+ if(flags & SWP_NOCOPYBITS) TRACE(" SWP_NOCOPYBITS");
+ if(flags & SWP_NOOWNERZORDER) TRACE(" SWP_NOOWNERZORDER");
+ if(flags & SWP_NOSENDCHANGING) TRACE(" SWP_NOSENDCHANGING");
+ if(flags & SWP_DEFERERASE) TRACE(" SWP_DEFERERASE");
+ if(flags & SWP_ASYNCWINDOWPOS) TRACE(" SWP_ASYNCWINDOWPOS");
+ if(flags & SWP_NOCLIENTSIZE) TRACE(" SWP_NOCLIENTSIZE");
+ if(flags & SWP_NOCLIENTMOVE) TRACE(" SWP_NOCLIENTMOVE");
+ if(flags & SWP_STATECHANGED) TRACE(" SWP_STATECHANGED");
+
+ if(flags & ~dumped_flags) TRACE(" %08x", flags & ~dumped_flags);
+ TRACE("\n");
+}
+#endif
BOOL FASTCALL
IntGetClientOrigin(PWND Window OPTIONAL, LPPOINT Point)
@@ -218,6 +252,30 @@
return pWnd;
}
return NULL;
+}
+
+VOID
+SelectWindowRgn( PWND Window, HRGN hRgnClip)
+{
+ if (Window->hrgnClip)
+ {
+ /* Delete no longer needed region handle */
+ IntGdiSetRegionOwner(Window->hrgnClip, GDI_OBJ_HMGR_POWNED);
+ GreDeleteObject(Window->hrgnClip);
+ Window->hrgnClip = NULL;
+ }
+
+ if (hRgnClip > HRGN_WINDOW)
+ {
+ /*if (Window != UserGetDesktopWindow()) // Window->fnid != FNID_DESKTOP)
+ {
+ NtGdiOffsetRgn(hRgnClip, Window->rcWindow.left, Window->rcWindow.top);
+ }*/
+ /* Set public ownership */
+ IntGdiSetRegionOwner(hRgnClip, GDI_OBJ_HMGR_PUBLIC);
+
+ Window->hrgnClip = hRgnClip;
+ }
}
//
@@ -1758,10 +1816,16 @@
HDC Dc;
RECTL CopyRect;
PWND Ancestor;
- BOOL bPointerInWindow;
+ BOOL bPointerInWindow, PosChanged = FALSE;
//PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
ASSERT_REFS_CO(Window);
+
+ TRACE("pwnd %p, after %p, %d,%d (%dx%d), flags %s",
+ Window, WndInsertAfter, x, y, cx, cy, flags);
+#if DBG
+ dump_winpos_flags(flags);
+#endif
/* FIXME: Get current active window from active queue. Why? since r2915. */
@@ -1862,6 +1926,13 @@
}
}
+ //// HACK 3
+ if (Window->hrgnNewFrame)
+ {
+ SelectWindowRgn( Window, Window->hrgnNewFrame ); // Should be
PSMWP->acvr->hrgnClip
+ Window->hrgnNewFrame = NULL;
+ }
+
WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect,
&NewClientRect, valid_rects);
// ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src
: %d %d %d %d\n", WvrFlags,
@@ -1884,6 +1955,7 @@
WinPosInternalMoveWindow(Window,
NewClientRect.left - OldClientRect.left,
NewClientRect.top - OldClientRect.top);
+ PosChanged = TRUE;
}
Window->rcWindow = NewWindowRect;
@@ -1951,11 +2023,12 @@
* class need to be completely repainted on (horizontal/vertical) size
* change.
*/
- if ( VisBefore != NULL &&
- VisAfter != NULL &&
- !(WinPos.flags & SWP_NOCOPYBITS) &&
- ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) &&
- !(Window->ExStyle & WS_EX_TRANSPARENT) )
+ if ( ( VisBefore != NULL &&
+ VisAfter != NULL &&
+ !(WinPos.flags & SWP_NOCOPYBITS) &&
+ ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) &&
+ !(Window->ExStyle & WS_EX_TRANSPARENT) ) ||
+ ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) &&
VisBefore) )
{
/*
@@ -2000,8 +2073,9 @@
REGION_Delete(CopyRgn);
CopyRgn = NULL;
}
- else if (OldWindowRect.left != NewWindowRect.left ||
- OldWindowRect.top != NewWindowRect.top)
+ else if ( OldWindowRect.left != NewWindowRect.left ||
+ OldWindowRect.top != NewWindowRect.top ||
+ (WinPos.flags & SWP_FRAMECHANGED) )
{
HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
PREGION DcRgnObj = REGION_LockRgn(DcRgn);
@@ -2041,7 +2115,19 @@
{
CopyRgn = NULL;
}
-
+#if 0
+ /////// Fixes NoPopup tests but breaks msg_paint tests.
+ if ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) &&
VisBefore)
+ {
+ PWND Parent = Window->spwndParent;
+ ERR("SWP_FRAMECHANGED no chg\n");
+ if ( !(Window->style & WS_CHILD) && (Parent) &&
(Parent->style & WS_CLIPCHILDREN))
+ {
+ ERR("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n");
+ //IntInvalidateWindows( Window, VisBefore, /*RDW_ERASE |*/ RDW_FRAME |
RDW_INVALIDATE | RDW_ALLCHILDREN);
+ }
+ }
+#endif
/* We need to redraw what wasn't visible before */
if (VisAfter != NULL)
{
@@ -3303,20 +3389,16 @@
RETURN( 0);
}
- if (Window->hrgnClip)
- {
- /* Delete no longer needed region handle */
- IntGdiSetRegionOwner(Window->hrgnClip, GDI_OBJ_HMGR_POWNED);
- GreDeleteObject(Window->hrgnClip);
- }
-
+ //// HACK 1 : Work around the lack of supporting DeferWindowPos.
if (hrgnCopy)
{
- /* Set public ownership */
- IntGdiSetRegionOwner(hrgnCopy, GDI_OBJ_HMGR_PUBLIC);
- }
- Window->hrgnClip = hrgnCopy;
-
+ Window->hrgnNewFrame = hrgnCopy; // Should be PSMWP->acvr->hrgnClip
+ }
+ else
+ {
+ Window->hrgnNewFrame = (HRGN) 1;
+ }
+ //// HACK 2
Ret = co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, bRedraw ? flags :
(flags|SWP_NOREDRAW) );
RETURN( (INT)Ret);