diff options
-rw-r--r-- | vcl/inc/window.h | 20 | ||||
-rw-r--r-- | vcl/source/outdev/rect.cxx | 2 | ||||
-rw-r--r-- | vcl/source/window/cursor.cxx | 9 | ||||
-rw-r--r-- | vcl/source/window/paint.cxx | 215 |
4 files changed, 146 insertions, 100 deletions
diff --git a/vcl/inc/window.h b/vcl/inc/window.h index 60f9b1ae52ad..213e2154b9a7 100644 --- a/vcl/inc/window.h +++ b/vcl/inc/window.h @@ -378,6 +378,26 @@ public: ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > mxDNDListenerContainer; }; +/// Sets up the buffer to have settings matching the window, and restores the original state in the dtor. +class PaintBufferGuard +{ + ImplFrameData* mpFrameData; + VclPtr<vcl::Window> m_pWindow; + bool mbBackground; + Wallpaper maBackground; + AllSettings maSettings; + long mnOutOffX; + long mnOutOffY; + Rectangle m_aPaintRect; +public: + PaintBufferGuard(ImplFrameData* pFrameData, vcl::Window* pWindow); + ~PaintBufferGuard(); + /// If this is called, then the dtor will also copy rRectangle to the window from the buffer, before restoring the state. + void SetPaintRect(const Rectangle& rRectangle); + /// Returns either the frame's buffer or the window, in case of no buffering. + vcl::RenderContext* GetRenderContext(); +}; + // helper methods bool ImplHandleMouseEvent( vcl::Window* pWindow, MouseNotifyEvent nSVEvent, bool bMouseLeave, diff --git a/vcl/source/outdev/rect.cxx b/vcl/source/outdev/rect.cxx index dfa491a527e8..03afdf9893bd 100644 --- a/vcl/source/outdev/rect.cxx +++ b/vcl/source/outdev/rect.cxx @@ -131,6 +131,7 @@ void OutputDevice::DrawRect( const Rectangle& rRect, void OutputDevice::Invert( const Rectangle& rRect, sal_uInt16 nFlags ) { + assert(!is_double_buffered_window()); if ( !IsDeviceOutputNecessary() ) return; @@ -163,6 +164,7 @@ void OutputDevice::Invert( const Rectangle& rRect, sal_uInt16 nFlags ) void OutputDevice::Invert( const Polygon& rPoly, sal_uInt16 nFlags ) { + assert(!is_double_buffered_window()); if ( !IsDeviceOutputNecessary() ) return; diff --git a/vcl/source/window/cursor.cxx b/vcl/source/window/cursor.cxx index 0bcad8056cfb..1968a26975b3 100644 --- a/vcl/source/window/cursor.cxx +++ b/vcl/source/window/cursor.cxx @@ -44,7 +44,9 @@ struct ImplCursorData static void ImplCursorInvert( ImplCursorData* pData ) { vcl::Window* pWindow = pData->mpWindow; - vcl::RenderContext* pRenderContext = pWindow->GetOutDev(); + PaintBufferGuard aGuard(pWindow->ImplGetWindowImpl()->mpFrameData, pWindow); + vcl::RenderContext* pRenderContext = aGuard.GetRenderContext(); + Rectangle aPaintRect; bool bMapMode = pRenderContext->IsMapModeEnabled(); pRenderContext->EnableMapMode( false ); sal_uInt16 nInvertStyle; @@ -109,11 +111,16 @@ static void ImplCursorInvert( ImplCursorData* pData ) if ( pData->mnOrientation ) aPoly.Rotate( pData->maPixRotOff, pData->mnOrientation ); pRenderContext->Invert( aPoly, nInvertStyle ); + aPaintRect = aPoly.GetBoundRect(); } } else + { pRenderContext->Invert( aRect, nInvertStyle ); + aPaintRect = aRect; + } pRenderContext->EnableMapMode( bMapMode ); + aGuard.SetPaintRect(pRenderContext->PixelToLogic(aPaintRect)); } void vcl::Cursor::ImplDraw() diff --git a/vcl/source/window/paint.cxx b/vcl/source/window/paint.cxx index 81f601ddcec2..19f5cdcea419 100644 --- a/vcl/source/window/paint.cxx +++ b/vcl/source/window/paint.cxx @@ -40,87 +40,124 @@ #define IMPL_PAINT_ERASE ((sal_uInt16)0x0010) #define IMPL_PAINT_CHECKRTL ((sal_uInt16)0x0020) -/// Sets up the buffer to have settings matching the window, and restore the original state in the dtor. -class PaintBufferGuard +// PaintBufferGuard + +PaintBufferGuard::PaintBufferGuard(ImplFrameData* pFrameData, vcl::Window* pWindow) + : mpFrameData(pFrameData), + m_pWindow(pWindow), + mbBackground(false), + mnOutOffX(0), + mnOutOffY(0) { - ImplFrameData* mpFrameData; - bool mbBackground; - Wallpaper maBackground; - AllSettings maSettings; - long mnOutOffX; - long mnOutOffY; -public: - PaintBufferGuard(ImplFrameData* pFrameData, vcl::Window* pWindow) - : mpFrameData(pFrameData), - mbBackground(false), - mnOutOffX(0), - mnOutOffY(0) - { - // transfer various settings - // FIXME: this must disappear as we move to RenderContext only, - // the painting must become state-less, so that no actual - // vcl::Window setting affects this - mbBackground = pFrameData->mpBuffer->IsBackground(); - if (pWindow->IsBackground()) + if (!pFrameData->mpBuffer) + return; + + // transfer various settings + // FIXME: this must disappear as we move to RenderContext only, + // the painting must become state-less, so that no actual + // vcl::Window setting affects this + mbBackground = pFrameData->mpBuffer->IsBackground(); + if (pWindow->IsBackground()) + { + maBackground = pFrameData->mpBuffer->GetBackground(); + pFrameData->mpBuffer->SetBackground(pWindow->GetBackground()); + } + //else + //SAL_WARN("vcl.doublebuffering", "the root of the double-buffering hierarchy should not have a transparent background"); + + PushFlags nFlags = PushFlags::NONE; + nFlags |= PushFlags::CLIPREGION; + nFlags |= PushFlags::FILLCOLOR; + nFlags |= PushFlags::FONT; + nFlags |= PushFlags::LINECOLOR; + nFlags |= PushFlags::MAPMODE; + maSettings = pFrameData->mpBuffer->GetSettings(); + nFlags |= PushFlags::REFPOINT; + nFlags |= PushFlags::TEXTCOLOR; + nFlags |= PushFlags::TEXTLINECOLOR; + nFlags |= PushFlags::OVERLINECOLOR; + nFlags |= PushFlags::TEXTFILLCOLOR; + nFlags |= PushFlags::TEXTALIGN; + nFlags |= PushFlags::RASTEROP; + nFlags |= PushFlags::TEXTLAYOUTMODE; + nFlags |= PushFlags::TEXTLANGUAGE; + pFrameData->mpBuffer->Push(nFlags); + pFrameData->mpBuffer->SetClipRegion(pWindow->GetClipRegion()); + pFrameData->mpBuffer->SetFillColor(pWindow->GetFillColor()); + pFrameData->mpBuffer->SetFont(pWindow->GetFont()); + pFrameData->mpBuffer->SetLineColor(pWindow->GetLineColor()); + pFrameData->mpBuffer->SetMapMode(pWindow->GetMapMode()); + pFrameData->mpBuffer->SetRefPoint(pWindow->GetRefPoint()); + pFrameData->mpBuffer->SetSettings(pWindow->GetSettings()); + pFrameData->mpBuffer->SetTextColor(pWindow->GetTextColor()); + pFrameData->mpBuffer->SetTextLineColor(pWindow->GetTextLineColor()); + pFrameData->mpBuffer->SetOverlineColor(pWindow->GetOverlineColor()); + pFrameData->mpBuffer->SetTextFillColor(pWindow->GetTextFillColor()); + pFrameData->mpBuffer->SetTextAlign(pWindow->GetTextAlign()); + pFrameData->mpBuffer->SetRasterOp(pWindow->GetRasterOp()); + pFrameData->mpBuffer->SetLayoutMode(pWindow->GetLayoutMode()); + pFrameData->mpBuffer->SetDigitLanguage(pWindow->GetDigitLanguage()); + + mnOutOffX = pFrameData->mpBuffer->GetOutOffXPixel(); + mnOutOffY = pFrameData->mpBuffer->GetOutOffYPixel(); + pFrameData->mpBuffer->SetOutOffXPixel(pWindow->GetOutOffXPixel()); + pFrameData->mpBuffer->SetOutOffYPixel(pWindow->GetOutOffYPixel()); +} + +PaintBufferGuard::~PaintBufferGuard() +{ + if (!mpFrameData->mpBuffer) + return; + + if (!m_aPaintRect.IsEmpty()) + { + // copy the buffer content to the actual window + // export VCL_DOUBLEBUFFERING_AVOID_PAINT=1 to see where we are + // painting directly instead of using Invalidate() + // [ie. everything you can see was painted directly to the + // window either above or in eg. an event handler] + if (!getenv("VCL_DOUBLEBUFFERING_AVOID_PAINT")) { - maBackground = pFrameData->mpBuffer->GetBackground(); - pFrameData->mpBuffer->SetBackground(pWindow->GetBackground()); + // Make sure that the +1 value GetSize() adds to the size is in pixels. + Size aPaintRectSize; + if (m_pWindow->GetMapMode().GetMapUnit() == MAP_PIXEL) + { + aPaintRectSize = m_aPaintRect.GetSize(); + } + else + { + Rectangle aRectanglePixel = m_pWindow->LogicToPixel(m_aPaintRect); + aPaintRectSize = m_pWindow->PixelToLogic(aRectanglePixel.GetSize()); + } + + m_pWindow->DrawOutDev(m_aPaintRect.TopLeft(), aPaintRectSize, m_aPaintRect.TopLeft(), aPaintRectSize, *mpFrameData->mpBuffer.get()); } - //else - //SAL_WARN("vcl.doublebuffering", "the root of the double-buffering hierarchy should not have a transparent background"); - - PushFlags nFlags = PushFlags::NONE; - nFlags |= PushFlags::CLIPREGION; - nFlags |= PushFlags::FILLCOLOR; - nFlags |= PushFlags::FONT; - nFlags |= PushFlags::LINECOLOR; - nFlags |= PushFlags::MAPMODE; - maSettings = pFrameData->mpBuffer->GetSettings(); - nFlags |= PushFlags::REFPOINT; - nFlags |= PushFlags::TEXTCOLOR; - nFlags |= PushFlags::TEXTLINECOLOR; - nFlags |= PushFlags::OVERLINECOLOR; - nFlags |= PushFlags::TEXTFILLCOLOR; - nFlags |= PushFlags::TEXTALIGN; - nFlags |= PushFlags::RASTEROP; - nFlags |= PushFlags::TEXTLAYOUTMODE; - nFlags |= PushFlags::TEXTLANGUAGE; - pFrameData->mpBuffer->Push(nFlags); - pFrameData->mpBuffer->SetClipRegion(pWindow->GetClipRegion()); - pFrameData->mpBuffer->SetFillColor(pWindow->GetFillColor()); - pFrameData->mpBuffer->SetFont(pWindow->GetFont()); - pFrameData->mpBuffer->SetLineColor(pWindow->GetLineColor()); - pFrameData->mpBuffer->SetMapMode(pWindow->GetMapMode()); - pFrameData->mpBuffer->SetRefPoint(pWindow->GetRefPoint()); - pFrameData->mpBuffer->SetSettings(pWindow->GetSettings()); - pFrameData->mpBuffer->SetTextColor(pWindow->GetTextColor()); - pFrameData->mpBuffer->SetTextLineColor(pWindow->GetTextLineColor()); - pFrameData->mpBuffer->SetOverlineColor(pWindow->GetOverlineColor()); - pFrameData->mpBuffer->SetTextFillColor(pWindow->GetTextFillColor()); - pFrameData->mpBuffer->SetTextAlign(pWindow->GetTextAlign()); - pFrameData->mpBuffer->SetRasterOp(pWindow->GetRasterOp()); - pFrameData->mpBuffer->SetLayoutMode(pWindow->GetLayoutMode()); - pFrameData->mpBuffer->SetDigitLanguage(pWindow->GetDigitLanguage()); - - mnOutOffX = pFrameData->mpBuffer->GetOutOffXPixel(); - mnOutOffY = pFrameData->mpBuffer->GetOutOffYPixel(); - pFrameData->mpBuffer->SetOutOffXPixel(pWindow->GetOutOffXPixel()); - pFrameData->mpBuffer->SetOutOffYPixel(pWindow->GetOutOffYPixel()); - } - ~PaintBufferGuard() - { - // Restore buffer state. - mpFrameData->mpBuffer->SetOutOffXPixel(mnOutOffX); - mpFrameData->mpBuffer->SetOutOffYPixel(mnOutOffY); - - mpFrameData->mpBuffer->Pop(); - mpFrameData->mpBuffer->SetSettings(maSettings); - if (mbBackground) - mpFrameData->mpBuffer->SetBackground(maBackground); - else - mpFrameData->mpBuffer->SetBackground(); } -}; + + // Restore buffer state. + mpFrameData->mpBuffer->SetOutOffXPixel(mnOutOffX); + mpFrameData->mpBuffer->SetOutOffYPixel(mnOutOffY); + + mpFrameData->mpBuffer->Pop(); + mpFrameData->mpBuffer->SetSettings(maSettings); + if (mbBackground) + mpFrameData->mpBuffer->SetBackground(maBackground); + else + mpFrameData->mpBuffer->SetBackground(); +} + +void PaintBufferGuard::SetPaintRect(const Rectangle& rRectangle) +{ + m_aPaintRect = rRectangle; +} + +vcl::RenderContext* PaintBufferGuard::GetRenderContext() +{ + if (mpFrameData->mpBuffer) + return mpFrameData->mpBuffer; + else + return m_pWindow; +} class PaintHelper { @@ -200,28 +237,8 @@ void PaintHelper::PaintBuffer() assert(pFrameData->mbInBufferedPaint); assert(m_bStartedBufferedPaint); - // copy the buffer content to the actual window - // export VCL_DOUBLEBUFFERING_AVOID_PAINT=1 to see where we are - // painting directly instead of using Invalidate() - // [ie. everything you can see was painted directly to the - // window either above or in eg. an event handler] - if (!getenv("VCL_DOUBLEBUFFERING_AVOID_PAINT")) - { - // Make sure that the +1 value GetSize() adds to the size is in pixels. - Size aPaintRectSize; - if (m_pWindow->GetMapMode().GetMapUnit() == MAP_PIXEL) - { - aPaintRectSize = m_aPaintRect.GetSize(); - } - else - { - Rectangle aRectanglePixel = m_pWindow->LogicToPixel(m_aPaintRect); - aPaintRectSize = m_pWindow->PixelToLogic(aRectanglePixel.GetSize()); - } - - PaintBufferGuard g(pFrameData, m_pWindow); - m_pWindow->DrawOutDev(m_aPaintRect.TopLeft(), aPaintRectSize, m_aPaintRect.TopLeft(), aPaintRectSize, *pFrameData->mpBuffer.get()); - } + PaintBufferGuard aGuard(pFrameData, m_pWindow); + aGuard.SetPaintRect(m_aPaintRect); } void PaintHelper::DoPaint(const vcl::Region* pRegion) |