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 if (!QGuiApplication::focusObject() || !inputInterface)
88 return;
89
90 auto *currentSurface = surfaceForWindow(mCurrentWindow);
91
92 if (currentSurface && !inputMethodAccepted()) {
93 inputInterface->disableSurface(currentSurface);
94 mCurrentWindow.clear();
95 } else if (!currentSurface && inputMethodAccepted()) {
96 QWindow *window = QGuiApplication::focusWindow();
97 if (auto *focusSurface = surfaceForWindow(window)) {
98 inputInterface->enableSurface(focusSurface);
99 mCurrentWindow = window;
100 }
101 }
102
103 inputInterface->updateState(queries, QWaylandTextInputInterface::update_state_change);
104}
105
106void QWaylandInputContext::invokeAction(QInputMethod::Action action, int cursorPostion)
107{
108 QWaylandTextInputInterface *inputInterface = textInput();
109 if (!inputInterface)
110 return;
111
112 if (action == QInputMethod::Click)
113 inputInterface->setCursorInsidePreedit(cursorPostion);
114}
115
117{
118 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
119
120 QWaylandTextInputInterface *inputInterface = textInput();
121 if (!inputInterface)
122 return;
123
124 inputInterface->showInputPanel();
125}
126
128{
129 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
130
131 QWaylandTextInputInterface *inputInterface = textInput();
132 if (!inputInterface)
133 return;
134
135 inputInterface->hideInputPanel();
136}
137
139{
140 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
141
142 QWaylandTextInputInterface *inputInterface = textInput();
143 if (!inputInterface)
144 return QPlatformInputContext::isInputPanelVisible();
145
146 return inputInterface->isInputPanelVisible();
147}
148
150{
151 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
152
153 QWaylandTextInputInterface *inputInterface = textInput();
154 if (!inputInterface)
155 return QPlatformInputContext::keyboardRect();
156
157 return inputInterface->keyboardRect();
158}
159
161{
162 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
163
164 QWaylandTextInputInterface *inputInterface = textInput();
165 if (!inputInterface)
166 return QPlatformInputContext::locale();
167
168 return inputInterface->locale();
169}
170
172{
173 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
174
175 QWaylandTextInputInterface *inputInterface = textInput();
176 if (!inputInterface)
177 return QPlatformInputContext::inputDirection();
178
179 return inputInterface->inputDirection();
180}
181
183{
184 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
185#if QT_CONFIG(xkbcommon)
186 m_focusObject = object;
187#else
188 Q_UNUSED(object);
189#endif
190
191 QWaylandTextInputInterface *inputInterface = textInput();
192 if (!inputInterface)
193 return;
194
195 QWindow *window = QGuiApplication::focusWindow();
196
197 if (window && window->handle()) {
198 if (mCurrentWindow.data() != window) {
199 if (!inputMethodAccepted()) {
200 auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
201 if (surface)
202 inputInterface->disableSurface(surface);
203 mCurrentWindow.clear();
204 } else {
205 auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
206 if (surface) {
207 inputInterface->enableSurface(surface);
208 mCurrentWindow = window;
209 } else {
210 mCurrentWindow.clear();
211 }
212 }
213 }
214 if (mCurrentWindow)
215 inputInterface->updateState(Qt::ImQueryAll, QWaylandTextInputInterface::update_state_enter);
216 return;
217 }
218
219 if (mCurrentWindow)
220 mCurrentWindow.clear();
221}
222
224{
225 return mDisplay->defaultInputDevice() ? mDisplay->defaultInputDevice()->textInput() : nullptr;
226}
227
228#if QT_CONFIG(xkbcommon)
229
231{
232 if (m_initialized)
233 return;
234
235 if (!m_XkbContext) {
236 qCWarning(qLcQpaInputMethods) << "error: xkb context has not been set on" << metaObject()->className();
237 return;
238 }
239
240 m_initialized = true;
241 const char *const locale = setlocale(LC_CTYPE, nullptr);
242 qCDebug(qLcQpaInputMethods) << "detected locale (LC_CTYPE):" << locale;
243
245 if (m_composeTable)
247
248 if (!m_composeTable) {
249 qCWarning(qLcQpaInputMethods, "failed to create compose table");
250 return;
251 }
252 if (!m_composeState) {
253 qCWarning(qLcQpaInputMethods, "failed to create compose state");
254 return;
255 }
256}
257
259{
260 auto keyEvent = static_cast<const QKeyEvent *>(event);
261 if (keyEvent->type() != QEvent::KeyPress)
262 return false;
263
264 if (!inputMethodAccepted())
265 return false;
266
267 // lazy initialization - we don't want to do this on an app startup
269
271 return false;
272
274
277 return true;
279 reset();
280 return false;
282 {
283 const int size = xkb_compose_state_get_utf8(m_composeState, nullptr, 0);
284 QVarLengthArray<char, 32> buffer(size + 1);
287
290
291 if (!m_focusObject && qApp)
293
294 if (m_focusObject)
296 else
297 qCWarning(qLcQpaInputMethods, "no focus object");
298
299 reset();
300 return true;
301 }
303 return false;
304 default:
306 }
307}
308
309#endif
310
311}
312
313QT_END_NAMESPACE
314
315#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)