diff options
-rw-r--r-- | examples/wayland/pure-qml/qml/main.qml | 1 | ||||
-rw-r--r-- | src/client/qwaylanddisplay.cpp | 81 | ||||
-rw-r--r-- | src/client/qwaylanddisplay_p.h | 4 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandclient.cpp | 12 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandclient.h | 15 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp | 7 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandquickitem.cpp | 7 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandseat.cpp | 20 | ||||
-rw-r--r-- | src/compositor/extensions/qwaylandqttextinputmethodmanager.cpp | 4 | ||||
-rw-r--r-- | src/compositor/extensions/qwaylandtextinputmanager.cpp | 6 |
10 files changed, 134 insertions, 23 deletions
diff --git a/examples/wayland/pure-qml/qml/main.qml b/examples/wayland/pure-qml/qml/main.qml index 5a0f324ec..837672764 100644 --- a/examples/wayland/pure-qml/qml/main.qml +++ b/examples/wayland/pure-qml/qml/main.qml @@ -79,6 +79,7 @@ WaylandCompositor { // Extension for Input Method (QT_IM_MODULE) support at compositor-side // ![text input] + TextInputManager {} QtTextInputMethodManager {} // ![text input] } diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index 6b1d7fa40..9ae6abd90 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -307,6 +307,75 @@ void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function<bo } } +void QWaylandDisplay::checkTextInputProtocol() +{ + if (mClientSideInputContextRequested) { + qCDebug(lcQpaWayland) << "mClientSideInputContextRequested is false, no need for text input."; + return; + } + + QStringList tips, timps; // for text input protocols and text input manager protocols + tips << QLatin1String(QtWayland::qt_text_input_method_v1::interface()->name) + << QLatin1String(QtWayland::zwp_text_input_v2::interface()->name); + timps << QLatin1String(QtWayland::qt_text_input_method_manager_v1::interface()->name) + << QLatin1String(QtWayland::zwp_text_input_manager_v2::interface()->name); + + bool found = false; + QString tiProtocols = QString::fromLocal8Bit(qgetenv("QT_WAYLAND_TEXT_INPUT_PROTOCOL")); + qCDebug(lcQpaWayland) << "QT_WAYLAND_TEXT_INPUT_PROTOCOL=" << tiProtocols; + if (!tiProtocols.isEmpty()) { + QStringList keys = tiProtocols.split(QLatin1Char(';')); + for (const QString &k : keys) { + int index = tips.indexOf(k); + if (index >= 0 && hasRegistryGlobal(timps[index]) && registerTextInputManager(timps, index)) + found = true; + } + } + + if (!found) { + for (int i = 0; i < timps.size(); i++) { + if (hasRegistryGlobal(timps[i]) && registerTextInputManager(timps, i)) + found = true; + } + } + + if (!found) + qCDebug(lcQpaWayland) << "Didn't find any supported text input protocol."; +} + +bool QWaylandDisplay::registerTextInputManager(const QStringList &protocols, int index) +{ + if (protocols.size() > 2 || index < 0 || index >= 2) + return false; + + QString p = protocols.at(index); + if (index == 0) { + for (const RegistryGlobal &global : mGlobals) { + if (global.interface == p) { + mTextInputMethodManager.reset(new QtWayland::qt_text_input_method_manager_v1(global.registry, global.id, 1)); + for (QWaylandInputDevice *inputDevice : qAsConst(mInputDevices)) + inputDevice->setTextInputMethod(new QWaylandTextInputMethod(this, mTextInputMethodManager->get_text_input_method(inputDevice->wl_seat()))); + mWaylandIntegration->reconfigureInputContext(); + return true; + } + } + } + + if (index == 1) { + for (const RegistryGlobal &global : mGlobals) { + if (global.interface == p) { + mTextInputManager.reset(new QtWayland::zwp_text_input_manager_v2(global.registry, global.id, 1)); + for (QWaylandInputDevice *inputDevice : qAsConst(mInputDevices)) + inputDevice->setTextInput(new QWaylandTextInput(this, mTextInputManager->get_text_input(inputDevice->wl_seat()))); + mWaylandIntegration->reconfigureInputContext(); + return true; + } + } + } + + return false; +} + QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const { for (auto screen : qAsConst(mScreens)) { @@ -362,16 +431,6 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin } else if (interface == QLatin1String(QWaylandPrimarySelectionDeviceManagerV1::interface()->name)) { mPrimarySelectionManager.reset(new QWaylandPrimarySelectionDeviceManagerV1(this, id, 1)); #endif - } else if (interface == QLatin1String(QtWayland::qt_text_input_method_manager_v1::interface()->name) && !mClientSideInputContextRequested) { - mTextInputMethodManager.reset(new QtWayland::qt_text_input_method_manager_v1(registry, id, 1)); - for (QWaylandInputDevice *inputDevice : qAsConst(mInputDevices)) - inputDevice->setTextInputMethod(new QWaylandTextInputMethod(this, mTextInputMethodManager->get_text_input_method(inputDevice->wl_seat()))); - mWaylandIntegration->reconfigureInputContext(); - } else if (interface == QLatin1String(QtWayland::zwp_text_input_manager_v2::interface()->name) && !mClientSideInputContextRequested) { - mTextInputManager.reset(new QtWayland::zwp_text_input_manager_v2(registry, id, 1)); - for (QWaylandInputDevice *inputDevice : qAsConst(mInputDevices)) - inputDevice->setTextInput(new QWaylandTextInput(this, mTextInputManager->get_text_input(inputDevice->wl_seat()))); - mWaylandIntegration->reconfigureInputContext(); } else if (interface == QLatin1String(QWaylandHardwareIntegration::interface()->name)) { bool disableHardwareIntegration = qEnvironmentVariableIntValue("QT_WAYLAND_DISABLE_HW_INTEGRATION"); if (!disableHardwareIntegration) { @@ -392,6 +451,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin const auto copy = mRegistryListeners; // be prepared for listeners unregistering on notification for (Listener l : copy) (*l.listener)(l.data, registry, id, interface, version); + + checkTextInputProtocol(); } void QWaylandDisplay::registry_global_remove(uint32_t id) diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h index 5fc7aec32..fc928ff3b 100644 --- a/src/client/qwaylanddisplay_p.h +++ b/src/client/qwaylanddisplay_p.h @@ -221,6 +221,7 @@ public: void dispatchQueueWhile(wl_event_queue *queue, std::function<bool()> condition, int timeout = -1); bool isKeyboardAvailable() const; + public slots: void blockingReadEvents(); void flushRequests(); @@ -231,6 +232,9 @@ private: void handleWaylandSync(); void requestWaylandSync(); + void checkTextInputProtocol(); + bool registerTextInputManager(const QStringList &protocols, int index); + struct Listener { Listener() = default; Listener(RegistryListener incomingListener, diff --git a/src/compositor/compositor_api/qwaylandclient.cpp b/src/compositor/compositor_api/qwaylandclient.cpp index 9ca61d608..466dd7157 100644 --- a/src/compositor/compositor_api/qwaylandclient.cpp +++ b/src/compositor/compositor_api/qwaylandclient.cpp @@ -103,6 +103,7 @@ public: */ QWaylandClient::QWaylandClient(QWaylandCompositor *compositor, wl_client *client) : QObject(*new QWaylandClientPrivate(compositor, client)) + , mTextInputProtocols(TextInputProtocol::NoProtocol) { Q_D(QWaylandClient); @@ -273,6 +274,17 @@ void QWaylandClient::close() d->compositor->destroyClient(this); } +QWaylandClient::TextInputProtocols QWaylandClient::textInputProtocols() const +{ + return mTextInputProtocols; +} + +void QWaylandClient::setTextInputProtocols(TextInputProtocols p) +{ + if (mTextInputProtocols != p) + mTextInputProtocols = p; +} + QT_END_NAMESPACE #include "moc_qwaylandclient.cpp" diff --git a/src/compositor/compositor_api/qwaylandclient.h b/src/compositor/compositor_api/qwaylandclient.h index 3d215aa74..667d7f644 100644 --- a/src/compositor/compositor_api/qwaylandclient.h +++ b/src/compositor/compositor_api/qwaylandclient.h @@ -61,6 +61,19 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandClient : public QObject public: ~QWaylandClient() override; + enum TextInputProtocol { + NoProtocol = 0, + QtTextInputMethodV1 = 1, + TextInputV2 = 2, + + QtTextInputMethod = QtTextInputMethodV1, + TextInput = TextInputV2 + }; + Q_DECLARE_FLAGS(TextInputProtocols, TextInputProtocol) + + TextInputProtocols textInputProtocols() const; + void setTextInputProtocols(TextInputProtocols p); + static QWaylandClient *fromWlClient(QWaylandCompositor *compositor, wl_client *wlClient); QWaylandCompositor *compositor() const; @@ -79,6 +92,8 @@ public Q_SLOTS: private: explicit QWaylandClient(QWaylandCompositor *compositor, wl_client *client); + + TextInputProtocols mTextInputProtocols; }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp b/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp index 31d6757b5..9c52f6469 100644 --- a/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp +++ b/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp @@ -79,9 +79,10 @@ void QWaylandInputMethodControl::inputMethodEvent(QInputMethodEvent *event) Q_D(QWaylandInputMethodControl); QWaylandTextInput *textInput = d->textInput(); + QWaylandQtTextInputMethod *textInputMethod = d->textInputMethod(); if (textInput) { textInput->sendInputMethodEvent(event); - } else if (QWaylandQtTextInputMethod *textInputMethod = d->textInputMethod()) { + } else if (textInputMethod) { textInputMethod->sendInputMethodEvent(event); } else { event->ignore(); @@ -172,11 +173,15 @@ QWaylandInputMethodControlPrivate::QWaylandInputMethodControlPrivate(QWaylandSur QWaylandQtTextInputMethod *QWaylandInputMethodControlPrivate::textInputMethod() const { + if (!surface->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::QtTextInputMethodV1)) + return nullptr; return QWaylandQtTextInputMethod::findIn(seat); } QWaylandTextInput *QWaylandInputMethodControlPrivate::textInput() const { + if (!surface->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV2)) + return nullptr; return QWaylandTextInput::findIn(seat); } diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp index d8e61fba3..d1b14ceb5 100644 --- a/src/compositor/compositor_api/qwaylandquickitem.cpp +++ b/src/compositor/compositor_api/qwaylandquickitem.cpp @@ -1120,13 +1120,16 @@ void QWaylandQuickItem::takeFocus(QWaylandSeat *device) } target->setKeyboardFocus(surface()); - { + qCDebug(qLcWaylandCompositorInputMethods) << Q_FUNC_INFO << " surface:" << surface() + << ", client:" << surface()->client() + << ", textinputprotocol:" << (int)(surface()->client()->textInputProtocols()); + if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV2)) { QWaylandTextInput *textInput = QWaylandTextInput::findIn(target); if (textInput) textInput->setFocus(surface()); } - { + if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::QtTextInputMethodV1)) { QWaylandQtTextInputMethod *textInputMethod = QWaylandQtTextInputMethod::findIn(target); if (textInputMethod) textInputMethod->setFocus(surface()); diff --git a/src/compositor/compositor_api/qwaylandseat.cpp b/src/compositor/compositor_api/qwaylandseat.cpp index ad664ccf9..9f607c5d9 100644 --- a/src/compositor/compositor_api/qwaylandseat.cpp +++ b/src/compositor/compositor_api/qwaylandseat.cpp @@ -469,16 +469,20 @@ void QWaylandSeat::sendFullKeyEvent(QKeyEvent *event) #if QT_CONFIG(im) if (keyboardFocus()->inputMethodControl()->enabled() && event->nativeScanCode() == 0) { - QWaylandTextInput *textInput = QWaylandTextInput::findIn(this); - if (textInput) { - textInput->sendKeyEvent(event); - return; + if (keyboardFocus()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV2)) { + QWaylandTextInput *textInput = QWaylandTextInput::findIn(this); + if (textInput) { + textInput->sendKeyEvent(event); + return; + } } - QWaylandQtTextInputMethod *textInputMethod = QWaylandQtTextInputMethod::findIn(this); - if (textInputMethod) { - textInputMethod->sendKeyEvent(event); - return; + if (keyboardFocus()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::QtTextInputMethodV1)) { + QWaylandQtTextInputMethod *textInputMethod = QWaylandQtTextInputMethod::findIn(this); + if (textInputMethod) { + textInputMethod->sendKeyEvent(event); + return; + } } } #endif diff --git a/src/compositor/extensions/qwaylandqttextinputmethodmanager.cpp b/src/compositor/extensions/qwaylandqttextinputmethodmanager.cpp index 8b41d5920..f90eb658b 100644 --- a/src/compositor/extensions/qwaylandqttextinputmethodmanager.cpp +++ b/src/compositor/extensions/qwaylandqttextinputmethodmanager.cpp @@ -50,6 +50,10 @@ void QWaylandQtTextInputMethodManagerPrivate::text_input_method_manager_v1_get_t if (textInput == nullptr) textInput = new QWaylandQtTextInputMethod(seat, compositor); textInput->add(resource->client(), id, wl_resource_get_version(resource->handle)); + QWaylandClient *client = QWaylandClient::fromWlClient(compositor, resource->client()); + QWaylandClient::TextInputProtocols p = client->textInputProtocols(); + client->setTextInputProtocols(p.setFlag(QWaylandClient::TextInputProtocol::QtTextInputMethodV1)); + if (!textInput->isInitialized()) textInput->initialize(); } diff --git a/src/compositor/extensions/qwaylandtextinputmanager.cpp b/src/compositor/extensions/qwaylandtextinputmanager.cpp index ae95b9659..15d68c977 100644 --- a/src/compositor/extensions/qwaylandtextinputmanager.cpp +++ b/src/compositor/extensions/qwaylandtextinputmanager.cpp @@ -47,10 +47,12 @@ void QWaylandTextInputManagerPrivate::zwp_text_input_manager_v2_get_text_input(R QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(q->extensionContainer()); QWaylandSeat *seat = QWaylandSeat::fromSeatResource(seatResource); QWaylandTextInput *textInput = QWaylandTextInput::findIn(seat); - if (!textInput) { + if (!textInput) textInput = new QWaylandTextInput(seat, compositor); - } textInput->add(resource->client(), id, wl_resource_get_version(resource->handle)); + QWaylandClient *client = QWaylandClient::fromWlClient(compositor, resource->client()); + QWaylandClient::TextInputProtocols p = client->textInputProtocols(); + client->setTextInputProtocols(p.setFlag(QWaylandClient::TextInputProtocol::TextInputV2)); if (!textInput->isInitialized()) textInput->initialize(); } |