Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwaylandinputcontext.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
7
8#include <QtGui/QGuiApplication>
9#include <QtGui/QTextCharFormat>
10#include <QtGui/QWindow>
11#include <QtCore/QVarLengthArray>
12
16
17#if QT_CONFIG(xkbcommon)
18#include <locale.h>
19#endif
20
22
23Q_LOGGING_CATEGORY(qLcQpaInputMethods, "qt.qpa.input.methods")
24
25namespace QtWaylandClient {
26
27QWaylandInputContext::QWaylandInputContext(QWaylandDisplay *display)
28 : mDisplay(display)
29{
30}
31
33{
34#if QT_CONFIG(xkbcommon)
35 xkb_compose_state_unref(m_composeState);
36 xkb_compose_table_unref(m_composeTable);
37#endif
38}
39
41{
42 return mDisplay->textInputManagerv2() != nullptr || mDisplay->textInputManagerv1() != nullptr || mDisplay->textInputManagerv3() != nullptr;
43}
44
46{
47 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
48#if QT_CONFIG(xkbcommon)
49 if (m_composeState)
50 xkb_compose_state_reset(m_composeState);
51#endif
52
53 QPlatformInputContext::reset();
54
55 QWaylandTextInputInterface *inputInterface = textInput();
56 if (!inputInterface)
57 return;
58
59 inputInterface->reset();
60}
61
63{
64 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
65
66 QWaylandTextInputInterface *inputInterface = textInput();
67 if (!inputInterface)
68 return;
69
70 inputInterface->commit();
71}
72
73static ::wl_surface *surfaceForWindow(QWindow *window)
74{
75 if (!window || !window->handle())
76 return nullptr;
77
78 auto *waylandWindow = static_cast<QWaylandWindow *>(window->handle());
79 return waylandWindow->wlSurface();
80}
81
82void QWaylandInputContext::update(Qt::InputMethodQueries queries)
83{
84 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO << queries;
85
86 QWaylandTextInputInterface *inputInterface = textInput();
87
88 // When a client changing focusObject, update could be called
89 // before setFocusObject, but it will not be processed.
90 if ((m_focusObject != QGuiApplication::focusObject()) || !inputInterface)
91 return;
92
93 inputInterface->updateState(queries, QWaylandTextInputInterface::update_state_change);
94}
95
96void QWaylandInputContext::invokeAction(QInputMethod::Action action, int cursorPostion)
97{
98 QWaylandTextInputInterface *inputInterface = textInput();
99 if (!inputInterface)
100 return;
101
102 if (action == QInputMethod::Click)
103 inputInterface->setCursorInsidePreedit(cursorPostion);
104}
105
107{
108 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
109
110 QWaylandTextInputInterface *inputInterface = textInput();
111 if (!inputInterface)
112 return;
113
114 inputInterface->showInputPanel();
115}
116
118{
119 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
120
121 QWaylandTextInputInterface *inputInterface = textInput();
122 if (!inputInterface)
123 return;
124
125 inputInterface->hideInputPanel();
126}
127
129{
130 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
131
132 QWaylandTextInputInterface *inputInterface = textInput();
133 if (!inputInterface)
134 return QPlatformInputContext::isInputPanelVisible();
135
136 return inputInterface->isInputPanelVisible();
137}
138
140{
141 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
142
143 QWaylandTextInputInterface *inputInterface = textInput();
144 if (!inputInterface)
145 return QPlatformInputContext::keyboardRect();
146
147 return inputInterface->keyboardRect();
148}
149
151{
152 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
153
154 QWaylandTextInputInterface *inputInterface = textInput();
155 if (!inputInterface)
156 return QPlatformInputContext::locale();
157
158 return inputInterface->locale();
159}
160
162{
163 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
164
165 QWaylandTextInputInterface *inputInterface = textInput();
166 if (!inputInterface)
167 return QPlatformInputContext::inputDirection();
168
169 return inputInterface->inputDirection();
170}
171
173{
174 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
175
176 QWaylandTextInputInterface *inputInterface = textInput();
177 if (!inputInterface)
178 return;
179
180 if (m_focusObject == object)
181 return;
182
183 if (mCurrentWindow) {
184 if (auto currentSurface = surfaceForWindow(mCurrentWindow))
185 inputInterface->disableSurface(currentSurface);
186 mCurrentWindow.clear();
187 }
188
189 if (object && inputMethodAccepted()) {
190 mCurrentWindow = QGuiApplication::focusWindow();
191 if (auto currentSurface = surfaceForWindow(mCurrentWindow)) {
192 inputInterface->enableSurface(currentSurface);
193 inputInterface->updateState(Qt::ImQueryAll, QWaylandTextInputInterface::update_state_enter);
194 }
195 }
196 m_focusObject = object;
197}
198
200{
201 return mDisplay->defaultInputDevice() ? mDisplay->defaultInputDevice()->textInput() : nullptr;
202}
203
204#if QT_CONFIG(xkbcommon)
205
207{
208 if (m_initialized)
209 return;
210
211 if (!m_XkbContext) {
212 qCWarning(qLcQpaInputMethods) << "error: xkb context has not been set on" << metaObject()->className();
213 return;
214 }
215
216 m_initialized = true;
217 const char *const locale = setlocale(LC_CTYPE, nullptr);
218 qCDebug(qLcQpaInputMethods) << "detected locale (LC_CTYPE):" << locale;
219
221 if (m_composeTable)
223
224 if (!m_composeTable) {
225 qCWarning(qLcQpaInputMethods, "failed to create compose table");
226 return;
227 }
228 if (!m_composeState) {
229 qCWarning(qLcQpaInputMethods, "failed to create compose state");
230 return;
231 }
232}
233
235{
236 auto keyEvent = static_cast<const QKeyEvent *>(event);
237 if (keyEvent->type() != QEvent::KeyPress)
238 return false;
239
240 if (!inputMethodAccepted())
241 return false;
242
243 // lazy initialization - we don't want to do this on an app startup
245
247 return false;
248
250
253 return true;
255 reset();
256 return false;
258 {
259 const int size = xkb_compose_state_get_utf8(m_composeState, nullptr, 0);
260 QVarLengthArray<char, 32> buffer(size + 1);
263
266
267 if (!m_focusObject && qApp)
269
270 if (m_focusObject)
272 else
273 qCWarning(qLcQpaInputMethods, "no focus object");
274
275 reset();
276 return true;
277 }
279 return false;
280 default:
282 }
283}
284
285#endif
286
287}
288
289QT_END_NAMESPACE
290
291#include "moc_qwaylandinputcontext_p.cpp"
void hideInputPanel() override
Request to hide input panel.
QRectF keyboardRect() const override
This function can be reimplemented to return virtual keyboard rectangle in currently active window co...
void reset() override
Method to be called when input method needs to be reset.
void showInputPanel() override
Request to show input panel.
Qt::LayoutDirection inputDirection() const override
void invokeAction(QInputMethod::Action, int cursorPosition) override
Called when the word currently being composed in the input item is tapped by the user.
void setFocusObject(QObject *object) override
This virtual method gets called to notify updated focus to object.
bool isValid() const override
Returns input context validity.
bool isInputPanelVisible() const override
Returns input panel visibility status.
void update(Qt::InputMethodQueries) override
Notification on editor updates.
virtual void enableSurface(::wl_surface *surface)=0
virtual bool isInputPanelVisible() const =0
virtual void setCursorInsidePreedit(int cursor)=0
virtual void disableSurface(::wl_surface *surface)=0
Combined button and popup list for selecting options.
::wl_surface * surfaceForWindow(QWindow *window)