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
35
37{
38 return mDisplay->textInputManagerv2() != nullptr || mDisplay->textInputManagerv1() != nullptr || mDisplay->textInputManagerv3() != nullptr;
39}
40
42{
43 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
44#if QT_CONFIG(xkbcommon)
45 if (m_composeState)
46 xkb_compose_state_reset(m_composeState);
47#endif
48
49 QPlatformInputContext::reset();
50
51 QWaylandTextInputInterface *inputInterface = textInput();
52 if (!inputInterface)
53 return;
54
55 inputInterface->reset();
56}
57
59{
60 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
61
62 QWaylandTextInputInterface *inputInterface = textInput();
63 if (!inputInterface)
64 return;
65
66 inputInterface->commit();
67}
68
69static ::wl_surface *surfaceForWindow(QWindow *window)
70{
71 if (!window || !window->handle())
72 return nullptr;
73
74 auto *waylandWindow = static_cast<QWaylandWindow *>(window->handle());
75 return waylandWindow->wlSurface();
76}
77
78void QWaylandInputContext::update(Qt::InputMethodQueries queries)
79{
80 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO << queries;
81
82 QWaylandTextInputInterface *inputInterface = textInput();
83 if (!QGuiApplication::focusObject() || !inputInterface)
84 return;
85
86 auto *currentSurface = surfaceForWindow(mCurrentWindow);
87
88 if (currentSurface && !inputMethodAccepted()) {
89 inputInterface->disableSurface(currentSurface);
90 mCurrentWindow.clear();
91 } else if (!currentSurface && inputMethodAccepted()) {
92 QWindow *window = QGuiApplication::focusWindow();
93 if (auto *focusSurface = surfaceForWindow(window)) {
94 inputInterface->enableSurface(focusSurface);
95 mCurrentWindow = window;
96 }
97 }
98
99 inputInterface->updateState(queries, QWaylandTextInputInterface::update_state_change);
100}
101
102void QWaylandInputContext::invokeAction(QInputMethod::Action action, int cursorPostion)
103{
104 QWaylandTextInputInterface *inputInterface = textInput();
105 if (!inputInterface)
106 return;
107
108 if (action == QInputMethod::Click)
109 inputInterface->setCursorInsidePreedit(cursorPostion);
110}
111
113{
114 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
115
116 QWaylandTextInputInterface *inputInterface = textInput();
117 if (!inputInterface)
118 return;
119
120 inputInterface->showInputPanel();
121}
122
124{
125 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
126
127 QWaylandTextInputInterface *inputInterface = textInput();
128 if (!inputInterface)
129 return;
130
131 inputInterface->hideInputPanel();
132}
133
135{
136 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
137
138 QWaylandTextInputInterface *inputInterface = textInput();
139 if (!inputInterface)
140 return QPlatformInputContext::isInputPanelVisible();
141
142 return inputInterface->isInputPanelVisible();
143}
144
146{
147 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
148
149 QWaylandTextInputInterface *inputInterface = textInput();
150 if (!inputInterface)
151 return QPlatformInputContext::keyboardRect();
152
153 return inputInterface->keyboardRect();
154}
155
157{
158 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
159
160 QWaylandTextInputInterface *inputInterface = textInput();
161 if (!inputInterface)
162 return QPlatformInputContext::locale();
163
164 return inputInterface->locale();
165}
166
168{
169 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
170
171 QWaylandTextInputInterface *inputInterface = textInput();
172 if (!inputInterface)
173 return QPlatformInputContext::inputDirection();
174
175 return inputInterface->inputDirection();
176}
177
179{
180 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
181#if QT_CONFIG(xkbcommon)
182 m_focusObject = object;
183#else
184 Q_UNUSED(object);
185#endif
186
187 QWaylandTextInputInterface *inputInterface = textInput();
188 if (!inputInterface)
189 return;
190
191 QWindow *window = QGuiApplication::focusWindow();
192
193 if (window && window->handle()) {
194 if (mCurrentWindow.data() != window) {
195 if (!inputMethodAccepted()) {
196 auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
197 if (surface)
198 inputInterface->disableSurface(surface);
199 mCurrentWindow.clear();
200 } else {
201 auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
202 if (surface) {
203 inputInterface->enableSurface(surface);
204 mCurrentWindow = window;
205 } else {
206 mCurrentWindow.clear();
207 }
208 }
209 }
210 if (mCurrentWindow)
211 inputInterface->updateState(Qt::ImQueryAll, QWaylandTextInputInterface::update_state_enter);
212 return;
213 }
214
215 if (mCurrentWindow)
216 mCurrentWindow.clear();
217}
218
220{
221 return mDisplay->defaultInputDevice() ? mDisplay->defaultInputDevice()->textInput() : nullptr;
222}
223
224#if QT_CONFIG(xkbcommon)
225
227{
228 if (m_initialized)
229 return;
230
231 if (!m_XkbContext) {
232 qCWarning(qLcQpaInputMethods) << "error: xkb context has not been set on" << metaObject()->className();
233 return;
234 }
235
236 m_initialized = true;
237 const char *const locale = setlocale(LC_CTYPE, nullptr);
238 qCDebug(qLcQpaInputMethods) << "detected locale (LC_CTYPE):" << locale;
239
241 if (m_composeTable)
243
244 if (!m_composeTable) {
245 qCWarning(qLcQpaInputMethods, "failed to create compose table");
246 return;
247 }
248 if (!m_composeState) {
249 qCWarning(qLcQpaInputMethods, "failed to create compose state");
250 return;
251 }
252}
253
255{
256 auto keyEvent = static_cast<const QKeyEvent *>(event);
257 if (keyEvent->type() != QEvent::KeyPress)
258 return false;
259
260 if (!inputMethodAccepted())
261 return false;
262
263 // lazy initialization - we don't want to do this on an app startup
265
267 return false;
268
270
273 return true;
275 reset();
276 return false;
278 {
279 const int size = xkb_compose_state_get_utf8(m_composeState, nullptr, 0);
280 QVarLengthArray<char, 32> buffer(size + 1);
283
286
287 if (!m_focusObject && qApp)
289
290 if (m_focusObject)
292 else
293 qCWarning(qLcQpaInputMethods, "no focus object");
294
295 reset();
296 return true;
297 }
299 return false;
300 default:
302 }
303}
304
305#endif
306
307}
308
309QT_END_NAMESPACE
310
311#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)