[neon/qt/qtwayland/Neon/release] debian: Backport upstream patch to fix accented and dead key combinations.

Dmitry Shachnev null at kde.org
Sun May 1 00:37:57 BST 2022


Git commit f37c12750da1486d029411414a590453383eb737 by Dmitry Shachnev.
Committed on 27/06/2021 at 10:15.
Pushed by sitter into branch 'Neon/release'.

Backport upstream patch to fix accented and dead key combinations.

Closes: #990348.

M  +3    -0    debian/changelog
A  +230  -0    debian/patches/fix_dead_keys.diff
M  +1    -0    debian/patches/series

https://invent.kde.org/neon/qt/qtwayland/commit/f37c12750da1486d029411414a590453383eb737

diff --git a/debian/changelog b/debian/changelog
index 15f38ed..2aaf720 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,8 @@
 qtwayland-opensource-src (5.15.2-3) UNRELEASED; urgency=medium
 
+  [ Dmitry Shachnev ]
+  * Backport upstream patch to fix accented and dead key combinations
+    (closes: #990348).
 
  -- Debian Qt/KDE Maintainers <debian-qt-kde at lists.debian.org>  Sun, 27 Jun 2021 13:08:24 +0300
 
diff --git a/debian/patches/fix_dead_keys.diff b/debian/patches/fix_dead_keys.diff
new file mode 100644
index 0000000..c2073e2
--- /dev/null
+++ b/debian/patches/fix_dead_keys.diff
@@ -0,0 +1,230 @@
+Description: allow QWaylandInputContext to accept composed key combinations
+ At the moment, we are forcing user to choose to either compose or use
+ the text-input channel. This patch brings some of the QComposeInputContext
+ functionality in order to let applications understand dead key
+ combinations like they are supposed to.
+ .
+ Having it in QWaylandInputContext rather than in QWaylandInputDevice
+ should solve the problems 3aedd01271dc4f4a13103d632df224971ab2b6df had
+ with 57c4af2b18c0fb1d266b245a107fa6cb876b9d9e, because we are doing it
+ in the input context rather than before. This way, if the user is
+ overriding the input method (e.g. by setting QT_IM_MODULE), all the key
+ strokes will still be properly forwarded to the module to use.
+ .
+ This in turn allows us to solve https://bugs.kde.org/show_bug.cgi?id=411729
+ and https://bugs.kde.org/show_bug.cgi?id=405388 since we don't need to
+ choose anymore between physical and virual keyboards anymore.
+Origin: upstream, https://code.qt.io/cgit/qt/qtwayland.git/commit/?id=cca1b94190a094b5
+Last-Update: 2021-06-27
+
+--- a/src/client/qwaylanddisplay_p.h
++++ b/src/client/qwaylanddisplay_p.h
+@@ -175,8 +175,6 @@ public:
+     QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
+     QWaylandXdgOutputManagerV1 *xdgOutputManager() const { return mXdgOutputManager.data(); }
+ 
+-    bool usingInputContextFromCompositor() const { return mUsingInputContextFromCompositor; }
+-
+     struct RegistryGlobal {
+         uint32_t id;
+         QString interface;
+@@ -282,7 +280,6 @@ private:
+     QReadWriteLock m_frameQueueLock;
+ 
+     bool mClientSideInputContextRequested = !QPlatformInputContextFactory::requested().isNull();
+-    bool mUsingInputContextFromCompositor = false;
+ 
+     void registry_global(uint32_t id, const QString &interface, uint32_t version) override;
+     void registry_global_remove(uint32_t id) override;
+--- a/src/client/qwaylandinputcontext.cpp
++++ b/src/client/qwaylandinputcontext.cpp
+@@ -406,6 +406,8 @@ bool QWaylandInputContext::isValid() con
+ void QWaylandInputContext::reset()
+ {
+     qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
++    if (m_composeState)
++        xkb_compose_state_reset(m_composeState);
+ 
+     QPlatformInputContext::reset();
+ 
+@@ -526,9 +528,14 @@ Qt::LayoutDirection QWaylandInputContext
+     return textInput()->inputDirection();
+ }
+ 
+-void QWaylandInputContext::setFocusObject(QObject *)
++void QWaylandInputContext::setFocusObject(QObject *object)
+ {
+     qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
++#if QT_CONFIG(xkbcommon)
++    m_focusObject = object;
++#else
++    Q_UNUSED(object);
++#endif
+ 
+     if (!textInput())
+         return;
+@@ -561,6 +568,92 @@ QWaylandTextInput *QWaylandInputContext:
+     return mDisplay->defaultInputDevice()->textInput();
+ }
+ 
++#if QT_CONFIG(xkbcommon)
++
++void QWaylandInputContext::ensureInitialized()
++{
++    if (m_initialized)
++        return;
++
++    if (!m_XkbContext) {
++        qCWarning(qLcQpaInputMethods) << "error: xkb context has not been set on" << metaObject()->className();
++        return;
++    }
++
++    m_initialized = true;
++    const char *locale = setlocale(LC_CTYPE, "");
++    if (!locale)
++        locale = setlocale(LC_CTYPE, nullptr);
++    qCDebug(qLcQpaInputMethods) << "detected locale (LC_CTYPE):" << locale;
++
++    m_composeTable = xkb_compose_table_new_from_locale(m_XkbContext, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
++    if (m_composeTable)
++        m_composeState = xkb_compose_state_new(m_composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
++
++    if (!m_composeTable) {
++        qCWarning(qLcQpaInputMethods, "failed to create compose table");
++        return;
++    }
++    if (!m_composeState) {
++        qCWarning(qLcQpaInputMethods, "failed to create compose state");
++        return;
++    }
++}
++
++bool QWaylandInputContext::filterEvent(const QEvent *event)
++{
++    auto keyEvent = static_cast<const QKeyEvent *>(event);
++    if (keyEvent->type() != QEvent::KeyPress)
++        return false;
++
++    if (!inputMethodAccepted())
++        return false;
++
++    // lazy initialization - we don't want to do this on an app startup
++    ensureInitialized();
++
++    if (!m_composeTable || !m_composeState)
++        return false;
++
++    xkb_compose_state_feed(m_composeState, keyEvent->nativeVirtualKey());
++
++    switch (xkb_compose_state_get_status(m_composeState)) {
++    case XKB_COMPOSE_COMPOSING:
++        return true;
++    case XKB_COMPOSE_CANCELLED:
++        reset();
++        return false;
++    case XKB_COMPOSE_COMPOSED:
++    {
++        const int size = xkb_compose_state_get_utf8(m_composeState, nullptr, 0);
++        QVarLengthArray<char, 32> buffer(size + 1);
++        xkb_compose_state_get_utf8(m_composeState, buffer.data(), buffer.size());
++        QString composedText = QString::fromUtf8(buffer.constData());
++
++        QInputMethodEvent event;
++        event.setCommitString(composedText);
++
++        if (!m_focusObject && qApp)
++            m_focusObject = qApp->focusObject();
++
++        if (m_focusObject)
++            QCoreApplication::sendEvent(m_focusObject, &event);
++        else
++            qCWarning(qLcQpaInputMethods, "no focus object");
++
++        reset();
++        return true;
++    }
++    case XKB_COMPOSE_NOTHING:
++        return false;
++    default:
++        Q_UNREACHABLE();
++        return false;
++    }
++}
++
++#endif
++
+ }
+ 
+ QT_END_NAMESPACE
+--- a/src/client/qwaylandinputcontext_p.h
++++ b/src/client/qwaylandinputcontext_p.h
+@@ -61,6 +61,10 @@
+ 
+ #include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
+ #include <qwaylandinputmethodeventbuilder_p.h>
++#include <qtwaylandclientglobal_p.h>
++#if QT_CONFIG(xkbcommon)
++#include <xkbcommon/xkbcommon-compose.h>
++#endif
+ 
+ struct wl_callback;
+ struct wl_callback_listener;
+@@ -155,11 +159,28 @@ public:
+ 
+     void setFocusObject(QObject *object) override;
+ 
++#if QT_CONFIG(xkbcommon)
++    bool filterEvent(const QEvent *event) override;
++
++    // This invokable is called from QXkbCommon::setXkbContext().
++    Q_INVOKABLE void setXkbContext(struct xkb_context *context) { m_XkbContext = context; }
++#endif
++
+ private:
+     QWaylandTextInput *textInput() const;
+ 
+     QWaylandDisplay *mDisplay = nullptr;
+     QPointer<QWindow> mCurrentWindow;
++
++#if QT_CONFIG(xkbcommon)
++    void ensureInitialized();
++
++    bool m_initialized = false;
++    QObject *m_focusObject = nullptr;
++    xkb_compose_table *m_composeTable = nullptr;
++    xkb_compose_state *m_composeState = nullptr;
++    struct xkb_context *m_XkbContext = nullptr;
++#endif
+ };
+ 
+ }
+--- a/src/client/qwaylandinputdevice.cpp
++++ b/src/client/qwaylandinputdevice.cpp
+@@ -1201,7 +1201,7 @@ void QWaylandInputDevice::Keyboard::hand
+     QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
+     bool filtered = false;
+ 
+-    if (inputContext && !mParent->mQDisplay->usingInputContextFromCompositor()) {
++    if (inputContext) {
+         QKeyEvent event(type, key, modifiers, nativeScanCode, nativeVirtualKey,
+                         nativeModifiers, text, autorepeat, count);
+         event.setTimestamp(timestamp);
+--- a/src/client/qwaylandintegration.cpp
++++ b/src/client/qwaylandintegration.cpp
+@@ -474,13 +474,11 @@ void QWaylandIntegration::reconfigureInp
+ 
+ #if QT_CONFIG(xkbcommon)
+     QXkbCommon::setXkbContext(mInputContext.data(), mDisplay->xkbContext());
++    if (QWaylandInputContext* waylandInput = qobject_cast<QWaylandInputContext*>(mInputContext.get())) {
++        waylandInput->setXkbContext(mDisplay->xkbContext());
++    }
+ #endif
+ 
+-    // Even if compositor-side input context handling has been requested, we fallback to
+-    // client-side handling if compositor does not provide the text-input extension. This
+-    // is why we need to check here which input context actually is being used.
+-    mDisplay->mUsingInputContextFromCompositor = qobject_cast<QWaylandInputContext *>(mInputContext.data());
+-
+     qCDebug(lcQpaWayland) << "using input method:" << inputContext()->metaObject()->className();
+ }
+ 
diff --git a/debian/patches/series b/debian/patches/series
index 3a8561e..36a7d79 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,2 @@
 skip_animated_cursor_test.diff
+fix_dead_keys.diff



More information about the Neon-commits mailing list