summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/wayland/pure-qml/qml/main.qml1
-rw-r--r--src/client/qwaylanddisplay.cpp81
-rw-r--r--src/client/qwaylanddisplay_p.h4
-rw-r--r--src/compositor/compositor_api/qwaylandclient.cpp12
-rw-r--r--src/compositor/compositor_api/qwaylandclient.h15
-rw-r--r--src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp7
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp7
-rw-r--r--src/compositor/compositor_api/qwaylandseat.cpp20
-rw-r--r--src/compositor/extensions/qwaylandqttextinputmethodmanager.cpp4
-rw-r--r--src/compositor/extensions/qwaylandtextinputmanager.cpp6
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();
}