From 1d878e0ba598698b17d10fa3f7faa646ff26fe41 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 19 Sep 2005 10:39:26 +0000 Subject: [PATCH] Partial clean-up of the painting functions: - Get rid of the DCX_WINDOWPAINT flag (it wasn't used anyway). - Remove the PaintPosted field from message queue, we don't need it. - Use screen cooridnates for the WindowUpdate region instead of window relative ones. - Fix the algorithm for retrieving paint messages to respect the painting order. - Remove the NCUpdateRegion field from window object and calculate it on demand. - Fix GetDCEx to take region in screen coordinates. svn path=/trunk/; revision=17931 --- reactos/subsys/win32k/include/dce.h | 2 +- reactos/subsys/win32k/include/msgqueue.h | 2 - reactos/subsys/win32k/include/window.h | 1 - reactos/subsys/win32k/ntuser/msgqueue.c | 6 - reactos/subsys/win32k/ntuser/painting.c | 474 ++++++++++++----------- reactos/subsys/win32k/ntuser/vis.c | 34 +- reactos/subsys/win32k/ntuser/windc.c | 73 +--- reactos/subsys/win32k/ntuser/winpos.c | 26 +- reactos/subsys/win32k/objects/cliprgn.c | 9 +- 9 files changed, 295 insertions(+), 332 deletions(-) diff --git a/reactos/subsys/win32k/include/dce.h b/reactos/subsys/win32k/include/dce.h index 14ec008d91a..2fa17381a7b 100644 --- a/reactos/subsys/win32k/include/dce.h +++ b/reactos/subsys/win32k/include/dce.h @@ -39,7 +39,7 @@ typedef struct tagDCE #define DCX_DCEEMPTY 0x00000800 #define DCX_DCEBUSY 0x00001000 #define DCX_DCEDIRTY 0x00002000 -#define DCX_WINDOWPAINT 0x00020000 +#define DCX_USESTYLE 0x00010000 #define DCX_KEEPCLIPRGN 0x00040000 #define DCX_NOCLIPCHILDREN 0x00080000 diff --git a/reactos/subsys/win32k/include/msgqueue.h b/reactos/subsys/win32k/include/msgqueue.h index 534d75b648a..7d20b9ae1bf 100644 --- a/reactos/subsys/win32k/include/msgqueue.h +++ b/reactos/subsys/win32k/include/msgqueue.h @@ -81,8 +81,6 @@ typedef struct _USER_MESSAGE_QUEUE ULONG LastMsgRead; /* Current window with focus (ie. receives keyboard input) for this queue. */ HWND FocusWindow; - /* True if a window needs painting. */ - BOOLEAN PaintPosted; /* Count of paints pending. */ ULONG PaintCount; /* Current active window for this queue. */ diff --git a/reactos/subsys/win32k/include/window.h b/reactos/subsys/win32k/include/window.h index 162dc1186cb..c9b01a96fed 100644 --- a/reactos/subsys/win32k/include/window.h +++ b/reactos/subsys/win32k/include/window.h @@ -60,7 +60,6 @@ typedef struct _WINDOW_OBJECT UINT IDMenu; /* Handle of region of the window to be updated. */ HANDLE UpdateRegion; - HANDLE NCUpdateRegion; /* Handle of the window region. */ HANDLE WindowRegion; /* Pointer to the owning thread's message queue. */ diff --git a/reactos/subsys/win32k/ntuser/msgqueue.c b/reactos/subsys/win32k/ntuser/msgqueue.c index f362cb130f3..d2f1806af5e 100644 --- a/reactos/subsys/win32k/ntuser/msgqueue.c +++ b/reactos/subsys/win32k/ntuser/msgqueue.c @@ -103,7 +103,6 @@ VOID FASTCALL MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue) { Queue->PaintCount++; - Queue->PaintPosted = TRUE; Queue->QueueBits |= QS_PAINT; Queue->ChangedBits |= QS_PAINT; if (Queue->WakeMask & QS_PAINT) @@ -114,10 +113,6 @@ VOID FASTCALL MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue) { Queue->PaintCount--; - if (Queue->PaintCount == 0) - { - Queue->PaintPosted = FALSE; - } } @@ -1341,7 +1336,6 @@ MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQu KeQueryTickCount(&LargeTickCount); MessageQueue->LastMsgRead = LargeTickCount.u.LowPart; MessageQueue->FocusWindow = NULL; - MessageQueue->PaintPosted = FALSE; MessageQueue->PaintCount = 0; MessageQueue->WakeMask = ~0; MessageQueue->NewMessagesHandle = NULL; diff --git a/reactos/subsys/win32k/ntuser/painting.c b/reactos/subsys/win32k/ntuser/painting.c index b489bdd42fc..51f42a273be 100644 --- a/reactos/subsys/win32k/ntuser/painting.c +++ b/reactos/subsys/win32k/ntuser/painting.c @@ -35,10 +35,52 @@ #define NDEBUG #include -#define DCX_USESTYLE 0x10000 - /* PRIVATE FUNCTIONS **********************************************************/ +/** + * @name IntIntersectWithParents + * + * Intersect window rectangle with all parent client rectangles. + * + * @param Child + * Pointer to child window to start intersecting from. + * @param WindowRect + * Pointer to rectangle that we want to intersect in screen + * coordinates on input and intersected rectangle on output (if TRUE + * is returned). + * + * @return + * If any parent is minimized or invisible or the resulting rectangle + * is empty then FALSE is returned. Otherwise TRUE is returned. + */ + +BOOL FASTCALL +IntIntersectWithParents(PWINDOW_OBJECT Child, PRECT WindowRect) +{ + PWINDOW_OBJECT ParentWindow; + + ParentWindow = Child->Parent; + while (ParentWindow != NULL) + { + if (!(ParentWindow->Style & WS_VISIBLE) || + (ParentWindow->Style & WS_MINIMIZE)) + { + return FALSE; + } + + if (!IntGdiIntersectRect(WindowRect, WindowRect, &ParentWindow->ClientRect)) + { + return FALSE; + } + + /* FIXME: Layered windows. */ + + ParentWindow = ParentWindow->Parent; + } + + return TRUE; +} + VOID FASTCALL IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion) { @@ -46,30 +88,130 @@ IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion) while (ParentWindow) { - if (!(ParentWindow->Style & WS_CLIPCHILDREN)) - { - if (ParentWindow->UpdateRegion != 0) - { - INT OffsetX, OffsetY; + if (ParentWindow->Style & WS_CLIPCHILDREN) + break; - /* - * We must offset the child region by the offset of the - * child rect in the parent. - */ - OffsetX = Child->WindowRect.left - ParentWindow->WindowRect.left; - OffsetY = Child->WindowRect.top - ParentWindow->WindowRect.top; - NtGdiOffsetRgn(ValidRegion, OffsetX, OffsetY); - NtGdiCombineRgn(ParentWindow->UpdateRegion, ParentWindow->UpdateRegion, - ValidRegion, RGN_DIFF); - /* FIXME: If the resulting region is empty, remove fake posted paint message */ - NtGdiOffsetRgn(ValidRegion, -OffsetX, -OffsetY); - } + if (ParentWindow->UpdateRegion != 0) + { + NtGdiCombineRgn(ParentWindow->UpdateRegion, ParentWindow->UpdateRegion, + ValidRegion, RGN_DIFF); + /* FIXME: If the resulting region is empty, remove fake posted paint message */ } ParentWindow = ParentWindow->Parent; } } +/** + * @name IntCalcWindowRgn + * + * Get a window or client region. + */ + +HRGN FASTCALL +IntCalcWindowRgn(PWINDOW_OBJECT Window, BOOL Client) +{ + HRGN hRgnWindow; + UINT RgnType; + + if (Client) + hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect); + else + hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); + + if (Window->WindowRegion != NULL && !(Window->Style & WS_MINIMIZE)) + { + NtGdiOffsetRgn(hRgnWindow, + -Window->WindowRect.left, + -Window->WindowRect.top); + RgnType = NtGdiCombineRgn(hRgnWindow, hRgnWindow, Window->WindowRegion, RGN_AND); + NtGdiOffsetRgn(hRgnWindow, + Window->WindowRect.left, + Window->WindowRect.top); + } + + return hRgnWindow; +} + +/** + * @name IntGetNCUpdateRgn + * + * Get non-client update region of a window and optionally validate it. + * + * @param Window + * Pointer to window to get the NC update region from. + * @param Validate + * Set to TRUE to force validating the NC update region. + * + * @return + * Handle to NC update region. The caller is responsible for deleting + * it. + */ + +HRGN FASTCALL +IntGetNCUpdateRgn(PWINDOW_OBJECT Window, BOOL Validate) +{ + HRGN hRgnNonClient; + HRGN hRgnWindow; + UINT RgnType; + + if (Window->UpdateRegion != NULL && + Window->UpdateRegion != (HRGN)1) + { + hRgnNonClient = NtGdiCreateRectRgn(0, 0, 0, 0); + hRgnWindow = IntCalcWindowRgn(Window, TRUE); + + /* + * If region creation fails it's safe to fallback to whole + * window region. + */ + + if (hRgnNonClient == NULL) + { + return (HRGN)1; + } + + RgnType = NtGdiCombineRgn(hRgnNonClient, Window->UpdateRegion, + hRgnWindow, RGN_DIFF); + if (RgnType == ERROR) + { + NtGdiDeleteObject(hRgnNonClient); + return (HRGN)1; + } + else if (RgnType == NULLREGION) + { + NtGdiDeleteObject(hRgnNonClient); + return NULL; + } + + /* + * Remove the nonclient region from the standard update region if + * we were asked for it. + */ + + if (Validate) + { + if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion, + hRgnWindow, RGN_AND) == NULLREGION) + { + GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess()); + NtGdiDeleteObject(Window->UpdateRegion); + Window->UpdateRegion = NULL; + if (!(Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)) + MsqDecPaintCountQueue(Window->MessageQueue); + } + } + + NtGdiDeleteObject(hRgnWindow); + + return hRgnNonClient; + } + else + { + return Window->UpdateRegion; + } +} + /* * IntPaintWindows * @@ -85,44 +227,37 @@ co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags) if (Flags & (RDW_ERASENOW | RDW_UPDATENOW)) { - if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT) + if (Window->UpdateRegion) { - if (Window->NCUpdateRegion) - { - IntValidateParent(Window, Window->NCUpdateRegion); - } - TempRegion = Window->NCUpdateRegion; - if ((HANDLE) 1 != TempRegion && NULL != TempRegion) - { - GDIOBJ_SetOwnership(TempRegion, PsGetCurrentProcess()); - } - Window->NCUpdateRegion = NULL; - Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT; - MsqDecPaintCountQueue(Window->MessageQueue); - co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0); - if ((HANDLE) 1 != TempRegion && NULL != TempRegion) - { - /* NOTE: The region can already be deleted! */ - GDIOBJ_FreeObj(TempRegion, GDI_OBJECT_TYPE_REGION | GDI_OBJECT_TYPE_SILENT); - } + IntValidateParent(Window, Window->UpdateRegion); } - if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND) + if (Flags & RDW_UPDATENOW) { - if (Window->UpdateRegion) + if (Window->UpdateRegion != NULL || + Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT) { - /* - * This surely wrong! Why we would want to validate the parent? - * It breaks quite a few things including dummy WM_ERASEBKGND - * implementations that return only TRUE and have corresponding - * WM_PAINT that doesn't paint the whole client area. - * I left the code here so that no one will readd it again! - * - Filip - */ - /* IntValidateParent(Window, Window->UpdateRegion); */ - hDC = UserGetDCEx(Window, 0, DCX_CACHE | DCX_USESTYLE | - DCX_INTERSECTUPDATE); - if (hDC != NULL) + co_IntSendMessage(hWnd, WM_PAINT, 0, 0); + } + } + else + { + if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT) + { + TempRegion = IntGetNCUpdateRgn(Window, TRUE); + Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT; + MsqDecPaintCountQueue(Window->MessageQueue); + co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0); + if ((HANDLE) 1 != TempRegion && NULL != TempRegion) + { + /* NOTE: The region can already be deleted! */ + GDIOBJ_FreeObj(TempRegion, GDI_OBJECT_TYPE_REGION | GDI_OBJECT_TYPE_SILENT); + } + } + + if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND) + { + if (Window->UpdateRegion) { if (co_IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0)) { @@ -132,22 +267,12 @@ co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags) } } } - - if (Flags & RDW_UPDATENOW) - { - if (Window->UpdateRegion != NULL || - Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT) - { - co_IntSendMessage(hWnd, WM_PAINT, 0, 0); - } - } } /* * Check that the window is still valid at this point */ - - if (! IntIsWindow(hWnd)) + if (!IntIsWindow(hWnd)) { return; } @@ -156,7 +281,7 @@ co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags) * Paint child windows. */ if (!(Flags & RDW_NOCHILDREN) && !(Window->Style & WS_MINIMIZE) && - ((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN))) + ((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN))) { HWND *List, *phWnd; @@ -164,13 +289,11 @@ co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags) { for (phWnd = List; *phWnd; ++phWnd) { - Window = UserGetWindowObject(*phWnd); + Window = IntGetWindowObject(*phWnd); if (Window && (Window->Style & WS_VISIBLE)) { - UserRefObjectCo(Window); co_IntPaintWindows(Window, Flags); - UserDerefObjectCo(Window); - + ObmDereferenceObject(Window); } } ExFreePool(List); @@ -200,15 +323,18 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags) HRGN hRgnWindow; hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); - NtGdiOffsetRgn(hRgnWindow, - -Window->WindowRect.left, - -Window->WindowRect.top); RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnWindow, RGN_AND); NtGdiDeleteObject(hRgnWindow); } else { + NtGdiOffsetRgn(hRgn, + -Window->WindowRect.left, + -Window->WindowRect.top); RgnType = NtGdiCombineRgn(hRgn, hRgn, Window->WindowRegion, RGN_AND); + NtGdiOffsetRgn(hRgn, + Window->WindowRect.left, + Window->WindowRect.top); } /* @@ -278,60 +404,6 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags) Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT; } - /* - * Split the nonclient update region. - */ - - if (NULL != Window->UpdateRegion) - { - HRGN hRgnWindow, hRgnNonClient; - - hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect); - NtGdiOffsetRgn(hRgnWindow, - -Window->WindowRect.left, - -Window->WindowRect.top); - - hRgnNonClient = NtGdiCreateRectRgn(0, 0, 0, 0); - if (NtGdiCombineRgn(hRgnNonClient, Window->UpdateRegion, - hRgnWindow, RGN_DIFF) == NULLREGION) - { - NtGdiDeleteObject(hRgnNonClient); - hRgnNonClient = NULL; - } - else - { - GDIOBJ_SetOwnership(hRgnNonClient, NULL); - } - - /* - * Remove the nonclient region from the standard update region. - */ - if (NtGdiCombineRgn(Window->UpdateRegion, Window->UpdateRegion, - hRgnWindow, RGN_AND) == NULLREGION) - { - GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess()); - NtGdiDeleteObject(Window->UpdateRegion); - Window->UpdateRegion = NULL; - } - - if (Window->NCUpdateRegion == NULL) - { - Window->NCUpdateRegion = hRgnNonClient; - } - else - { - if(NULL != hRgnNonClient) - { - NtGdiCombineRgn(Window->NCUpdateRegion, Window->NCUpdateRegion, - hRgnNonClient, RGN_OR); - GDIOBJ_SetOwnership(hRgnNonClient, PsGetCurrentProcess()); - NtGdiDeleteObject(hRgnNonClient); - } - } - - NtGdiDeleteObject(hRgnWindow); - } - /* * Process children if needed */ @@ -358,9 +430,6 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags) */ HRGN hRgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0); NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY); - NtGdiOffsetRgn(hRgnTemp, - Window->WindowRect.left - Child->WindowRect.left, - Window->WindowRect.top - Child->WindowRect.top); IntInvalidateWindows(Child, hRgnTemp, Flags); NtGdiDeleteObject(hRgnTemp); } @@ -407,20 +476,16 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags) BOOL FASTCALL IntIsWindowDrawable(PWINDOW_OBJECT Window) { - PWINDOW_OBJECT Wnd = Window; + PWINDOW_OBJECT Wnd; - do + for (Wnd = Window; Wnd != NULL; Wnd = Wnd->Parent) { if (!(Wnd->Style & WS_VISIBLE) || ((Wnd->Style & WS_MINIMIZE) && (Wnd != Window))) { return FALSE; } - - Wnd = Wnd->Parent; - } - while(Wnd); return TRUE; } @@ -453,7 +518,7 @@ co_UserRedrawWindow(PWINDOW_OBJECT Window, const RECT* UpdateRect, HRGN UpdateRg /* * Step 2. * Transform the parameters UpdateRgn and UpdateRect into - * a region hRgn specified in window coordinates. + * a region hRgn specified in screen coordinates. */ if (Flags & (RDW_INVALIDATE | RDW_VALIDATE)) @@ -461,35 +526,30 @@ co_UserRedrawWindow(PWINDOW_OBJECT Window, const RECT* UpdateRect, HRGN UpdateRg if (UpdateRgn != NULL) { hRgn = NtGdiCreateRectRgn(0, 0, 0, 0); - NtGdiCombineRgn(hRgn, UpdateRgn, NULL, RGN_COPY); - NtGdiOffsetRgn(hRgn, - Window->ClientRect.left - Window->WindowRect.left, - Window->ClientRect.top - Window->WindowRect.top); + if (NtGdiCombineRgn(hRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION) + NtGdiDeleteObject(hRgn); + else + NtGdiOffsetRgn(hRgn, Window->ClientRect.left, Window->ClientRect.top); } - else - if (UpdateRect != NULL) + else if (UpdateRect != NULL) + { + if (!IntGdiIsEmptyRect(UpdateRect)) { hRgn = UnsafeIntCreateRectRgnIndirect((RECT *)UpdateRect); - NtGdiOffsetRgn(hRgn, - Window->ClientRect.left - Window->WindowRect.left, - Window->ClientRect.top - Window->WindowRect.top); + NtGdiOffsetRgn(hRgn, Window->ClientRect.left, Window->ClientRect.top); } - else - if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) || - (Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME)) - { - hRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); - NtGdiOffsetRgn(hRgn, - -Window->WindowRect.left, - -Window->WindowRect.top); - } - else - { - hRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect); - NtGdiOffsetRgn(hRgn, - -Window->WindowRect.left, - -Window->WindowRect.top); - } + } + else if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) || + (Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME)) + { + if (!IntGdiIsEmptyRect(&Window->WindowRect)) + hRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); + } + else + { + if (!IntGdiIsEmptyRect(&Window->ClientRect)) + hRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect); + } } /* @@ -497,7 +557,8 @@ co_UserRedrawWindow(PWINDOW_OBJECT Window, const RECT* UpdateRect, HRGN UpdateRg * Adjust the window update region depending on hRgn and flags. */ - if (Flags & (RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOINTERNALPAINT)) + if (Flags & (RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOINTERNALPAINT) && + hRgn != NULL) { IntInvalidateWindows(Window, hRgn, Flags); } @@ -534,84 +595,55 @@ IntIsWindowDirty(PWINDOW_OBJECT Window) (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)); } -HWND STDCALL -IntFindWindowToRepaint(HWND hWnd, PW32THREAD Thread) +HWND FASTCALL +IntFindWindowToRepaint(PWINDOW_OBJECT Window, PW32THREAD Thread) { - PWINDOW_OBJECT Window; - PWINDOW_OBJECT Child; - HWND hFoundWnd = NULL; + HWND hChild; - if (!(Window = UserGetWindowObject(hWnd))) - return NULL; - - if (IntIsWindowDirty(Window) && - IntWndBelongsToThread(Window, Thread)) + while (Window != NULL) { - return hWnd; - } - - for (Child = Window->FirstChild; Child; Child = Child->NextSibling) - { - if (IntIsWindowDirty(Child) && - IntWndBelongsToThread(Child, Thread)) + /* FIXME: Transparent windows. */ + if (IntIsWindowDirty(Window) && + IntWndBelongsToThread(Window, Thread)) { - hFoundWnd = Child->hSelf; - break; + return Window->hSelf; } - } - if (hFoundWnd == NULL) - { - HWND *List; - INT i; - - List = IntWinListChildren(Window); - if (List != NULL) + if (Window->FirstChild) { - for (i = 0; List[i]; i++) - { - hFoundWnd = IntFindWindowToRepaint(List[i], Thread); - if (hFoundWnd != NULL) - break; - } - ExFreePool(List); + hChild = IntFindWindowToRepaint(Window->FirstChild, Thread); + if (hChild != NULL) + return hChild; } + + Window = Window->NextSibling; } - return hFoundWnd; + return NULL; } BOOL FASTCALL IntGetPaintMessage(HWND hWnd, UINT MsgFilterMin, UINT MsgFilterMax, PW32THREAD Thread, MSG *Message, BOOL Remove) { - PWINDOW_OBJECT Window; PUSER_MESSAGE_QUEUE MessageQueue = (PUSER_MESSAGE_QUEUE)Thread->MessageQueue; - if (!MessageQueue->PaintPosted) + if (!MessageQueue->PaintCount) return FALSE; if ((MsgFilterMin != 0 || MsgFilterMax != 0) && (MsgFilterMin > WM_PAINT || MsgFilterMax < WM_PAINT)) return FALSE; - if (hWnd) - Message->hwnd = IntFindWindowToRepaint(hWnd, PsGetWin32Thread()); - else - Message->hwnd = IntFindWindowToRepaint(IntGetDesktopWindow(), PsGetWin32Thread()); + Message->hwnd = IntFindWindowToRepaint(UserGetDesktopWindow(), PsGetWin32Thread()); if (Message->hwnd == NULL) { - if (NULL == hWnd) - { - DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n"); - MessageQueue->PaintPosted = 0; - MessageQueue->PaintCount = 0; - } + DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n"); return FALSE; } - if (!(Window = UserGetWindowObject(Message->hwnd))) + if (hWnd != NULL && Message->hwnd != hWnd) return FALSE; Message->message = WM_PAINT; @@ -700,14 +732,7 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs) { HRGN hRgn; - if (Window->NCUpdateRegion != (HANDLE)1 && - Window->NCUpdateRegion != NULL) - { - GDIOBJ_SetOwnership(Window->NCUpdateRegion, PsGetCurrentProcess()); - } - hRgn = Window->NCUpdateRegion; - IntValidateParent(Window, Window->NCUpdateRegion); - Window->NCUpdateRegion = NULL; + hRgn = IntGetNCUpdateRgn(Window, FALSE); Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT; MsqDecPaintCountQueue(Window->MessageQueue); co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0); @@ -720,8 +745,7 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs) RtlZeroMemory(&Ps, sizeof(PAINTSTRUCT)); - Ps.hdc = UserGetDCEx(Window, 0, DCX_INTERSECTUPDATE | DCX_WINDOWPAINT | DCX_USESTYLE); - + Ps.hdc = UserGetDCEx(Window, Window->UpdateRegion, DCX_INTERSECTRGN | DCX_USESTYLE); if (!Ps.hdc) { RETURN( NULL); @@ -730,22 +754,20 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs) if (Window->UpdateRegion != NULL) { MsqDecPaintCountQueue(Window->MessageQueue); - IntValidateParent(Window, Window->UpdateRegion); Rgn = RGNDATA_LockRgn(Window->UpdateRegion); if (NULL != Rgn) { UnsafeIntGetRgnBox(Rgn, &Ps.rcPaint); RGNDATA_UnlockRgn(Rgn); IntGdiOffsetRect(&Ps.rcPaint, - Window->WindowRect.left - Window->ClientRect.left, - Window->WindowRect.top - Window->ClientRect.top); + -Window->ClientRect.left, + -Window->ClientRect.top); } else { IntGetClientRect(Window, &Ps.rcPaint); } GDIOBJ_SetOwnership(Window->UpdateRegion, PsGetCurrentProcess()); - NtGdiDeleteObject(Window->UpdateRegion); Window->UpdateRegion = NULL; } else @@ -755,6 +777,7 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs) IntGetClientRect(Window, &Ps.rcPaint); } + Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT; if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND) @@ -898,10 +921,7 @@ co_UserGetUpdateRgn(PWINDOW_OBJECT Window, HRGN hRgn, BOOL bErase) else { RegionType = NtGdiCombineRgn(hRgn, Window->UpdateRegion, hRgn, RGN_COPY); - NtGdiOffsetRgn( - hRgn, - Window->WindowRect.left - Window->ClientRect.left, - Window->WindowRect.top - Window->ClientRect.top); + NtGdiOffsetRgn(hRgn, -Window->ClientRect.left, -Window->ClientRect.top); } if (bErase && RegionType != NULLREGION && RegionType != ERROR) diff --git a/reactos/subsys/win32k/ntuser/vis.c b/reactos/subsys/win32k/ntuser/vis.c index f837136e555..df61439dbed 100644 --- a/reactos/subsys/win32k/ntuser/vis.c +++ b/reactos/subsys/win32k/ntuser/vis.c @@ -38,37 +38,30 @@ VIS_ComputeVisibleRegion( BOOLEAN ClipSiblings) { HRGN VisRgn, ClipRgn; - INT LeftOffset, TopOffset; PWINDOW_OBJECT PreviousWindow, CurrentWindow, CurrentSibling; if (!(Window->Style & WS_VISIBLE)) { - return NtGdiCreateRectRgn(0, 0, 0, 0); + return NULL; } if (ClientArea) { - if(!(ClipRgn = VIS_ComputeVisibleRegion(Window, FALSE, ClipChildren, ClipSiblings))) + if (!(ClipRgn = VIS_ComputeVisibleRegion(Window, FALSE, ClipChildren, ClipSiblings))) { - return NtGdiCreateRectRgn(0, 0, 0, 0); + return NULL; } - if(!(VisRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect))) + if (!(VisRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect))) { NtGdiDeleteObject(VisRgn); - return NtGdiCreateRectRgn(0, 0, 0, 0); + return NULL; } - LeftOffset = Window->ClientRect.left - Window->WindowRect.left; - TopOffset = Window->ClientRect.top - Window->WindowRect.top; - NtGdiOffsetRgn(VisRgn, -Window->WindowRect.left, -Window->WindowRect.top); NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND); NtGdiDeleteObject(ClipRgn); - NtGdiOffsetRgn(VisRgn, -LeftOffset, -TopOffset); return VisRgn; } VisRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); - LeftOffset = Window->WindowRect.left; - TopOffset = Window->WindowRect.top; /* * Walk through all parent windows and for each clip the visble region @@ -83,14 +76,15 @@ VIS_ComputeVisibleRegion( if (!(CurrentWindow->Style & WS_VISIBLE)) { NtGdiDeleteObject(VisRgn); - return NtGdiCreateRectRgn(0, 0, 0, 0); + return NULL; } + ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWindow->ClientRect); NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND); NtGdiDeleteObject(ClipRgn); if ((PreviousWindow->Style & WS_CLIPSIBLINGS) || - (PreviousWindow == Window && ClipSiblings)) + (PreviousWindow == Window && ClipSiblings)) { CurrentSibling = CurrentWindow->FirstChild; while (CurrentSibling != NULL && CurrentSibling != PreviousWindow) @@ -99,7 +93,7 @@ VIS_ComputeVisibleRegion( { ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentSibling->WindowRect); /* Combine it with the window region if available */ - if(CurrentSibling->WindowRegion && !(CurrentSibling->Style & WS_MINIMIZE)) + if (CurrentSibling->WindowRegion && !(CurrentSibling->Style & WS_MINIMIZE)) { NtGdiOffsetRgn(ClipRgn, -CurrentSibling->WindowRect.left, -CurrentSibling->WindowRect.top); NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->WindowRegion, RGN_AND); @@ -125,7 +119,7 @@ VIS_ComputeVisibleRegion( { ClipRgn = UnsafeIntCreateRectRgnIndirect(&CurrentWindow->WindowRect); /* Combine it with the window region if available */ - if(CurrentWindow->WindowRegion && !(CurrentWindow->Style & WS_MINIMIZE)) + if (CurrentWindow->WindowRegion && !(CurrentWindow->Style & WS_MINIMIZE)) { NtGdiOffsetRgn(ClipRgn, -CurrentWindow->WindowRect.left, -CurrentWindow->WindowRect.top); NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->WindowRegion, RGN_AND); @@ -138,15 +132,13 @@ VIS_ComputeVisibleRegion( } } - if(Window->WindowRegion && !(Window->Style & WS_MINIMIZE)) + if (Window->WindowRegion && !(Window->Style & WS_MINIMIZE)) { - NtGdiOffsetRgn(VisRgn, -LeftOffset, -TopOffset); + NtGdiOffsetRgn(VisRgn, -Window->WindowRect.left, -Window->WindowRect.top); NtGdiCombineRgn(VisRgn, VisRgn, Window->WindowRegion, RGN_AND); - return VisRgn; + NtGdiOffsetRgn(VisRgn, Window->WindowRect.left, Window->WindowRect.top); } - NtGdiOffsetRgn(VisRgn, -LeftOffset, -TopOffset); - return VisRgn; } diff --git a/reactos/subsys/win32k/ntuser/windc.c b/reactos/subsys/win32k/ntuser/windc.c index 14ff2b84d40..2bc8219b8c5 100644 --- a/reactos/subsys/win32k/ntuser/windc.c +++ b/reactos/subsys/win32k/ntuser/windc.c @@ -34,8 +34,6 @@ #define NDEBUG #include -#define DCX_USESTYLE 0x10000 - /* GLOBALS *******************************************************************/ /* NOTE - I think we should store this per window station (including gdi objects) */ @@ -187,7 +185,7 @@ DceSetDrawable(PWINDOW_OBJECT Window OPTIONAL, HDC hDC, ULONG Flags, STATIC VOID FASTCALL DceDeleteClipRgn(DCE* Dce) { - Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN | DCX_WINDOWPAINT); + Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN); if (Dce->DCXFlags & DCX_KEEPCLIPRGN ) { @@ -216,7 +214,7 @@ DceReleaseDC(DCE* dce) /* restore previous visible region */ if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) && - (dce->DCXFlags & (DCX_CACHE | DCX_WINDOWPAINT)) ) + (dce->DCXFlags & DCX_CACHE) ) { DceDeleteClipRgn(dce); } @@ -273,23 +271,6 @@ DceUpdateVisRgn(DCE *Dce, PWINDOW_OBJECT Window, ULONG Flags) { hRgnVisible = NtGdiCreateRectRgn(0, 0, 0, 0); } - else - { - if (0 == (Flags & DCX_WINDOW)) - { - NtGdiOffsetRgn( - hRgnVisible, - Parent->ClientRect.left - Window->ClientRect.left, - Parent->ClientRect.top - Window->ClientRect.top); - } - else - { - NtGdiOffsetRgn( - hRgnVisible, - Parent->WindowRect.left - Window->WindowRect.left, - Parent->WindowRect.top - Window->WindowRect.top); - } - } } else if (Window == NULL) { @@ -482,7 +463,7 @@ UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL, HANDLE ClipRegion, ULONG Flags) } Dce->hwndCurrent = (Window ? Window->hSelf : NULL); - Dce->DCXFlags = DcxFlags | (Flags & DCX_WINDOWPAINT) | DCX_DCEBUSY; + Dce->DCXFlags = DcxFlags | DCX_DCEBUSY; if (0 == (Flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) && NULL != ClipRegion) { @@ -498,21 +479,8 @@ UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL, HANDLE ClipRegion, ULONG Flags) if (0 != (Flags & DCX_INTERSECTUPDATE) && NULL == ClipRegion) { - Dce->hClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0); - if (Dce->hClipRgn && Window->UpdateRegion) - { - GDIOBJ_SetOwnership(Dce->hClipRgn, NULL); - NtGdiCombineRgn(Dce->hClipRgn, Window->UpdateRegion, NULL, RGN_COPY); - if(Window->WindowRegion && !(Window->Style & WS_MINIMIZE)) - NtGdiCombineRgn(Dce->hClipRgn, Dce->hClipRgn, Window->WindowRegion, RGN_AND); - if (!(Flags & DCX_WINDOW)) - { - NtGdiOffsetRgn(Dce->hClipRgn, - Window->WindowRect.left - Window->ClientRect.left, - Window->WindowRect.top - Window->ClientRect.top); - } - } - Flags |= DCX_INTERSECTRGN; + Flags |= DCX_INTERSECTRGN | DCX_KEEPCLIPRGN; + ClipRegion = Window->UpdateRegion; } if (ClipRegion == (HRGN) 1) @@ -521,40 +489,17 @@ UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL, HANDLE ClipRegion, ULONG Flags) { Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect); GDIOBJ_SetOwnership(Dce->hClipRgn, NULL); - if(!Window->WindowRegion || (Window->Style & WS_MINIMIZE)) - { - NtGdiOffsetRgn(Dce->hClipRgn, -Window->ClientRect.left, -Window->ClientRect.top); - } - else - { - NtGdiOffsetRgn(Dce->hClipRgn, -Window->WindowRect.left, -Window->WindowRect.top); - NtGdiCombineRgn(Dce->hClipRgn, Dce->hClipRgn, Window->WindowRegion, RGN_AND); - NtGdiOffsetRgn(Dce->hClipRgn, -(Window->ClientRect.left - Window->WindowRect.left), - -(Window->ClientRect.top - Window->WindowRect.top)); - } } else { Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); GDIOBJ_SetOwnership(Dce->hClipRgn, NULL); - NtGdiOffsetRgn(Dce->hClipRgn, -Window->WindowRect.left, - -Window->WindowRect.top); - if(Window->WindowRegion && !(Window->Style & WS_MINIMIZE)) - NtGdiCombineRgn(Dce->hClipRgn, Dce->hClipRgn, Window->WindowRegion, RGN_AND); } } - else if (NULL != ClipRegion) + else if (ClipRegion != NULL) { - Dce->hClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0); - if (Dce->hClipRgn) - { - GDIOBJ_SetOwnership(Dce->hClipRgn, NULL); - if(!Window->WindowRegion || (Window->Style & WS_MINIMIZE)) - NtGdiCombineRgn(Dce->hClipRgn, ClipRegion, NULL, RGN_COPY); - else - NtGdiCombineRgn(Dce->hClipRgn, ClipRegion, Window->WindowRegion, RGN_AND); - } - NtGdiDeleteObject(ClipRegion); + Dce->hClipRgn = ClipRegion; + GDIOBJ_SetOwnership(Dce->hClipRgn, NULL); } DceSetDrawable(Window, Dce->hDC, Flags, UpdateClipOrigin); @@ -705,9 +650,9 @@ DceFreeDCE(PDCE dce, BOOLEAN Force) } NtGdiDeleteDC(dce->hDC); + GDIOBJ_SetOwnership(dce->hClipRgn, PsGetCurrentProcess()); if (dce->hClipRgn && ! (dce->DCXFlags & DCX_KEEPCLIPRGN)) { - GDIOBJ_SetOwnership(dce->hClipRgn, PsGetCurrentProcess()); NtGdiDeleteObject(dce->hClipRgn); } diff --git a/reactos/subsys/win32k/ntuser/winpos.c b/reactos/subsys/win32k/ntuser/winpos.c index be04b9d6770..4ef2fa7ebbf 100644 --- a/reactos/subsys/win32k/ntuser/winpos.c +++ b/reactos/subsys/win32k/ntuser/winpos.c @@ -959,6 +959,7 @@ co_WinPosSetWindowPos( else if(VisRgn) { RGNDATA_UnlockRgn(VisRgn); + NtGdiOffsetRgn(VisBefore, -Window->WindowRect.left, -Window->WindowRect.top); } } } @@ -1081,6 +1082,13 @@ co_WinPosSetWindowPos( Window->Style |= WS_VISIBLE; } + if (Window->UpdateRegion != NULL && Window->UpdateRegion != (HRGN)1) + { + NtGdiOffsetRgn(Window->UpdateRegion, + NewWindowRect.left - OldWindowRect.left, + NewWindowRect.top - OldWindowRect.top); + } + DceResetActiveDCEs(Window); if (!(WinPos.flags & SWP_NOREDRAW)) @@ -1099,6 +1107,7 @@ co_WinPosSetWindowPos( else if(VisRgn) { RGNDATA_UnlockRgn(VisRgn); + NtGdiOffsetRgn(VisAfter, -Window->WindowRect.left, -Window->WindowRect.top); } /* @@ -1136,11 +1145,9 @@ co_WinPosSetWindowPos( /* No use in copying bits which are in the update region. */ if (Window->UpdateRegion != NULL) { + NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top); NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF); - } - if (Window->NCUpdateRegion != NULL) - { - NtGdiCombineRgn(CopyRgn, CopyRgn, Window->NCUpdateRegion, RGN_DIFF); + NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top); } /* @@ -1163,6 +1170,7 @@ co_WinPosSetWindowPos( { RGNDATA_UnlockRgn(VisRgn); } + /* * Small trick here: there is no function to bitblt a region. So * we set the region as the clipping region, take the bounding box @@ -1172,11 +1180,10 @@ co_WinPosSetWindowPos( * Since NtUserGetDCEx takes ownership of the clip region, we need * to create a copy of CopyRgn and pass that. We need CopyRgn later */ - HRGN ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0); - - NtGdiCombineRgn(ClipRgn, CopyRgn, NULL, RGN_COPY); - Dc = UserGetDCEx(Window, ClipRgn, DCX_WINDOW | DCX_CACHE | - DCX_INTERSECTRGN | DCX_CLIPSIBLINGS); + NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top); + Dc = UserGetDCEx(Window, CopyRgn, DCX_WINDOW | DCX_CACHE | + DCX_INTERSECTRGN | DCX_CLIPSIBLINGS | + DCX_KEEPCLIPRGN); NtGdiBitBlt(Dc, CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left, CopyRect.bottom - CopyRect.top, Dc, @@ -1184,6 +1191,7 @@ co_WinPosSetWindowPos( CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY); UserReleaseDC(Window, Dc); IntValidateParent(Window, CopyRgn); + NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top); } else if(VisRgn) { diff --git a/reactos/subsys/win32k/objects/cliprgn.c b/reactos/subsys/win32k/objects/cliprgn.c index 62fb2616e0d..21487394d92 100644 --- a/reactos/subsys/win32k/objects/cliprgn.c +++ b/reactos/subsys/win32k/objects/cliprgn.c @@ -83,10 +83,17 @@ NtGdiSelectVisRgn(HDC hdc, HRGN hrgn) dc->w.hVisRgn = NtGdiCreateRectRgn(0, 0, 0, 0); GDIOBJ_CopyOwnership(hdc, dc->w.hVisRgn); } + else + { + NtGdiOffsetRgn(dc->w.hVisRgn, dc->w.DCOrgX, dc->w.DCOrgY); + } retval = NtGdiCombineRgn(dc->w.hVisRgn, hrgn, 0, RGN_COPY); if ( retval != ERROR ) - CLIPPING_UpdateGCRegion(dc); + { + NtGdiOffsetRgn(dc->w.hVisRgn, -dc->w.DCOrgX, -dc->w.DCOrgY); + CLIPPING_UpdateGCRegion(dc); + } DC_UnlockDc(dc); return retval;