tdf#123779 Qt5 correctly fill Qt5Frame::maGeometry

The tooltip in the bug is actually not one, but the VCL implementation
of Gtk's popover widget triggered by SalFrame::ShowPopover. This has
no Qt equivalent, so we currently rely on the crude VCL version.

But for this maGeometry must contain the correct information, AKA the
absolute, unmirrored, paintable system geometry of the frame. Then the
window can be positioned correctly.

The patch gets rid of most of the code initially copied from gtk, when
this VCL backend was in a very early state.

Change-Id: Id44e4dc2aac41f1f01d51c4d8107892e644ef243
Reviewed-on: https://gerrit.libreoffice.org/74546
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
(cherry picked from commit 337b592a721bef2c54cbe8c4927e5cc5a68c2138)
Reviewed-on: https://gerrit.libreoffice.org/74566
diff --git a/vcl/inc/qt5/Qt5MainWindow.hxx b/vcl/inc/qt5/Qt5MainWindow.hxx
index a2a7e18..a083617 100644
--- a/vcl/inc/qt5/Qt5MainWindow.hxx
+++ b/vcl/inc/qt5/Qt5MainWindow.hxx
@@ -28,9 +28,10 @@
{
    Q_OBJECT

    Qt5Frame* m_pFrame;
    Qt5Frame& m_rFrame;

    virtual void closeEvent(QCloseEvent* pEvent) override;
    void moveEvent(QMoveEvent*) override;

public:
    Qt5MainWindow(Qt5Frame& rFrame, QWidget* parent = Q_NULLPTR,
diff --git a/vcl/inc/salframe.hxx b/vcl/inc/salframe.hxx
index 86ad6da..19293b9 100644
--- a/vcl/inc/salframe.hxx
+++ b/vcl/inc/salframe.hxx
@@ -124,7 +124,7 @@
                            SalFrame();
    virtual                 ~SalFrame() override;

    SalFrameGeometry        maGeometry;
    SalFrameGeometry        maGeometry; ///< absolute, unmirrored values

    // SalGeometryProvider
    virtual long GetWidth() const override { return maGeometry.nWidth; }
@@ -165,6 +165,7 @@
    const SalFrameGeometry& GetUnmirroredGeometry() const { return maGeometry; }

    virtual void            SetWindowState( const SalFrameState* pState ) = 0;
    // return the absolute, unmirrored system frame state
    // if this returns false the structure is uninitialised
    [[nodiscard]]
    virtual bool            GetWindowState( SalFrameState* pState ) = 0;
diff --git a/vcl/qt5/Qt5Frame.cxx b/vcl/qt5/Qt5Frame.cxx
index 6307a70..b0098474 100644
--- a/vcl/qt5/Qt5Frame.cxx
+++ b/vcl/qt5/Qt5Frame.cxx
@@ -171,8 +171,8 @@
    {
        maGeometry.nDisplayScreenNumber = 0;
        Size aDefSize = CalcDefaultSize();
        maGeometry.nX = -1;
        maGeometry.nY = -1;
        maGeometry.nX = 0;
        maGeometry.nY = 0;
        maGeometry.nWidth = aDefSize.Width();
        maGeometry.nHeight = aDefSize.Height();
        maGeometry.nTopDecoration = 0;
@@ -372,8 +372,7 @@
{
    assert(m_pQWidget);

    if (m_bDefaultSize)
        SetDefaultSize();
    SetDefaultSize();

    auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
    assert(pSalInst);
@@ -431,9 +430,13 @@

void Qt5Frame::SetDefaultSize()
{
    if (!m_bDefaultSize)
        return;

    Size aDefSize = CalcDefaultSize();
    SetPosSize(0, 0, aDefSize.Width(), aDefSize.Height(),
               SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT);
    assert(!m_bDefaultSize);
}

void Qt5Frame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags)
@@ -441,38 +444,57 @@
    if (!isWindow() || isChild(true, false))
        return;

    if ((nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT))
        && (nWidth > 0 && nHeight > 0) // sometimes stupid things happen
    )
    if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT))
    {
        m_bDefaultSize = false;
        if (isChild(false) || !m_pQWidget->isMaximized())
        {
            if (m_nStyle & SalFrameStyleFlags::SIZEABLE)
                asChild()->resize(nWidth, nHeight);
            else
                asChild()->setFixedSize(nWidth, nHeight);
            if (!(nFlags & SAL_FRAME_POSSIZE_WIDTH))
                nWidth = maGeometry.nWidth;
            else if (!(nFlags & SAL_FRAME_POSSIZE_HEIGHT))
                nHeight = maGeometry.nHeight;
            assert(nWidth > 0 && nHeight > 0);

            if (nWidth > 0 && nHeight > 0)
            {
                if (m_nStyle & SalFrameStyleFlags::SIZEABLE)
                    asChild()->resize(nWidth, nHeight);
                else
                    asChild()->setFixedSize(nWidth, nHeight);

                // assume the resize happened
                // needed for calculations and will eventuall be corrected by events
                maGeometry.nWidth = nWidth;
                maGeometry.nHeight = nHeight;
            }
        }
    }
    else if (m_bDefaultSize)
    else
        SetDefaultSize();

    m_bDefaultSize = false;

    if (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y))
    {
        if (m_pParent)
        {
            QRect aRect;
            if (m_pParent->GetTopLevelWindow())
                aRect = m_pParent->GetTopLevelWindow()->geometry();
            const SalFrameGeometry& aParentGeometry = m_pParent->maGeometry;
            if (QGuiApplication::isRightToLeft())
                nX = aParentGeometry.nX + aParentGeometry.nWidth - nX - maGeometry.nWidth - 1;
            else
                aRect = m_pParent->GetQWidget()->geometry();
                nX += aParentGeometry.nX;
            nY += aParentGeometry.nY;

            nX += aRect.x();
            nY += aRect.y();
            Qt5MainWindow* pTopLevel = m_pParent->GetTopLevelWindow();
            if (pTopLevel && pTopLevel->menuBar() && pTopLevel->menuBar()->isVisible())
                nY += pTopLevel->menuBar()->geometry().height();
        }

        if (!(nFlags & SAL_FRAME_POSSIZE_X))
            nX = maGeometry.nX;
        else if (!(nFlags & SAL_FRAME_POSSIZE_Y))
            nY = maGeometry.nY;

        // assume the reposition happened
        // needed for calculations and will eventually be corrected by events later
        maGeometry.nX = nX;
        maGeometry.nY = nY;

@@ -553,25 +575,15 @@
                | WindowStateMask::Height))
    {
        sal_uInt16 nPosSizeFlags = 0;
        QPoint aPos = m_pQWidget->pos();
        QPoint aParentPos;
        if (m_pParent)
            aParentPos = m_pParent->GetQWidget()->window()->pos();
        long nX = pState->mnX - aParentPos.x();
        long nY = pState->mnY - aParentPos.y();
        if (pState->mnMask & WindowStateMask::X)
            nPosSizeFlags |= SAL_FRAME_POSSIZE_X;
        else
            nX = aPos.x() - aParentPos.x();
        if (pState->mnMask & WindowStateMask::Y)
            nPosSizeFlags |= SAL_FRAME_POSSIZE_Y;
        else
            nY = aPos.y() - aParentPos.y();
        if (pState->mnMask & WindowStateMask::Width)
            nPosSizeFlags |= SAL_FRAME_POSSIZE_WIDTH;
        if (pState->mnMask & WindowStateMask::Height)
            nPosSizeFlags |= SAL_FRAME_POSSIZE_HEIGHT;
        SetPosSize(nX, nY, pState->mnWidth, pState->mnHeight, nPosSizeFlags);
        SetPosSize(pState->mnX, pState->mnY, pState->mnWidth, pState->mnHeight, nPosSizeFlags);
    }
    else if (pState->mnMask & WindowStateMask::State && !isChild())
    {
@@ -596,11 +608,18 @@
    }
    else
    {
        // geometry() is the drawable area, which is wanted here
        QRect rect = asChild()->geometry();
        pState->mnX = rect.x();
        pState->mnY = rect.y();
        pState->mnWidth = rect.width();
        pState->mnHeight = rect.height();
        // the menubar is drawn natively, adjust for that
        if (maGeometry.nTopDecoration)
        {
            pState->mnY += maGeometry.nTopDecoration;
            pState->mnHeight -= maGeometry.nTopDecoration;
        }
        pState->mnMask |= WindowStateMask::X | WindowStateMask::Y | WindowStateMask::Width
                          | WindowStateMask::Height;
    }
@@ -730,8 +749,6 @@
    return true;
}

// do we even need it? void Qt5Frame::Flush(const tools::Rectangle& /*rRect*/) {}

void Qt5Frame::SetInputContext(SalInputContext* pContext)
{
    if (!pContext)
diff --git a/vcl/qt5/Qt5MainWindow.cxx b/vcl/qt5/Qt5MainWindow.cxx
index fd4e097..a78097f 100644
--- a/vcl/qt5/Qt5MainWindow.cxx
+++ b/vcl/qt5/Qt5MainWindow.cxx
@@ -17,7 +17,7 @@

Qt5MainWindow::Qt5MainWindow(Qt5Frame& rFrame, QWidget* parent, Qt::WindowFlags f)
    : QMainWindow(parent, f)
    , m_pFrame(&rFrame)
    , m_rFrame(rFrame)
{
    QAccessible::installFactory(Qt5AccessibleWidget::customFactory);
}
@@ -25,7 +25,7 @@
void Qt5MainWindow::closeEvent(QCloseEvent* pEvent)
{
    bool bRet = false;
    bRet = m_pFrame->CallCallback(SalEvent::Close, nullptr);
    bRet = m_rFrame.CallCallback(SalEvent::Close, nullptr);

    if (bRet)
        pEvent->accept();
@@ -35,3 +35,10 @@
    else
        pEvent->ignore();
}

void Qt5MainWindow::moveEvent(QMoveEvent* pEvent)
{
    m_rFrame.maGeometry.nX = pEvent->pos().x();
    m_rFrame.maGeometry.nY = pEvent->pos().y();
    m_rFrame.CallCallback(SalEvent::Move, nullptr);
}
diff --git a/vcl/qt5/Qt5Widget.cxx b/vcl/qt5/Qt5Widget.cxx
index 4513ab9..3b4c114 100644
--- a/vcl/qt5/Qt5Widget.cxx
+++ b/vcl/qt5/Qt5Widget.cxx
@@ -74,23 +74,26 @@

void Qt5Widget::resizeEvent(QResizeEvent* pEvent)
{
    const int nWidth = pEvent->size().width();
    const int nHeight = pEvent->size().height();

    m_rFrame.maGeometry.nWidth = nWidth;
    m_rFrame.maGeometry.nHeight = nHeight;

    if (m_rFrame.m_bUseCairo)
    {
        int width = size().width();
        int height = size().height();

        if (m_rFrame.m_pSvpGraphics)
        {
            cairo_surface_t* pSurface
                = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
                = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight);
            cairo_surface_set_user_data(pSurface, SvpSalGraphics::getDamageKey(),
                                        &m_rFrame.m_aDamageHandler, nullptr);
            m_rFrame.m_pSvpGraphics->setSurface(pSurface, basegfx::B2IVector(width, height));
            m_rFrame.m_pSvpGraphics->setSurface(pSurface, basegfx::B2IVector(nWidth, nHeight));
            UniqueCairoSurface old_surface(m_rFrame.m_pSurface.release());
            m_rFrame.m_pSurface.reset(pSurface);

            int min_width = qMin(pEvent->oldSize().width(), pEvent->size().width());
            int min_height = qMin(pEvent->oldSize().height(), pEvent->size().height());
            int min_width = qMin(pEvent->oldSize().width(), nWidth);
            int min_height = qMin(pEvent->oldSize().height(), nHeight);

            SalTwoRect rect(0, 0, min_width, min_height, 0, 0, min_width, min_height);

@@ -102,11 +105,10 @@
        QImage* pImage = nullptr;

        if (m_rFrame.m_pQImage)
            pImage = new QImage(
                m_rFrame.m_pQImage->copy(0, 0, pEvent->size().width(), pEvent->size().height()));
            pImage = new QImage(m_rFrame.m_pQImage->copy(0, 0, nWidth, nHeight));
        else
        {
            pImage = new QImage(size(), Qt5_DefaultFormat32);
            pImage = new QImage(nWidth, nHeight, Qt5_DefaultFormat32);
            pImage->fill(Qt::transparent);
        }

@@ -114,9 +116,6 @@
        m_rFrame.m_pQImage.reset(pImage);
    }

    m_rFrame.maGeometry.nWidth = size().width();
    m_rFrame.maGeometry.nHeight = size().height();

    m_rFrame.CallCallback(SalEvent::Resize, nullptr);
}

@@ -251,7 +250,15 @@
    QWidget::dropEvent(event);
}

void Qt5Widget::moveEvent(QMoveEvent*) { m_rFrame.CallCallback(SalEvent::Move, nullptr); }
void Qt5Widget::moveEvent(QMoveEvent* event)
{
    if (m_rFrame.m_pTopLevel)
        return;

    m_rFrame.maGeometry.nX = event->pos().x();
    m_rFrame.maGeometry.nY = event->pos().y();
    m_rFrame.CallCallback(SalEvent::Move, nullptr);
}

void Qt5Widget::showEvent(QShowEvent*)
{