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 auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
196 if (surface)
197 inputInterface->disableSurface(surface);
198 mCurrentWindow.clear();
199 } else {
200 auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
201 if (surface) {
202 inputInterface->enableSurface(surface);
203 mCurrentWindow = window;
204 } else {
205 mCurrentWindow.clear();
206 }
207 }
208 }
209 if (mCurrentWindow)
210 inputInterface->updateState(Qt::ImQueryAll, QWaylandTextInputInterface::update_state_enter);
211 return;
212 }
213
214 if (mCurrentWindow)
215 mCurrentWindow.clear();
216}
217
219{
220 return mDisplay->defaultInputDevice() ? mDisplay->defaultInputDevice()->textInput() : nullptr;
221}
222
223#if QT_CONFIG(xkbcommon)
224
226{
227 if (m_initialized)
228 return;
229
230 if (!m_XkbContext) {
231 qCWarning(qLcQpaInputMethods) << "error: xkb context has not been set on" << metaObject()->className();
232 return;
233 }
234
235 m_initialized = true;
236 const char *const locale = setlocale(LC_CTYPE, nullptr);
237 qCDebug(qLcQpaInputMethods) << "detected locale (LC_CTYPE):" << locale;
238
240 if (m_composeTable)
242
243 if (!m_composeTable) {
244 qCWarning(qLcQpaInputMethods, "failed to create compose table");
245 return;
246 }
247 if (!m_composeState) {
248 qCWarning(qLcQpaInputMethods, "failed to create compose state");
249 return;
250 }
251}
252
254{
255 auto keyEvent = static_cast<const QKeyEvent *>(event);
256 if (keyEvent->type() != QEvent::KeyPress)
257 return false;
258
259 if (!inputMethodAccepted())
260 return false;
261
262 // lazy initialization - we don't want to do this on an app startup
264
266 return false;
267
269
272 return true;
274 reset();
275 return false;
277 {
278 const int size = xkb_compose_state_get_utf8(m_composeState, nullptr, 0);
279 QVarLengthArray<char, 32> buffer(size + 1);
282
285
286 if (!m_focusObject && qApp)
288
289 if (m_focusObject)
291 else
292 qCWarning(qLcQpaInputMethods, "no focus object");
293
294 reset();
295 return true;
296 }
298 return false;
299 default:
301 }
302}
303
304#endif
305
306}
307
308QT_END_NAMESPACE
309
310#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)