vcl/source/window/paint.cxx | 1363 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1363 insertions(+)
New commits: commit e76dc5b422084f68cc4b27eea4cdbef3d3e7a1a9 Author: Chris Sherlock <chris.sherloc...@gmail.com> Date: Fri May 23 23:12:37 2014 +1000 vcl: add paint.cxx Change-Id: I1ab01c1acec9147812841c1deee17413cee88962 diff --git a/vcl/source/window/paint.cxx b/vcl/source/window/paint.cxx new file mode 100644 index 0000000..18fab8a --- /dev/null +++ b/vcl/source/window/paint.cxx @@ -0,0 +1,1363 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> + +#include <vcl/window.hxx> +#include <vcl/dialog.hxx> +#include <vcl/virdev.hxx> +#include <vcl/cursor.hxx> +#include <vcl/settings.hxx> + +#include <sal/types.h> + +#include <window.h> +#include <salgdi.hxx> +#include <salframe.hxx> +#include <svdata.hxx> + +#define IMPL_PAINT_PAINT ((sal_uInt16)0x0001) +#define IMPL_PAINT_PAINTALL ((sal_uInt16)0x0002) +#define IMPL_PAINT_PAINTALLCHILDREN ((sal_uInt16)0x0004) +#define IMPL_PAINT_PAINTCHILDREN ((sal_uInt16)0x0008) +#define IMPL_PAINT_ERASE ((sal_uInt16)0x0010) +#define IMPL_PAINT_CHECKRTL ((sal_uInt16)0x0020) + + +class PaintHelper +{ +private: + Window* m_pWindow; + Region* m_pChildRegion; + Rectangle m_aSelectionRect; + Rectangle m_aPaintRect; + Region m_aPaintRegion; + sal_uInt16 m_nPaintFlags; + bool m_bPop; + bool m_bRestoreCursor; +public: + PaintHelper(Window *pWindow, sal_uInt16 nPaintFlags); + void SetPop() + { + m_bPop = true; + } + void SetPaintRect(const Rectangle& rRect) + { + m_aPaintRect = rRect; + } + void SetSelectionRect(const Rectangle& rRect) + { + m_aSelectionRect = rRect; + } + void SetRestoreCursor(bool bRestoreCursor) + { + m_bRestoreCursor = bRestoreCursor; + } + bool GetRestoreCursor() const + { + return m_bRestoreCursor; + } + sal_uInt16 GetPaintFlags() const + { + return m_nPaintFlags; + } + Region& GetPaintRegion() + { + return m_aPaintRegion; + } + void DoPaint(const Region* pRegion); + ~PaintHelper(); +}; + +PaintHelper::PaintHelper(Window *pWindow, sal_uInt16 nPaintFlags) + : m_pWindow(pWindow) + , m_pChildRegion(NULL) + , m_nPaintFlags(nPaintFlags) + , m_bPop(false) + , m_bRestoreCursor(false) +{ +} + +void PaintHelper::DoPaint(const Region* pRegion) +{ + WindowImpl* pWindowImpl = m_pWindow->ImplGetWindowImpl(); + Region* pWinChildClipRegion = m_pWindow->ImplGetWinChildClipRegion(); + if ( pWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL ) + pWindowImpl->maInvalidateRegion = *pWinChildClipRegion; + else + { + if ( pRegion ) + pWindowImpl->maInvalidateRegion.Union( *pRegion ); + + if( pWindowImpl->mpWinData && pWindowImpl->mbTrackVisible ) + /* #98602# need to repaint all children within the + * tracking rectangle, so the following invert + * operation takes places without traces of the previous + * one. + */ + pWindowImpl->maInvalidateRegion.Union( *pWindowImpl->mpWinData->mpTrackRect ); + + if ( pWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN ) + m_pChildRegion = new Region( pWindowImpl->maInvalidateRegion ); + pWindowImpl->maInvalidateRegion.Intersect( *pWinChildClipRegion ); + } + pWindowImpl->mnPaintFlags = 0; + if ( !pWindowImpl->maInvalidateRegion.IsEmpty() ) + { + m_pWindow->PushPaintHelper(this); + m_pWindow->Paint(m_aPaintRect); + } +} + +void Window::PushPaintHelper(PaintHelper *pHelper) +{ + pHelper->SetPop(); + + if ( mpWindowImpl->mpCursor ) + pHelper->SetRestoreCursor(mpWindowImpl->mpCursor->ImplSuspend()); + + mbInitClipRegion = true; + mpWindowImpl->mbInPaint = true; + + // restore Paint-Region + Region &rPaintRegion = pHelper->GetPaintRegion(); + rPaintRegion = mpWindowImpl->maInvalidateRegion; + Rectangle aPaintRect = rPaintRegion.GetBoundRect(); + + // - RTL - re-mirror paint rect and region at this window + if( ImplIsAntiparallel() ) + { + const OutputDevice *pOutDev = GetOutDev(); + pOutDev->ReMirror( aPaintRect ); + pOutDev->ReMirror( rPaintRegion ); + } + aPaintRect = ImplDevicePixelToLogic( aPaintRect); + mpWindowImpl->mpPaintRegion = &rPaintRegion; + mpWindowImpl->maInvalidateRegion.SetEmpty(); + + if ( (pHelper->GetPaintFlags() & IMPL_PAINT_ERASE) && IsBackground() ) + { + if ( IsClipRegion() ) + { + Region aOldRegion = GetClipRegion(); + SetClipRegion(); + Erase(); + SetClipRegion( aOldRegion ); + } + else + Erase(); + } + + // #98943# trigger drawing of toolbox selection after all childern are painted + if( mpWindowImpl->mbDrawSelectionBackground ) + pHelper->SetSelectionRect(aPaintRect); + pHelper->SetPaintRect(aPaintRect); +} + +void Window::PopPaintHelper(PaintHelper *pHelper) +{ + if ( mpWindowImpl->mpWinData ) + { + if ( mpWindowImpl->mbFocusVisible ) + ImplInvertFocus( *(mpWindowImpl->mpWinData->mpFocusRect) ); + } + mpWindowImpl->mbInPaint = false; + mbInitClipRegion = true; + mpWindowImpl->mpPaintRegion = NULL; + if ( mpWindowImpl->mpCursor ) + mpWindowImpl->mpCursor->ImplResume(pHelper->GetRestoreCursor()); +} + +PaintHelper::~PaintHelper() +{ + WindowImpl* pWindowImpl = m_pWindow->ImplGetWindowImpl(); + if (m_bPop) + { + m_pWindow->PopPaintHelper(this); + } + + if ( m_nPaintFlags & (IMPL_PAINT_PAINTALLCHILDREN | IMPL_PAINT_PAINTCHILDREN) ) + { + // Paint from the bottom child window and frontward. + Window* pTempWindow = pWindowImpl->mpLastChild; + while ( pTempWindow ) + { + if ( pTempWindow->mpWindowImpl->mbVisible ) + pTempWindow->ImplCallPaint( m_pChildRegion, m_nPaintFlags ); + pTempWindow = pTempWindow->mpWindowImpl->mpPrev; + } + } + + if ( pWindowImpl->mpWinData && pWindowImpl->mbTrackVisible && (pWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) ) + /* #98602# need to invert the tracking rect AFTER + * the children have painted + */ + m_pWindow->InvertTracking( *(pWindowImpl->mpWinData->mpTrackRect), pWindowImpl->mpWinData->mnTrackFlags ); + + // #98943# draw toolbox selection + if( !m_aSelectionRect.IsEmpty() ) + m_pWindow->DrawSelectionBackground( m_aSelectionRect, 3, false, true, false ); + + delete m_pChildRegion; +} + +void Window::ImplCallPaint( const Region* pRegion, sal_uInt16 nPaintFlags ) +{ + // call PrePaint. PrePaint may add to the invalidate region as well as + // other parameters used below. + PrePaint(); + + mpWindowImpl->mbPaintFrame = false; + + if ( nPaintFlags & IMPL_PAINT_PAINTALLCHILDREN ) + mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINT | IMPL_PAINT_PAINTALLCHILDREN | (nPaintFlags & IMPL_PAINT_PAINTALL); + if ( nPaintFlags & IMPL_PAINT_PAINTCHILDREN ) + mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTCHILDREN; + if ( nPaintFlags & IMPL_PAINT_ERASE ) + mpWindowImpl->mnPaintFlags |= IMPL_PAINT_ERASE; + if ( nPaintFlags & IMPL_PAINT_CHECKRTL ) + mpWindowImpl->mnPaintFlags |= IMPL_PAINT_CHECKRTL; + if ( !mpWindowImpl->mpFirstChild ) + mpWindowImpl->mnPaintFlags &= ~IMPL_PAINT_PAINTALLCHILDREN; + + if ( mpWindowImpl->mbPaintDisabled ) + { + if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL ) + Invalidate( INVALIDATE_NOCHILDREN | INVALIDATE_NOERASE | INVALIDATE_NOTRANSPARENT | INVALIDATE_NOCLIPCHILDREN ); + else if ( pRegion ) + Invalidate( *pRegion, INVALIDATE_NOCHILDREN | INVALIDATE_NOERASE | INVALIDATE_NOTRANSPARENT | INVALIDATE_NOCLIPCHILDREN ); + return; + } + + nPaintFlags = mpWindowImpl->mnPaintFlags & ~(IMPL_PAINT_PAINT); + + PaintHelper aHelper(this, nPaintFlags); + + if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINT ) + aHelper.DoPaint(pRegion); + else + mpWindowImpl->mnPaintFlags = 0; +} + +void Window::ImplCallOverlapPaint() +{ + // emit overlapping windows first + Window* pTempWindow = mpWindowImpl->mpFirstOverlap; + while ( pTempWindow ) + { + if ( pTempWindow->mpWindowImpl->mbReallyVisible ) + pTempWindow->ImplCallOverlapPaint(); + pTempWindow = pTempWindow->mpWindowImpl->mpNext; + } + + // only then ourself + if ( mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDREN) ) + { + // - RTL - notify ImplCallPaint to check for re-mirroring (CHECKRTL) + // because we were called from the Sal layer + ImplCallPaint( NULL, mpWindowImpl->mnPaintFlags /*| IMPL_PAINT_CHECKRTL */); + } +} + +void Window::ImplPostPaint() +{ + if ( !ImplDoTiledRendering() && !mpWindowImpl->mpFrameData->maPaintTimer.IsActive() ) + mpWindowImpl->mpFrameData->maPaintTimer.Start(); +} + +IMPL_LINK_NOARG(Window, ImplHandlePaintHdl) +{ + // save paint events until layout is done + if (!ImplDoTiledRendering() && IsDialog() && static_cast<const Dialog*>(this)->hasPendingLayout()) + { + mpWindowImpl->mpFrameData->maPaintTimer.Start(); + return 0; + } + + // save paint events until resizing is done + if( !ImplDoTiledRendering() && + mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData->maResizeTimer.IsActive() ) + mpWindowImpl->mpFrameData->maPaintTimer.Start(); + else if ( mpWindowImpl->mbReallyVisible ) + ImplCallOverlapPaint(); + return 0; +} + +IMPL_LINK_NOARG(Window, ImplHandleResizeTimerHdl) +{ + if( mpWindowImpl->mbReallyVisible ) + { + ImplCallResize(); + if( ImplDoTiledRendering() ) + { + ImplHandlePaintHdl(NULL); + } + else if( mpWindowImpl->mpFrameData->maPaintTimer.IsActive() ) + { + mpWindowImpl->mpFrameData->maPaintTimer.Stop(); + mpWindowImpl->mpFrameData->maPaintTimer.GetTimeoutHdl().Call( NULL ); + } + } + + return 0; +} + +void Window::ImplInvalidateFrameRegion( const Region* pRegion, sal_uInt16 nFlags ) +{ + // set PAINTCHILDREN for all parent windows till the first OverlapWindow + if ( !ImplIsOverlapWindow() ) + { + Window* pTempWindow = this; + sal_uInt16 nTranspPaint = IsPaintTransparent() ? IMPL_PAINT_PAINT : 0; + do + { + pTempWindow = pTempWindow->ImplGetParent(); + if ( pTempWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTCHILDREN ) + break; + pTempWindow->mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTCHILDREN | nTranspPaint; + if( ! pTempWindow->IsPaintTransparent() ) + nTranspPaint = 0; + } + while ( !pTempWindow->ImplIsOverlapWindow() ); + } + + // set Paint-Flags + mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINT; + if ( nFlags & INVALIDATE_CHILDREN ) + mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTALLCHILDREN; + if ( !(nFlags & INVALIDATE_NOERASE) ) + mpWindowImpl->mnPaintFlags |= IMPL_PAINT_ERASE; + if ( !pRegion ) + mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTALL; + + // if not everything has to be redrawn, add the region to it + if ( !(mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL) ) + mpWindowImpl->maInvalidateRegion.Union( *pRegion ); + + // Handle transparent windows correctly: invalidate must be done on the first opaque parent + if( ((IsPaintTransparent() && !(nFlags & INVALIDATE_NOTRANSPARENT)) || (nFlags & INVALIDATE_TRANSPARENT) ) + && ImplGetParent() ) + { + Window *pParent = ImplGetParent(); + while( pParent && pParent->IsPaintTransparent() ) + pParent = pParent->ImplGetParent(); + if( pParent ) + { + Region *pChildRegion; + if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL ) + // invalidate the whole child window region in the parent + pChildRegion = ImplGetWinChildClipRegion(); + else + // invalidate the same region in the parent that has to be repainted in the child + pChildRegion = &mpWindowImpl->maInvalidateRegion; + + nFlags |= INVALIDATE_CHILDREN; // paint should also be done on all children + nFlags &= ~INVALIDATE_NOERASE; // parent should paint and erase to create proper background + pParent->ImplInvalidateFrameRegion( pChildRegion, nFlags ); + } + } + ImplPostPaint(); +} + +void Window::ImplInvalidateOverlapFrameRegion( const Region& rRegion ) +{ + Region aRegion = rRegion; + + ImplClipBoundaries( aRegion, true, true ); + if ( !aRegion.IsEmpty() ) + ImplInvalidateFrameRegion( &aRegion, INVALIDATE_CHILDREN ); + + // now we invalidate the overlapping windows + Window* pTempWindow = mpWindowImpl->mpFirstOverlap; + while ( pTempWindow ) + { + if ( pTempWindow->IsVisible() ) + pTempWindow->ImplInvalidateOverlapFrameRegion( rRegion ); + + pTempWindow = pTempWindow->mpWindowImpl->mpNext; + } +} + +void Window::ImplInvalidateParentFrameRegion( Region& rRegion ) +{ + if ( mpWindowImpl->mbOverlapWin ) + mpWindowImpl->mpFrameWindow->ImplInvalidateOverlapFrameRegion( rRegion ); + else + { + if( ImplGetParent() ) + ImplGetParent()->ImplInvalidateFrameRegion( &rRegion, INVALIDATE_CHILDREN ); + } +} + +void Window::ImplInvalidate( const Region* pRegion, sal_uInt16 nFlags ) +{ + + // reset background storage + if ( mpWindowImpl->mpFrameData->mpFirstBackWin ) + ImplInvalidateAllOverlapBackgrounds(); + + // check what has to be redrawn + bool bInvalidateAll = !pRegion; + + // take Transparent-Invalidate into account + Window* pOpaqueWindow = this; + if ( (mpWindowImpl->mbPaintTransparent && !(nFlags & INVALIDATE_NOTRANSPARENT)) || (nFlags & INVALIDATE_TRANSPARENT) ) + { + Window* pTempWindow = pOpaqueWindow->ImplGetParent(); + while ( pTempWindow ) + { + if ( !pTempWindow->IsPaintTransparent() ) + { + pOpaqueWindow = pTempWindow; + nFlags |= INVALIDATE_CHILDREN; + bInvalidateAll = false; + break; + } + + if ( pTempWindow->ImplIsOverlapWindow() ) + break; + + pTempWindow = pTempWindow->ImplGetParent(); + } + } + + // assemble region + sal_uInt16 nOrgFlags = nFlags; + if ( !(nFlags & (INVALIDATE_CHILDREN | INVALIDATE_NOCHILDREN)) ) + { + if ( GetStyle() & WB_CLIPCHILDREN ) + nFlags |= INVALIDATE_NOCHILDREN; + else + nFlags |= INVALIDATE_CHILDREN; + } + if ( (nFlags & INVALIDATE_NOCHILDREN) && mpWindowImpl->mpFirstChild ) + bInvalidateAll = false; + if ( bInvalidateAll ) + ImplInvalidateFrameRegion( NULL, nFlags ); + else + { + Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ); + Region aRegion( aRect ); + if ( pRegion ) + { + // --- RTL --- remirror region before intersecting it + if ( ImplIsAntiparallel() ) + { + const OutputDevice *pOutDev = GetOutDev(); + + Region aRgn( *pRegion ); + pOutDev->ReMirror( aRgn ); + aRegion.Intersect( aRgn ); + } + else + aRegion.Intersect( *pRegion ); + } + ImplClipBoundaries( aRegion, true, true ); + if ( nFlags & INVALIDATE_NOCHILDREN ) + { + nFlags &= ~INVALIDATE_CHILDREN; + if ( !(nFlags & INVALIDATE_NOCLIPCHILDREN) ) + { + if ( nOrgFlags & INVALIDATE_NOCHILDREN ) + ImplClipAllChildren( aRegion ); + else + { + if ( ImplClipChildren( aRegion ) ) + nFlags |= INVALIDATE_CHILDREN; + } + } + } + if ( !aRegion.IsEmpty() ) + ImplInvalidateFrameRegion( &aRegion, nFlags ); // transparency is handled here, pOpaqueWindow not required + } + + if ( nFlags & INVALIDATE_UPDATE ) + pOpaqueWindow->Update(); // start painting at the opaque parent +} + +void Window::ImplMoveInvalidateRegion( const Rectangle& rRect, + long nHorzScroll, long nVertScroll, + bool bChildren ) +{ + if ( (mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTALL)) == IMPL_PAINT_PAINT ) + { + Region aTempRegion = mpWindowImpl->maInvalidateRegion; + aTempRegion.Intersect( rRect ); + aTempRegion.Move( nHorzScroll, nVertScroll ); + mpWindowImpl->maInvalidateRegion.Union( aTempRegion ); + } + + if ( bChildren && (mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTCHILDREN) ) + { + Window* pWindow = mpWindowImpl->mpFirstChild; + while ( pWindow ) + { + pWindow->ImplMoveInvalidateRegion( rRect, nHorzScroll, nVertScroll, true ); + pWindow = pWindow->mpWindowImpl->mpNext; + } + } +} + +void Window::ImplMoveAllInvalidateRegions( const Rectangle& rRect, + long nHorzScroll, long nVertScroll, + bool bChildren ) +{ + // also shift Paint-Region when paints need processing + ImplMoveInvalidateRegion( rRect, nHorzScroll, nVertScroll, bChildren ); + // Paint-Region should be shifted, as drawn by the parents + if ( !ImplIsOverlapWindow() ) + { + Region aPaintAllRegion; + Window* pPaintAllWindow = this; + do + { + pPaintAllWindow = pPaintAllWindow->ImplGetParent(); + if ( pPaintAllWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN ) + { + if ( pPaintAllWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL ) + { + aPaintAllRegion.SetEmpty(); + break; + } + else + aPaintAllRegion.Union( pPaintAllWindow->mpWindowImpl->maInvalidateRegion ); + } + } + while ( !pPaintAllWindow->ImplIsOverlapWindow() ); + if ( !aPaintAllRegion.IsEmpty() ) + { + aPaintAllRegion.Move( nHorzScroll, nVertScroll ); + sal_uInt16 nPaintFlags = 0; + if ( bChildren ) + mpWindowImpl->mnPaintFlags |= INVALIDATE_CHILDREN; + ImplInvalidateFrameRegion( &aPaintAllRegion, nPaintFlags ); + } + } +} + +void Window::ImplValidateFrameRegion( const Region* pRegion, sal_uInt16 nFlags ) +{ + if ( !pRegion ) + mpWindowImpl->maInvalidateRegion.SetEmpty(); + else + { + // when all child windows have to be drawn we need to invalidate them before doing so + if ( (mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN) && mpWindowImpl->mpFirstChild ) + { + Region aChildRegion = mpWindowImpl->maInvalidateRegion; + if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL ) + { + Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ); + aChildRegion = aRect; + } + Window* pChild = mpWindowImpl->mpFirstChild; + while ( pChild ) + { + pChild->Invalidate( aChildRegion, INVALIDATE_CHILDREN | INVALIDATE_NOTRANSPARENT ); + pChild = pChild->mpWindowImpl->mpNext; + } + } + if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL ) + { + Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ); + mpWindowImpl->maInvalidateRegion = aRect; + } + mpWindowImpl->maInvalidateRegion.Exclude( *pRegion ); + } + mpWindowImpl->mnPaintFlags &= ~IMPL_PAINT_PAINTALL; + + if ( nFlags & VALIDATE_CHILDREN ) + { + Window* pChild = mpWindowImpl->mpFirstChild; + while ( pChild ) + { + pChild->ImplValidateFrameRegion( pRegion, nFlags ); + pChild = pChild->mpWindowImpl->mpNext; + } + } +} + +void Window::ImplValidate( const Region* pRegion, sal_uInt16 nFlags ) +{ + // assemble region + bool bValidateAll = !pRegion; + sal_uInt16 nOrgFlags = nFlags; + if ( !(nFlags & (VALIDATE_CHILDREN | VALIDATE_NOCHILDREN)) ) + { + if ( GetStyle() & WB_CLIPCHILDREN ) + nFlags |= VALIDATE_NOCHILDREN; + else + nFlags |= VALIDATE_CHILDREN; + } + if ( (nFlags & VALIDATE_NOCHILDREN) && mpWindowImpl->mpFirstChild ) + bValidateAll = false; + if ( bValidateAll ) + ImplValidateFrameRegion( NULL, nFlags ); + else + { + Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ); + Region aRegion( aRect ); + if ( pRegion ) + aRegion.Intersect( *pRegion ); + ImplClipBoundaries( aRegion, true, true ); + if ( nFlags & VALIDATE_NOCHILDREN ) + { + nFlags &= ~VALIDATE_CHILDREN; + if ( nOrgFlags & VALIDATE_NOCHILDREN ) + ImplClipAllChildren( aRegion ); + else + { + if ( ImplClipChildren( aRegion ) ) + nFlags |= VALIDATE_CHILDREN; + } + } + if ( !aRegion.IsEmpty() ) + ImplValidateFrameRegion( &aRegion, nFlags ); + } +} + +void Window::ImplUpdateAll( bool bOverlapWindows ) +{ + if ( !mpWindowImpl->mbReallyVisible ) + return; + + bool bFlush = false; + if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame ) + { + Point aPoint( 0, 0 ); + Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) ); + ImplInvalidateOverlapFrameRegion( aRegion ); + if ( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) ) + bFlush = true; + } + + // an update changes the OverlapWindow, such that for later paints + // not too much has to be drawn, if ALLCHILDREN etc. is set + Window* pWindow = ImplGetFirstOverlapWindow(); + if ( bOverlapWindows ) + pWindow->ImplCallOverlapPaint(); + else + { + if ( pWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDREN) ) + pWindow->ImplCallPaint( NULL, pWindow->mpWindowImpl->mnPaintFlags ); + } + + if ( bFlush ) + Flush(); +} + +void Window::PrePaint() +{ +} + +void Window::Paint( const Rectangle& rRect ) +{ + ImplCallEventListeners( VCLEVENT_WINDOW_PAINT, (void*)&rRect ); +} + +void Window::PostPaint() +{ +} + +void Window::SetPaintTransparent( bool bTransparent ) +{ + + // transparency is not useful for frames as the background would have to be provided by a different frame + if( bTransparent && mpWindowImpl->mbFrame ) + return; + + if ( mpWindowImpl->mpBorderWindow ) + mpWindowImpl->mpBorderWindow->SetPaintTransparent( bTransparent ); + + mpWindowImpl->mbPaintTransparent = bTransparent; +} + +void Window::SetWindowRegionPixel() +{ + + if ( mpWindowImpl->mpBorderWindow ) + mpWindowImpl->mpBorderWindow->SetWindowRegionPixel(); + else if( mpWindowImpl->mbFrame ) + { + mpWindowImpl->maWinRegion = Region(true); + mpWindowImpl->mbWinRegion = false; + mpWindowImpl->mpFrame->ResetClipRegion(); + } + else + { + if ( mpWindowImpl->mbWinRegion ) + { + mpWindowImpl->maWinRegion = Region(true); + mpWindowImpl->mbWinRegion = false; + ImplSetClipFlag(); + + if ( IsReallyVisible() ) + { + // restore background storage + if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mpSaveBackDev ) + ImplDeleteOverlapBackground(); + if ( mpWindowImpl->mpFrameData->mpFirstBackWin ) + ImplInvalidateAllOverlapBackgrounds(); + Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ); + Region aRegion( aRect ); + ImplInvalidateParentFrameRegion( aRegion ); + } + } + } +} + +void Window::SetWindowRegionPixel( const Region& rRegion ) +{ + + if ( mpWindowImpl->mpBorderWindow ) + mpWindowImpl->mpBorderWindow->SetWindowRegionPixel( rRegion ); + else if( mpWindowImpl->mbFrame ) + { + if( !rRegion.IsNull() ) + { + mpWindowImpl->maWinRegion = rRegion; + mpWindowImpl->mbWinRegion = ! rRegion.IsEmpty(); + + if( mpWindowImpl->mbWinRegion ) + { + // set/update ClipRegion + RectangleVector aRectangles; + mpWindowImpl->maWinRegion.GetRegionRectangles(aRectangles); + mpWindowImpl->mpFrame->BeginSetClipRegion(aRectangles.size()); + + for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter) + { + mpWindowImpl->mpFrame->UnionClipRegion( + aRectIter->Left(), + aRectIter->Top(), + aRectIter->GetWidth(), // orig nWidth was ((R - L) + 1), same as GetWidth does + aRectIter->GetHeight()); // same for height + } + + mpWindowImpl->mpFrame->EndSetClipRegion(); + + //long nX; + //long nY; + //long nWidth; + //long nHeight; + //sal_uLong nRectCount; + //ImplRegionInfo aInfo; + //sal_Bool bRegionRect; + + //nRectCount = mpWindowImpl->maWinRegion.GetRectCount(); + //mpWindowImpl->mpFrame->BeginSetClipRegion( nRectCount ); + //bRegionRect = mpWindowImpl->maWinRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight ); + //while ( bRegionRect ) + //{ + // mpWindowImpl->mpFrame->UnionClipRegion( nX, nY, nWidth, nHeight ); + // bRegionRect = mpWindowImpl->maWinRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight ); + //} + //mpWindowImpl->mpFrame->EndSetClipRegion(); + } + else + SetWindowRegionPixel(); + } + else + SetWindowRegionPixel(); + } + else + { + if ( rRegion.IsNull() ) + { + if ( mpWindowImpl->mbWinRegion ) + { + mpWindowImpl->maWinRegion = Region(true); + mpWindowImpl->mbWinRegion = false; + ImplSetClipFlag(); + } + } + else + { + mpWindowImpl->maWinRegion = rRegion; + mpWindowImpl->mbWinRegion = true; + ImplSetClipFlag(); + } + + if ( IsReallyVisible() ) + { + // restore background storage + if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mpSaveBackDev ) + ImplDeleteOverlapBackground(); + if ( mpWindowImpl->mpFrameData->mpFirstBackWin ) + ImplInvalidateAllOverlapBackgrounds(); + Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ); + Region aRegion( aRect ); + ImplInvalidateParentFrameRegion( aRegion ); + } + } +} + +const Region& Window::GetWindowRegionPixel() const +{ + + if ( mpWindowImpl->mpBorderWindow ) + return mpWindowImpl->mpBorderWindow->GetWindowRegionPixel(); + else + return mpWindowImpl->maWinRegion; +} + +bool Window::IsWindowRegionPixel() const +{ + + if ( mpWindowImpl->mpBorderWindow ) + return mpWindowImpl->mpBorderWindow->IsWindowRegionPixel(); + else + return mpWindowImpl->mbWinRegion; +} + +Region Window::GetPaintRegion() const +{ + + if ( mpWindowImpl->mpPaintRegion ) + { + Region aRegion = *mpWindowImpl->mpPaintRegion; + aRegion.Move( -mnOutOffX, -mnOutOffY ); + return PixelToLogic( aRegion ); + } + else + { + Region aPaintRegion(true); + return aPaintRegion; + } +} + +void Window::Invalidate( sal_uInt16 nFlags ) +{ + + if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight ) + return; + + ImplInvalidate( NULL, nFlags ); +} + +void Window::Invalidate( const Rectangle& rRect, sal_uInt16 nFlags ) +{ + + if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight ) + return; + + OutputDevice *pOutDev = GetOutDev(); + Rectangle aRect = pOutDev->ImplLogicToDevicePixel( rRect ); + if ( !aRect.IsEmpty() ) + { + Region aRegion( aRect ); + ImplInvalidate( &aRegion, nFlags ); + } +} + +void Window::Invalidate( const Region& rRegion, sal_uInt16 nFlags ) +{ + + if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight ) + return; + + if ( rRegion.IsNull() ) + ImplInvalidate( NULL, nFlags ); + else + { + Region aRegion = ImplPixelToDevicePixel( LogicToPixel( rRegion ) ); + if ( !aRegion.IsEmpty() ) + ImplInvalidate( &aRegion, nFlags ); + } +} + +void Window::Validate( sal_uInt16 nFlags ) +{ + + if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight ) + return; + + ImplValidate( NULL, nFlags ); +} + +bool Window::HasPaintEvent() const +{ + + if ( !mpWindowImpl->mbReallyVisible ) + return false; + + if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame ) + return true; + + if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINT ) + return true; + + if ( !ImplIsOverlapWindow() ) + { + const Window* pTempWindow = this; + do + { + pTempWindow = pTempWindow->ImplGetParent(); + if ( pTempWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINTCHILDREN | IMPL_PAINT_PAINTALLCHILDREN) ) + return true; + } + while ( !pTempWindow->ImplIsOverlapWindow() ); + } + + return false; +} + +void Window::Update() +{ + + if ( mpWindowImpl->mpBorderWindow ) + { + mpWindowImpl->mpBorderWindow->Update(); + return; + } + + if ( !mpWindowImpl->mbReallyVisible ) + return; + + bool bFlush = false; + if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame ) + { + Point aPoint( 0, 0 ); + Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) ); + ImplInvalidateOverlapFrameRegion( aRegion ); + if ( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) ) + bFlush = true; + } + + // First we should skip all windows which are Paint-Transparent + Window* pUpdateWindow = this; + Window* pWindow = pUpdateWindow; + while ( !pWindow->ImplIsOverlapWindow() ) + { + if ( !pWindow->mpWindowImpl->mbPaintTransparent ) + { + pUpdateWindow = pWindow; + break; + } + pWindow = pWindow->ImplGetParent(); + } + // In order to limit drawing, an update only draws the window which + // has PAINTALLCHILDREN set + pWindow = pUpdateWindow; + do + { + if ( pWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN ) + pUpdateWindow = pWindow; + if ( pWindow->ImplIsOverlapWindow() ) + break; + pWindow = pWindow->ImplGetParent(); + } + while ( pWindow ); + + // if there is something to paint, trigger a Paint + if ( pUpdateWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDREN) ) + { + ImplDelData aDogTag(this); + + // trigger an update also for system windows on top of us, + // otherwise holes would remain + Window* pUpdateOverlapWindow = ImplGetFirstOverlapWindow()->mpWindowImpl->mpFirstOverlap; + while ( pUpdateOverlapWindow ) + { + pUpdateOverlapWindow->Update(); + pUpdateOverlapWindow = pUpdateOverlapWindow->mpWindowImpl->mpNext; + } + + pUpdateWindow->ImplCallPaint( NULL, pUpdateWindow->mpWindowImpl->mnPaintFlags ); + + if (aDogTag.IsDead()) + return; + bFlush = true; + } + + if ( bFlush ) + Flush(); +} + +void Window::ImplPaintToDevice( OutputDevice* i_pTargetOutDev, const Point& i_rPos ) +{ + bool bRVisible = mpWindowImpl->mbReallyVisible; + mpWindowImpl->mbReallyVisible = mpWindowImpl->mbVisible; + bool bDevOutput = mbDevOutput; + mbDevOutput = true; + + const OutputDevice *pOutDev = GetOutDev(); + long nOldDPIX = pOutDev->GetDPIX(); + long nOldDPIY = pOutDev->GetDPIY(); + mnDPIX = i_pTargetOutDev->GetDPIX(); + mnDPIY = i_pTargetOutDev->GetDPIY(); + bool bOutput = IsOutputEnabled(); + EnableOutput(); + + DBG_ASSERT( GetMapMode().GetMapUnit() == MAP_PIXEL, "MapMode must be PIXEL based" ); + if ( GetMapMode().GetMapUnit() != MAP_PIXEL ) + return; + + // preserve graphicsstate + Push(); + Region aClipRegion( GetClipRegion() ); + SetClipRegion(); + + GDIMetaFile* pOldMtf = GetConnectMetaFile(); + GDIMetaFile aMtf; + SetConnectMetaFile( &aMtf ); + + // put a push action to metafile + Push(); + // copy graphics state to metafile + Font aCopyFont = GetFont(); + if( nOldDPIX != mnDPIX || nOldDPIY != mnDPIY ) + { + aCopyFont.SetHeight( aCopyFont.GetHeight() * mnDPIY / nOldDPIY ); + aCopyFont.SetWidth( aCopyFont.GetWidth() * mnDPIX / nOldDPIX ); + } + SetFont( aCopyFont ); + SetTextColor( GetTextColor() ); + if( IsLineColor() ) + SetLineColor( GetLineColor() ); + else + SetLineColor(); + if( IsFillColor() ) + SetFillColor( GetFillColor() ); + else + SetFillColor(); + if( IsTextLineColor() ) + SetTextLineColor( GetTextLineColor() ); + else + SetTextLineColor(); + if( IsOverlineColor() ) + SetOverlineColor( GetOverlineColor() ); + else + SetOverlineColor(); + if( IsTextFillColor() ) + SetTextFillColor( GetTextFillColor() ); + else + SetTextFillColor(); + SetTextAlign( GetTextAlign() ); + SetRasterOp( GetRasterOp() ); + if( IsRefPoint() ) + SetRefPoint( GetRefPoint() ); + else + SetRefPoint(); + SetLayoutMode( GetLayoutMode() ); + SetDigitLanguage( GetDigitLanguage() ); + Rectangle aPaintRect( Point( 0, 0 ), GetOutputSizePixel() ); + aClipRegion.Intersect( aPaintRect ); + SetClipRegion( aClipRegion ); + + // do the actual paint + + // background + if( ! IsPaintTransparent() && IsBackground() && ! (GetParentClipMode() & PARENTCLIPMODE_NOCLIP ) ) + Erase(); + // foreground + Paint( aPaintRect ); + // put a pop action to metafile + Pop(); + + SetConnectMetaFile( pOldMtf ); + EnableOutput( bOutput ); + mpWindowImpl->mbReallyVisible = bRVisible; + + // paint metafile to VDev + VirtualDevice* pMaskedDevice = new VirtualDevice( *i_pTargetOutDev, 0, 0 ); + pMaskedDevice->SetOutputSizePixel( GetOutputSizePixel() ); + pMaskedDevice->EnableRTL( IsRTLEnabled() ); + aMtf.WindStart(); + aMtf.Play( pMaskedDevice ); + BitmapEx aBmpEx( pMaskedDevice->GetBitmapEx( Point( 0, 0 ), pMaskedDevice->GetOutputSizePixel() ) ); + i_pTargetOutDev->DrawBitmapEx( i_rPos, aBmpEx ); + // get rid of virtual device now so they don't pile up during recursive calls + delete pMaskedDevice, pMaskedDevice = NULL; + + for( Window* pChild = mpWindowImpl->mpFirstChild; pChild; pChild = pChild->mpWindowImpl->mpNext ) + { + if( pChild->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame && pChild->IsVisible() ) + { + long nDeltaX = pChild->mnOutOffX - mnOutOffX; + + if( pOutDev->HasMirroredGraphics() ) + nDeltaX = mnOutWidth - nDeltaX - pChild->mnOutWidth; + long nDeltaY = pChild->GetOutOffYPixel() - GetOutOffYPixel(); + Point aPos( i_rPos ); + Point aDelta( nDeltaX, nDeltaY ); + aPos += aDelta; + pChild->ImplPaintToDevice( i_pTargetOutDev, aPos ); + } + } + + // restore graphics state + Pop(); + + EnableOutput( bOutput ); + mpWindowImpl->mbReallyVisible = bRVisible; + mbDevOutput = bDevOutput; + mnDPIX = nOldDPIX; + mnDPIY = nOldDPIY; +} + +void Window::PaintToDevice( OutputDevice* pDev, const Point& rPos, const Size& /*rSize*/ ) +{ + // FIXME: scaling: currently this is for pixel copying only + + DBG_ASSERT( ! pDev->HasMirroredGraphics(), "PaintToDevice to mirroring graphics" ); + DBG_ASSERT( ! pDev->IsRTLEnabled(), "PaintToDevice to mirroring device" ); + + Window* pRealParent = NULL; + if( ! mpWindowImpl->mbVisible ) + { + Window* pTempParent = ImplGetDefaultWindow(); + if( pTempParent ) + pTempParent->EnableChildTransparentMode(); + pRealParent = GetParent(); + SetParent( pTempParent ); + // trigger correct visibility flags for children + Show(); + Hide(); + } + + bool bVisible = mpWindowImpl->mbVisible; + mpWindowImpl->mbVisible = true; + + if( mpWindowImpl->mpBorderWindow ) + mpWindowImpl->mpBorderWindow->ImplPaintToDevice( pDev, rPos ); + else + ImplPaintToDevice( pDev, rPos ); + + mpWindowImpl->mbVisible = bVisible; + + if( pRealParent ) + SetParent( pRealParent ); +} + +void Window::Erase() +{ + if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() ) + return; + + bool bNativeOK = false; + + ControlPart aCtrlPart = ImplGetWindowImpl()->mnNativeBackground; + if( aCtrlPart != 0 && ! IsControlBackground() ) + { + Rectangle aCtrlRegion( Point(), GetOutputSizePixel() ); + ControlState nState = 0; + + if( IsEnabled() ) + nState |= CTRL_STATE_ENABLED; + + bNativeOK = DrawNativeControl( CTRL_WINDOW_BACKGROUND, aCtrlPart, aCtrlRegion, + nState, ImplControlValue(), OUString() ); + } + + if ( mbBackground && ! bNativeOK ) + { + RasterOp eRasterOp = GetRasterOp(); + if ( eRasterOp != ROP_OVERPAINT ) + SetRasterOp( ROP_OVERPAINT ); + DrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground ); + if ( eRasterOp != ROP_OVERPAINT ) + SetRasterOp( eRasterOp ); + } + + if( mpAlphaVDev ) + mpAlphaVDev->Erase(); +} + +void Window::ImplScroll( const Rectangle& rRect, + long nHorzScroll, long nVertScroll, sal_uInt16 nFlags ) +{ + if ( !IsDeviceOutputNecessary() ) + return; + + nHorzScroll = ImplLogicWidthToDevicePixel( nHorzScroll ); + nVertScroll = ImplLogicHeightToDevicePixel( nVertScroll ); + + if ( !nHorzScroll && !nVertScroll ) + return; + + // restore background storage + if ( mpWindowImpl->mpFrameData->mpFirstBackWin ) + ImplInvalidateAllOverlapBackgrounds(); + + if ( mpWindowImpl->mpCursor ) + mpWindowImpl->mpCursor->ImplSuspend(); + + sal_uInt16 nOrgFlags = nFlags; + if ( !(nFlags & (SCROLL_CHILDREN | SCROLL_NOCHILDREN)) ) + { + if ( GetStyle() & WB_CLIPCHILDREN ) + nFlags |= SCROLL_NOCHILDREN; + else + nFlags |= SCROLL_CHILDREN; + } + + Region aInvalidateRegion; + bool bScrollChildren = (nFlags & SCROLL_CHILDREN) != 0; + bool bErase = (nFlags & SCROLL_NOERASE) == 0; + + if ( !mpWindowImpl->mpFirstChild ) + bScrollChildren = false; + + OutputDevice *pOutDev = GetOutDev(); + + // --- RTL --- check if this window requires special action + bool bReMirror = ( ImplIsAntiparallel() ); + + Rectangle aRectMirror( rRect ); + if( bReMirror ) + { + // --- RTL --- make sure the invalidate region of this window is + // computed in the same coordinate space as the one from the overlap windows + pOutDev->ReMirror( aRectMirror ); + } + + // adapt paint areas + ImplMoveAllInvalidateRegions( aRectMirror, nHorzScroll, nVertScroll, bScrollChildren ); + + if ( !(nFlags & SCROLL_NOINVALIDATE) ) + { + ImplCalcOverlapRegion( aRectMirror, aInvalidateRegion, !bScrollChildren, true, false ); + + // --- RTL --- + // if the scrolling on the device is performed in the opposite direction + // then move the overlaps in that direction to compute the invalidate region + // on the correct side, i.e., revert nHorzScroll + + if ( !aInvalidateRegion.IsEmpty() ) + { + aInvalidateRegion.Move( bReMirror ? -nHorzScroll : nHorzScroll, nVertScroll ); + bErase = true; + } + if ( !(nFlags & SCROLL_NOWINDOWINVALIDATE) ) + { + Rectangle aDestRect( aRectMirror ); + aDestRect.Move( bReMirror ? -nHorzScroll : nHorzScroll, nVertScroll ); + Region aWinInvalidateRegion( aRectMirror ); + aWinInvalidateRegion.Exclude( aDestRect ); + + aInvalidateRegion.Union( aWinInvalidateRegion ); + } + } + + Point aPoint( mnOutOffX, mnOutOffY ); + Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) ); + if ( nFlags & SCROLL_CLIP ) + aRegion.Intersect( rRect ); + if ( mpWindowImpl->mbWinRegion ) + aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) ); + + aRegion.Exclude( aInvalidateRegion ); + + ImplClipBoundaries( aRegion, false, true ); + if ( !bScrollChildren ) + { + if ( nOrgFlags & SCROLL_NOCHILDREN ) + ImplClipAllChildren( aRegion ); + else + ImplClipChildren( aRegion ); + } + if ( mbClipRegion && (nFlags & SCROLL_USECLIPREGION) ) + aRegion.Intersect( maRegion ); + if ( !aRegion.IsEmpty() ) + { + if ( mpWindowImpl->mpWinData ) + { + if ( mpWindowImpl->mbFocusVisible ) + ImplInvertFocus( *(mpWindowImpl->mpWinData->mpFocusRect) ); + if ( mpWindowImpl->mbTrackVisible && (mpWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) ) + InvertTracking( *(mpWindowImpl->mpWinData->mpTrackRect), mpWindowImpl->mpWinData->mnTrackFlags ); + } +#ifndef IOS + // This seems completely unnecessary with tiled rendering, and + // causes the "AquaSalGraphics::copyArea() for non-layered + // graphics" message. Presumably we should bypass this on all + // platforms when dealing with a "window" that uses tiled + // rendering at the moment. Unclear how to figure that out, + // though. Also unclear whether we actually could just not + // create a "frame window", whatever that exactly is, in the + // tiled rendering case, or at least for platforms where tiles + // rendering is all there is. + + SalGraphics* pGraphics = ImplGetFrameGraphics(); + if ( pGraphics ) + { + if( bReMirror ) + { + // --- RTL --- frame coordinates require re-mirroring + pOutDev->ReMirror( aRegion ); + } + + pOutDev->SelectClipRegion( aRegion, pGraphics ); + pGraphics->CopyArea( rRect.Left()+nHorzScroll, rRect.Top()+nVertScroll, + rRect.Left(), rRect.Top(), + rRect.GetWidth(), rRect.GetHeight(), + SAL_COPYAREA_WINDOWINVALIDATE, this ); + } +#endif + if ( mpWindowImpl->mpWinData ) + { + if ( mpWindowImpl->mbFocusVisible ) + ImplInvertFocus( *(mpWindowImpl->mpWinData->mpFocusRect) ); + if ( mpWindowImpl->mbTrackVisible && (mpWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) ) + InvertTracking( *(mpWindowImpl->mpWinData->mpTrackRect), mpWindowImpl->mpWinData->mnTrackFlags ); + } + } + + if ( !aInvalidateRegion.IsEmpty() ) + { + // --- RTL --- the invalidate region for this windows is already computed in frame coordinates + // so it has to be re-mirrored before calling the Paint-handler + mpWindowImpl->mnPaintFlags |= IMPL_PAINT_CHECKRTL; + + sal_uInt16 nPaintFlags = INVALIDATE_CHILDREN; + if ( !bErase ) + nPaintFlags |= INVALIDATE_NOERASE; + if ( !bScrollChildren ) + { + if ( nOrgFlags & SCROLL_NOCHILDREN ) + ImplClipAllChildren( aInvalidateRegion ); + else + ImplClipChildren( aInvalidateRegion ); + } + ImplInvalidateFrameRegion( &aInvalidateRegion, nPaintFlags ); + } + + if ( bScrollChildren ) + { + Window* pWindow = mpWindowImpl->mpFirstChild; + while ( pWindow ) + { + Point aPos = pWindow->GetPosPixel(); + aPos += Point( nHorzScroll, nVertScroll ); + pWindow->SetPosPixel( aPos ); + + pWindow = pWindow->mpWindowImpl->mpNext; + } + } + + if ( nFlags & SCROLL_UPDATE ) + Update(); + + if ( mpWindowImpl->mpCursor ) + mpWindowImpl->mpCursor->ImplResume(); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits