summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2015-08-07 16:35:11 +0200
committerTomaž Vajngerl <quikee@gmail.com>2015-08-07 15:27:48 +0000
commitec5da2f76adbfeaf1cebc6fb0e0dea08a7bdfe79 (patch)
treed8aa8d78a82650d45c447e8e978813054610d3c0
parent48bb50302187536339f680d850c90a3e4512c996 (diff)
Resolves: tdf#92982 vcl rendercontext: handle buffered paint of vcl::Cursor
Instead of painting on the vcl::Window directly, take a PaintBufferGuard, and use the vcl::RenderContext of it, that may be either the vcl::Window or the toplevel frame's buffer. Trigger the paint of the buffer by informing the guard what area was painted. In case of direct painting, both the ctor and the dtor of the guard is a NOP. This means that finally we can also assert Invert() calls on the output device, so that direct paint can't happen when double-buffering. Also: - make PaintBufferGuard visible outside paint.cxx - move buffer paint logic to PaintBufferGuard (cherry picked from commits c85b25114a756e1abb3e68a4c7d3630c486917b5, a6c7a0bf105c399d087e2d9f843dbd9b175fdf42 and c64a7ce1fcd1e30956a77530d0b76ad493841024) Change-Id: I0322563369dc63b3c49061cbe7c4a911cb13a2e2 Reviewed-on: https://gerrit.libreoffice.org/17576 Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> Tested-by: Jenkins <ci@libreoffice.org>
-rw-r--r--vcl/inc/window.h20
-rw-r--r--vcl/source/outdev/rect.cxx2
-rw-r--r--vcl/source/window/cursor.cxx9
-rw-r--r--vcl/source/window/paint.cxx215
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)