1// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qwaylandinputmethodcontrol.h"
5#include "qwaylandinputmethodcontrol_p.h"
6
7#include "qwaylandcompositor.h"
8#include "qwaylandseat.h"
9#include "qwaylandsurface.h"
10#include "qwaylandview.h"
11#include "qwaylandtextinput.h"
12#if QT_WAYLAND_TEXT_INPUT_V4_WIP
13#include "qwaylandtextinputv4.h"
14#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
15#include "qwaylandqttextinputmethod.h"
16
17#include <QtGui/QInputMethodEvent>
18
19QWaylandInputMethodControl::QWaylandInputMethodControl(QWaylandSurface *surface)
20 : QObject(*new QWaylandInputMethodControlPrivate(surface), surface)
21{
22 connect(sender: d_func()->compositor, signal: &QWaylandCompositor::defaultSeatChanged,
23 context: this, slot: &QWaylandInputMethodControl::defaultSeatChanged);
24
25 updateTextInput();
26
27#if QT_WAYLAND_TEXT_INPUT_V4_WIP
28 QWaylandTextInputV4 *textInputV4 = d_func()->textInputV4();
29 if (textInputV4) {
30 connect(textInputV4, &QWaylandTextInputV4::surfaceEnabled, this, &QWaylandInputMethodControl::surfaceEnabled);
31 connect(textInputV4, &QWaylandTextInputV4::surfaceDisabled, this, &QWaylandInputMethodControl::surfaceDisabled);
32 connect(textInputV4, &QWaylandTextInputV4::updateInputMethod, this, &QWaylandInputMethodControl::updateInputMethod);
33 }
34#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
35
36 QWaylandQtTextInputMethod *textInputMethod = d_func()->textInputMethod();
37 if (textInputMethod) {
38 connect(sender: textInputMethod, signal: &QWaylandQtTextInputMethod::surfaceEnabled, context: this, slot: &QWaylandInputMethodControl::surfaceEnabled);
39 connect(sender: textInputMethod, signal: &QWaylandQtTextInputMethod::surfaceDisabled, context: this, slot: &QWaylandInputMethodControl::surfaceDisabled);
40 connect(sender: textInputMethod, signal: &QWaylandQtTextInputMethod::updateInputMethod, context: this, slot: &QWaylandInputMethodControl::updateInputMethod);
41 }
42}
43
44QVariant QWaylandInputMethodControl::inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const
45{
46 Q_D(const QWaylandInputMethodControl);
47
48 QWaylandTextInput *textInput = d->textInput();
49 if (textInput != nullptr && textInput->focus() == d->surface)
50 return textInput->inputMethodQuery(property: query, argument);
51
52#if QT_WAYLAND_TEXT_INPUT_V4_WIP
53 QWaylandTextInputV4 *textInputV4 = d->textInputV4();
54 if (textInputV4 != nullptr && textInputV4->focus() == d->surface)
55 return textInputV4->inputMethodQuery(query, argument);
56#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
57
58 QWaylandQtTextInputMethod *textInputMethod = d_func()->textInputMethod();
59 if (textInputMethod && textInputMethod->focusedSurface() == d->surface)
60 return textInputMethod->inputMethodQuery(property: query, argument);
61
62 return QVariant();
63}
64
65void QWaylandInputMethodControl::inputMethodEvent(QInputMethodEvent *event)
66{
67 Q_D(QWaylandInputMethodControl);
68
69 if (QWaylandTextInput *textInput = d->textInput()) {
70 textInput->sendInputMethodEvent(event);
71#if QT_WAYLAND_TEXT_INPUT_V4_WIP
72 } else if (QWaylandTextInputV4 *textInputV4 = d->textInputV4()) {
73 textInputV4->sendInputMethodEvent(event);
74#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
75 } else if (QWaylandQtTextInputMethod *textInputMethod = d->textInputMethod()) {
76 textInputMethod->sendInputMethodEvent(event);
77 } else {
78 event->ignore();
79 }
80}
81
82bool QWaylandInputMethodControl::enabled() const
83{
84 Q_D(const QWaylandInputMethodControl);
85
86 return d->enabled;
87}
88
89void QWaylandInputMethodControl::setEnabled(bool enabled)
90{
91 Q_D(QWaylandInputMethodControl);
92
93 if (d->enabled == enabled)
94 return;
95
96 d->enabled = enabled;
97 emit enabledChanged(enabled);
98 emit updateInputMethod(queries: Qt::ImQueryInput);
99}
100
101void QWaylandInputMethodControl::surfaceEnabled(QWaylandSurface *surface)
102{
103 Q_D(QWaylandInputMethodControl);
104
105 if (surface == d->surface)
106 setEnabled(true);
107}
108
109void QWaylandInputMethodControl::surfaceDisabled(QWaylandSurface *surface)
110{
111 Q_D(QWaylandInputMethodControl);
112
113 if (surface == d->surface)
114 setEnabled(false);
115}
116
117void QWaylandInputMethodControl::setSurface(QWaylandSurface *surface)
118{
119 Q_D(QWaylandInputMethodControl);
120
121 if (d->surface == surface)
122 return;
123
124 d->surface = surface;
125
126 QWaylandTextInput *textInput = d->textInput();
127#if QT_WAYLAND_TEXT_INPUT_V4_WIP
128 QWaylandTextInputV4 *textInputV4 = d->textInputV4();
129#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
130 QWaylandQtTextInputMethod *textInputMethod = d->textInputMethod();
131 setEnabled((textInput && textInput->isSurfaceEnabled(surface: d->surface))
132#if QT_WAYLAND_TEXT_INPUT_V4_WIP
133 || (textInputV4 && textInputV4->isSurfaceEnabled(d->surface))
134#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
135 || (textInputMethod && textInputMethod->isSurfaceEnabled(surface: d->surface)));
136}
137
138void QWaylandInputMethodControl::updateTextInput()
139{
140 QWaylandTextInput *textInput = d_func()->textInput();
141
142 if (textInput) {
143 connect(sender: textInput, signal: &QWaylandTextInput::surfaceEnabled, context: this, slot: &QWaylandInputMethodControl::surfaceEnabled, type: Qt::UniqueConnection);
144 connect(sender: textInput, signal: &QWaylandTextInput::surfaceDisabled, context: this, slot: &QWaylandInputMethodControl::surfaceDisabled, type: Qt::UniqueConnection);
145 connect(sender: textInput, signal: &QWaylandTextInput::updateInputMethod, context: this, slot: &QWaylandInputMethodControl::updateInputMethod, type: Qt::UniqueConnection);
146 }
147}
148
149void QWaylandInputMethodControl::defaultSeatChanged()
150{
151 Q_D(QWaylandInputMethodControl);
152
153 disconnect(sender: d->textInput(), signal: nullptr, receiver: this, member: nullptr);
154#if QT_WAYLAND_TEXT_INPUT_V4_WIP
155 disconnect(d->textInputV4(), nullptr, this, nullptr);
156#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
157 disconnect(sender: d->textInputMethod(), signal: nullptr, receiver: this, member: nullptr);
158
159 d->seat = d->compositor->defaultSeat();
160 QWaylandTextInput *textInput = d->textInput();
161#if QT_WAYLAND_TEXT_INPUT_V4_WIP
162 QWaylandTextInputV4 *textInputV4 = d->textInputV4();
163#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
164 QWaylandQtTextInputMethod *textInputMethod = d->textInputMethod();
165
166 if (textInput) {
167 connect(sender: textInput, signal: &QWaylandTextInput::surfaceEnabled, context: this, slot: &QWaylandInputMethodControl::surfaceEnabled);
168 connect(sender: textInput, signal: &QWaylandTextInput::surfaceDisabled, context: this, slot: &QWaylandInputMethodControl::surfaceDisabled);
169 }
170
171#if QT_WAYLAND_TEXT_INPUT_V4_WIP
172 if (textInputV4) {
173 connect(textInputV4, &QWaylandTextInputV4::surfaceEnabled, this, &QWaylandInputMethodControl::surfaceEnabled);
174 connect(textInputV4, &QWaylandTextInputV4::surfaceDisabled, this, &QWaylandInputMethodControl::surfaceDisabled);
175 }
176#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
177
178 if (textInputMethod) {
179 connect(sender: textInputMethod, signal: &QWaylandQtTextInputMethod::surfaceEnabled, context: this, slot: &QWaylandInputMethodControl::surfaceEnabled);
180 connect(sender: textInputMethod, signal: &QWaylandQtTextInputMethod::surfaceDisabled, context: this, slot: &QWaylandInputMethodControl::surfaceDisabled);
181 }
182
183 setEnabled((textInput && textInput->isSurfaceEnabled(surface: d->surface))
184#if QT_WAYLAND_TEXT_INPUT_V4_WIP
185 || (textInputV4 && textInputV4->isSurfaceEnabled(d->surface))
186#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
187 || (textInputMethod && textInputMethod->isSurfaceEnabled(surface: d->surface)));
188}
189
190QWaylandInputMethodControlPrivate::QWaylandInputMethodControlPrivate(QWaylandSurface *surface)
191 : compositor(surface->compositor())
192 , seat(compositor->defaultSeat())
193 , surface(surface)
194{
195}
196
197QWaylandQtTextInputMethod *QWaylandInputMethodControlPrivate::textInputMethod() const
198{
199 if (!surface->client() || !surface->client()->textInputProtocols().testFlag(flag: QWaylandClient::TextInputProtocol::QtTextInputMethodV1))
200 return nullptr;
201 return QWaylandQtTextInputMethod::findIn(container: seat);
202}
203
204QWaylandTextInput *QWaylandInputMethodControlPrivate::textInput() const
205{
206 if (!surface->client() || !surface->client()->textInputProtocols().testFlag(flag: QWaylandClient::TextInputProtocol::TextInputV2))
207 return nullptr;
208 return QWaylandTextInput::findIn(container: seat);
209}
210
211#if QT_WAYLAND_TEXT_INPUT_V4_WIP
212QWaylandTextInputV4 *QWaylandInputMethodControlPrivate::textInputV4() const
213{
214 return QWaylandTextInputV4::findIn(seat);
215}
216#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
217
218#include "moc_qwaylandinputmethodcontrol.cpp"
219

source code of qtwayland/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp