Commit 7caa1f6b authored by Alexandre Julliard's avatar Alexandre Julliard

Beginnings of inter-process GetDC support.

Use a standard list for the DCE list. Small cleanups.
parent a9e0fb1b
...@@ -36,20 +36,10 @@ typedef enum ...@@ -36,20 +36,10 @@ typedef enum
DCE_WINDOW_DC /* This is a window DC (style CS_OWNDC) */ DCE_WINDOW_DC /* This is a window DC (style CS_OWNDC) */
} DCE_TYPE; } DCE_TYPE;
struct tagDCE;
typedef struct tagDCE extern struct tagDCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type );
{ extern void DCE_FreeDCE( struct tagDCE *dce );
struct tagDCE *next;
HDC hDC;
HWND hwndCurrent;
HWND hwndDC;
HRGN hClipRgn;
DCE_TYPE type;
DWORD DCXflags;
} DCE;
extern DCE* DCE_AllocDCE( HWND hWnd, DCE_TYPE type );
extern DCE* DCE_FreeDCE( DCE *dce );
extern void DCE_FreeWindowDCE( HWND ); extern void DCE_FreeWindowDCE( HWND );
extern BOOL DCE_InvalidateDCE( HWND, const RECT* ); extern BOOL DCE_InvalidateDCE( HWND, const RECT* );
......
...@@ -34,16 +34,27 @@ ...@@ -34,16 +34,27 @@
#include "dce.h" #include "dce.h"
#include "win.h" #include "win.h"
#include "user_private.h" #include "user_private.h"
#include "wine/debug.h"
#include "windef.h" #include "windef.h"
#include "wingdi.h" #include "wingdi.h"
#include "wownt32.h" #include "wownt32.h"
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "wine/winuser16.h" #include "wine/winuser16.h"
#include "wine/debug.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(dc); WINE_DEFAULT_DEBUG_CHANNEL(dc);
static DCE *firstDCE; typedef struct tagDCE
{
struct list entry;
HDC hDC;
HWND hwndCurrent;
HRGN hClipRgn;
DCE_TYPE type;
DWORD DCXflags;
} DCE;
static struct list dce_list = LIST_INIT(dce_list);
static void DCE_DeleteClipRgn( DCE* ); static void DCE_DeleteClipRgn( DCE* );
static INT DCE_ReleaseDC( DCE* ); static INT DCE_ReleaseDC( DCE* );
...@@ -58,7 +69,7 @@ static void DCE_DumpCache(void) ...@@ -58,7 +69,7 @@ static void DCE_DumpCache(void)
USER_Lock(); USER_Lock();
for(dce = firstDCE; dce; dce = dce->next) LIST_FOR_EACH_ENTRY( dce, &dce_list, DCE, entry )
{ {
TRACE("\t[0x%08x] hWnd %p, dcx %08x, %s %s\n", TRACE("\t[0x%08x] hWnd %p, dcx %08x, %s %s\n",
(unsigned)dce, dce->hwndCurrent, (unsigned)dce->DCXflags, (unsigned)dce, dce->hwndCurrent, (unsigned)dce->DCXflags,
...@@ -95,6 +106,7 @@ DCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type ) ...@@ -95,6 +106,7 @@ DCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type )
dce->hwndCurrent = hWnd; dce->hwndCurrent = hWnd;
dce->hClipRgn = 0; dce->hClipRgn = 0;
dce->type = type;
if( type != DCE_CACHE_DC ) /* owned or class DC */ if( type != DCE_CACHE_DC ) /* owned or class DC */
{ {
...@@ -110,8 +122,7 @@ DCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type ) ...@@ -110,8 +122,7 @@ DCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type )
else dce->DCXflags = DCX_CACHE | DCX_DCEEMPTY; else dce->DCXflags = DCX_CACHE | DCX_DCEEMPTY;
USER_Lock(); USER_Lock();
dce->next = firstDCE; list_add_head( &dce_list, &dce->entry );
firstDCE = dce;
USER_Unlock(); USER_Unlock();
return dce; return dce;
} }
...@@ -120,19 +131,12 @@ DCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type ) ...@@ -120,19 +131,12 @@ DCE *DCE_AllocDCE( HWND hWnd, DCE_TYPE type )
/*********************************************************************** /***********************************************************************
* DCE_FreeDCE * DCE_FreeDCE
*/ */
DCE* DCE_FreeDCE( DCE *dce ) void DCE_FreeDCE( DCE *dce )
{ {
DCE **ppDCE, *ret; if (!dce) return;
if (!dce) return NULL;
USER_Lock(); USER_Lock();
list_remove( &dce->entry );
ppDCE = &firstDCE;
while (*ppDCE && (*ppDCE != dce)) ppDCE = &(*ppDCE)->next;
if (*ppDCE == dce) *ppDCE = dce->next;
ret = *ppDCE;
USER_Unlock(); USER_Unlock();
SetDCHook(dce->hDC, NULL, 0L); SetDCHook(dce->hDC, NULL, 0L);
...@@ -140,8 +144,6 @@ DCE* DCE_FreeDCE( DCE *dce ) ...@@ -140,8 +144,6 @@ DCE* DCE_FreeDCE( DCE *dce )
DeleteDC( dce->hDC ); DeleteDC( dce->hDC );
if (dce->hClipRgn) DeleteObject(dce->hClipRgn); if (dce->hClipRgn) DeleteObject(dce->hClipRgn);
HeapFree( GetProcessHeap(), 0, dce ); HeapFree( GetProcessHeap(), 0, dce );
return ret;
} }
/*********************************************************************** /***********************************************************************
...@@ -151,54 +153,44 @@ DCE* DCE_FreeDCE( DCE *dce ) ...@@ -151,54 +153,44 @@ DCE* DCE_FreeDCE( DCE *dce )
*/ */
void DCE_FreeWindowDCE( HWND hwnd ) void DCE_FreeWindowDCE( HWND hwnd )
{ {
DCE *pDCE; struct list *ptr, *next;
WND *pWnd = WIN_GetPtr( hwnd ); WND *pWnd = WIN_GetPtr( hwnd );
pDCE = firstDCE; LIST_FOR_EACH_SAFE( ptr, next, &dce_list )
while( pDCE )
{
if( pDCE->hwndCurrent == hwnd )
{ {
if( pDCE == pWnd->dce ) /* owned or Class DCE*/ DCE *pDCE = LIST_ENTRY( ptr, DCE, entry );
{
if (pWnd->clsStyle & CS_OWNDC) /* owned DCE*/ if (pDCE->hwndCurrent != hwnd) continue;
switch( pDCE->type )
{ {
pDCE = DCE_FreeDCE( pDCE ); case DCE_WINDOW_DC:
DCE_FreeDCE( pDCE );
pWnd->dce = NULL; pWnd->dce = NULL;
continue; break;
} case DCE_CLASS_DC:
else if( pDCE->DCXflags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN) ) /* Class DCE*/ if( pDCE->DCXflags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN) )
{ {
if (USER_Driver.pReleaseDC) if (USER_Driver.pReleaseDC)
USER_Driver.pReleaseDC( pDCE->hwndCurrent, pDCE->hDC ); USER_Driver.pReleaseDC( pDCE->hwndCurrent, pDCE->hDC );
DCE_DeleteClipRgn( pDCE ); DCE_DeleteClipRgn( pDCE );
pDCE->hwndCurrent = 0; pDCE->hwndCurrent = 0;
} }
} break;
else case DCE_CACHE_DC:
{
if( pDCE->DCXflags & DCX_DCEBUSY ) /* shared cache DCE */ if( pDCE->DCXflags & DCX_DCEBUSY ) /* shared cache DCE */
{ {
/* FIXME: AFAICS we are doing the right thing here so WARN("[%p] GetDC() without ReleaseDC()!\n",hwnd);
* this should be a WARN. 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 WARN when Wine is more stable
* (for 1.0?).
*/
ERR("[%p] GetDC() without ReleaseDC()!\n",hwnd);
DCE_ReleaseDC( pDCE ); DCE_ReleaseDC( pDCE );
} }
if (pDCE->hwndCurrent && USER_Driver.pReleaseDC) if (pDCE->hwndCurrent && USER_Driver.pReleaseDC)
USER_Driver.pReleaseDC( pDCE->hwndCurrent, pDCE->hDC ); USER_Driver.pReleaseDC( pDCE->hwndCurrent, pDCE->hDC );
pDCE->DCXflags &= DCX_CACHE; pDCE->DCXflags &= DCX_CACHE;
pDCE->DCXflags |= DCX_DCEEMPTY; pDCE->DCXflags |= DCX_DCEEMPTY;
pDCE->hwndCurrent = 0; pDCE->hwndCurrent = 0;
break;
} }
} }
pDCE = pDCE->next;
}
WIN_ReleasePtr( pWnd ); WIN_ReleasePtr( pWnd );
} }
...@@ -280,7 +272,7 @@ BOOL DCE_InvalidateDCE(HWND hwnd, const RECT* pRectUpdate) ...@@ -280,7 +272,7 @@ BOOL DCE_InvalidateDCE(HWND hwnd, const RECT* pRectUpdate)
/* walk all DCEs and fixup non-empty entries */ /* walk all DCEs and fixup non-empty entries */
for (dce = firstDCE; (dce); dce = dce->next) LIST_FOR_EACH_ENTRY( dce, &dce_list, DCE, entry )
{ {
if (dce->DCXflags & DCX_DCEEMPTY) continue; if (dce->DCXflags & DCX_DCEEMPTY) continue;
if ((dce->hwndCurrent == hwndScope) && !(dce->DCXflags & DCX_CLIPCHILDREN)) if ((dce->hwndCurrent == hwndScope) && !(dce->DCXflags & DCX_CLIPCHILDREN))
...@@ -341,7 +333,8 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags ) ...@@ -341,7 +333,8 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
DWORD dcxFlags = 0; DWORD dcxFlags = 0;
BOOL bUpdateVisRgn = TRUE; BOOL bUpdateVisRgn = TRUE;
BOOL bUpdateClipOrigin = FALSE; BOOL bUpdateClipOrigin = FALSE;
HWND parent, full; HWND parent;
LONG window_style;
TRACE("hwnd %p, hrgnClip %p, flags %08lx\n", hwnd, hrgnClip, flags); TRACE("hwnd %p, hrgnClip %p, flags %08lx\n", hwnd, hrgnClip, flags);
...@@ -353,13 +346,16 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags ) ...@@ -353,13 +346,16 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
} }
if (!hwnd) hwnd = GetDesktopWindow(); if (!hwnd) hwnd = GetDesktopWindow();
if (!(full = WIN_IsCurrentProcess( hwnd ))) else hwnd = WIN_GetFullHandle( hwnd );
if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
if (wndPtr == WND_OTHER_PROCESS)
{ {
FIXME( "not supported yet on other process window %p\n", hwnd ); wndPtr = NULL;
return 0; USER_Lock();
} }
hwnd = full;
if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0; window_style = GetWindowLongW( hwnd, GWL_STYLE );
/* fixup flags */ /* fixup flags */
...@@ -369,16 +365,16 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags ) ...@@ -369,16 +365,16 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
{ {
flags &= ~( DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP); flags &= ~( DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP);
if( wndPtr->dwStyle & WS_CLIPSIBLINGS ) if( window_style & WS_CLIPSIBLINGS )
flags |= DCX_CLIPSIBLINGS; flags |= DCX_CLIPSIBLINGS;
if ( !(flags & DCX_WINDOW) ) if ( !(flags & DCX_WINDOW) )
{ {
if (wndPtr->clsStyle & CS_PARENTDC) flags |= DCX_PARENTCLIP; if (GetClassLongW( hwnd, GCL_STYLE ) & CS_PARENTDC) flags |= DCX_PARENTCLIP;
if (wndPtr->dwStyle & WS_CLIPCHILDREN && if (window_style & WS_CLIPCHILDREN && !(window_style & WS_MINIMIZE))
!(wndPtr->dwStyle & WS_MINIMIZE) ) flags |= DCX_CLIPCHILDREN; flags |= DCX_CLIPCHILDREN;
if (!wndPtr->dce) flags |= DCX_CACHE; if (!wndPtr || !wndPtr->dce) flags |= DCX_CACHE;
} }
} }
...@@ -394,7 +390,7 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags ) ...@@ -394,7 +390,7 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
if( flags & DCX_PARENTCLIP ) if( flags & DCX_PARENTCLIP )
{ {
LONG parent_style = GetWindowLongW( parent, GWL_STYLE ); LONG parent_style = GetWindowLongW( parent, GWL_STYLE );
if( (wndPtr->dwStyle & WS_VISIBLE) && (parent_style & WS_VISIBLE) ) if( (window_style & WS_VISIBLE) && (parent_style & WS_VISIBLE) )
{ {
flags &= ~DCX_CLIPCHILDREN; flags &= ~DCX_CLIPCHILDREN;
if (parent_style & WS_CLIPSIBLINGS) flags |= DCX_CLIPSIBLINGS; if (parent_style & WS_CLIPSIBLINGS) flags |= DCX_CLIPSIBLINGS;
...@@ -408,17 +404,14 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags ) ...@@ -408,17 +404,14 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
if (flags & DCX_CACHE) if (flags & DCX_CACHE)
{ {
DCE* dceEmpty; DCE *dceEmpty = NULL, *dceUnused = NULL;
DCE* dceUnused;
dceEmpty = dceUnused = NULL;
/* Strategy: First, we attempt to find a non-empty but unused DCE with /* 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 * compatible flags. Next, we look for an empty entry. If the cache is
* full we have to purge one of the unused entries. * full we have to purge one of the unused entries.
*/ */
for (dce = firstDCE; (dce); dce = dce->next) LIST_FOR_EACH_ENTRY( dce, &dce_list, DCE, entry )
{ {
if ((dce->DCXflags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE ) if ((dce->DCXflags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE )
{ {
...@@ -440,7 +433,8 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags ) ...@@ -440,7 +433,8 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
} }
} }
if (!dce) dce = (dceEmpty) ? dceEmpty : dceUnused; if (&dce->entry == &dce_list) /* nothing found */
dce = dceEmpty ? dceEmpty : dceUnused;
/* if there's no dce empty or unused, allocate a new one */ /* if there's no dce empty or unused, allocate a new one */
if (!dce) if (!dce)
...@@ -488,7 +482,8 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags ) ...@@ -488,7 +482,8 @@ HDC WINAPI GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
TRACE("(%p,%p,0x%lx): returning %p\n", hwnd, hrgnClip, flags, hdc); TRACE("(%p,%p,0x%lx): returning %p\n", hwnd, hrgnClip, flags, hdc);
END: END:
WIN_ReleasePtr(wndPtr); if (wndPtr) WIN_ReleasePtr(wndPtr);
else USER_Unlock();
return hdc; return hdc;
} }
...@@ -533,17 +528,19 @@ INT WINAPI ReleaseDC( HWND hwnd, HDC hdc ) ...@@ -533,17 +528,19 @@ INT WINAPI ReleaseDC( HWND hwnd, HDC hdc )
DCE * dce; DCE * dce;
INT nRet = 0; INT nRet = 0;
USER_Lock();
dce = firstDCE;
TRACE("%p %p\n", hwnd, hdc ); TRACE("%p %p\n", hwnd, hdc );
while (dce && (dce->hDC != hdc)) dce = dce->next; USER_Lock();
LIST_FOR_EACH_ENTRY( dce, &dce_list, DCE, entry )
if ( dce ) {
if (dce->hDC == hdc)
{
if ( dce->DCXflags & DCX_DCEBUSY ) if ( dce->DCXflags & DCX_DCEBUSY )
nRet = DCE_ReleaseDC( dce ); nRet = DCE_ReleaseDC( dce );
break;
}
}
USER_Unlock(); USER_Unlock();
return nRet; return nRet;
...@@ -615,14 +612,17 @@ BOOL16 WINAPI DCHook16( HDC16 hDC, WORD code, DWORD data, LPARAM lParam ) ...@@ -615,14 +612,17 @@ BOOL16 WINAPI DCHook16( HDC16 hDC, WORD code, DWORD data, LPARAM lParam )
HWND WINAPI WindowFromDC( HDC hDC ) HWND WINAPI WindowFromDC( HDC hDC )
{ {
DCE *dce; DCE *dce;
HWND hwnd; HWND hwnd = 0;
USER_Lock(); USER_Lock();
dce = firstDCE; LIST_FOR_EACH_ENTRY( dce, &dce_list, DCE, entry )
{
while (dce && (dce->hDC != hDC)) dce = dce->next; if (dce->hDC == hDC)
{
hwnd = dce ? dce->hwndCurrent : 0; hwnd = dce->hwndCurrent;
break;
}
}
USER_Unlock(); USER_Unlock();
return hwnd; return hwnd;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment