[Libreoffice-commits] core.git: vcl/inc vcl/source

Miklos Vajna vmiklos at collabora.co.uk
Thu Jul 30 07:49:23 PDT 2015


 vcl/inc/window.h             |    1 +
 vcl/source/window/paint.cxx  |   33 +++++++++++++++++++--------------
 vcl/source/window/window.cxx |    3 +++
 3 files changed, 23 insertions(+), 14 deletions(-)

New commits:
commit ea5e83abcfa1406c401b8a1ec91efda65373b74b
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Jul 30 15:51:34 2015 +0200

    tdf#92982 vcl: stop creating/disposing the paint buffer in PaintHelper
    
    Instead:
    
    - create it early in Window::ImplInit(), except for the default window
      (that one is a chicken-and-egg problem, as creating a VirtualDevice
      invokes ImplGetDefaultWindow(), but creating the default window then
      would create a VirtualDevice)
    - only erase the painted area of the buffer, don't create it
    - use a separate bool in the frame state to track if we're in the middle
      of a (possibly recursive) buffered paint
    
    And with that, rename CreateBuffer() to StartBufferedPaint(), as it does
    not create the buffer anymore.
    
    Change-Id: Ib33e8afa36977aa809f0ea2158a369f288cba8c7

diff --git a/vcl/inc/window.h b/vcl/inc/window.h
index 39b94c0..f4976f2 100644
--- a/vcl/inc/window.h
+++ b/vcl/inc/window.h
@@ -180,6 +180,7 @@ struct ImplFrameData
 
     bool                mbInternalDragGestureRecognizer;
     VclPtr<VirtualDevice> mpBuffer; ///< Buffer for the double-buffering
+    bool mbInBufferedPaint; ///< PaintHelper is in the process of painting into this buffer.
 };
 
 struct ImplAccessibleInfos
diff --git a/vcl/source/window/paint.cxx b/vcl/source/window/paint.cxx
index a94e3d0..29aaa2d 100644
--- a/vcl/source/window/paint.cxx
+++ b/vcl/source/window/paint.cxx
@@ -85,8 +85,8 @@ public:
     }
     void DoPaint(const vcl::Region* pRegion);
 
-    /// Create the buffer, and set it up to have the same settings as m_pWindow.
-    void CreateBuffer();
+    /// Start buffered paint: set it up to have the same settings as m_pWindow.
+    void StartBufferedPaint();
 
     /// Setup the buffer according to the settings of the current m_pWindow.
     void SetupBuffer();
@@ -107,12 +107,17 @@ PaintHelper::PaintHelper(vcl::Window *pWindow, sal_uInt16 nPaintFlags)
 {
 }
 
-void PaintHelper::CreateBuffer()
+void PaintHelper::StartBufferedPaint()
 {
     ImplFrameData* pFrameData = m_pWindow->mpWindowImpl->mpFrameData;
-    assert(!pFrameData->mpBuffer);
+    assert(!pFrameData->mbInBufferedPaint);
 
-    pFrameData->mpBuffer = VclPtrInstance<VirtualDevice>();
+    // Instead of creating a new VirtualDevice, just erase the area we'll be
+    // painting over, as VirtualDevice::ImplInitVirDev() would do.
+    pFrameData->mpBuffer->SetBackground(Wallpaper(Color(COL_WHITE)));
+    pFrameData->mpBuffer->Erase(m_aPaintRect);
+
+    pFrameData->mbInBufferedPaint = true;
     m_bCreatedBuffer = true;
 
     SetupBuffer();
@@ -164,7 +169,7 @@ void PaintHelper::SetupBuffer()
 void PaintHelper::PaintBuffer()
 {
     ImplFrameData* pFrameData = m_pWindow->mpWindowImpl->mpFrameData;
-    assert(pFrameData->mpBuffer);
+    assert(pFrameData->mbInBufferedPaint);
     assert(m_bCreatedBuffer);
 
     pFrameData->mpBuffer->mnOutOffX = 0;
@@ -178,7 +183,7 @@ void PaintHelper::PaintBuffer()
     if (!getenv("VCL_DOUBLEBUFFERING_AVOID_PAINT"))
     {
         // The map mode of m_pWindow and/or the buffer may have changed since
-        // CreateBuffer(), set it back to what it was, otherwise unwanted
+        // StartBufferedPaint(), set it back to what it was, otherwise unwanted
         // scaling or translating may happen.
         m_pWindow->SetMapMode(m_aPaintRectMapMode);
         pFrameData->mpBuffer->SetMapMode(m_aPaintRectMapMode);
@@ -204,7 +209,7 @@ void PaintHelper::DoPaint(const vcl::Region* pRegion)
     WindowImpl* pWindowImpl = m_pWindow->ImplGetWindowImpl();
     vcl::Region* pWinChildClipRegion = m_pWindow->ImplGetWinChildClipRegion();
     ImplFrameData* pFrameData = m_pWindow->mpWindowImpl->mpFrameData;
-    if (pWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL || pFrameData->mpBuffer)
+    if (pWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL || pFrameData->mbInBufferedPaint)
     {
         pWindowImpl->maInvalidateRegion = *pWinChildClipRegion;
     }
@@ -231,16 +236,16 @@ void PaintHelper::DoPaint(const vcl::Region* pRegion)
         m_pWindow->BeginPaint();
 
         // double-buffering: setup the buffer if it does not exist
-        if (!pFrameData->mpBuffer && m_pWindow->SupportsDoubleBuffering())
-            CreateBuffer();
+        if (!pFrameData->mbInBufferedPaint && m_pWindow->SupportsDoubleBuffering())
+            StartBufferedPaint();
 
         // double-buffering: if this window does not support double-buffering,
         // but we are in the middle of double-buffered paint, we might be
         // losing information
-        if (pFrameData->mpBuffer && !m_pWindow->SupportsDoubleBuffering())
+        if (pFrameData->mbInBufferedPaint && !m_pWindow->SupportsDoubleBuffering())
             SAL_WARN("vcl.doublebuffering", "non-double buffered window in the double-buffered hierarchy, painting directly: " << typeid(*m_pWindow.get()).name());
 
-        if (pFrameData->mpBuffer && m_pWindow->SupportsDoubleBuffering())
+        if (pFrameData->mbInBufferedPaint && m_pWindow->SupportsDoubleBuffering())
         {
             // double-buffering
             SetupBuffer();
@@ -518,10 +523,10 @@ PaintHelper::~PaintHelper()
 
     // double-buffering: paint in case we created the buffer, the children are
     // already painted inside
-    if (m_bCreatedBuffer && pFrameData->mpBuffer)
+    if (m_bCreatedBuffer && pFrameData->mbInBufferedPaint)
     {
         PaintBuffer();
-        pFrameData->mpBuffer.disposeAndClear();
+        pFrameData->mbInBufferedPaint = false;
     }
 
     // #98943# draw toolbox selection
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index fc35c6f4..4cfffbb 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -1074,6 +1074,9 @@ void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* p
         mpWindowImpl->mpFrameData->maResizeIdle.SetIdleHdl( LINK( this, Window, ImplHandleResizeTimerHdl ) );
         mpWindowImpl->mpFrameData->maResizeIdle.SetDebugName( "vcl::Window maResizeIdle" );
         mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = false;
+        if (!(nStyle & WB_DEFAULTWIN) && SupportsDoubleBuffering())
+            mpWindowImpl->mpFrameData->mpBuffer = VclPtrInstance<VirtualDevice>();
+        mpWindowImpl->mpFrameData->mbInBufferedPaint = false;
 
         if ( pRealParent && IsTopWindow() )
         {


More information about the Libreoffice-commits mailing list