From 1231d02b035012940cb6c570f64aa048d2aa888d Mon Sep 17 00:00:00 2001 From: Jason Filby Date: Sat, 24 Aug 2002 11:09:17 +0000 Subject: [PATCH] Initial code for NtUserGetDC svn path=/trunk/; revision=3387 --- reactos/include/defines.h | 2 + reactos/include/user32/wininternal.h | 10 +- reactos/include/win32k/gdiobj.h | 1 + reactos/include/win32k/ntuser.h | 6 +- reactos/lib/user32/windows/dc.c | 6 +- reactos/subsys/win32k/include/window.h | 3 + reactos/subsys/win32k/ntuser/stubs.c | 11 +- reactos/subsys/win32k/ntuser/windc.c | 168 ++++++++++++++++++++++++- reactos/subsys/win32k/ntuser/window.c | 13 +- 9 files changed, 197 insertions(+), 23 deletions(-) diff --git a/reactos/include/defines.h b/reactos/include/defines.h index 54fc05b0fa3..6e2cbbcd09e 100644 --- a/reactos/include/defines.h +++ b/reactos/include/defines.h @@ -1291,6 +1291,8 @@ extern "C" { #define DCX_EXCLUDERGN (0x40L) #define DCX_INTERSECTRGN (0x80L) #define DCX_VALIDATE (0x200000L) +#define DCX_USESTYLE (0x00010000L) +#define DCX_NORECOMPUTE (0x00100000L) /* GetDeviceCaps */ #define DRIVERVERSION (0) diff --git a/reactos/include/user32/wininternal.h b/reactos/include/user32/wininternal.h index ac0464ca637..30dd71c0b2c 100644 --- a/reactos/include/user32/wininternal.h +++ b/reactos/include/user32/wininternal.h @@ -1,5 +1,9 @@ #define WIN_NCACTIVATED (0x0080) -#define DCX_KEEPCLIPRGN (0x40000) -#define DCX_USESTYLE (0x10000) -#define DCX_WINDOWPAINT (0x20000) +/* internal DCX flags */ +#define DCX_DCEEMPTY 0x00000800 +#define DCX_DCEBUSY 0x00001000 +#define DCX_DCEDIRTY 0x00002000 +#define DCX_WINDOWPAINT 0x00020000 +#define DCX_KEEPCLIPRGN 0x00040000 +#define DCX_NOCLIPCHILDREN 0x00080000 diff --git a/reactos/include/win32k/gdiobj.h b/reactos/include/win32k/gdiobj.h index eee272fa501..419d0454a9b 100644 --- a/reactos/include/win32k/gdiobj.h +++ b/reactos/include/win32k/gdiobj.h @@ -23,6 +23,7 @@ #define GO_METAFILE_DC_MAGIC 0x4f51 #define GO_ENHMETAFILE_MAGIC 0x4f52 #define GO_ENHMETAFILE_DC_MAGIC 0x4f53 +#define GO_DCE_MAGIC 0x4f54 #define GO_MAGIC_DONTCARE 0xffff /* (RJJ) swiped stock handles from wine */ diff --git a/reactos/include/win32k/ntuser.h b/reactos/include/win32k/ntuser.h index 56a89171ba0..11ec1697a67 100644 --- a/reactos/include/win32k/ntuser.h +++ b/reactos/include/win32k/ntuser.h @@ -616,11 +616,9 @@ NtUserGetCursorInfo( DWORD STDCALL -NtUserGetDC( - DWORD Unknown0); +NtUserGetDC(HWND hWnd); -HDC STDCALL -NtUserGetDCEx(HWND hWnd, HANDLE hRegion, ULONG Flags); +HDC STDCALL NtUserGetDCEx(HWND hWnd, HANDLE hRegion, ULONG Flags); DWORD STDCALL diff --git a/reactos/lib/user32/windows/dc.c b/reactos/lib/user32/windows/dc.c index 8285de817c4..d496973b3ce 100644 --- a/reactos/lib/user32/windows/dc.c +++ b/reactos/lib/user32/windows/dc.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dc.c,v 1.6 2002/06/13 20:36:40 dwelch Exp $ +/* $Id: dc.c,v 1.7 2002/08/24 11:09:17 jfilby Exp $ * * PROJECT: ReactOS user32.dll * FILE: lib/user32/windows/input.c @@ -39,7 +39,7 @@ STDCALL GetDC( HWND hWnd) { - return (HDC)0; + return NtUserGetDC(hWnd); } HDC @@ -49,7 +49,7 @@ GetDCEx( HRGN hrgnClip, DWORD flags) { - return (HDC)0; + return NtUserGetDCEx(hWnd, hrgnClip, flags); } HDC STDCALL diff --git a/reactos/subsys/win32k/include/window.h b/reactos/subsys/win32k/include/window.h index 75e25b5fc29..848d6a7a739 100644 --- a/reactos/subsys/win32k/include/window.h +++ b/reactos/subsys/win32k/include/window.h @@ -6,6 +6,7 @@ #include #include #include +#include typedef struct _INTERNALPOS { @@ -72,6 +73,8 @@ typedef struct _WINDOW_OBJECT LIST_ENTRY ThreadListEntry; /* Pointer to the parent window. */ struct _WINDOW_OBJECT* Parent; + /* DC Entries (DCE) */ + PDCE dce; } WINDOW_OBJECT, *PWINDOW_OBJECT; /* Window flags. */ diff --git a/reactos/subsys/win32k/ntuser/stubs.c b/reactos/subsys/win32k/ntuser/stubs.c index 6a33ae7aacd..70b89301a18 100644 --- a/reactos/subsys/win32k/ntuser/stubs.c +++ b/reactos/subsys/win32k/ntuser/stubs.c @@ -825,16 +825,6 @@ NtUserGetCursorInfo( return 0; } -DWORD -STDCALL -NtUserGetDC( - DWORD Unknown0) -{ - UNIMPLEMENTED - - return 0; -} - DWORD STDCALL NtUserGetDoubleClickTime(VOID) @@ -1424,6 +1414,7 @@ NtUserScrollDC( DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) + { UNIMPLEMENTED diff --git a/reactos/subsys/win32k/ntuser/windc.c b/reactos/subsys/win32k/ntuser/windc.c index 1d5ace5d7c4..52427e177f6 100644 --- a/reactos/subsys/win32k/ntuser/windc.c +++ b/reactos/subsys/win32k/ntuser/windc.c @@ -1,4 +1,4 @@ -/* $Id: windc.c,v 1.2 2002/07/17 21:04:57 dwelch Exp $ +/* $Id: windc.c,v 1.3 2002/08/24 11:09:17 jfilby Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -20,12 +20,19 @@ #include #include #include +#include #define NDEBUG #include +static PDCE firstDCE; + /* FUNCTIONS *****************************************************************/ +VOID DCE_FreeWindowDCE(HWND); +INT DCE_ExcludeRgn(HDC, HWND, HRGN); +BOOL DCE_InvalidateDCE(HWND, const PRECTL); + BOOL STATIC DceGetVisRect(PWINDOW_OBJECT Window, BOOL ClientArea, RECT* Rect) { @@ -225,10 +232,167 @@ NtUserReleaseDC(HWND hWnd, HDC hDc) } +DWORD +STDCALL +NtUserGetDC(HWND hWnd) +{ + if (!hWnd) + return NtUserGetDCEx(0, 0, DCX_CACHE | DCX_WINDOW); + return NtUserGetDCEx(hWnd, 0, DCX_USESTYLE); +} + HDC STDCALL NtUserGetDCEx(HWND hWnd, HANDLE hRegion, ULONG Flags) { - + HDC hdc = 0; + HDCE hdce; + PDCE dce; + DWORD dcxFlags = 0; + BOOL bUpdateVisRgn = TRUE; + BOOL bUpdateClipOrigin = FALSE; + HWND parent, full; + PWINDOW_OBJECT Window; + + DPRINT("hWnd %04x, hRegion %04x, Flags %08x\n", hWnd, hRegion, (unsigned)Flags); + + if (!hWnd) hWnd = W32kGetDesktopWindow(); + if (!(Window = W32kGetWindowObject(hWnd))) return 0; + + // fixup flags + + if (Flags & (DCX_WINDOW | DCX_PARENTCLIP)) 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->ExStyle & CS_PARENTDC) Flags |= DCX_PARENTCLIP; + + if (Window->Style & WS_CLIPCHILDREN && + !(Window->Style & WS_MINIMIZE)) Flags |= DCX_CLIPCHILDREN; + if (!Window->dce) Flags |= DCX_CACHE; + } + } + + if (Flags & DCX_WINDOW) Flags &= ~DCX_CLIPCHILDREN; + + parent = W32kGetParentWindow(hWnd); + if (!parent || (parent == W32kGetDesktopWindow())) + Flags = (Flags & ~DCX_PARENTCLIP) | DCX_CLIPSIBLINGS; + + // it seems parent clip is ignored when clipping siblings or children + if (Flags & (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN)) Flags &= ~DCX_PARENTCLIP; + + if(Flags & DCX_PARENTCLIP) + { + LONG parent_style = NtUserGetWindowLong(parent, GWL_STYLE); + if((Window->Style & WS_VISIBLE) && (parent_style & WS_VISIBLE)) + { + Flags &= ~DCX_CLIPCHILDREN; + if (parent_style & WS_CLIPSIBLINGS) Flags |= DCX_CLIPSIBLINGS; + } + } + + // find a suitable DCE + + dcxFlags = Flags & (DCX_PARENTCLIP | DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | + DCX_CACHE | DCX_WINDOW); + + if (Flags & DCX_CACHE) + { + PDCE dceEmpty; + PDCE dceUnused; + + dceEmpty = dceUnused = NULL; + + /* Strategy: First, we attempt to find a non-empty but unused DCE with + * compatible flags. Next, we look for an empty entry. If the cache is + * full we have to purge one of the unused entries. + */ + + for (dce = firstDCE; (dce); 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_CLIPSIBLINGS | DCX_CLIPCHILDREN | + DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP)) == dcxFlags)) + { + DPRINT("Found valid %08x dce [%04x], flags %08x\n", + (unsigned)dce, hWnd, (unsigned)dcxFlags); + bUpdateVisRgn = FALSE; + bUpdateClipOrigin = TRUE; + break; + } + } + } + + if (!dce) dce = (dceEmpty) ? dceEmpty : dceUnused; + + // if there's no dce empty or unused, allocate a new one + if (!dce) + { + hdce = DCEOBJ_AllocDCE(); + if (hdce == NULL) + { + return 0; + } + dce = DCEOBJ_LockDCE(hdce); + dce->type = DCE_CACHE_DC; + } + } + else + { + dce = Window->dce; + if (dce && dce->hwndCurrent == hWnd) + { + DPRINT("skipping hVisRgn update\n"); + bUpdateVisRgn = FALSE; // updated automatically, via DCHook() + } + } + if (!dce) + { + hdc = 0; + goto END; + } + + if (!(Flags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN))) hRegion = 0; + + if (((Flags ^ dce->DCXflags) & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) && + (dce->hClipRgn != hRegion)) + { + // if the extra clip region has changed, get rid of the old one +/* DCE_DeleteClipRgn(dce); */ + } + + dce->hwndCurrent = hWnd; + dce->hClipRgn = hRegion; + dce->DCXflags = Flags & (DCX_PARENTCLIP | DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | + DCX_CACHE | DCX_WINDOW | DCX_WINDOWPAINT | + DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_EXCLUDERGN); + dce->DCXflags |= DCX_DCEBUSY; + dce->DCXflags &= ~DCX_DCEDIRTY; + hdc = dce->hDC; + +/* if (bUpdateVisRgn) SetHookFlags(hdc, DCHF_INVALIDATEVISRGN); // force update */ + +/* if (!USER_Driver.pGetDC(hWnd, hdc, hRegion, Flags)) hdc = 0; */ + + DPRINT("(%04x,%04x,0x%lx): returning %04x\n", hWnd, hRegion, Flags, hdc); + +END: +/* WIN_ReleasePtr(Window); */ + return hdc; } /* EOF */ diff --git a/reactos/subsys/win32k/ntuser/window.c b/reactos/subsys/win32k/ntuser/window.c index 067e25bde60..1fb7bd805d9 100644 --- a/reactos/subsys/win32k/ntuser/window.c +++ b/reactos/subsys/win32k/ntuser/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.9 2002/07/17 21:04:57 dwelch Exp $ +/* $Id: window.c,v 1.10 2002/08/24 11:09:17 jfilby Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -85,6 +85,16 @@ W32kIsDesktopWindow(HWND hWnd) return(IsDesktop); } +HWND W32kGetDesktopWindow() +{ + return W32kGetActiveDesktop()->DesktopWindow; +} + +HWND W32kGetParentWindow(HWND hWnd) +{ + return W32kGetWindowObject(hWnd)->ParentHandle; +} + PWINDOW_OBJECT W32kGetWindowObject(HWND hWnd) { @@ -776,6 +786,7 @@ NtUserSetInternalWindowPos(DWORD Unknown0, UNIMPLEMENTED return 0; + } DWORD STDCALL