}
BOOL FASTCALL
-IntValidateParent(PWND Child, HRGN hValidateRgn, BOOL Recurse)
+IntValidateParent(PWND Child, PREGION ValidateRgn, BOOL Recurse)
{
- PWND ParentWnd = Child->spwndParent;
+ PWND ParentWnd = Child;
+ if (ParentWnd->style & WS_CHILD)
+ {
+ do
+ ParentWnd = ParentWnd->spwndParent;
+ while (ParentWnd->style & WS_CHILD);
+ }
+// Hax out for drawing issues.
+// if (!(ParentWnd->state & WNDS_SYNCPAINTPENDING)) Recurse = FALSE;
+
+ ParentWnd = Child->spwndParent;
while (ParentWnd)
{
if (ParentWnd->style & WS_CLIPCHILDREN)
return FALSE;
IntInvalidateWindows( ParentWnd,
- hValidateRgn,
+ ValidateRgn,
RDW_VALIDATE | RDW_NOCHILDREN);
}
return TRUE;
}
+/*
+ Synchronize painting to the top-level windows of other threads.
+*/
+VOID FASTCALL
+IntSendSyncPaint(PWND Wnd, ULONG Flags)
+{
+ PTHREADINFO ptiCur, ptiWnd;
+ PUSER_SENT_MESSAGE Message;
+ PLIST_ENTRY Entry;
+ BOOL bSend = TRUE;
+
+ ptiWnd = Wnd->head.pti;
+ ptiCur = PsGetCurrentThreadWin32Thread();
+ /*
+ Not the current thread, Wnd is in send Nonclient paint also in send erase background and it is visiable.
+ */
+ if ( Wnd->head.pti != ptiCur &&
+ Wnd->state & WNDS_SENDNCPAINT &&
+ Wnd->state & WNDS_SENDERASEBACKGROUND &&
+ Wnd->style & WS_VISIBLE)
+ {
+ // For testing, if you see this, break out the Champagne and have a party!
+ ERR("SendSyncPaint Wnd in State!\n");
+ if (!IsListEmpty(&ptiWnd->SentMessagesListHead))
+ {
+ // Scan sent queue messages to see if we received sync paint messages.
+ Entry = ptiWnd->SentMessagesListHead.Flink;
+ Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
+ do
+ {
+ ERR("LOOP it\n");
+ if (Message->Msg.message == WM_SYNCPAINT &&
+ Message->Msg.hwnd == UserHMGetHandle(Wnd))
+ { // Already received so exit out.
+ ERR("SendSyncPaint Found one in the Sent Msg Queue!\n");
+ bSend = FALSE;
+ break;
+ }
+ Entry = Message->ListEntry.Flink;
+ Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
+ }
+ while (Entry != &ptiWnd->SentMessagesListHead);
+ }
+ if (bSend)
+ {
+ ERR("Sending WM_SYNCPAINT\n");
+ // This message has no parameters. But it does! Pass Flags along.
+ co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SYNCPAINT, Flags, 0);
+ Wnd->state |= WNDS_SYNCPAINTPENDING;
+ }
+ }
+
+ // Send to all the children if this is the desktop window.
+ if ( Wnd == UserGetDesktopWindow() )
+ {
+ if ( Flags & RDW_ALLCHILDREN ||
+ ( !(Flags & RDW_NOCHILDREN) && Wnd->style & WS_CLIPCHILDREN))
+ {
+ PWND spwndChild = Wnd->spwndChild;
+ while(spwndChild)
+ {
+ if ( spwndChild->style & WS_CHILD &&
+ spwndChild->head.pti != ptiCur)
+ {
+ spwndChild = spwndChild->spwndNext;
+ continue;
+ }
+ IntSendSyncPaint( spwndChild, Flags );
+ spwndChild = spwndChild->spwndNext;
+ }
+ }
+ }
+}
+
/**
* @name IntCalcWindowRgn
*
HRGN hRgnWindow;
if (Client)
- hRgnWindow = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
+ {
+ hRgnWindow = NtGdiCreateRectRgn(
+ Wnd->rcClient.left,
+ Wnd->rcClient.top,
+ Wnd->rcClient.right,
+ Wnd->rcClient.bottom);
+ }
else
- hRgnWindow = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
+ {
+ hRgnWindow = NtGdiCreateRectRgn(
+ Wnd->rcWindow.left,
+ Wnd->rcWindow.top,
+ Wnd->rcWindow.right,
+ Wnd->rcWindow.bottom);
+ }
if (Wnd->hrgnClip != NULL && !(Wnd->style & WS_MINIMIZE))
{
{
GreDeleteObject(hRgnWindow);
GreDeleteObject(hRgnNonClient);
+ Window->state &= ~WNDS_UPDATEDIRTY;
return NULL;
}
{
IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(Window->hrgnUpdate);
+ Window->state &= ~WNDS_UPDATEDIRTY;
Window->hrgnUpdate = NULL;
if (!(Window->state & WNDS_INTERNALPAINT))
- MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
+ MsqDecPaintCountQueue(Window->head.pti);
}
}
HWND hWnd = Wnd->head.h;
HRGN TempRegion;
+ Wnd->state &= ~WNDS_PAINTNOTPROCESSED;
+
if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
{
if (Wnd->hrgnUpdate)
{
- if (!IntValidateParent(Wnd, Wnd->hrgnUpdate, Recurse))
- return;
+ PREGION RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
+ if (RgnUpdate)
+ {
+ if (!IntValidateParent(Wnd, RgnUpdate, Recurse))
+ {
+ RGNOBJAPI_Unlock(RgnUpdate);
+ return;
+ }
+ RGNOBJAPI_Unlock(RgnUpdate);
+ }
}
if (Flags & RDW_UPDATENOW)
{
- if (Wnd->hrgnUpdate != NULL ||
- Wnd->state & WNDS_INTERNALPAINT)
+ if ((Wnd->hrgnUpdate != NULL ||
+ Wnd->state & WNDS_INTERNALPAINT))
{
+ Wnd->state2 |= WNDS2_WMPAINTSENT;
co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
}
}
- else
+ else if (Wnd->head.pti == PsGetCurrentThreadWin32Thread())
{
if (Wnd->state & WNDS_SENDNCPAINT)
{
TempRegion = IntGetNCUpdateRgn(Wnd, TRUE);
Wnd->state &= ~WNDS_SENDNCPAINT;
- MsqDecPaintCountQueue(Wnd->head.pti->MessageQueue);
- co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0);
-
+ if ( Wnd == GetW32ThreadInfo()->MessageQueue->spwndActive &&
+ !(Wnd->state & WNDS_ACTIVEFRAME))
+ {
+ Wnd->state |= WNDS_ACTIVEFRAME;
+ Wnd->state &= ~WNDS_NONCPAINT;
+ }
+ if (TempRegion) co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0);
}
if (Wnd->state & WNDS_SENDERASEBACKGROUND)
}
}
}
+ else
+ {
+ Wnd->state &= ~(WNDS_SENDNCPAINT|WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
+ }
/*
* Check that the window is still valid at this point
UserDerefObjectCo(Wnd);
}
}
- ExFreePool(List);
+ ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
}
}
}
* co_WinPosSetWindowPos, IntValidateParent, co_UserRedrawWindow.
*/
VOID FASTCALL
-IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
+IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
{
INT RgnType;
- BOOL HadPaintMessage, HadNCPaintMessage;
- BOOL HasPaintMessage, HasNCPaintMessage;
+ BOOL HadPaintMessage;
TRACE("IntInvalidateWindows start\n");
+
+ Wnd->state |= WNDS_PAINTNOTPROCESSED;
+
/*
* If the nonclient is not to be redrawn, clip the region to the client
* rect
*/
if (0 != (Flags & RDW_INVALIDATE) && 0 == (Flags & RDW_FRAME))
{
- HRGN hRgnClient;
+ PREGION RgnClient;
- hRgnClient = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
- RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnClient, RGN_AND);
- GreDeleteObject(hRgnClient);
+ RgnClient = IntSysCreateRectpRgnIndirect(&Wnd->rcClient);
+ if (RgnClient)
+ {
+ RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnClient, RGN_AND);
+ REGION_Delete(RgnClient);
+ }
}
/*
if (!Wnd->hrgnClip || (Wnd->style & WS_MINIMIZE))
{
- HRGN hRgnWindow;
-
- hRgnWindow = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
- RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnWindow, RGN_AND);
- GreDeleteObject(hRgnWindow);
+ PREGION RgnWindow = IntSysCreateRectpRgnIndirect(&Wnd->rcWindow);
+ if (RgnWindow)
+ {
+ RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnWindow, RGN_AND);
+ REGION_Delete(RgnWindow);
+ }
}
else
{
- NtGdiOffsetRgn( hRgn,
- -Wnd->rcWindow.left,
- -Wnd->rcWindow.top);
- RgnType = NtGdiCombineRgn(hRgn, hRgn, Wnd->hrgnClip, RGN_AND);
- NtGdiOffsetRgn( hRgn,
- Wnd->rcWindow.left,
- Wnd->rcWindow.top);
+ PREGION RgnClip = RGNOBJAPI_Lock(Wnd->hrgnClip, NULL);
+ if (RgnClip)
+ {
+ IntGdiOffsetRgn( Rgn,
+ -Wnd->rcWindow.left,
+ -Wnd->rcWindow.top);
+ RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnClip, RGN_AND);
+ IntGdiOffsetRgn( Rgn,
+ Wnd->rcWindow.left,
+ Wnd->rcWindow.top);
+ RGNOBJAPI_Unlock(RgnClip);
+ }
}
/*
* Save current state of pending updates
*/
- HadPaintMessage = Wnd->hrgnUpdate != NULL ||
- Wnd->state & WNDS_INTERNALPAINT;
- HadNCPaintMessage = Wnd->state & WNDS_SENDNCPAINT;
+ HadPaintMessage = IntIsWindowDirty(Wnd);
/*
* Update the region and flags
*/
- if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
+ // The following flags are used to invalidate the window.
+ if (Flags & (RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_ERASE|RDW_FRAME))
{
- if (Wnd->hrgnUpdate == NULL)
+ if (Flags & RDW_INTERNALPAINT)
{
- Wnd->hrgnUpdate = IntSysCreateRectRgn(0, 0, 0, 0);
- IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_PUBLIC);
+ Wnd->state |= WNDS_INTERNALPAINT;
}
- if (NtGdiCombineRgn(Wnd->hrgnUpdate, Wnd->hrgnUpdate,
- hRgn, RGN_OR) == NULLREGION)
+ if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
{
- IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
- GreDeleteObject(Wnd->hrgnUpdate);
- Wnd->hrgnUpdate = NULL;
- }
+ PREGION RgnUpdate;
- if (Flags & RDW_FRAME)
- Wnd->state |= WNDS_SENDNCPAINT;
- if (Flags & RDW_ERASE)
- Wnd->state |= WNDS_SENDERASEBACKGROUND;
+ Wnd->state &= ~WNDS_NONCPAINT;
- Flags |= RDW_FRAME;
- }
+ /* If not the same thread set it dirty. */
+ if (Wnd->head.pti != PsGetCurrentThreadWin32Thread())
+ {
+ Wnd->state |= WNDS_UPDATEDIRTY;
+ if (Wnd->state2 & WNDS2_WMPAINTSENT)
+ Wnd->state2 |= WNDS2_ENDPAINTINVALIDATE;
+ }
- if (Flags & RDW_VALIDATE && RgnType != NULLREGION)
- {
- if (Wnd->hrgnUpdate != NULL)
- {
- if (NtGdiCombineRgn(Wnd->hrgnUpdate, Wnd->hrgnUpdate,
- hRgn, RGN_DIFF) == NULLREGION)
+ if (Flags & RDW_FRAME)
+ Wnd->state |= WNDS_SENDNCPAINT;
+ if (Flags & RDW_ERASE)
+ Wnd->state |= WNDS_SENDERASEBACKGROUND;
+
+ if (Wnd->hrgnUpdate == NULL)
+ {
+ Wnd->hrgnUpdate = NtGdiCreateRectRgn(0, 0, 0, 0);
+ IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_PUBLIC);
+ }
+
+ RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
+ if (RgnUpdate)
{
- IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
- GreDeleteObject(Wnd->hrgnUpdate);
- Wnd->hrgnUpdate = NULL;
+ RgnType = IntGdiCombineRgn(RgnUpdate, RgnUpdate, Rgn, RGN_OR);
+ RGNOBJAPI_Unlock(RgnUpdate);
+ if (RgnType == NULLREGION)
+ {
+ IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+ GreDeleteObject(Wnd->hrgnUpdate);
+ Wnd->hrgnUpdate = NULL;
+ }
}
+ Flags |= RDW_FRAME; // For children.
}
+ } // The following flags are used to validate the window.
+ else if (Flags & (RDW_VALIDATE|RDW_NOINTERNALPAINT|RDW_NOERASE|RDW_NOFRAME))
+ {
+ /* FIXME: Handle WNDS_UPDATEDIRTY */
- if (Wnd->hrgnUpdate == NULL)
- Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
- if (Flags & RDW_NOFRAME)
- Wnd->state &= ~WNDS_SENDNCPAINT;
- if (Flags & RDW_NOERASE)
- Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
- }
+ if (Flags & RDW_NOINTERNALPAINT)
+ {
+ Wnd->state &= ~WNDS_INTERNALPAINT;
+ }
- if (Flags & RDW_INTERNALPAINT)
- {
- Wnd->state |= WNDS_INTERNALPAINT;
- }
+ if (Flags & RDW_VALIDATE && RgnType != NULLREGION)
+ {
+ if (Flags & RDW_NOFRAME)
+ Wnd->state &= ~WNDS_SENDNCPAINT;
+ if (Flags & RDW_NOERASE)
+ Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
- if (Flags & RDW_NOINTERNALPAINT)
- {
- Wnd->state &= ~WNDS_INTERNALPAINT;
+ if (Wnd->hrgnUpdate != NULL)
+ {
+ PREGION RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
+
+ if (RgnUpdate)
+ {
+ RgnType = IntGdiCombineRgn(RgnUpdate, RgnUpdate, Rgn, RGN_DIFF);
+ RGNOBJAPI_Unlock(RgnUpdate);
+
+ if(RgnType == NULLREGION)
+ {
+ IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+ GreDeleteObject(Wnd->hrgnUpdate);
+ Wnd->hrgnUpdate = NULL;
+ }
+ }
+ }
+
+ if (Wnd->hrgnUpdate == NULL)
+ Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
+ }
}
/*
/*
* Recursive call to update children hrgnUpdate
*/
- HRGN hRgnTemp = IntSysCreateRectRgn(0, 0, 0, 0);
- NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY);
- IntInvalidateWindows(Child, hRgnTemp, Flags);
- GreDeleteObject(hRgnTemp);
+ PREGION RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
+ if (RgnTemp)
+ {
+ IntGdiCombineRgn(RgnTemp, Rgn, 0, RGN_COPY);
+ IntInvalidateWindows(Child, RgnTemp, Flags);
+ REGION_Delete(RgnTemp);
+ }
}
-
}
}
* Fake post paint messages to window message queue if needed
*/
- HasPaintMessage = Wnd->hrgnUpdate != NULL ||
- Wnd->state & WNDS_INTERNALPAINT;
- HasNCPaintMessage = Wnd->state & WNDS_SENDNCPAINT;
-
- if (HasPaintMessage != HadPaintMessage)
+ if (HadPaintMessage != IntIsWindowDirty(Wnd))
{
if (HadPaintMessage)
- MsqDecPaintCountQueue(Wnd->head.pti->MessageQueue);
- else
- MsqIncPaintCountQueue(Wnd->head.pti->MessageQueue);
- }
-
- if (HasNCPaintMessage != HadNCPaintMessage)
- {
- if (HadNCPaintMessage)
- MsqDecPaintCountQueue(Wnd->head.pti->MessageQueue);
+ MsqDecPaintCountQueue(Wnd->head.pti);
else
- MsqIncPaintCountQueue(Wnd->head.pti->MessageQueue);
+ MsqIncPaintCountQueue(Wnd->head.pti);
}
TRACE("IntInvalidateWindows exit\n");
}
co_UserRedrawWindow(
PWND Window,
const RECTL* UpdateRect,
- HRGN UpdateRgn,
+ PREGION UpdateRgn,
ULONG Flags)
{
- HRGN hRgn = NULL;
+ PREGION TmpRgn = NULL;
TRACE("co_UserRedrawWindow start\n");
/*
if (Flags & (RDW_INVALIDATE | RDW_VALIDATE)) // Both are OKAY!
{
- if (UpdateRgn != NULL)
+ if (UpdateRgn)
{
- hRgn = IntSysCreateRectRgn(0, 0, 0, 0);
- if (NtGdiCombineRgn(hRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION)
- {
- GreDeleteObject(hRgn);
- hRgn = NULL;
- }
- else
- NtGdiOffsetRgn(hRgn, Window->rcClient.left, Window->rcClient.top);
+ TmpRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
+ if (IntGdiCombineRgn(TmpRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION)
+ {
+ REGION_Delete(TmpRgn);
+ TmpRgn = NULL;
+ }
+ else
+ {
+ IntGdiOffsetRgn(TmpRgn, Window->rcClient.left, Window->rcClient.top);
+ }
}
else if (UpdateRect != NULL)
{
if (!RECTL_bIsEmptyRect(UpdateRect))
{
- hRgn = IntSysCreateRectRgnIndirect((RECTL *)UpdateRect);
- NtGdiOffsetRgn(hRgn, Window->rcClient.left, Window->rcClient.top);
+ TmpRgn = IntSysCreateRectpRgnIndirect(UpdateRect);
+ IntGdiOffsetRgn(TmpRgn, Window->rcClient.left, Window->rcClient.top);
}
}
else if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) ||
(Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME))
{
if (!RECTL_bIsEmptyRect(&Window->rcWindow))
- hRgn = IntSysCreateRectRgnIndirect(&Window->rcWindow);
+ TmpRgn = IntSysCreateRectpRgnIndirect(&Window->rcWindow);
}
else
{
if (!RECTL_bIsEmptyRect(&Window->rcClient))
- hRgn = IntSysCreateRectRgnIndirect(&Window->rcClient);
+ TmpRgn = IntSysCreateRectpRgnIndirect(&Window->rcClient);
}
}
*/
if (Flags & (RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOINTERNALPAINT) &&
- hRgn != NULL)
+ TmpRgn != NULL)
{
- IntInvalidateWindows(Window, hRgn, Flags);
+ IntInvalidateWindows(Window, TmpRgn, Flags);
}
/*
if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
{
+ if (Flags & RDW_ERASENOW) IntSendSyncPaint(Window, Flags);
co_IntPaintWindows(Window, Flags, FALSE);
}
* Cleanup ;-)
*/
- if (hRgn != NULL)
+ if (TmpRgn != NULL)
{
- GreDeleteObject(hRgn);
+ REGION_Delete(TmpRgn);
}
TRACE("co_UserRedrawWindow exit\n");
BOOL FASTCALL
IntIsWindowDirty(PWND Wnd)
{
- return (Wnd->style & WS_VISIBLE) &&
- ((Wnd->hrgnUpdate != NULL) ||
- (Wnd->state & WNDS_INTERNALPAINT) ||
- (Wnd->state & WNDS_SENDNCPAINT));
+ return ( Wnd->style & WS_VISIBLE &&
+ ( Wnd->hrgnUpdate != NULL ||
+ Wnd->state & WNDS_INTERNALPAINT ) );
}
-HWND FASTCALL
+PWND FASTCALL
IntFindWindowToRepaint(PWND Window, PTHREADINFO Thread)
{
- HWND hChild;
+ PWND hChild;
PWND TempWindow;
for (; Window != NULL; Window = Window->spwndNext)
IntWndBelongsToThread(TempWindow, Thread) &&
IntIsWindowDirty(TempWindow))
{
- return TempWindow->head.h;
+ return TempWindow;
}
}
}
- return Window->head.h;
+ return Window;
}
if (Window->spwndChild)
return hChild;
}
}
-
- return NULL;
+ return Window;
}
BOOL FASTCALL
MSG *Message,
BOOL Remove)
{
- if (!Thread->cPaintsReady)
- return FALSE;
+ PWND PaintWnd;
if ((MsgFilterMin != 0 || MsgFilterMax != 0) &&
(MsgFilterMin > WM_PAINT || MsgFilterMax < WM_PAINT))
return FALSE;
- Message->hwnd = IntFindWindowToRepaint(UserGetDesktopWindow(), PsGetCurrentThreadWin32Thread());
+ if (Thread->TIF_flags & TIF_SYSTEMTHREAD )
+ {
+ ERR("WM_PAINT is in a System Thread!\n");
+ }
+
+ PaintWnd = IntFindWindowToRepaint(UserGetDesktopWindow(), Thread);
+
+ Message->hwnd = PaintWnd ? UserHMGetHandle(PaintWnd) : NULL;
if (Message->hwnd == NULL)
{
- ERR("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found! Counts %d\n",Thread->cPaintsReady);
+ ERR("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found! Counts %u\n",Thread->cPaintsReady);
/* Hack to stop spamming the debuglog ! */
Thread->cPaintsReady = 0;
return FALSE;
}
- if (Window != NULL && Message->hwnd != Window->head.h)
+ if (Window != NULL && PaintWnd != Window)
return FALSE;
- Message->message = WM_PAINT;
+ if (PaintWnd->state & WNDS_INTERNALPAINT)
+ {
+ PaintWnd->state &= ~WNDS_INTERNALPAINT;
+ if (!PaintWnd->hrgnUpdate)
+ MsqDecPaintCountQueue(Thread);
+ }
+ PaintWnd->state2 &= ~WNDS2_WMPAINTSENT;
+ PaintWnd->state &= ~WNDS_UPDATEDIRTY;
Message->wParam = Message->lParam = 0;
-
+ Message->message = WM_PAINT;
return TRUE;
}
CaretInfo = ActiveMessageQueue->CaretInfo;
hWndCaret = CaretInfo->hWnd;
- WndCaret = UserGetWindowObject(hWndCaret);
+ WndCaret = ValidateHwndNoErr(hWndCaret);
// FIXME: Check for WndCaret can be NULL
if (WndCaret == Window ||
return Ret;
}
-/* PUBLIC FUNCTIONS ***********************************************************/
-
-/*
- * NtUserBeginPaint
- *
- * Status
- * @implemented
- */
-
-HDC APIENTRY
-NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs)
+HDC FASTCALL
+IntBeginPaint(PWND Window, PPAINTSTRUCT Ps)
{
- PWND Window = NULL;
- PAINTSTRUCT Ps;
- NTSTATUS Status;
- DECLARE_RETURN(HDC);
- USER_REFERENCE_ENTRY Ref;
-
- TRACE("Enter NtUserBeginPaint\n");
- UserEnterExclusive();
-
- if (!(Window = UserGetWindowObject(hWnd)))
- {
- RETURN( NULL);
- }
-
- UserRefObjectCo(Window, &Ref);
-
co_UserHideCaret(Window);
+ Window->state2 |= WNDS2_STARTPAINT;
+ Window->state &= ~WNDS_PAINTNOTPROCESSED;
+
if (Window->state & WNDS_SENDNCPAINT)
{
HRGN hRgn;
+ Window->state &= ~WNDS_UPDATEDIRTY;
hRgn = IntGetNCUpdateRgn(Window, FALSE);
Window->state &= ~WNDS_SENDNCPAINT;
- MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
- co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
+ co_IntSendMessage(UserHMGetHandle(Window), WM_NCPAINT, (WPARAM)hRgn, 0);
if (hRgn != HRGN_WINDOW && hRgn != NULL && GreIsHandleValid(hRgn))
{
- /* NOTE: The region can already by deleted! */
+ /* NOTE: The region can already be deleted! */
GreDeleteObject(hRgn);
}
}
+ else
+ {
+ Window->state &= ~WNDS_UPDATEDIRTY;
+ }
- RtlZeroMemory(&Ps, sizeof(PAINTSTRUCT));
+ RtlZeroMemory(Ps, sizeof(PAINTSTRUCT));
- Ps.hdc = UserGetDCEx( Window,
+ Ps->hdc = UserGetDCEx( Window,
Window->hrgnUpdate,
DCX_INTERSECTRGN | DCX_USESTYLE);
- if (!Ps.hdc)
+ if (!Ps->hdc)
{
- RETURN(NULL);
+ return NULL;
}
if (Window->hrgnUpdate != NULL)
{
- MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
- GdiGetClipBox(Ps.hdc, &Ps.rcPaint);
+ MsqDecPaintCountQueue(Window->head.pti);
+ GdiGetClipBox(Ps->hdc, &Ps->rcPaint);
IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
/* The region is part of the dc now and belongs to the process! */
Window->hrgnUpdate = NULL;
else
{
if (Window->state & WNDS_INTERNALPAINT)
- MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
+ MsqDecPaintCountQueue(Window->head.pti);
- IntGetClientRect(Window, &Ps.rcPaint);
+ IntGetClientRect(Window, &Ps->rcPaint);
}
Window->state &= ~WNDS_INTERNALPAINT;
if (Window->state & WNDS_SENDERASEBACKGROUND)
{
Window->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
- Ps.fErase = !co_IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)Ps.hdc, 0);
- if ( Ps.fErase )
+ Ps->fErase = !co_IntSendMessage(UserHMGetHandle(Window), WM_ERASEBKGND, (WPARAM)Ps->hdc, 0);
+ if ( Ps->fErase )
{
Window->state |= (WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
}
}
else
{
- Ps.fErase = FALSE;
+ Ps->fErase = FALSE;
}
if (Window->hrgnUpdate)
{
PWND Child;
for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
{
- IntInvalidateWindows(Child, Window->hrgnUpdate, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);
+ if (Child->hrgnUpdate == NULL && Child->state & WNDS_SENDNCPAINT) // Helped fixing test_redrawnow.
+ IntInvalidateWindows(Child, NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
}
}
+ return Ps->hdc;
+}
+
+BOOL FASTCALL
+IntEndPaint(PWND Wnd, PPAINTSTRUCT Ps)
+{
+ HDC hdc = NULL;
+
+ hdc = Ps->hdc;
+
+ UserReleaseDC(Wnd, hdc, TRUE);
+
+ Wnd->state2 &= ~(WNDS2_WMPAINTSENT|WNDS2_STARTPAINT);
+
+ co_UserShowCaret(Wnd);
+
+ return TRUE;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*
+ * NtUserBeginPaint
+ *
+ * Status
+ * @implemented
+ */
+
+HDC APIENTRY
+NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* UnsafePs)
+{
+ PWND Window = NULL;
+ PAINTSTRUCT Ps;
+ NTSTATUS Status;
+ HDC hDC;
+ USER_REFERENCE_ENTRY Ref;
+ DECLARE_RETURN(HDC);
+
+ TRACE("Enter NtUserBeginPaint\n");
+ UserEnterExclusive();
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN( NULL);
+ }
+
+ UserRefObjectCo(Window, &Ref);
+
+ hDC = IntBeginPaint(Window, &Ps);
Status = MmCopyToCaller(UnsafePs, &Ps, sizeof(PAINTSTRUCT));
if (! NT_SUCCESS(Status))
RETURN(NULL);
}
- RETURN(Ps.hdc);
+ RETURN(hDC);
CLEANUP:
if (Window) UserDerefObjectCo(Window);
- TRACE("Leave NtUserBeginPaint, ret=%i\n",_ret_);
+ TRACE("Leave NtUserBeginPaint, ret=%p\n",_ret_);
UserLeave();
END_CLEANUP;
NtUserEndPaint(HWND hWnd, CONST PAINTSTRUCT* pUnsafePs)
{
NTSTATUS Status = STATUS_SUCCESS;
- PWND Window;
- DECLARE_RETURN(BOOL);
+ PWND Window = NULL;
+ PAINTSTRUCT Ps;
USER_REFERENCE_ENTRY Ref;
- HDC hdc = NULL;
+ DECLARE_RETURN(BOOL);
TRACE("Enter NtUserEndPaint\n");
UserEnterExclusive();
RETURN(FALSE);
}
+ UserRefObjectCo(Window, &Ref); // Here for the exception.
+
_SEH2_TRY
{
ProbeForRead(pUnsafePs, sizeof(*pUnsafePs), 1);
- hdc = pUnsafePs->hdc;
+ RtlCopyMemory(&Ps, pUnsafePs, sizeof(PAINTSTRUCT));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
RETURN(FALSE);
}
- UserReleaseDC(Window, hdc, TRUE);
-
- UserRefObjectCo(Window, &Ref);
- co_UserShowCaret(Window);
- UserDerefObjectCo(Window);
-
- RETURN(TRUE);
+ RETURN(IntEndPaint(Window, &Ps));
CLEANUP:
+ if (Window) UserDerefObjectCo(Window);
+
TRACE("Leave NtUserEndPaint, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
if (!Ret) goto Exit;
- if (!( pWnd = (PWND)UserGetObject(gHandleTable, finfo.hwnd, otWindow)) ||
+ if (!( pWnd = (PWND)UserGetObject(gHandleTable, finfo.hwnd, TYPE_WINDOW)) ||
finfo.cbSize != sizeof(FLASHWINFO) ||
finfo.dwFlags & ~(FLASHW_ALL|FLASHW_TIMER|FLASHW_TIMERNOFG) )
{
}
INT FASTCALL
-co_UserGetUpdateRgn(PWND Window, HRGN hRgn, BOOL bErase)
+co_UserGetUpdateRgn(PWND Window, PREGION Rgn, BOOL bErase)
{
- int RegionType;
- RECTL Rect;
+ int RegionType;
+ RECTL Rect;
+ PREGION UpdateRgn;
- ASSERT_REFS_CO(Window);
+ ASSERT_REFS_CO(Window);
- if (Window->hrgnUpdate == NULL)
- {
- RegionType = (NtGdiSetRectRgn(hRgn, 0, 0, 0, 0) ? NULLREGION : ERROR);
- }
- else
- {
- Rect = Window->rcClient;
- IntIntersectWithParents(Window, &Rect);
- NtGdiSetRectRgn(hRgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
- RegionType = NtGdiCombineRgn(hRgn, hRgn, Window->hrgnUpdate, RGN_AND);
- NtGdiOffsetRgn(hRgn, -Window->rcClient.left, -Window->rcClient.top);
- }
+ Window->state &= ~WNDS_UPDATEDIRTY;
+
+ if (Window->hrgnUpdate == NULL)
+ {
+ REGION_SetRectRgn(Rgn, 0, 0, 0, 0);
+ return NULLREGION;
+ }
+
+ UpdateRgn = RGNOBJAPI_Lock(Window->hrgnUpdate, NULL);
+ if (!UpdateRgn)
+ return ERROR;
+
+ Rect = Window->rcClient;
+ IntIntersectWithParents(Window, &Rect);
+ REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
+ RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
+ IntGdiOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
+ RGNOBJAPI_Unlock(UpdateRgn);
if (bErase && RegionType != NULLREGION && RegionType != ERROR)
{
PWND Window;
INT ret;
USER_REFERENCE_ENTRY Ref;
+ PREGION Rgn = NULL;
TRACE("Enter NtUserGetUpdateRgn\n");
UserEnterExclusive();
RETURN(ERROR);
}
+ /* Use a system region, we can't hold GDI locks when doing roundtrips to user mode */
+ Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
+ if (!Rgn)
+ RETURN(ERROR);
+
UserRefObjectCo(Window, &Ref);
- ret = co_UserGetUpdateRgn(Window, hRgn, bErase);
+ ret = co_UserGetUpdateRgn(Window, Rgn, bErase);
UserDerefObjectCo(Window);
RETURN(ret);
CLEANUP:
+ if (Rgn && (_ret_ != ERROR))
+ {
+ PREGION TheRgn = RGNOBJAPI_Lock(hRgn, NULL);
+ if (!TheRgn)
+ {
+ EngSetLastError(ERROR_INVALID_HANDLE);
+ _ret_ = ERROR;
+ }
+ IntGdiCombineRgn(TheRgn, Rgn, NULL, RGN_COPY);
+ RGNOBJAPI_Unlock(TheRgn);
+ }
+
+ if (Rgn)
+ REGION_Delete(Rgn);
+
TRACE("Leave NtUserGetUpdateRgn, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
RETURN(FALSE);
}
+ Window->state &= ~WNDS_UPDATEDIRTY;
+
if (Window->hrgnUpdate == NULL)
{
Rect.left = Rect.top = Rect.right = Rect.bottom = 0;
BOOL Ret;
USER_REFERENCE_ENTRY Ref;
NTSTATUS Status = STATUS_SUCCESS;
+ PREGION RgnUpdate = NULL;
DECLARE_RETURN(BOOL);
TRACE("Enter NtUserRedrawWindow\n");
RETURN( FALSE);
}
+ /* We can't hold lock on GDI obects while doing roundtrips to user mode,
+ * so use a copy instead */
+ if (hrgnUpdate)
+ {
+ PREGION RgnTemp;
+
+ RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
+ if (!RgnUpdate)
+ {
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ RETURN(FALSE);
+ }
+
+ RgnTemp = RGNOBJAPI_Lock(hrgnUpdate, NULL);
+ if (!RgnTemp)
+ {
+ EngSetLastError(ERROR_INVALID_HANDLE);
+ RETURN(FALSE);
+ }
+ IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
+ RGNOBJAPI_Unlock(RgnTemp);
+ }
+
UserRefObjectCo(Wnd, &Ref);
Ret = co_UserRedrawWindow( Wnd,
lprcUpdate ? &SafeUpdateRect : NULL,
- hrgnUpdate,
+ RgnUpdate,
flags);
UserDerefObjectCo(Wnd);
RETURN( Ret);
CLEANUP:
+ if (RgnUpdate)
+ REGION_Delete(RgnUpdate);
TRACE("Leave NtUserRedrawWindow, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
INT dy,
const RECTL *prcScroll,
const RECTL *prcClip,
- HRGN hrgnUpdate,
+ PREGION RgnUpdate,
RECTL *prcUpdate)
{
PDC pDC;
/* Calculate the region that was invalidated by moving or
could not be copied, because it was not visible */
- if (hrgnUpdate || prcUpdate)
+ if (RgnUpdate || prcUpdate)
{
- HRGN hrgnOwn, hrgnTmp;
- PREGION prgnTmp;
+ PREGION RgnOwn, RgnTmp;
pDC = DC_LockDc(hDC);
if (!pDC)
rcDst = rcScroll;
RECTL_vOffsetRect(&rcDst, dx, dy);
RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
- if (hrgnUpdate)
+ if (RgnUpdate)
{
- hrgnOwn = hrgnUpdate;
- if (!NtGdiSetRectRgn(hrgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom))
- {
- DC_UnlockDc(pDC);
- return ERROR;
- }
+ RgnOwn = RgnUpdate;
+ REGION_SetRectRgn(RgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom);
}
else
{
- hrgnOwn = IntSysCreateRectRgnIndirect(&rcDst);
+ RgnOwn = IntSysCreateRectpRgnIndirect(&rcDst);
}
/* Add the source rect */
- hrgnTmp = IntSysCreateRectRgnIndirect(&rcSrc);
- NtGdiCombineRgn(hrgnOwn, hrgnOwn, hrgnTmp, RGN_OR);
+ RgnTmp = IntSysCreateRectpRgnIndirect(&rcSrc);
+ IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_OR);
/* Substract the part of the dest that was visible in source */
- prgnTmp = RGNOBJAPI_Lock(hrgnTmp, NULL);
- IntGdiCombineRgn(prgnTmp, prgnTmp, pDC->prgnVis, RGN_AND);
- RGNOBJAPI_Unlock(prgnTmp);
- NtGdiOffsetRgn(hrgnTmp, dx, dy);
- Result = NtGdiCombineRgn(hrgnOwn, hrgnOwn, hrgnTmp, RGN_DIFF);
+ IntGdiCombineRgn(RgnTmp, RgnTmp, pDC->prgnVis, RGN_AND);
+ IntGdiOffsetRgn(RgnTmp, dx, dy);
+ Result = IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_DIFF);
/* DO NOT Unlock DC while messing with prgnVis! */
DC_UnlockDc(pDC);
- GreDeleteObject(hrgnTmp);
+ REGION_Delete(RgnTmp);
if (prcUpdate)
{
- IntGdiGetRgnBox(hrgnOwn, prcUpdate);
+ REGION_GetRgnBox(RgnOwn, prcUpdate);
}
- if (!hrgnUpdate)
+ if (!RgnUpdate)
{
- GreDeleteObject(hrgnOwn);
+ REGION_Delete(RgnOwn);
}
}
else
RECTL rcScroll, rcClip, rcUpdate;
NTSTATUS Status = STATUS_SUCCESS;
DWORD Result;
+ PREGION RgnUpdate = NULL;
TRACE("Enter NtUserScrollDC\n");
UserEnterExclusive();
RETURN(FALSE);
}
+ if (hrgnUpdate)
+ {
+ RgnUpdate = RGNOBJAPI_Lock(hrgnUpdate, NULL);
+ if (!RgnUpdate)
+ RETURN(FALSE);
+ }
+
Result = UserScrollDC( hDC,
dx,
dy,
prcUnsafeScroll? &rcScroll : 0,
prcUnsafeClip? &rcClip : 0,
- hrgnUpdate,
+ RgnUpdate,
prcUnsafeUpdate? &rcUpdate : NULL);
if(Result == ERROR)
{
RETURN(TRUE);
CLEANUP:
- TRACE("Leave NtUserScrollDC, ret=%i\n",_ret_);
+ if (RgnUpdate)
+ RGNOBJAPI_Unlock(RgnUpdate);
+ TRACE("Leave NtUserScrollDC, ret=%lu\n",_ret_);
UserLeave();
END_CLEANUP;
}
INT Result;
PWND Window = NULL, CaretWnd;
HDC hDC;
- HRGN hrgnOwn = NULL, hrgnTemp;
+ PREGION RgnUpdate = NULL, RgnTemp, RgnWinupd = NULL;
HWND hwndCaret;
+ DWORD dcxflags = 0;
+ int rdw_flags;
NTSTATUS Status = STATUS_SUCCESS;
DECLARE_RETURN(DWORD);
USER_REFERENCE_ENTRY Ref, CaretRef;
RETURN(NULLREGION);
}
+ /* We must use a copy of the region, as we can't hold an exclusive lock
+ * on it while doing callouts to user-mode */
+ RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
+ if(!RgnUpdate)
+ {
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ RETURN(ERROR);
+ }
+
if (hrgnUpdate)
- hrgnOwn = hrgnUpdate;
+ {
+ RgnTemp = RGNOBJAPI_Lock(hrgnUpdate, NULL);
+ if (!RgnTemp)
+ {
+ EngSetLastError(ERROR_INVALID_HANDLE);
+ RETURN(ERROR);
+ }
+ IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
+ RGNOBJAPI_Unlock(RgnTemp);
+ }
+
+ /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
+ if (flags & SW_SCROLLWNDDCE)
+ {
+ dcxflags = DCX_USESTYLE;
+
+ if (!(Window->pcls->style & (CS_OWNDC|CS_CLASSDC)))
+ dcxflags |= DCX_CACHE; // AH??? wine~ If not Powned or with Class go Cheap!
+
+ if (flags & SW_SCROLLCHILDREN && Window->style & WS_CLIPCHILDREN)
+ dcxflags |= DCX_CACHE|DCX_NOCLIPCHILDREN;
+ }
else
- hrgnOwn = IntSysCreateRectRgn(0, 0, 0, 0);
+ {
+ /* So in this case ScrollWindowEx uses Cache DC. */
+ dcxflags = DCX_CACHE|DCX_USESTYLE;
+ if (flags & SW_SCROLLCHILDREN) dcxflags |= DCX_NOCLIPCHILDREN;
+ }
- hDC = UserGetDCEx(Window, 0, DCX_CACHE | DCX_USESTYLE);
+ hDC = UserGetDCEx(Window, 0, dcxflags);
if (!hDC)
{
/* FIXME: SetLastError? */
RETURN(ERROR);
}
+ rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ? RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE ;
+
rcCaret = rcScroll;
hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
Result = UserScrollDC( hDC,
dx,
dy,
- &rcScroll,
- &rcClip,
- hrgnOwn,
+ &rcScroll,
+ &rcClip,
+ RgnUpdate,
prcUnsafeUpdate? &rcUpdate : NULL);
UserReleaseDC(Window, hDC, FALSE);
/*
* Take into account the fact that some damage may have occurred during
- * the scroll.
+ * the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end.
*/
- hrgnTemp = IntSysCreateRectRgn(0, 0, 0, 0);
- if (co_UserGetUpdateRgn(Window, hrgnTemp, FALSE) != NULLREGION)
+ RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
+ if (!RgnTemp)
{
- HRGN hrgnClip = IntSysCreateRectRgnIndirect(&rcClip);
- NtGdiOffsetRgn(hrgnTemp, dx, dy);
- NtGdiCombineRgn(hrgnTemp, hrgnTemp, hrgnClip, RGN_AND);
- co_UserRedrawWindow(Window, NULL, hrgnTemp, RDW_INVALIDATE | RDW_ERASE);
- GreDeleteObject(hrgnClip);
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ RETURN(ERROR);
}
- GreDeleteObject(hrgnTemp);
+
+ if (co_UserGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
+ {
+ PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
+ if (RgnClip)
+ {
+ if (hrgnUpdate)
+ {
+ RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
+ IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
+ }
+ IntGdiOffsetRgn(RgnTemp, dx, dy);
+ IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
+ if (hrgnUpdate)
+ IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
+ co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
+ REGION_Delete(RgnClip);
+ }
+ }
+ REGION_Delete(RgnTemp);
if (flags & SW_SCROLLCHILDREN)
{
UserRefObjectCo(Child, &WndRef);
co_WinPosSetWindowPos(Child, 0, rcChild.left + dx, rcChild.top + dy, 0, 0,
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE |
- SWP_NOREDRAW);
+ SWP_NOREDRAW | SWP_DEFERERASE);
UserDerefObjectCo(Child);
}
}
if (flags & (SW_INVALIDATE | SW_ERASE))
{
- co_UserRedrawWindow(Window, NULL, hrgnOwn, RDW_INVALIDATE | RDW_ERASE |
+ co_UserRedrawWindow(Window, NULL, RgnUpdate, rdw_flags |
((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0));
}
- if ((CaretWnd = UserGetWindowObject(hwndCaret)))
+ if (hwndCaret && (CaretWnd = UserGetWindowObject(hwndCaret)))
{
UserRefObjectCo(CaretWnd, &CaretRef);
RETURN(Result);
CLEANUP:
- if (hrgnOwn && !hrgnUpdate)
+ if (hrgnUpdate && (_ret_ != ERROR))
{
- GreDeleteObject(hrgnOwn);
+ /* Give everything back to the caller */
+ RgnTemp = RGNOBJAPI_Lock(hrgnUpdate, NULL);
+ /* The handle should still be valid */
+ ASSERT(RgnTemp);
+ if (RgnWinupd)
+ IntGdiCombineRgn(RgnTemp, RgnUpdate, RgnWinupd, RGN_OR);
+ else
+ IntGdiCombineRgn(RgnTemp, RgnUpdate, NULL, RGN_COPY);
+ RGNOBJAPI_Unlock(RgnTemp);
+ }
+
+ if (RgnWinupd)
+ {
+ REGION_Delete(RgnWinupd);
+ }
+
+ if (RgnUpdate)
+ {
+ REGION_Delete(RgnUpdate);
}
if (Window)
UserDerefObjectCo(Window);
- TRACE("Leave NtUserScrollWindowEx, ret=%i\n",_ret_);
+ TRACE("Leave NtUserScrollWindowEx, ret=%lu\n",_ret_);
UserLeave();
END_CLEANUP;
}
{
PCURICON_OBJECT pIcon = NULL;
- if (!hIcon && pWnd)
+ if (hIcon)
{
- hIcon = pWnd->pcls->hIconSm; // FIXME: Windows does not do that
- if(!hIcon)
- hIcon = pWnd->pcls->hIcon;
+ pIcon = UserGetCurIconObject(hIcon);
+ }
+ else if (pWnd)
+ {
+ pIcon = NC_IconForWindow(pWnd);
+ // FIXME: NC_IconForWindow should reference it for us */
+ if (pIcon)
+ UserReferenceObject(pIcon);
}
-
- if (hIcon)
- pIcon = UserGetCurIconObject(hIcon);
if (pIcon)
{
LONG x = Rect.left - cx/2 + 1 + (Rect.bottom - Rect.top)/2; // this is really what Window does
LONG y = (Rect.top + Rect.bottom)/2 - cy/2; // center
UserDrawIconEx(hDc, x, y, pIcon, cx, cy, 0, NULL, DI_NORMAL);
+ UserDereferenceObject(pIcon);
+ }
+ else
+ {
+ HasIcon = FALSE;
}
}
- if (hIcon)
+ if (HasIcon)
Rect.left += Rect.bottom - Rect.top;
if((uFlags & DC_TEXT))
FASTCALL
UserRealizePalette(HDC hdc)
{
- HWND hWnd;
+ HWND hWnd, hWndDesktop;
DWORD Ret;
Ret = IntGdiRealizePalette(hdc);
hWnd = IntWindowFromDC(hdc);
if (hWnd) // Send broadcast if dc is associated with a window.
{ // FYI: Thread locked in CallOneParam.
+ hWndDesktop = IntGetDesktopWindow();
+ if ( hWndDesktop != hWnd )
+ {
+ PWND pWnd = UserGetWindowObject(hWndDesktop);
+ ERR("RealizePalette Desktop.");
+ hdc = UserGetWindowDC(pWnd);
+ IntPaintDesktop(hdc);
+ UserReleaseDC(pWnd,hdc,FALSE);
+ }
UserSendNotifyMessage((HWND)HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)hWnd, 0);
}
}
CONST RECT *lpUnsafeRect,
BOOL bErase)
{
- return NtUserRedrawWindow(hWnd, lpUnsafeRect, NULL, RDW_INVALIDATE | (bErase? RDW_ERASE : 0));
+ UINT flags = RDW_INVALIDATE | (bErase ? RDW_ERASE : 0);
+ if (!hWnd)
+ {
+ flags = RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW;
+ lpUnsafeRect = NULL;
+ }
+ return NtUserRedrawWindow(hWnd, lpUnsafeRect, NULL, flags);
}
BOOL
HRGN hRgn,
BOOL bErase)
{
+ if (!hWnd)
+ {
+ EngSetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return FALSE;
+ }
return NtUserRedrawWindow(hWnd, NULL, hRgn, RDW_INVALIDATE | (bErase? RDW_ERASE : 0));
}
if (hwnd)
{
- Window = UserGetWindowObject(hwnd);
- // TODO: Add Desktop and MessageBox check via FNID's.
+ if (!(Window = UserGetWindowObject(hwnd)) || // FIXME:
+ Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
+ Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
+ {
+ goto Exit;
+ }
+
if ( Window )
{
/* Validate flags and check it as a mask for 0 or 1. */
EngSetLastError(ERROR_INVALID_PARAMETER);
}
}
-
+Exit:
UserLeave();
return Ret;
}
HWND hWnd,
const RECT *lpRect)
{
- if (hWnd)
+ UINT flags = RDW_VALIDATE;
+ if (!hWnd)
{
- return NtUserRedrawWindow(hWnd, lpRect, NULL, RDW_VALIDATE );
+ flags = RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW;
+ lpRect = NULL;
}
- return NtUserRedrawWindow(hWnd, lpRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ERASENOW|RDW_ALLCHILDREN);
+ return NtUserRedrawWindow(hWnd, lpRect, NULL, flags);
}
/* EOF */