summaryrefslogtreecommitdiff
path: root/vcl/win/source/gdi/salgdi2.cxx
diff options
context:
space:
mode:
authorRüdiger Timm <rt@openoffice.org>2005-01-07 08:27:58 +0000
committerRüdiger Timm <rt@openoffice.org>2005-01-07 08:27:58 +0000
commitb4899a4e104d6a3b5d37e5f5dd20cb611673351f (patch)
treef87711ed805f9587b88b8f1f1a41a8793346bea1 /vcl/win/source/gdi/salgdi2.cxx
parent7671a59ffceba624bbd64ad09acf782b651eb35d (diff)
INTEGRATION: CWS vcl32 (1.5.254); FILE MERGED
2004/11/23 15:56:40 ssa 1.5.254.1: #i36344# exclude overlapped regions from scrolling to reduce flickering
Diffstat (limited to 'vcl/win/source/gdi/salgdi2.cxx')
-rw-r--r--vcl/win/source/gdi/salgdi2.cxx121
1 files changed, 88 insertions, 33 deletions
diff --git a/vcl/win/source/gdi/salgdi2.cxx b/vcl/win/source/gdi/salgdi2.cxx
index c6f9d6f4cb73..33be13930c9e 100644
--- a/vcl/win/source/gdi/salgdi2.cxx
+++ b/vcl/win/source/gdi/salgdi2.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: salgdi2.cxx,v $
*
- * $Revision: 1.5 $
+ * $Revision: 1.6 $
*
- * last change: $Author: vg $ $Date: 2004-01-06 14:55:19 $
+ * last change: $Author: rt $ $Date: 2005-01-07 09:27:58 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -86,6 +86,9 @@
#include <salgdi.h>
#endif
+// defined in salframe.cxx
+extern void ImplSalGetWorkArea( HWND hWnd, RECT *pRect, const RECT *pParentRect );
+
// =======================================================================
void WinSalGraphics::copyBits( const SalTwoRect* pPosAry, SalGraphics* pSrcGraphics )
@@ -177,26 +180,26 @@ void WinSalGraphics::copyArea( long nDestX, long nDestY,
long nSrcWidth, long nSrcHeight,
USHORT nFlags )
{
- BitBlt( mhDC,
- (int)nDestX, (int)nDestY,
- (int)nSrcWidth, (int)nSrcHeight,
- mhDC,
- (int)nSrcX, (int)nSrcY,
- SRCCOPY );
+ bool bRestoreClipRgn = false;
+ HRGN hOldClipRgn = 0;
+ int nOldClipRgnType = ERROR;
+ HRGN hInvalidateRgn = 0;
// Muessen die ueberlappenden Bereiche auch invalidiert werden?
if ( (nFlags & SAL_COPYAREA_WINDOWINVALIDATE) && mbWindow )
{
- // Overlap-Bereich berechnen und invalidieren
+ // compute and invalidate those parts that were either off-screen or covered by other windows
+ // while performing the above BitBlt
+ // those regions then have to be invalidated as they contain useless/wrong data
RECT aSrcRect;
RECT aClipRect;
RECT aTempRect;
RECT aTempRect2;
- HRGN hInvalidateRgn;
HRGN hTempRgn;
HWND hWnd;
int nRgnType;
+ // restrict srcRect to this window (calc intersection)
aSrcRect.left = (int)nSrcX;
aSrcRect.top = (int)nSrcY;
aSrcRect.right = aSrcRect.left+(int)nSrcWidth;
@@ -204,10 +207,8 @@ void WinSalGraphics::copyArea( long nDestX, long nDestY,
GetClientRect( mhWnd, &aClipRect );
if ( IntersectRect( &aSrcRect, &aSrcRect, &aClipRect ) )
{
- // Rechteck in Screen-Koordinaaten umrechnen
+ // transform srcRect to screen coordinates
POINT aPt;
- int nScreenDX = GetSystemMetrics( SM_CXSCREEN );
- int nScreenDY = GetSystemMetrics( SM_CYSCREEN );
aPt.x = 0;
aPt.y = 0;
ClientToScreen( mhWnd, &aPt );
@@ -216,8 +217,11 @@ void WinSalGraphics::copyArea( long nDestX, long nDestY,
aSrcRect.right += aPt.x;
aSrcRect.bottom += aPt.y;
hInvalidateRgn = 0;
- // Bereiche ausserhalb des sichtbaren Bereiches berechnen
- ImplCalcOutSideRgn( aSrcRect, 0, 0, nScreenDX, nScreenDY, hInvalidateRgn );
+
+ // compute the parts that are off screen (ie invisible)
+ RECT theScreen;
+ ImplSalGetWorkArea( NULL, &theScreen, NULL ); // find the screen area taking multiple monitors into account
+ ImplCalcOutSideRgn( aSrcRect, theScreen.left, theScreen.top, theScreen.right, theScreen.bottom, hInvalidateRgn );
// Bereiche die von anderen Fenstern ueberlagert werden berechnen
HRGN hTempRgn2 = 0;
@@ -231,7 +235,7 @@ void WinSalGraphics::copyArea( long nDestX, long nDestY,
{
hWndTopWindow = ::GetParent( hWndTopWindow );
- // Test, if the Parent clip our window
+ // Test, if the Parent clips our window
GetClientRect( hWndTopWindow, &aTempRect );
POINT aPt2;
aPt2.x = 0;
@@ -255,6 +259,7 @@ void WinSalGraphics::copyArea( long nDestX, long nDestY,
hInvalidateRgn );
}
}
+ // retrieve the top-most (z-order) child window
hWnd = GetWindow( GetDesktopWindow(), GW_CHILD );
while ( hWnd )
{
@@ -265,55 +270,105 @@ void WinSalGraphics::copyArea( long nDestX, long nDestY,
GetWindowRect( hWnd, &aTempRect );
if ( IntersectRect( &aTempRect2, &aSrcRect, &aTempRect ) )
{
+ // hWnd covers part or all of aSrcRect
if ( !hInvalidateRgn )
hInvalidateRgn = CreateRectRgnIndirect( &aSrcRect );
+
+ // get full bounding box of hWnd
hTempRgn = CreateRectRgnIndirect( &aTempRect );
+
+ // get region of hWnd (the window may be shaped)
if ( !hTempRgn2 )
hTempRgn2 = CreateRectRgn( 0, 0, 0, 0 );
nRgnType = GetWindowRgn( hWnd, hTempRgn2 );
if ( (nRgnType != ERROR) && (nRgnType != NULLREGION) )
{
+ // convert window region to screen coordinates
OffsetRgn( hTempRgn2, aTempRect.left, aTempRect.top );
+ // and intersect with the window's bounding box
CombineRgn( hTempRgn, hTempRgn, hTempRgn2, RGN_AND );
}
+ // finally compute that part of aSrcRect which is not covered by any parts of hWnd
CombineRgn( hInvalidateRgn, hInvalidateRgn, hTempRgn, RGN_DIFF );
DeleteRegion( hTempRgn );
}
}
+ // retrieve the next window in the z-order, i.e. the window below hwnd
hWnd = GetWindow( hWnd, GW_HWNDNEXT );
}
if ( hTempRgn2 )
DeleteRegion( hTempRgn2 );
if ( hInvalidateRgn )
{
+ // hInvalidateRgn contains the fully visible parts of the original srcRect
hTempRgn = CreateRectRgnIndirect( &aSrcRect );
+ // substract it from the original rect to get the occluded parts
nRgnType = CombineRgn( hInvalidateRgn, hTempRgn, hInvalidateRgn, RGN_DIFF );
+ DeleteRegion( hTempRgn );
+
if ( (nRgnType != ERROR) && (nRgnType != NULLREGION) )
{
+ // move the occluded parts to the destination pos
int nOffX = (int)(nDestX-nSrcX);
int nOffY = (int)(nDestY-nSrcY);
OffsetRgn( hInvalidateRgn, nOffX-aPt.x, nOffY-aPt.y );
- // Combine Invalidate Region with existing ClipRegion
- if ( GetClipRgn( mhDC, hTempRgn ) == 1 )
- nRgnType = CombineRgn( hInvalidateRgn, hTempRgn, hInvalidateRgn, RGN_AND );
- if ( (nRgnType != ERROR) && (nRgnType != NULLREGION) )
- {
- InvalidateRgn( mhWnd, hInvalidateRgn, TRUE );
- // Hier loesen wir nur ein Update aus, wenn es der
- // MainThread ist, damit es beim Bearbeiten der
- // Paint-Message keinen Deadlock gibt, da der
- // SolarMutex durch diesen Thread schon gelockt ist
- SalData* pSalData = GetSalData();
- DWORD nCurThreadId = GetCurrentThreadId();
- if ( pSalData->mnAppThreadId == nCurThreadId )
- UpdateWindow( mhWnd );
- }
+
+ // by excluding hInvalidateRgn from the system's clip region
+ // we will prevent bitblt from copying useless data
+ // epsecially now shadows from overlapping windows will appear (#i36344)
+ hOldClipRgn = CreateRectRgn( 0, 0, 0, 0 );
+ nOldClipRgnType = GetClipRgn( mhDC, hOldClipRgn );
+
+ bRestoreClipRgn = TRUE; // indicate changed clipregion and force invalidate
+ ExtSelectClipRgn( mhDC, hInvalidateRgn, RGN_DIFF );
}
- DeleteRegion( hTempRgn );
- DeleteRegion( hInvalidateRgn );
}
}
}
+
+ BitBlt( mhDC,
+ (int)nDestX, (int)nDestY,
+ (int)nSrcWidth, (int)nSrcHeight,
+ mhDC,
+ (int)nSrcX, (int)nSrcY,
+ SRCCOPY );
+
+ if( bRestoreClipRgn )
+ {
+ // restore old clip region
+ if( nOldClipRgnType != ERROR )
+ SelectClipRgn( mhDC, hOldClipRgn);
+ DeleteRegion( hOldClipRgn );
+
+ // invalidate regions that were not copied
+ bool bInvalidate = true;
+
+ // Combine Invalidate Region with existing ClipRegion
+ HRGN hTempRgn = CreateRectRgn( 0, 0, 0, 0 );
+ if ( GetClipRgn( mhDC, hTempRgn ) == 1 )
+ {
+ int nRgnType = CombineRgn( hInvalidateRgn, hTempRgn, hInvalidateRgn, RGN_AND );
+ if ( (nRgnType == ERROR) || (nRgnType == NULLREGION) )
+ bInvalidate = false;
+ }
+ DeleteRegion( hTempRgn );
+
+ if ( bInvalidate )
+ {
+ InvalidateRgn( mhWnd, hInvalidateRgn, TRUE );
+ // Hier loesen wir nur ein Update aus, wenn es der
+ // MainThread ist, damit es beim Bearbeiten der
+ // Paint-Message keinen Deadlock gibt, da der
+ // SolarMutex durch diesen Thread schon gelockt ist
+ SalData* pSalData = GetSalData();
+ DWORD nCurThreadId = GetCurrentThreadId();
+ if ( pSalData->mnAppThreadId == nCurThreadId )
+ UpdateWindow( mhWnd );
+ }
+
+ DeleteRegion( hInvalidateRgn );
+ }
+
}
// -----------------------------------------------------------------------