Qt 6.x
The Qt SDK
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
33{
34}
35
37{
38#if QT_WAYLAND_TEXT_INPUT_V4_WIP
39 return mDisplay->textInputManagerv2() != nullptr || mDisplay->textInputManagerv1() != nullptr || mDisplay->textInputManagerv4() != nullptr;
40#else // QT_WAYLAND_TEXT_INPUT_V4_WIP
41 return mDisplay->textInputManagerv2() != nullptr || mDisplay->textInputManagerv1() != nullptr;
42#endif // QT_WAYLAND_TEXT_INPUT_V4_WIP
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
54
55 if (!textInput())
56 return;
57
58 textInput()->reset();
59}
60
62{
63 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
64
65 if (!textInput())
66 return;
67
68 textInput()->commit();
69}
70
71static ::wl_surface *surfaceForWindow(QWindow *window)
72{
73 if (!window || !window->handle())
74 return nullptr;
75
76 auto *waylandWindow = static_cast<QWaylandWindow *>(window->handle());
77 return waylandWindow->wlSurface();
78}
79
80void QWaylandInputContext::update(Qt::InputMethodQueries queries)
81{
82 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO << queries;
83
84 if (!QGuiApplication::focusObject() || !textInput())
85 return;
86
87 auto *currentSurface = surfaceForWindow(mCurrentWindow);
88
89 if (currentSurface && !inputMethodAccepted()) {
90 textInput()->disableSurface(currentSurface);
91 mCurrentWindow.clear();
92 } else if (!currentSurface && inputMethodAccepted()) {
94 if (auto *focusSurface = surfaceForWindow(window)) {
95 textInput()->enableSurface(focusSurface);
96 mCurrentWindow = window;
97 }
98 }
99
101}
102
104{
105 if (!textInput())
106 return;
107
108 if (action == QInputMethod::Click)
109 textInput()->setCursorInsidePreedit(cursorPostion);
110}
111
113{
114 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
115
116 if (!textInput())
117 return;
118
119 textInput()->showInputPanel();
120}
121
123{
124 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
125
126 if (!textInput())
127 return;
128
129 textInput()->hideInputPanel();
130}
131
133{
134 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
135
136 if (!textInput())
138
139 return textInput()->isInputPanelVisible();
140}
141
143{
144 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
145
146 if (!textInput())
148
149 return textInput()->keyboardRect();
150}
151
153{
154 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
155
156 if (!textInput())
158
159 return textInput()->locale();
160}
161
163{
164 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
165
166 if (!textInput())
168
169 return textInput()->inputDirection();
170}
171
173{
174 qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO;
175#if QT_CONFIG(xkbcommon)
176 m_focusObject = object;
177#else
178 Q_UNUSED(object);
179#endif
180
181 if (!textInput())
182 return;
183
185
186 if (mCurrentWindow && mCurrentWindow->handle()) {
187 if (mCurrentWindow.data() != window || !inputMethodAccepted()) {
188 auto *surface = static_cast<QWaylandWindow *>(mCurrentWindow->handle())->wlSurface();
189 if (surface)
190 textInput()->disableSurface(surface);
191 mCurrentWindow.clear();
192 }
193 }
194
195 if (window && window->handle() && inputMethodAccepted()) {
196 if (mCurrentWindow.data() != window) {
197 auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
198 if (surface) {
199 textInput()->enableSurface(surface);
200 mCurrentWindow = window;
201 }
202 }
204 }
205}
206
207QWaylandTextInputInterface *QWaylandInputContext::textInput() const
208{
209 return mDisplay->defaultInputDevice() ? mDisplay->defaultInputDevice()->textInput() : nullptr;
210}
211
212#if QT_CONFIG(xkbcommon)
213
214void QWaylandInputContext::ensureInitialized()
215{
216 if (m_initialized)
217 return;
218
219 if (!m_XkbContext) {
220 qCWarning(qLcQpaInputMethods) << "error: xkb context has not been set on" << metaObject()->className();
221 return;
222 }
223
224 m_initialized = true;
225 const char *const locale = setlocale(LC_CTYPE, nullptr);
226 qCDebug(qLcQpaInputMethods) << "detected locale (LC_CTYPE):" << locale;
227
228 m_composeTable = xkb_compose_table_new_from_locale(m_XkbContext, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
229 if (m_composeTable)
230 m_composeState = xkb_compose_state_new(m_composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
231
232 if (!m_composeTable) {
233 qCWarning(qLcQpaInputMethods, "failed to create compose table");
234 return;
235 }
236 if (!m_composeState) {
237 qCWarning(qLcQpaInputMethods, "failed to create compose state");
238 return;
239 }
240}
241
243{
244 auto keyEvent = static_cast<const QKeyEvent *>(event);
245 if (keyEvent->type() != QEvent::KeyPress)
246 return false;
247
248 if (!inputMethodAccepted())
249 return false;
250
251 // lazy initialization - we don't want to do this on an app startup
253
254 if (!m_composeTable || !m_composeState)
255 return false;
256
257 xkb_compose_state_feed(m_composeState, keyEvent->nativeVirtualKey());
258
259 switch (xkb_compose_state_get_status(m_composeState)) {
260 case XKB_COMPOSE_COMPOSING:
261 return true;
262 case XKB_COMPOSE_CANCELLED:
263 reset();
264 return false;
265 case XKB_COMPOSE_COMPOSED:
266 {
267 const int size = xkb_compose_state_get_utf8(m_composeState, nullptr, 0);
269 xkb_compose_state_get_utf8(m_composeState, buffer.data(), buffer.size());
270 QString composedText = QString::fromUtf8(buffer.constData());
271
273 event.setCommitString(composedText);
274
275 if (!m_focusObject && qApp)
276 m_focusObject = qApp->focusObject();
277
278 if (m_focusObject)
279 QCoreApplication::sendEvent(m_focusObject, &event);
280 else
281 qCWarning(qLcQpaInputMethods, "no focus object");
282
283 reset();
284 return true;
285 }
286 case XKB_COMPOSE_NOTHING:
287 return false;
288 default:
289 Q_UNREACHABLE_RETURN(false);
290 }
291}
292
293#endif
294
295}
296
298
299#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:624
Action
Indicates the kind of action performed by the user.
The QKeyEvent class describes a key event.
Definition qevent.h:423
\inmodule QtCore
Definition qobject.h:90
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()
Definition qpointer.h:70
T * data() const
Definition qpointer.h:56
\inmodule QtCore\reentrant
Definition qrect.h:483
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
\inmodule QtGui
Definition qwindow.h:63
QtWayland::zwp_text_input_manager_v4 * textInputManagerv4() 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
virtual void enableSurface(::wl_surface *surface)=0
virtual bool isInputPanelVisible() const =0
virtual QRectF keyboardRect() const =0
virtual void setCursorInsidePreedit(int cursor)=0
virtual void disableSurface(::wl_surface *surface)=0
virtual Qt::LayoutDirection inputDirection() const =0
virtual void updateState(Qt::InputMethodQueries queries, uint32_t flags)=0
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]