tdf#71087 sfx2: avoid flicker in the start center

There were a couple of problems here:

1) BackingWindow now does double-buffering to avoid flicker when e.g.
navigating with the keyboard in sfx2::RecentDocsView

2) But then the menu background turned into white (instead of the
gradient), so MenuBarWindow needs to differentiate between doing its own
buffering vs painting into a buffer.

3) The focus rectangles were always painted directly, so keyboard
navigation in the startcenter lost focus rectangles, making it hard to
see which button is active currently. Fix this by explicitly painting a
tracking rectangle in PushButton::ImplDrawPushButton().

This brings an improvement for the Windows GDI and Linux gen backends.
Windows GL and Linux gtk3 is meant to be unchanged, they were already
flicker-free here.

Change-Id: Ib01e330c244c2b38a5b5c52399692e19ff811de3
Reviewed-on: https://gerrit.libreoffice.org/77969
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
diff --git a/sfx2/source/dialog/backingcomp.cxx b/sfx2/source/dialog/backingcomp.cxx
index 1de9a2d..a810f0b 100644
--- a/sfx2/source/dialog/backingcomp.cxx
+++ b/sfx2/source/dialog/backingcomp.cxx
@@ -576,6 +576,12 @@ void SAL_CALL BackingComp::dispose()
    {
        m_xWindow->removeEventListener(this);
        m_xWindow->removeKeyListener(this);
        VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(m_xWindow);
        auto pBack = dynamic_cast<BackingWindow*>(pWindow.get());
        if (pBack)
        {
            pBack->RequestDoubleBuffering(false);
        }
        m_xWindow.clear();
    }

@@ -660,6 +666,10 @@ void SAL_CALL BackingComp::initialize( /*IN*/ const css::uno::Sequence< css::uno
    // create the component window
    VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(xParentWindow);
    VclPtr<vcl::Window> pWindow = VclPtr<BackingWindow>::Create(pParent);
    if (!pWindow->IsNativeControlSupported(ControlType::Pushbutton, ControlPart::Focus))
    {
        pWindow->RequestDoubleBuffering(true);
    }
    m_xWindow = VCLUnoHelper::GetInterface(pWindow);

    if (!m_xWindow.is())
diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx
index 8669e65..27b6bd4 100644
--- a/vcl/source/control/button.cxx
+++ b/vcl/source/control/button.cxx
@@ -1080,7 +1080,13 @@ void PushButton::ImplDrawPushButton(vcl::RenderContext& rRenderContext)
                                  aInRect, bDrawMenuSep, nButtonStyle);

        if (HasFocus())
        {
            ShowFocus(ImplGetFocusRect());
            if (SupportsDoubleBuffering())
            {
                rRenderContext.Invert(ImplGetFocusRect(), InvertFlags::TrackFrame);
            }
        }
    }

    if (!bNativeOK)
@@ -1107,6 +1113,10 @@ void PushButton::ImplDrawPushButton(vcl::RenderContext& rRenderContext)
        if (HasFocus())
        {
            ShowFocus(ImplGetFocusRect());
            if (SupportsDoubleBuffering())
            {
                rRenderContext.Invert(ImplGetFocusRect(), InvertFlags::TrackFrame);
            }
        }
    }
}
diff --git a/vcl/source/window/bufferdevice.cxx b/vcl/source/window/bufferdevice.cxx
index d148058..ccdf541 100644
--- a/vcl/source/window/bufferdevice.cxx
+++ b/vcl/source/window/bufferdevice.cxx
@@ -31,6 +31,8 @@ BufferDevice::~BufferDevice()
vcl::RenderContext* BufferDevice::operator->() { return m_pBuffer.get(); }

vcl::RenderContext& BufferDevice::operator*() { return *m_pBuffer; }

vcl::RenderContext& BufferDevice::GetRenderContext() { return *m_pBuffer; }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/window/bufferdevice.hxx b/vcl/source/window/bufferdevice.hxx
index 26bf28e..75e89f9 100644
--- a/vcl/source/window/bufferdevice.hxx
+++ b/vcl/source/window/bufferdevice.hxx
@@ -25,6 +25,7 @@ class BufferDevice
public:
    BufferDevice(const VclPtr<vcl::Window>& pWindow, vcl::RenderContext& rRenderContext);
    ~BufferDevice();
    vcl::RenderContext& GetRenderContext();

    vcl::RenderContext* operator->();
    vcl::RenderContext& operator*();
diff --git a/vcl/source/window/menubarwindow.cxx b/vcl/source/window/menubarwindow.cxx
index 2cff7f1..ba9025a 100644
--- a/vcl/source/window/menubarwindow.cxx
+++ b/vcl/source/window/menubarwindow.cxx
@@ -914,8 +914,20 @@ void MenuBarWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Recta
        return;
    }

    // Make sure that all actual rendering happens in one go to avoid flicker.
    vcl::BufferDevice pBuffer(this, rRenderContext);
    vcl::RenderContext* pBuffer = nullptr;
    std::unique_ptr<vcl::BufferDevice> pBufferDevice;
    if (SupportsDoubleBuffering())
    {
        // No need to buffer twice, just set up the background.
        pBuffer = &rRenderContext;
        pBuffer->Erase(tools::Rectangle(Point(GetOutOffXPixel(), GetOutOffYPixel()), GetOutputSizePixel()));
    }
    else
    {
        // Make sure that all actual rendering happens in one go to avoid flicker.
        pBufferDevice.reset(new vcl::BufferDevice(this, rRenderContext));
        pBuffer = &pBufferDevice->GetRenderContext();
    }

    if (rRenderContext.IsNativeControlSupported(ControlType::Menubar, ControlPart::Entire))
    {