Commit d99df2b7 authored by Alexandre Julliard's avatar Alexandre Julliard

Only reset the clip region in GetDC() if a new region is specified.

Don't release the clip region for window DCs in ReleaseDC(), except when called from EndPaint(). Added a bunch of tests.
parent af305c74
...@@ -250,7 +250,7 @@ static BOOL send_erase( HWND hwnd, UINT flags, HRGN client_rgn, ...@@ -250,7 +250,7 @@ static BOOL send_erase( HWND hwnd, UINT flags, HRGN client_rgn,
if (hdc_ret || (flags & UPDATE_ERASE)) if (hdc_ret || (flags & UPDATE_ERASE))
{ {
UINT dcx_flags = DCX_INTERSECTRGN | DCX_WINDOWPAINT | DCX_USESTYLE; UINT dcx_flags = DCX_INTERSECTRGN | DCX_USESTYLE;
if (IsIconic(hwnd)) dcx_flags |= DCX_WINDOW; if (IsIconic(hwnd)) dcx_flags |= DCX_WINDOW;
if ((hdc = GetDCEx( hwnd, client_rgn, dcx_flags ))) if ((hdc = GetDCEx( hwnd, client_rgn, dcx_flags )))
...@@ -409,8 +409,7 @@ HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps ) ...@@ -409,8 +409,7 @@ HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps )
BOOL WINAPI EndPaint( HWND hwnd, const PAINTSTRUCT *lps ) BOOL WINAPI EndPaint( HWND hwnd, const PAINTSTRUCT *lps )
{ {
if (!lps) return FALSE; if (!lps) return FALSE;
if (USER_Driver.pReleaseDC) USER_Driver.pReleaseDC( hwnd, lps->hdc, TRUE );
ReleaseDC( hwnd, lps->hdc );
ShowCaret( hwnd ); ShowCaret( hwnd );
return TRUE; return TRUE;
} }
...@@ -465,7 +464,7 @@ HDC WINAPI GetWindowDC( HWND hwnd ) ...@@ -465,7 +464,7 @@ HDC WINAPI GetWindowDC( HWND hwnd )
*/ */
INT WINAPI ReleaseDC( HWND hwnd, HDC hdc ) INT WINAPI ReleaseDC( HWND hwnd, HDC hdc )
{ {
if (USER_Driver.pReleaseDC) return USER_Driver.pReleaseDC( hwnd, hdc ); if (USER_Driver.pReleaseDC) return USER_Driver.pReleaseDC( hwnd, hdc, FALSE );
return 0; return 0;
} }
......
...@@ -102,7 +102,7 @@ typedef struct tagUSER_DRIVER { ...@@ -102,7 +102,7 @@ typedef struct tagUSER_DRIVER {
BOOL (*pDestroyWindow)(HWND); BOOL (*pDestroyWindow)(HWND);
HDC (*pGetDCEx)(HWND,HRGN,DWORD); HDC (*pGetDCEx)(HWND,HRGN,DWORD);
DWORD (*pMsgWaitForMultipleObjectsEx)(DWORD,const HANDLE*,DWORD,DWORD,DWORD); DWORD (*pMsgWaitForMultipleObjectsEx)(DWORD,const HANDLE*,DWORD,DWORD,DWORD);
BOOL (*pReleaseDC)(HWND,HDC); BOOL (*pReleaseDC)(HWND,HDC,BOOL);
BOOL (*pScrollDC)(HDC, INT, INT, const RECT *, const RECT *, HRGN, LPRECT); BOOL (*pScrollDC)(HDC, INT, INT, const RECT *, const RECT *, HRGN, LPRECT);
void (*pSetFocus)(HWND); void (*pSetFocus)(HWND);
HWND (*pSetParent)(HWND,HWND); HWND (*pSetParent)(HWND,HWND);
......
...@@ -17,14 +17,6 @@ ...@@ -17,14 +17,6 @@
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Note: Visible regions of CS_OWNDC/CS_CLASSDC window DCs
* have to be updated dynamically.
*
* Internal DCX flags:
*
* DCX_WINDOWPAINT - BeginPaint() is in effect
*/ */
#include "config.h" #include "config.h"
...@@ -151,11 +143,12 @@ static HWND get_top_clipping_window( HWND hwnd ) ...@@ -151,11 +143,12 @@ static HWND get_top_clipping_window( HWND hwnd )
* Set the drawable, origin and dimensions for the DC associated to * Set the drawable, origin and dimensions for the DC associated to
* a given window. * a given window.
*/ */
static void set_drawable( struct dce *dce, DWORD flags, BOOL update_visrgn ) static void set_drawable( struct dce *dce, BOOL update_visrgn )
{ {
HWND top = get_top_clipping_window( dce->hwnd ); HWND top = get_top_clipping_window( dce->hwnd );
struct x11drv_escape_set_drawable escape; struct x11drv_escape_set_drawable escape;
struct x11drv_win_data *data; struct x11drv_win_data *data;
DWORD flags = dce->flags;
escape.mode = IncludeInferiors; escape.mode = IncludeInferiors;
/* don't clip siblings if using parent clip region */ /* don't clip siblings if using parent clip region */
...@@ -222,13 +215,14 @@ static void set_drawable( struct dce *dce, DWORD flags, BOOL update_visrgn ) ...@@ -222,13 +215,14 @@ static void set_drawable( struct dce *dce, DWORD flags, BOOL update_visrgn )
escape.code = X11DRV_SET_DRAWABLE; escape.code = X11DRV_SET_DRAWABLE;
ExtEscape( dce->hdc, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL ); ExtEscape( dce->hdc, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL );
if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) || update_visrgn) if (update_visrgn)
{ {
/* need to recompute the visible region */ /* need to recompute the visible region */
HRGN visRgn = get_server_visible_region( dce->hwnd, flags ); HRGN visRgn = get_server_visible_region( dce->hwnd, flags );
if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) if (dce->clip_rgn)
CombineRgn( visRgn, visRgn, dce->clip_rgn, (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF ); CombineRgn( visRgn, visRgn, dce->clip_rgn,
(flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
SelectVisRgn16( HDC_16(dce->hdc), HRGN_16(visRgn) ); SelectVisRgn16( HDC_16(dce->hdc), HRGN_16(visRgn) );
DeleteObject( visRgn ); DeleteObject( visRgn );
...@@ -266,7 +260,7 @@ static void delete_clip_rgn( struct dce *dce ) ...@@ -266,7 +260,7 @@ static void delete_clip_rgn( struct dce *dce )
{ {
if (!dce->clip_rgn) return; /* nothing to do */ if (!dce->clip_rgn) return; /* nothing to do */
dce->flags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN | DCX_WINDOWPAINT); dce->flags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN);
DeleteObject( dce->clip_rgn ); DeleteObject( dce->clip_rgn );
dce->clip_rgn = 0; dce->clip_rgn = 0;
...@@ -499,9 +493,10 @@ void invalidate_dce( HWND hwnd, const RECT *rect ) ...@@ -499,9 +493,10 @@ void invalidate_dce( HWND hwnd, const RECT *rect )
*/ */
HDC X11DRV_GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags ) HDC X11DRV_GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
{ {
static const DWORD clip_flags = DCX_PARENTCLIP | DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW;
struct x11drv_win_data *data = X11DRV_get_win_data( hwnd ); struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
struct dce *dce; struct dce *dce;
HDC hdc = 0;
BOOL bUpdateVisRgn = TRUE; BOOL bUpdateVisRgn = TRUE;
HWND parent; HWND parent;
LONG window_style = GetWindowLongW( hwnd, GWL_STYLE ); LONG window_style = GetWindowLongW( hwnd, GWL_STYLE );
...@@ -565,9 +560,7 @@ HDC X11DRV_GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags ) ...@@ -565,9 +560,7 @@ HDC X11DRV_GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
dceUnused = dce; dceUnused = dce;
if (!dce->hwnd) dceEmpty = dce; if (!dce->hwnd) dceEmpty = dce;
else if ((dce->hwnd == hwnd) && else if ((dce->hwnd == hwnd) && !((dce->flags ^ flags) & clip_flags))
(!((dce->flags ^ flags) & (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN |
DCX_WINDOW | DCX_PARENTCLIP))))
{ {
TRACE("\tfound valid %p dce [%p], flags %08lx\n", TRACE("\tfound valid %p dce [%p], flags %08lx\n",
dce, hwnd, dce->flags ); dce, hwnd, dce->flags );
...@@ -597,44 +590,48 @@ HDC X11DRV_GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags ) ...@@ -597,44 +590,48 @@ HDC X11DRV_GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
TRACE("\tskipping hVisRgn update\n"); TRACE("\tskipping hVisRgn update\n");
bUpdateVisRgn = FALSE; /* updated automatically, via DCHook() */ bUpdateVisRgn = FALSE; /* updated automatically, via DCHook() */
} }
else
{
/* we should free dce->clip_rgn here, but Windows apparently doesn't */
dce->flags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN);
dce->clip_rgn = 0;
}
} }
if (!(flags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN))) hrgnClip = 0; if (flags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN))
else if (!hrgnClip) hrgnClip = CreateRectRgn( 0, 0, 0, 0 );
if (((flags ^ dce->flags) & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) &&
(dce->clip_rgn != hrgnClip))
{ {
/* if the extra clip region has changed, get rid of the old one */ /* if the extra clip region has changed, get rid of the old one */
delete_clip_rgn( dce ); if (dce->clip_rgn != hrgnClip || ((flags ^ dce->flags) & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)))
delete_clip_rgn( dce );
dce->clip_rgn = hrgnClip;
if (!dce->clip_rgn) dce->clip_rgn = CreateRectRgn( 0, 0, 0, 0 );
dce->flags |= flags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN);
bUpdateVisRgn = TRUE;
} }
dce->hwnd = hwnd; dce->hwnd = hwnd;
dce->clip_rgn = hrgnClip; dce->flags = (dce->flags & ~clip_flags) | (flags & clip_flags);
dce->flags = flags & (DCX_PARENTCLIP | DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN |
DCX_CACHE | DCX_WINDOW | DCX_WINDOWPAINT |
DCX_INTERSECTRGN | DCX_EXCLUDERGN);
hdc = dce->hdc;
if (SetHookFlags16( HDC_16(hdc), DCHF_VALIDATEVISRGN )) bUpdateVisRgn = TRUE; /* DC was dirty */ if (SetHookFlags16( HDC_16(dce->hdc), DCHF_VALIDATEVISRGN ))
bUpdateVisRgn = TRUE; /* DC was dirty */
set_drawable( dce, flags, bUpdateVisRgn ); set_drawable( dce, bUpdateVisRgn );
if (!(flags & DCX_NORESETATTRS)) if (!(flags & DCX_NORESETATTRS))
{ {
RestoreDC( hdc, 1 ); /* initial save level is always 1 */ RestoreDC( dce->hdc, 1 ); /* initial save level is always 1 */
SaveDC( hdc ); /* save the state again for next time */ SaveDC( dce->hdc ); /* save the state again for next time */
} }
TRACE("(%p,%p,0x%lx): returning %p\n", hwnd, hrgnClip, flags, hdc); TRACE("(%p,%p,0x%lx): returning %p\n", hwnd, hrgnClip, flags, dce->hdc);
return hdc; return dce->hdc;
} }
/*********************************************************************** /***********************************************************************
* X11DRV_ReleaseDC (X11DRV.@) * X11DRV_ReleaseDC (X11DRV.@)
*/ */
BOOL X11DRV_ReleaseDC( HWND hwnd, HDC hdc ) BOOL X11DRV_ReleaseDC( HWND hwnd, HDC hdc, BOOL end_paint )
{ {
enum x11drv_escape_codes escape = X11DRV_GET_DCE; enum x11drv_escape_codes escape = X11DRV_GET_DCE;
struct dce *dce; struct dce *dce;
...@@ -647,7 +644,7 @@ BOOL X11DRV_ReleaseDC( HWND hwnd, HDC hdc ) ...@@ -647,7 +644,7 @@ BOOL X11DRV_ReleaseDC( HWND hwnd, HDC hdc )
sizeof(dce), (LPSTR)&dce )) dce = NULL; sizeof(dce), (LPSTR)&dce )) dce = NULL;
if (dce && dce->count) if (dce && dce->count)
{ {
if ((dce->flags & (DCX_CACHE | DCX_WINDOWPAINT))) delete_clip_rgn( dce ); if (end_paint || (dce->flags & DCX_CACHE)) delete_clip_rgn( dce );
if (dce->flags & DCX_CACHE) dce->count = 0; if (dce->flags & DCX_CACHE) dce->count = 0;
ret = TRUE; ret = TRUE;
} }
...@@ -677,7 +674,7 @@ static BOOL16 CALLBACK dc_hook( HDC16 hDC, WORD code, DWORD data, LPARAM lParam ...@@ -677,7 +674,7 @@ static BOOL16 CALLBACK dc_hook( HDC16 hDC, WORD code, DWORD data, LPARAM lParam
* DC is dirty (usually after SetHookFlags()). This * DC is dirty (usually after SetHookFlags()). This
* means that we have to recompute the visible region. * means that we have to recompute the visible region.
*/ */
if (dce->count) set_drawable( dce, dce->flags, TRUE ); if (dce->count) set_drawable( dce, TRUE );
else /* non-fatal but shouldn't happen */ else /* non-fatal but shouldn't happen */
WARN("DC is not in use!\n"); WARN("DC is not in use!\n");
break; break;
......
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
@ cdecl IsClipboardFormatAvailable(long) X11DRV_IsClipboardFormatAvailable @ cdecl IsClipboardFormatAvailable(long) X11DRV_IsClipboardFormatAvailable
@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) X11DRV_MsgWaitForMultipleObjectsEx @ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) X11DRV_MsgWaitForMultipleObjectsEx
@ cdecl RegisterClipboardFormat(str) X11DRV_RegisterClipboardFormat @ cdecl RegisterClipboardFormat(str) X11DRV_RegisterClipboardFormat
@ cdecl ReleaseDC(long long) X11DRV_ReleaseDC @ cdecl ReleaseDC(long long long) X11DRV_ReleaseDC
@ cdecl ResetSelectionOwner(long long) X11DRV_ResetSelectionOwner @ cdecl ResetSelectionOwner(long long) X11DRV_ResetSelectionOwner
@ cdecl ScrollDC(long long long ptr ptr long ptr) X11DRV_ScrollDC @ cdecl ScrollDC(long long long ptr ptr long ptr) X11DRV_ScrollDC
@ cdecl SetClipboardData(long long long long) X11DRV_SetClipboardData @ cdecl SetClipboardData(long long long long) X11DRV_SetClipboardData
......
...@@ -106,7 +106,4 @@ inline static void WIN_ReleasePtr( WND *ptr ) ...@@ -106,7 +106,4 @@ inline static void WIN_ReleasePtr( WND *ptr )
extern LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL unicode ); extern LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL unicode );
/* internal GetDC flag (FIXME) */
#define DCX_WINDOWPAINT 0x00020000
#endif /* __WINE_WIN_H */ #endif /* __WINE_WIN_H */
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