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