Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 <QLoggingCategory>
8#include <QtGui/QGuiApplication>
9#include <QtGui/QTextCharFormat>
10#include <QtGui/QWindow>
11#include <QtCore/QVarLengthArray>
12
13#include "qwaylanddisplay_p.h"
15#include "qwaylandwindow_p.h"
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
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()) {
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
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)
141
142 return inputInterface->isInputPanelVisible();
143}
144
146{
147 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
148
149 QWaylandTextInputInterface *inputInterface = textInput();
150 if (!inputInterface)
152
153 return inputInterface->keyboardRect();
154}
155
157{
158 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
159
160 QWaylandTextInputInterface *inputInterface = textInput();
161 if (!inputInterface)
163
164 return inputInterface->locale();
165}
166
168{
169 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
170
171 QWaylandTextInputInterface *inputInterface = textInput();
172 if (!inputInterface)
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
192
193 if (mCurrentWindow && mCurrentWindow->handle()) {
194 if (mCurrentWindow.data() != window || !inputMethodAccepted()) {
195 auto *surface = static_cast<QWaylandWindow *>(mCurrentWindow->handle())->wlSurface();
196 if (surface)
197 inputInterface->disableSurface(surface);
198 mCurrentWindow.clear();
199 }
200 }
201
202 if (window && window->handle() && inputMethodAccepted()) {
203 if (mCurrentWindow.data() != window) {
204 auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
205 if (surface) {
206 inputInterface->enableSurface(surface);
207 mCurrentWindow = window;
208 }
209 }
211 }
212}
213
214QWaylandTextInputInterface *QWaylandInputContext::textInput() const
215{
216 return mDisplay->defaultInputDevice() ? mDisplay->defaultInputDevice()->textInput() : nullptr;
217}
218
219#if QT_CONFIG(xkbcommon)
220
221void QWaylandInputContext::ensureInitialized()
222{
223 if (m_initialized)
224 return;
225
226 if (!m_XkbContext) {
227 qCWarning(qLcQpaInputMethods) << "error: xkb context has not been set on" << metaObject()->className();
228 return;
229 }
230
231 m_initialized = true;
232 const char *const locale = setlocale(LC_CTYPE, nullptr);
233 qCDebug(qLcQpaInputMethods) << "detected locale (LC_CTYPE):" << locale;
234
235 m_composeTable = xkb_compose_table_new_from_locale(m_XkbContext, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
236 if (m_composeTable)
237 m_composeState = xkb_compose_state_new(m_composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
238
239 if (!m_composeTable) {
240 qCWarning(qLcQpaInputMethods, "failed to create compose table");
241 return;
242 }
243 if (!m_composeState) {
244 qCWarning(qLcQpaInputMethods, "failed to create compose state");
245 return;
246 }
247}
248
250{
251 auto keyEvent = static_cast<const QKeyEvent *>(event);
252 if (keyEvent->type() != QEvent::KeyPress)
253 return false;
254
255 if (!inputMethodAccepted())
256 return false;
257
258 // lazy initialization - we don't want to do this on an app startup
260
261 if (!m_composeTable || !m_composeState)
262 return false;
263
264 xkb_compose_state_feed(m_composeState, keyEvent->nativeVirtualKey());
265
266 switch (xkb_compose_state_get_status(m_composeState)) {
267 case XKB_COMPOSE_COMPOSING:
268 return true;
269 case XKB_COMPOSE_CANCELLED:
270 reset();
271 return false;
272 case XKB_COMPOSE_COMPOSED:
273 {
274 const int size = xkb_compose_state_get_utf8(m_composeState, nullptr, 0);
275 QVarLengthArray<char, 32> buffer(size + 1);
276 xkb_compose_state_get_utf8(m_composeState, buffer.data(), buffer.size());
277 QString composedText = QString::fromUtf8(buffer.constData());
278
280 event.setCommitString(composedText);
281
282 if (!m_focusObject && qApp)
283 m_focusObject = qApp->focusObject();
284
285 if (m_focusObject)
286 QCoreApplication::sendEvent(m_focusObject, &event);
287 else
288 qCWarning(qLcQpaInputMethods, "no focus object");
289
290 reset();
291 return true;
292 }
293 case XKB_COMPOSE_NOTHING:
294 return false;
295 default:
296 Q_UNREACHABLE_RETURN(false);
297 }
298}
299
300#endif
301
302}
303
305
306#include "moc_qwaylandinputcontext_p.cpp"
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
\inmodule QtCore
Definition qcoreevent.h:45
@ KeyPress
Definition qcoreevent.h:64
static QObject * focusObject()
Returns the QObject in currently active window that will be final receiver of events tied to focus,...
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
The QInputMethodEvent class provides parameters for input method events.
Definition qevent.h:625
Action
Indicates the kind of action performed by the user.
The QKeyEvent class describes a key event.
Definition qevent.h:424
\inmodule QtCore
Definition qobject.h:103
virtual bool isInputPanelVisible() const
Returns input panel visibility status.
bool inputMethodAccepted() const
Returns true if current focus object supports input method events.
virtual QLocale locale() const
virtual bool filterEvent(const QEvent *event)
This function can be reimplemented to filter input events.
virtual void reset()
Method to be called when input method needs to be reset.
virtual Qt::LayoutDirection inputDirection() const
virtual QRectF keyboardRect() const
This function can be reimplemented to return virtual keyboard rectangle in currently active window co...
void clear() noexcept
Definition qpointer.h:87
T * data() const noexcept
Definition qpointer.h:73
\inmodule QtCore\reentrant
Definition qrect.h:484
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
\inmodule QtGui
Definition qwindow.h:63
QtWayland::zwp_text_input_manager_v3 * textInputManagerv3() const
QtWayland::zwp_text_input_manager_v1 * textInputManagerv1() const
QWaylandInputDevice * defaultInputDevice() const
QtWayland::zwp_text_input_manager_v2 * textInputManagerv2() const
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.
QWaylandTextInputInterface * textInput() const
::wl_surface * wlSurface() const
struct wl_display * display
Definition linuxdmabuf.h:41
Combined button and popup list for selecting options.
::wl_surface * surfaceForWindow(QWindow *window)
@ ImQueryAll
LayoutDirection
#define Q_FUNC_INFO
#define qApp
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
static void ensureInitialized()
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint object
[3]
GLenum GLuint buffer
struct _cl_event * event
#define Q_UNUSED(x)
obj metaObject() -> className()
aWidget window() -> setWindowTitle("New Window Title")
[2]