[Libreoffice-commits] core.git: vcl/source
Chris Sherlock
chris.sherlock79 at gmail.com
Fri May 23 06:14:04 PDT 2014
vcl/source/window/paint.cxx | 1363 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1363 insertions(+)
New commits:
commit e76dc5b422084f68cc4b27eea4cdbef3d3e7a1a9
Author: Chris Sherlock <chris.sherlock79 at 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: */
More information about the Libreoffice-commits
mailing list