tdf#124118 Qt5 post non-code keys via ExtTextInput

Originally I tried to implement the gtk3 way by shoving all key
input in some way through the QInputMethod. But that turned out
to be impossible, because all the nice input event filtering is
privately hidden in the platform abstraction. And it took me
much longer to realize that gtk3 is doing this.

Still the delivered code point in the KeyEvent is correct, so
this simply uses ExtTextInput events for non-code key events,
if LO has enabled input method support for a frame.

Change-Id: Ia9bb6baf013cf790deecb9675f8309e32294e982
Reviewed-on: https://gerrit.libreoffice.org/73322
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
diff --git a/vcl/inc/qt5/Qt5Widget.hxx b/vcl/inc/qt5/Qt5Widget.hxx
index af48dbe..6398fa7 100644
--- a/vcl/inc/qt5/Qt5Widget.hxx
+++ b/vcl/inc/qt5/Qt5Widget.hxx
@@ -48,6 +48,7 @@

    bool handleKeyEvent(QKeyEvent*, bool);
    void handleMouseButtonEvent(QMouseEvent*, bool);
    void commitText(const QString& aText) const;

    virtual bool event(QEvent*) override;

diff --git a/vcl/qt5/Qt5Widget.cxx b/vcl/qt5/Qt5Widget.cxx
index a6b3d29..63eb685 100644
--- a/vcl/qt5/Qt5Widget.cxx
+++ b/vcl/qt5/Qt5Widget.cxx
@@ -394,13 +394,35 @@
    return nCode;
}

void Qt5Widget::commitText(const QString& aText) const
{
    SalExtTextInputEvent aInputEvent;
    aInputEvent.mpTextAttr = nullptr;
    aInputEvent.mnCursorFlags = 0;
    aInputEvent.maText = toOUString(aText);
    aInputEvent.mnCursorPos = aInputEvent.maText.getLength();

    SolarMutexGuard aGuard;
    vcl::DeletionListener aDel(&m_rFrame);
    m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
    if (!aDel.isDeleted())
        m_rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
}

bool Qt5Widget::handleKeyEvent(QKeyEvent* pEvent, bool bDown)
{
    SalKeyEvent aEvent;
    sal_uInt16 nCode = GetKeyCode(pEvent->key(), pEvent->modifiers());
    if (bDown && nCode == 0 && !pEvent->text().isEmpty()
        && testAttribute(Qt::WA_InputMethodEnabled))
    {
        commitText(pEvent->text());
        return true;
    }

    SalKeyEvent aEvent;
    aEvent.mnCharCode = (pEvent->text().isEmpty() ? 0 : pEvent->text().at(0).unicode());
    aEvent.mnRepeat = 0;
    aEvent.mnCode = GetKeyCode(pEvent->key(), pEvent->modifiers());
    aEvent.mnCode = nCode;
    aEvent.mnCode |= GetKeyModCode(pEvent->modifiers());

    QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle);
@@ -483,24 +505,13 @@

void Qt5Widget::inputMethodEvent(QInputMethodEvent* pEvent)
{
    SolarMutexGuard aGuard;
    SalExtTextInputEvent aInputEvent;
    aInputEvent.mpTextAttr = nullptr;
    aInputEvent.mnCursorFlags = 0;

    vcl::DeletionListener aDel(&m_rFrame);

    if (!pEvent->commitString().isEmpty())
    {
        aInputEvent.maText = toOUString(pEvent->commitString());
        aInputEvent.mnCursorPos = aInputEvent.maText.getLength();
        if (!aDel.isDeleted())
            m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
        if (!aDel.isDeleted())
            m_rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
    }
        commitText(pEvent->commitString());
    else
    {
        SalExtTextInputEvent aInputEvent;
        aInputEvent.mpTextAttr = nullptr;
        aInputEvent.mnCursorFlags = 0;
        aInputEvent.maText = toOUString(pEvent->preeditString());
        aInputEvent.mnCursorPos = 0;

@@ -549,8 +560,9 @@
        const bool bIsEmpty = aInputEvent.maText.isEmpty();
        if (m_bNonEmptyIMPreeditSeen || !bIsEmpty)
        {
            if (!aDel.isDeleted())
                m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
            SolarMutexGuard aGuard;
            vcl::DeletionListener aDel(&m_rFrame);
            m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
            if (!aDel.isDeleted() && bIsEmpty)
                m_rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
            m_bNonEmptyIMPreeditSeen = !bIsEmpty;