diff options
author | JiDe Zhang <zhangjide@uniontech.com> | 2023-12-18 14:57:28 +0800 |
---|---|---|
committer | JiDe Zhang <zhangjide@uniontech.com> | 2024-03-05 12:26:10 +0800 |
commit | 8596998cb025a8338c9403f5ef9db5a23f5cc682 (patch) | |
tree | bae414b15b5adc0524d4e4bb6c0b1a2e35f13fe8 | |
parent | ca4774131b9b8ee40b4d7f5c1ba296af4700207f (diff) |
Add QT_IM_MODULES env to allows specify multi IM key
Like as QT_QPA_PLATFORM, supports specifying multiple keys, and can
perform fallback operations to prioritize the use of a certain plug-in.
This is useful when using Wayland and XWayland applications at the same
time. For an example, we can set "QT_IM_MODULES=wayland;fcitx", and the
wayland application will use the wayland input context plugin, the
xwayland application will use fcitx, which can't be done without adding
a new environment variable, if we specify "QT_IM_MODULE=wayland", the
XWayland applications may not be able to use the input method.
Fixes: QTBUG-120202
Change-Id: Iac408af241963147747a2fe685f1e27bf9d9ee64
Reviewed-by: Liang Qi <liang.qi@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: David Edmundson <davidedmundson@kde.org>
8 files changed, 49 insertions, 23 deletions
diff --git a/src/gui/kernel/qplatforminputcontextfactory.cpp b/src/gui/kernel/qplatforminputcontextfactory.cpp index 7074de56af..933d990f7c 100644 --- a/src/gui/kernel/qplatforminputcontextfactory.cpp +++ b/src/gui/kernel/qplatforminputcontextfactory.cpp @@ -28,10 +28,33 @@ QStringList QPlatformInputContextFactory::keys() #endif } -QString QPlatformInputContextFactory::requested() +QStringList QPlatformInputContextFactory::requested() { - QByteArray env = qgetenv("QT_IM_MODULE"); - return env.isNull() ? QString() : QString::fromLocal8Bit(env); + QStringList imList; + QByteArray env = qgetenv("QT_IM_MODULES"); + + if (!env.isEmpty()) + imList = QString::fromLocal8Bit(env).split(QChar::fromLatin1(';'), Qt::SkipEmptyParts); + + if (!imList.isEmpty()) + return imList; + + env = qgetenv("QT_IM_MODULE"); + if (!env.isEmpty()) + imList = {QString::fromLocal8Bit(env)}; + + return imList; +} + +QPlatformInputContext *QPlatformInputContextFactory::create(const QStringList& keys) +{ + for (const QString &key : keys) { + auto plugin = create(key); + if (plugin) + return plugin; + } + + return nullptr; } QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key) diff --git a/src/gui/kernel/qplatforminputcontextfactory_p.h b/src/gui/kernel/qplatforminputcontextfactory_p.h index 4968a51a8b..5f5881c508 100644 --- a/src/gui/kernel/qplatforminputcontextfactory_p.h +++ b/src/gui/kernel/qplatforminputcontextfactory_p.h @@ -27,7 +27,8 @@ class Q_GUI_EXPORT QPlatformInputContextFactory { public: static QStringList keys(); - static QString requested(); + static QStringList requested(); + static QPlatformInputContext *create(const QStringList &keys); static QPlatformInputContext *create(const QString &key); static QPlatformInputContext *create(); }; diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index d6d4ded3f2..038fe5172a 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -304,11 +304,11 @@ static bool needsBasicRenderloopWorkaround() void QAndroidPlatformIntegration::initialize() { - const QString icStr = QPlatformInputContextFactory::requested(); - if (icStr.isNull()) + const auto icStrs = QPlatformInputContextFactory::requested(); + if (icStrs.isEmpty()) m_inputContext.reset(new QAndroidInputContext); else - m_inputContext.reset(QPlatformInputContextFactory::create(icStr)); + m_inputContext.reset(QPlatformInputContextFactory::create(icStrs)); } bool QAndroidPlatformIntegration::hasCapability(Capability cap) const diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index ed2ab672b6..fce676158a 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -125,9 +125,9 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) #endif mFontDb.reset(new QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>); - QString icStr = QPlatformInputContextFactory::requested(); - icStr.isNull() ? mInputContext.reset(new QCocoaInputContext) - : mInputContext.reset(QPlatformInputContextFactory::create(icStr)); + auto icStrs = QPlatformInputContextFactory::requested(); + icStrs.isEmpty() ? mInputContext.reset(new QCocoaInputContext) + : mInputContext.reset(QPlatformInputContextFactory::create(icStrs)); initResources(); QMacAutoReleasePool pool; diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp index d2e7c8716c..01367bd56b 100644 --- a/src/plugins/platforms/wasm/qwasmintegration.cpp +++ b/src/plugins/platforms/wasm/qwasmintegration.cpp @@ -222,12 +222,12 @@ QPlatformOpenGLContext *QWasmIntegration::createPlatformOpenGLContext(QOpenGLCon void QWasmIntegration::initialize() { - if (qgetenv("QT_IM_MODULE").isEmpty() && touchPoints < 1) + auto icStrs = QPlatformInputContextFactory::requested(); + if (icStrs.isEmpty() && touchPoints < 1) return; - QString icStr = QPlatformInputContextFactory::requested(); - if (!icStr.isNull()) - m_inputContext.reset(QPlatformInputContextFactory::create(icStr)); + if (!icStrs.isEmpty()) + m_inputContext.reset(QPlatformInputContextFactory::create(icStrs)); else m_inputContext.reset(new QWasmInputContext()); } diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 01d364b0f0..6415c9ac50 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -256,9 +256,9 @@ QWindowsIntegration::~QWindowsIntegration() void QWindowsIntegration::initialize() { - QString icStr = QPlatformInputContextFactory::requested(); - icStr.isNull() ? d->m_inputContext.reset(new QWindowsInputContext) - : d->m_inputContext.reset(QPlatformInputContextFactory::create(icStr)); + auto icStrs = QPlatformInputContextFactory::requested(); + icStrs.isEmpty() ? d->m_inputContext.reset(new QWindowsInputContext) + : d->m_inputContext.reset(QPlatformInputContextFactory::create(icStrs)); } bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index 05b886d2da..e171f4d452 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -27,6 +27,7 @@ #include <QtGui/qaccessible.h> #include <QtGui/qguiapplication.h> #include <QtGui/qwindow.h> +#include <qpa/qplatforminputcontextfactory_p.h> #if !defined(Q_CC_BOR) && !defined (Q_CC_GNU) #include <comdef.h> @@ -434,7 +435,7 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR // The native OSK should be disabled if the Qt OSK is in use, // or if disabled via application attribute. - static bool imModuleEmpty = qEnvironmentVariableIsEmpty("QT_IM_MODULE"); + static bool imModuleEmpty = QPlatformInputContextFactory::requested().isEmpty(); bool nativeVKDisabled = QCoreApplication::testAttribute(Qt::AA_DisableNativeVirtualKeyboard); // If we want to disable the native OSK auto-showing diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index e76a34fce8..4dafae31e3 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -344,11 +344,12 @@ void QXcbIntegration::initialize() const auto defaultInputContext = "compose"_L1; // Perform everything that may potentially need the event dispatcher (timers, socket // notifiers) here instead of the constructor. - QString icStr = QPlatformInputContextFactory::requested(); - if (icStr.isNull()) - icStr = defaultInputContext; - m_inputContext.reset(QPlatformInputContextFactory::create(icStr)); - if (!m_inputContext && icStr != defaultInputContext && icStr != "none"_L1) + auto icStrs = QPlatformInputContextFactory::requested(); + if (icStrs.isEmpty()) + icStrs = { defaultInputContext }; + m_inputContext.reset(QPlatformInputContextFactory::create(icStrs)); + if (!m_inputContext && !icStrs.contains(defaultInputContext) + && icStrs != QStringList{"none"_L1}) m_inputContext.reset(QPlatformInputContextFactory::create(defaultInputContext)); connection()->keyboard()->initialize(); |