2003-10-06 18:49:50 +00:00
|
|
|
/*
|
|
|
|
* ReactOS W32 Subsystem
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
2004-03-23 18:08:07 +00:00
|
|
|
/* $Id: windc.c,v 1.61 2004/03/23 18:08:07 weiden Exp $
|
2003-10-06 18:49:50 +00:00
|
|
|
*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* PURPOSE: Window classes
|
|
|
|
* FILE: subsys/win32k/ntuser/class.c
|
|
|
|
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
|
|
* REVISION HISTORY:
|
|
|
|
* 06-06-2001 CSH Created
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
|
|
|
#include <ddk/ntddk.h>
|
|
|
|
#include <win32k/win32k.h>
|
|
|
|
#include <win32k/region.h>
|
|
|
|
#include <include/class.h>
|
|
|
|
#include <include/error.h>
|
|
|
|
#include <include/winsta.h>
|
|
|
|
#include <include/msgqueue.h>
|
|
|
|
#include <include/window.h>
|
2003-12-12 18:18:21 +00:00
|
|
|
#include <include/desktop.h>
|
2003-10-06 18:49:50 +00:00
|
|
|
#include <include/rect.h>
|
|
|
|
#include <include/dce.h>
|
|
|
|
#include <include/vis.h>
|
|
|
|
#include <include/object.h>
|
2003-12-13 15:49:32 +00:00
|
|
|
#include <include/intgdi.h>
|
2003-10-06 18:49:50 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
|
|
|
|
static PDCE FirstDce = NULL;
|
|
|
|
static HDC defaultDCstate;
|
|
|
|
|
|
|
|
#define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
|
|
|
|
DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP)
|
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
|
|
|
HRGN STDCALL
|
|
|
|
DceGetVisRgn(HWND hWnd, ULONG Flags, HWND hWndChild, ULONG CFlags)
|
|
|
|
{
|
|
|
|
PWINDOW_OBJECT Window;
|
|
|
|
HRGN VisRgn;
|
|
|
|
|
|
|
|
Window = IntGetWindowObject(hWnd);
|
|
|
|
|
|
|
|
if (NULL == Window)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-01-17 15:18:25 +00:00
|
|
|
VisRgn = VIS_ComputeVisibleRegion(Window,
|
2003-10-06 18:49:50 +00:00
|
|
|
0 == (Flags & DCX_WINDOW),
|
|
|
|
0 != (Flags & DCX_CLIPCHILDREN),
|
|
|
|
0 != (Flags & DCX_CLIPSIBLINGS));
|
|
|
|
|
|
|
|
IntReleaseWindowObject(Window);
|
|
|
|
|
|
|
|
return VisRgn;
|
|
|
|
}
|
|
|
|
|
|
|
|
HDC STDCALL
|
|
|
|
NtUserGetDC(HWND hWnd)
|
|
|
|
{
|
2003-11-19 09:10:36 +00:00
|
|
|
return NtUserGetDCEx(hWnd, NULL, NULL == hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE);
|
2003-10-06 18:49:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PDCE FASTCALL
|
|
|
|
DceAllocDCE(HWND hWnd, DCE_TYPE Type)
|
|
|
|
{
|
|
|
|
HDCE DceHandle;
|
|
|
|
DCE* Dce;
|
2003-12-13 15:49:32 +00:00
|
|
|
UNICODE_STRING DriverName;
|
2003-10-06 18:49:50 +00:00
|
|
|
|
|
|
|
DceHandle = DCEOBJ_AllocDCE();
|
|
|
|
if(!DceHandle)
|
|
|
|
return NULL;
|
|
|
|
|
2003-12-13 15:49:32 +00:00
|
|
|
RtlInitUnicodeString(&DriverName, L"DISPLAY");
|
|
|
|
|
2003-10-06 18:49:50 +00:00
|
|
|
Dce = DCEOBJ_LockDCE(DceHandle);
|
2003-12-14 19:39:50 +00:00
|
|
|
/* No real locking, just get the pointer */
|
|
|
|
DCEOBJ_UnlockDCE(DceHandle);
|
2003-10-09 07:30:02 +00:00
|
|
|
Dce->Self = DceHandle;
|
2003-12-13 15:49:32 +00:00
|
|
|
Dce->hDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL);
|
2003-10-06 18:49:50 +00:00
|
|
|
if (NULL == defaultDCstate)
|
|
|
|
{
|
|
|
|
defaultDCstate = NtGdiGetDCState(Dce->hDC);
|
2003-11-26 21:48:35 +00:00
|
|
|
GDIOBJ_SetOwnership(defaultDCstate, NULL);
|
2003-10-06 18:49:50 +00:00
|
|
|
}
|
|
|
|
Dce->hwndCurrent = hWnd;
|
|
|
|
Dce->hClipRgn = NULL;
|
|
|
|
Dce->next = FirstDce;
|
|
|
|
FirstDce = Dce;
|
|
|
|
|
|
|
|
if (Type != DCE_CACHE_DC)
|
|
|
|
{
|
|
|
|
Dce->DCXFlags = DCX_DCEBUSY;
|
|
|
|
if (hWnd != NULL)
|
|
|
|
{
|
|
|
|
PWINDOW_OBJECT WindowObject;
|
|
|
|
|
|
|
|
WindowObject = IntGetWindowObject(hWnd);
|
|
|
|
if (WindowObject->Style & WS_CLIPCHILDREN)
|
|
|
|
{
|
|
|
|
Dce->DCXFlags |= DCX_CLIPCHILDREN;
|
|
|
|
}
|
|
|
|
if (WindowObject->Style & WS_CLIPSIBLINGS)
|
|
|
|
{
|
|
|
|
Dce->DCXFlags |= DCX_CLIPSIBLINGS;
|
|
|
|
}
|
|
|
|
IntReleaseWindowObject(WindowObject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Dce->DCXFlags = DCX_CACHE | DCX_DCEEMPTY;
|
|
|
|
}
|
|
|
|
|
|
|
|
return(Dce);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID STATIC STDCALL
|
|
|
|
DceSetDrawable(PWINDOW_OBJECT WindowObject, HDC hDC, ULONG Flags,
|
|
|
|
BOOL SetClipOrigin)
|
|
|
|
{
|
|
|
|
DC *dc = DC_LockDc(hDC);
|
|
|
|
if(!dc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (WindowObject == NULL)
|
|
|
|
{
|
|
|
|
dc->w.DCOrgX = 0;
|
|
|
|
dc->w.DCOrgY = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Flags & DCX_WINDOW)
|
|
|
|
{
|
|
|
|
dc->w.DCOrgX = WindowObject->WindowRect.left;
|
|
|
|
dc->w.DCOrgY = WindowObject->WindowRect.top;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dc->w.DCOrgX = WindowObject->ClientRect.left;
|
|
|
|
dc->w.DCOrgY = WindowObject->ClientRect.top;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DC_UnlockDc(hDC);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STATIC VOID FASTCALL
|
|
|
|
DceDeleteClipRgn(DCE* Dce)
|
|
|
|
{
|
|
|
|
Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN | DCX_WINDOWPAINT);
|
|
|
|
|
|
|
|
if (Dce->DCXFlags & DCX_KEEPCLIPRGN )
|
|
|
|
{
|
|
|
|
Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
|
|
|
|
}
|
|
|
|
else if (Dce->hClipRgn > (HRGN) 1)
|
|
|
|
{
|
|
|
|
NtGdiDeleteObject(Dce->hClipRgn);
|
|
|
|
}
|
|
|
|
|
|
|
|
Dce->hClipRgn = NULL;
|
|
|
|
|
|
|
|
/* make it dirty so that the vis rgn gets recomputed next time */
|
|
|
|
Dce->DCXFlags |= DCX_DCEDIRTY;
|
|
|
|
}
|
|
|
|
|
|
|
|
STATIC INT FASTCALL
|
|
|
|
DceReleaseDC(DCE* dce)
|
|
|
|
{
|
|
|
|
if (DCX_DCEBUSY != (dce->DCXFlags & (DCX_DCEEMPTY | DCX_DCEBUSY)))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* restore previous visible region */
|
|
|
|
|
|
|
|
if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) &&
|
|
|
|
(dce->DCXFlags & (DCX_CACHE | DCX_WINDOWPAINT)) )
|
|
|
|
{
|
2003-10-09 07:30:02 +00:00
|
|
|
DceDeleteClipRgn(dce);
|
2003-10-06 18:49:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dce->DCXFlags & DCX_CACHE)
|
|
|
|
{
|
|
|
|
/* make the DC clean so that SetDCState doesn't try to update the vis rgn */
|
|
|
|
NtGdiSetHookFlags(dce->hDC, DCHF_VALIDATEVISRGN);
|
|
|
|
NtGdiSetDCState(dce->hDC, defaultDCstate);
|
|
|
|
dce->DCXFlags &= ~DCX_DCEBUSY;
|
|
|
|
if (dce->DCXFlags & DCX_DCEDIRTY)
|
|
|
|
{
|
|
|
|
/* don't keep around invalidated entries
|
|
|
|
* because SetDCState() disables hVisRgn updates
|
|
|
|
* by removing dirty bit. */
|
|
|
|
dce->hwndCurrent = 0;
|
|
|
|
dce->DCXFlags &= DCX_CACHE;
|
|
|
|
dce->DCXFlags |= DCX_DCEEMPTY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-02-02 22:09:05 +00:00
|
|
|
STATIC VOID FASTCALL
|
|
|
|
DceUpdateVisRgn(DCE *Dce, PWINDOW_OBJECT Window, ULONG Flags)
|
|
|
|
{
|
2004-02-22 12:25:35 +00:00
|
|
|
HANDLE hRgnVisible = NULL;
|
|
|
|
ULONG DcxFlags;
|
|
|
|
PWINDOW_OBJECT DesktopWindow;
|
2004-02-02 22:09:05 +00:00
|
|
|
|
2004-02-22 12:25:35 +00:00
|
|
|
if (Flags & DCX_PARENTCLIP)
|
|
|
|
{
|
2004-02-02 22:09:05 +00:00
|
|
|
PWINDOW_OBJECT Parent;
|
|
|
|
|
2004-02-24 01:30:58 +00:00
|
|
|
Parent = IntGetParentObject(Window);
|
|
|
|
if(!Parent)
|
|
|
|
{
|
|
|
|
hRgnVisible = NULL;
|
|
|
|
goto noparent;
|
|
|
|
}
|
|
|
|
|
2004-02-22 12:25:35 +00:00
|
|
|
if (Parent->Style & WS_CLIPSIBLINGS)
|
|
|
|
{
|
|
|
|
DcxFlags = DCX_CLIPSIBLINGS |
|
|
|
|
(Flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
|
|
|
|
}
|
2004-02-02 22:09:05 +00:00
|
|
|
else
|
2004-02-22 12:25:35 +00:00
|
|
|
{
|
|
|
|
DcxFlags = Flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
|
|
|
|
}
|
|
|
|
hRgnVisible = DceGetVisRgn(Parent->Self, DcxFlags, Window->Self, Flags);
|
|
|
|
if (hRgnVisible == NULL)
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2004-02-02 23:28:17 +00:00
|
|
|
DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
|
|
|
|
if (NULL != DesktopWindow)
|
2004-02-22 12:25:35 +00:00
|
|
|
{
|
|
|
|
hRgnVisible = UnsafeIntCreateRectRgnIndirect(&DesktopWindow->WindowRect);
|
|
|
|
IntReleaseWindowObject(DesktopWindow);
|
|
|
|
}
|
2004-02-02 23:28:17 +00:00
|
|
|
else
|
2004-02-22 12:25:35 +00:00
|
|
|
{
|
|
|
|
hRgnVisible = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-02-02 23:28:17 +00:00
|
|
|
hRgnVisible = DceGetVisRgn(Window->Self, Flags, 0, 0);
|
2004-02-22 12:25:35 +00:00
|
|
|
}
|
2004-02-02 22:09:05 +00:00
|
|
|
|
2004-02-24 01:30:58 +00:00
|
|
|
noparent:
|
2004-02-22 12:25:35 +00:00
|
|
|
if (Flags & DCX_INTERSECTRGN)
|
|
|
|
{
|
2004-02-02 22:09:05 +00:00
|
|
|
NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_AND);
|
2004-02-22 12:25:35 +00:00
|
|
|
}
|
2004-02-02 22:09:05 +00:00
|
|
|
|
2004-02-22 12:25:35 +00:00
|
|
|
if (Flags & DCX_EXCLUDERGN)
|
|
|
|
{
|
2004-02-02 22:09:05 +00:00
|
|
|
NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_DIFF);
|
2004-02-22 12:25:35 +00:00
|
|
|
}
|
2004-02-02 22:09:05 +00:00
|
|
|
|
2004-02-22 12:25:35 +00:00
|
|
|
Dce->DCXFlags &= ~DCX_DCEDIRTY;
|
|
|
|
NtGdiSelectVisRgn(Dce->hDC, hRgnVisible);
|
2004-02-02 22:09:05 +00:00
|
|
|
|
2004-02-22 12:25:35 +00:00
|
|
|
if (hRgnVisible != NULL)
|
|
|
|
{
|
2004-02-02 22:09:05 +00:00
|
|
|
NtGdiDeleteObject(hRgnVisible);
|
2004-02-22 12:25:35 +00:00
|
|
|
}
|
2004-02-02 22:09:05 +00:00
|
|
|
}
|
|
|
|
|
2003-10-06 18:49:50 +00:00
|
|
|
HDC STDCALL
|
|
|
|
NtUserGetDCEx(HWND hWnd, HANDLE ClipRegion, ULONG Flags)
|
|
|
|
{
|
2004-02-24 01:30:58 +00:00
|
|
|
PWINDOW_OBJECT Window, Parent;
|
2003-10-06 18:49:50 +00:00
|
|
|
ULONG DcxFlags;
|
|
|
|
DCE* Dce;
|
|
|
|
BOOL UpdateVisRgn = TRUE;
|
|
|
|
BOOL UpdateClipOrigin = FALSE;
|
|
|
|
|
|
|
|
if (NULL == hWnd)
|
|
|
|
{
|
|
|
|
Flags &= ~DCX_USESTYLE;
|
|
|
|
Window = NULL;
|
|
|
|
}
|
|
|
|
else if (NULL == (Window = IntGetWindowObject(hWnd)))
|
|
|
|
{
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL == Window || NULL == Window->Dce)
|
|
|
|
{
|
|
|
|
Flags |= DCX_CACHE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (Flags & DCX_USESTYLE)
|
|
|
|
{
|
|
|
|
Flags &= ~(DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP);
|
|
|
|
|
|
|
|
if (Window->Style & WS_CLIPSIBLINGS)
|
|
|
|
{
|
|
|
|
Flags |= DCX_CLIPSIBLINGS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(Flags & DCX_WINDOW))
|
|
|
|
{
|
|
|
|
if (Window->Class->style & CS_PARENTDC)
|
|
|
|
{
|
|
|
|
Flags |= DCX_PARENTCLIP;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Window->Style & WS_CLIPCHILDREN &&
|
|
|
|
!(Window->Style & WS_MINIMIZE))
|
|
|
|
{
|
|
|
|
Flags |= DCX_CLIPCHILDREN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Flags |= DCX_CACHE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Flags & DCX_NOCLIPCHILDREN)
|
|
|
|
{
|
|
|
|
Flags |= DCX_CACHE;
|
|
|
|
Flags |= ~(DCX_PARENTCLIP | DCX_CLIPCHILDREN);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Flags & DCX_WINDOW)
|
|
|
|
{
|
|
|
|
Flags = (Flags & ~DCX_CLIPCHILDREN) | DCX_CACHE;
|
|
|
|
}
|
|
|
|
|
2004-02-24 01:30:58 +00:00
|
|
|
Parent = (Window ? IntGetParentObject(Window) : NULL);
|
|
|
|
|
|
|
|
if (NULL == Window || !(Window->Style & WS_CHILD) || NULL == Parent)
|
2003-10-06 18:49:50 +00:00
|
|
|
{
|
|
|
|
Flags &= ~DCX_PARENTCLIP;
|
|
|
|
}
|
|
|
|
else if (Flags & DCX_PARENTCLIP)
|
|
|
|
{
|
|
|
|
Flags |= DCX_CACHE;
|
2004-02-21 13:13:27 +00:00
|
|
|
if ((Window->Style & WS_VISIBLE) &&
|
2004-02-24 01:30:58 +00:00
|
|
|
(Parent->Style & WS_VISIBLE))
|
2004-02-21 13:13:27 +00:00
|
|
|
{
|
|
|
|
Flags &= ~DCX_CLIPCHILDREN;
|
2004-02-24 01:30:58 +00:00
|
|
|
if (Parent->Style & WS_CLIPSIBLINGS)
|
2004-02-21 13:13:27 +00:00
|
|
|
{
|
|
|
|
Flags |= DCX_CLIPSIBLINGS;
|
|
|
|
}
|
|
|
|
}
|
2003-10-06 18:49:50 +00:00
|
|
|
}
|
|
|
|
|
2004-02-24 01:30:58 +00:00
|
|
|
if(Parent)
|
|
|
|
IntReleaseWindowObject(Parent);
|
|
|
|
|
2003-10-06 18:49:50 +00:00
|
|
|
DcxFlags = Flags & DCX_CACHECOMPAREMASK;
|
|
|
|
|
|
|
|
if (Flags & DCX_CACHE)
|
|
|
|
{
|
|
|
|
DCE* DceEmpty = NULL;
|
|
|
|
DCE* DceUnused = NULL;
|
|
|
|
|
|
|
|
for (Dce = FirstDce; Dce != NULL; Dce = Dce->next)
|
|
|
|
{
|
|
|
|
if ((Dce->DCXFlags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE)
|
|
|
|
{
|
|
|
|
DceUnused = Dce;
|
|
|
|
if (Dce->DCXFlags & DCX_DCEEMPTY)
|
|
|
|
{
|
|
|
|
DceEmpty = Dce;
|
|
|
|
}
|
|
|
|
else if (Dce->hwndCurrent == hWnd &&
|
|
|
|
((Dce->DCXFlags & DCX_CACHECOMPAREMASK) == DcxFlags))
|
|
|
|
{
|
|
|
|
#if 0 /* FIXME */
|
|
|
|
UpdateVisRgn = FALSE;
|
|
|
|
#endif
|
|
|
|
UpdateClipOrigin = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Dce == NULL)
|
|
|
|
{
|
|
|
|
Dce = (DceEmpty == NULL) ? DceEmpty : DceUnused;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Dce == NULL)
|
|
|
|
{
|
|
|
|
Dce = DceAllocDCE(NULL, DCE_CACHE_DC);
|
|
|
|
}
|
2003-10-20 17:57:05 +00:00
|
|
|
else if (! GDIOBJ_OwnedByCurrentProcess(Dce->Self))
|
|
|
|
{
|
2003-11-26 21:48:35 +00:00
|
|
|
GDIOBJ_SetOwnership(Dce->Self, PsGetCurrentProcess());
|
|
|
|
DC_SetOwnership(Dce->hDC, PsGetCurrentProcess());
|
2003-10-20 17:57:05 +00:00
|
|
|
}
|
2003-10-06 18:49:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Dce = Window->Dce;
|
2003-12-12 17:20:53 +00:00
|
|
|
if (NULL != Dce && Dce->hwndCurrent == hWnd)
|
|
|
|
{
|
|
|
|
UpdateVisRgn = FALSE; /* updated automatically, via DCHook() */
|
|
|
|
}
|
|
|
|
#if 1 /* FIXME */
|
|
|
|
UpdateVisRgn = TRUE;
|
2003-12-12 14:22:37 +00:00
|
|
|
#endif
|
2003-10-06 18:49:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL == Dce)
|
|
|
|
{
|
|
|
|
if(NULL != Window)
|
|
|
|
IntReleaseWindowObject(Window);
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
Dce->hwndCurrent = hWnd;
|
|
|
|
Dce->DCXFlags = DcxFlags | (Flags & DCX_WINDOWPAINT) | DCX_DCEBUSY;
|
|
|
|
|
|
|
|
if (0 == (Flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) && NULL != ClipRegion)
|
|
|
|
{
|
|
|
|
NtGdiDeleteObject(ClipRegion);
|
|
|
|
ClipRegion = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL != Dce->hClipRgn)
|
|
|
|
{
|
|
|
|
DceDeleteClipRgn(Dce);
|
2003-10-17 21:35:45 +00:00
|
|
|
Dce->hClipRgn = NULL;
|
2003-10-06 18:49:50 +00:00
|
|
|
}
|
|
|
|
|
2003-11-18 20:49:39 +00:00
|
|
|
if (0 != (Flags & DCX_INTERSECTUPDATE) && NULL == ClipRegion)
|
|
|
|
{
|
|
|
|
Dce->hClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
|
2003-11-19 09:10:36 +00:00
|
|
|
if (Dce->hClipRgn && Window->UpdateRegion)
|
|
|
|
{
|
2003-11-18 20:49:39 +00:00
|
|
|
NtGdiCombineRgn(Dce->hClipRgn, Window->UpdateRegion, NULL, RGN_COPY);
|
2004-03-23 18:08:07 +00:00
|
|
|
if(Window->WindowRegion && !(Window->Style & WS_MINIMIZE))
|
2004-03-23 16:32:20 +00:00
|
|
|
NtGdiCombineRgn(Dce->hClipRgn, Dce->hClipRgn, Window->WindowRegion, RGN_AND);
|
2003-11-19 09:10:36 +00:00
|
|
|
if (!(Flags & DCX_WINDOW))
|
|
|
|
{
|
2003-12-27 15:09:51 +00:00
|
|
|
NtGdiOffsetRgn(Dce->hClipRgn,
|
|
|
|
Window->WindowRect.left - Window->ClientRect.left,
|
|
|
|
Window->WindowRect.top - Window->ClientRect.top);
|
2003-11-19 09:10:36 +00:00
|
|
|
}
|
|
|
|
}
|
2003-11-20 21:21:29 +00:00
|
|
|
Flags |= DCX_INTERSECTRGN;
|
2003-11-18 20:49:39 +00:00
|
|
|
}
|
|
|
|
|
2003-12-03 08:19:03 +00:00
|
|
|
if (ClipRegion == (HRGN) 1)
|
2003-12-02 19:58:54 +00:00
|
|
|
{
|
|
|
|
if (!(Flags & DCX_WINDOW))
|
|
|
|
{
|
2003-12-03 08:19:03 +00:00
|
|
|
Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
|
2004-03-23 18:08:07 +00:00
|
|
|
if(!Window->WindowRegion || (Window->Style & WS_MINIMIZE))
|
|
|
|
{
|
|
|
|
NtGdiOffsetRgn(Dce->hClipRgn, -Window->ClientRect.left, -Window->ClientRect.top);
|
|
|
|
}
|
|
|
|
else
|
2004-03-23 16:32:20 +00:00
|
|
|
{
|
|
|
|
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));
|
|
|
|
}
|
2003-12-02 19:58:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-12-03 08:19:03 +00:00
|
|
|
Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
|
2003-12-27 15:09:51 +00:00
|
|
|
NtGdiOffsetRgn(Dce->hClipRgn, -Window->WindowRect.left,
|
|
|
|
-Window->WindowRect.top);
|
2004-03-23 18:08:07 +00:00
|
|
|
if(Window->WindowRegion && !(Window->Style & WS_MINIMIZE))
|
2004-03-23 16:32:20 +00:00
|
|
|
NtGdiCombineRgn(Dce->hClipRgn, Dce->hClipRgn, Window->WindowRegion, RGN_AND);
|
2003-12-02 19:58:54 +00:00
|
|
|
}
|
|
|
|
}
|
2003-12-03 08:19:03 +00:00
|
|
|
else if (NULL != ClipRegion)
|
2003-10-06 18:49:50 +00:00
|
|
|
{
|
|
|
|
Dce->hClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
|
2003-12-03 08:19:03 +00:00
|
|
|
if (Dce->hClipRgn)
|
|
|
|
{
|
2004-03-23 18:08:07 +00:00
|
|
|
if(!Window->WindowRegion || (Window->Style & WS_MINIMIZE))
|
2004-03-23 16:32:20 +00:00
|
|
|
NtGdiCombineRgn(Dce->hClipRgn, ClipRegion, NULL, RGN_COPY);
|
2004-03-23 18:08:07 +00:00
|
|
|
else
|
|
|
|
NtGdiCombineRgn(Dce->hClipRgn, ClipRegion, Window->WindowRegion, RGN_AND);
|
2003-12-03 08:19:03 +00:00
|
|
|
}
|
2003-10-06 18:49:50 +00:00
|
|
|
NtGdiDeleteObject(ClipRegion);
|
|
|
|
}
|
|
|
|
|
|
|
|
DceSetDrawable(Window, Dce->hDC, Flags, UpdateClipOrigin);
|
|
|
|
|
|
|
|
if (UpdateVisRgn)
|
|
|
|
{
|
2004-02-02 22:09:05 +00:00
|
|
|
DceUpdateVisRgn(Dce, Window, Flags);
|
2003-10-06 18:49:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL != Window)
|
|
|
|
{
|
|
|
|
IntReleaseWindowObject(Window);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(Dce->hDC);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL FASTCALL
|
|
|
|
DCE_InternalDelete(PDCE Dce)
|
|
|
|
{
|
|
|
|
PDCE PrevInList;
|
|
|
|
|
|
|
|
if (Dce == FirstDce)
|
|
|
|
{
|
|
|
|
FirstDce = Dce->next;
|
|
|
|
PrevInList = Dce;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (PrevInList = FirstDce; NULL != PrevInList; PrevInList = PrevInList->next)
|
|
|
|
{
|
|
|
|
if (Dce == PrevInList->next)
|
|
|
|
{
|
|
|
|
PrevInList->next = Dce->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(NULL != PrevInList);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL != PrevInList;
|
|
|
|
}
|
|
|
|
|
|
|
|
HWND FASTCALL
|
|
|
|
IntWindowFromDC(HDC hDc)
|
|
|
|
{
|
|
|
|
DCE *Dce;
|
|
|
|
for (Dce = FirstDce; Dce != NULL; Dce = Dce->next)
|
|
|
|
{
|
|
|
|
if(Dce->hDC == hDc)
|
|
|
|
{
|
|
|
|
return Dce->hwndCurrent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
INT STDCALL
|
|
|
|
NtUserReleaseDC(HWND hWnd, HDC hDc)
|
|
|
|
{
|
|
|
|
DCE *dce;
|
|
|
|
INT nRet = 0;
|
|
|
|
|
|
|
|
/* FIXME USER_Lock(); */
|
|
|
|
dce = FirstDce;
|
|
|
|
|
|
|
|
DPRINT("%p %p\n", hWnd, hDc);
|
|
|
|
|
|
|
|
while (dce && (dce->hDC != hDc))
|
|
|
|
{
|
|
|
|
dce = dce->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dce && (dce->DCXFlags & DCX_DCEBUSY))
|
|
|
|
{
|
|
|
|
nRet = DceReleaseDC(dce);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME USER_Unlock(); */
|
|
|
|
|
|
|
|
return nRet;
|
|
|
|
}
|
2003-10-09 07:30:02 +00:00
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* DceFreeDCE
|
|
|
|
*/
|
|
|
|
PDCE FASTCALL
|
|
|
|
DceFreeDCE(PDCE dce)
|
|
|
|
{
|
2003-11-24 21:20:35 +00:00
|
|
|
DCE *ret;
|
2003-10-09 07:30:02 +00:00
|
|
|
HANDLE hDce;
|
|
|
|
|
|
|
|
if (NULL == dce)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0 /* FIXME */
|
|
|
|
USER_Lock();
|
|
|
|
#endif
|
|
|
|
|
2003-11-24 21:20:35 +00:00
|
|
|
ret = dce->next;
|
2003-10-09 07:30:02 +00:00
|
|
|
|
|
|
|
#if 0 /* FIXME */
|
|
|
|
USER_Unlock();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0 /* FIXME */
|
|
|
|
SetDCHook(dce->hDC, NULL, 0L);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
NtGdiDeleteDC(dce->hDC);
|
|
|
|
if (dce->hClipRgn && ! (dce->DCXFlags & DCX_KEEPCLIPRGN))
|
|
|
|
{
|
|
|
|
NtGdiDeleteObject(dce->hClipRgn);
|
|
|
|
}
|
|
|
|
|
|
|
|
hDce = dce->Self;
|
|
|
|
DCEOBJ_FreeDCE(hDce);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2003-10-06 18:49:50 +00:00
|
|
|
|
|
|
|
|
2003-10-09 07:30:02 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* DceFreeWindowDCE
|
|
|
|
*
|
|
|
|
* Remove owned DCE and reset unreleased cache DCEs.
|
|
|
|
*/
|
|
|
|
void FASTCALL
|
2003-10-22 13:34:25 +00:00
|
|
|
DceFreeWindowDCE(PWINDOW_OBJECT Window)
|
2003-10-09 07:30:02 +00:00
|
|
|
{
|
|
|
|
DCE *pDCE;
|
|
|
|
|
|
|
|
pDCE = FirstDce;
|
|
|
|
while (pDCE)
|
|
|
|
{
|
2003-10-22 13:34:25 +00:00
|
|
|
if (pDCE->hwndCurrent == Window->Self)
|
2003-10-09 07:30:02 +00:00
|
|
|
{
|
2003-10-22 13:34:25 +00:00
|
|
|
if (pDCE == Window->Dce) /* owned or Class DCE*/
|
2003-10-09 07:30:02 +00:00
|
|
|
{
|
2003-10-22 13:34:25 +00:00
|
|
|
if (Window->Class->style & CS_OWNDC) /* owned DCE*/
|
2003-10-09 07:30:02 +00:00
|
|
|
{
|
|
|
|
pDCE = DceFreeDCE(pDCE);
|
2003-10-22 13:34:25 +00:00
|
|
|
Window->Dce = NULL;
|
2003-10-09 07:30:02 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (pDCE->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) /* Class DCE*/
|
|
|
|
{
|
|
|
|
DceDeleteClipRgn(pDCE);
|
|
|
|
pDCE->hwndCurrent = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pDCE->DCXFlags & DCX_DCEBUSY) /* shared cache DCE */
|
|
|
|
{
|
|
|
|
/* FIXME: AFAICS we are doing the right thing here so
|
|
|
|
* this should be a DPRINT. But this is best left as an ERR
|
|
|
|
* because the 'application error' is likely to come from
|
|
|
|
* another part of Wine (i.e. it's our fault after all).
|
|
|
|
* We should change this to DPRINT when ReactOS is more stable
|
|
|
|
* (for 1.0?).
|
|
|
|
*/
|
2003-10-22 13:34:25 +00:00
|
|
|
DPRINT1("[%p] GetDC() without ReleaseDC()!\n", Window->Self);
|
2003-10-09 07:30:02 +00:00
|
|
|
DceReleaseDC(pDCE);
|
|
|
|
}
|
|
|
|
|
|
|
|
pDCE->DCXFlags &= DCX_CACHE;
|
|
|
|
pDCE->DCXFlags |= DCX_DCEEMPTY;
|
|
|
|
pDCE->hwndCurrent = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pDCE = pDCE->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-24 21:20:35 +00:00
|
|
|
void FASTCALL
|
|
|
|
DceEmptyCache()
|
|
|
|
{
|
|
|
|
while (FirstDce != NULL)
|
|
|
|
{
|
|
|
|
DceFreeDCE(FirstDce);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-02-04 22:59:04 +00:00
|
|
|
VOID FASTCALL
|
|
|
|
DceResetActiveDCEs(PWINDOW_OBJECT Window, int DeltaX, int DeltaY)
|
2004-02-02 22:09:05 +00:00
|
|
|
{
|
|
|
|
DCE *pDCE;
|
|
|
|
PDC dc;
|
2004-02-04 22:59:04 +00:00
|
|
|
PWINDOW_OBJECT CurrentWindow;
|
2004-02-02 22:09:05 +00:00
|
|
|
|
|
|
|
if (NULL == Window)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pDCE = FirstDce;
|
|
|
|
while (pDCE)
|
|
|
|
{
|
2004-02-04 22:59:04 +00:00
|
|
|
if (0 == (pDCE->DCXFlags & DCX_DCEEMPTY))
|
2004-02-02 22:09:05 +00:00
|
|
|
{
|
2004-02-04 22:59:04 +00:00
|
|
|
if (Window->Self == pDCE->hwndCurrent)
|
|
|
|
{
|
|
|
|
CurrentWindow = Window;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CurrentWindow = IntGetWindowObject(pDCE->hwndCurrent);
|
|
|
|
if (NULL == CurrentWindow)
|
|
|
|
{
|
|
|
|
pDCE = pDCE->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2004-02-02 22:09:05 +00:00
|
|
|
dc = DC_LockDc(pDCE->hDC);
|
|
|
|
if (dc == NULL)
|
|
|
|
{
|
2004-02-04 22:59:04 +00:00
|
|
|
if (Window->Self != pDCE->hwndCurrent)
|
|
|
|
{
|
|
|
|
IntReleaseWindowObject(CurrentWindow);
|
|
|
|
}
|
2004-02-02 22:09:05 +00:00
|
|
|
pDCE = pDCE->next;
|
|
|
|
continue;
|
|
|
|
}
|
2004-02-04 22:59:04 +00:00
|
|
|
if ((0 != DeltaX || 0 != DeltaY)
|
|
|
|
&& (Window == CurrentWindow || IntIsChildWindow(Window->Self, CurrentWindow->Self)))
|
|
|
|
{
|
|
|
|
dc->w.DCOrgX += DeltaX;
|
|
|
|
dc->w.DCOrgY += DeltaY;
|
2004-02-08 22:02:40 +00:00
|
|
|
if (NULL != dc->w.hClipRgn)
|
|
|
|
{
|
|
|
|
NtGdiOffsetRgn(dc->w.hClipRgn, DeltaX, DeltaY);
|
|
|
|
}
|
|
|
|
if (NULL != pDCE->hClipRgn)
|
|
|
|
{
|
|
|
|
NtGdiOffsetRgn(pDCE->hClipRgn, DeltaX, DeltaY);
|
|
|
|
}
|
2004-02-04 22:59:04 +00:00
|
|
|
}
|
2004-02-02 22:09:05 +00:00
|
|
|
DC_UnlockDc(pDCE->hDC);
|
|
|
|
|
2004-02-04 22:59:04 +00:00
|
|
|
DceUpdateVisRgn(pDCE, CurrentWindow, pDCE->DCXFlags);
|
2004-02-02 22:09:05 +00:00
|
|
|
|
2004-02-04 22:59:04 +00:00
|
|
|
if (Window->Self != pDCE->hwndCurrent)
|
|
|
|
{
|
|
|
|
IntReleaseWindowObject(CurrentWindow);
|
|
|
|
}
|
2004-02-02 22:09:05 +00:00
|
|
|
}
|
|
|
|
pDCE = pDCE->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-06 18:49:50 +00:00
|
|
|
/* EOF */
|