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
qwaylandqttextinputmethod.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
6
7#include <QtGui/qevent.h>
8#include <QtGui/qguiapplication.h>
9#include <QtGui/qinputmethod.h>
10#include <QtGui/qcolor.h>
11#include <QtGui/qtextformat.h>
12
13#include <QtWaylandCompositor/qwaylandcompositor.h>
14#include <QtWaylandCompositor/qwaylandsurface.h>
15
17
22
23void QWaylandQtTextInputMethodPrivate::text_input_method_v1_enable(Resource *resource, struct ::wl_resource *surface)
24{
26 if (this->resource == resource) {
27 QWaylandSurface *waylandSurface = QWaylandSurface::fromResource(surface);
28 if (surface != nullptr) {
29 enabledSurfaces[resource] = waylandSurface;
30 emit q->surfaceEnabled(waylandSurface);
31 }
32 }
33}
34
35void QWaylandQtTextInputMethodPrivate::text_input_method_v1_disable(Resource *resource, struct ::wl_resource *surface)
36{
38 if (this->resource == resource) {
39 QWaylandSurface *waylandSurface = QWaylandSurface::fromResource(surface);
41
42 if (Q_UNLIKELY(enabledSurface != waylandSurface))
43 qCWarning(qLcWaylandCompositorInputMethods) << "Disabled surface does not match the one currently enabled";
44
45 emit q->surfaceEnabled(waylandSurface);
46 }
47}
48
50{
51 if (this->resource == resource)
52 wl_resource_destroy(resource->handle);
53}
54
56{
57 if (this->resource == resource)
58 qApp->inputMethod()->reset();
59}
60
62{
63 if (this->resource == resource)
64 qApp->inputMethod()->commit();
65}
66
68{
69 if (this->resource == resource)
70 qApp->inputMethod()->show();
71}
72
74{
75 if (this->resource == resource)
76 qApp->inputMethod()->hide();
77}
78
79void QWaylandQtTextInputMethodPrivate::text_input_method_v1_invoke_action(Resource *resource, int32_t type, int32_t cursorPosition)
80{
81 if (this->resource == resource)
82 qApp->inputMethod()->invokeAction(QInputMethod::Action(type), cursorPosition);
83}
84
85void QWaylandQtTextInputMethodPrivate::text_input_method_v1_update_cursor_rectangle(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
86{
87 if (this->resource == resource)
89}
90
92{
93 if (this->resource == resource)
94 updatingQueries = Qt::InputMethodQueries(queries);
95}
96
98{
99 if (this->resource == resource)
100 this->hints = Qt::InputMethodHints(hints);
101}
102
104{
105 if (this->resource == resource)
106 this->anchorPosition = anchorPosition;
107}
108
110{
111 if (this->resource == resource)
112 this->cursorPosition = cursorPosition;
113}
114
115void QWaylandQtTextInputMethodPrivate::text_input_method_v1_update_surrounding_text(Resource *resource, const QString &surroundingText, int32_t surroundingTextOffset)
116{
117 if (this->resource == resource) {
118 this->surroundingText = surroundingText;
119 this->surroundingTextOffset = surroundingTextOffset;
120 }
121}
122
124{
125 if (this->resource == resource)
126 this->absolutePosition = absolutePosition;
127}
128
130{
131 if (this->resource == resource)
132 this->preferredLanguage = preferredLanguage;
133}
134
136{
138 if (this->resource == resource && updatingQueries != 0) {
139 Qt::InputMethodQueries queries = updatingQueries;
140 updatingQueries = Qt::InputMethodQueries();
141 emit q->updateInputMethod(queries);
142 }
143}
144
146{
147 if (this->resource == resource)
148 waitingForSync = false;
149}
150
153{
154 connect(&d_func()->focusDestroyListener, &QWaylandDestroyListener::fired,
155 this, &QWaylandQtTextInputMethod::focusSurfaceDestroyed);
156
157 connect(qGuiApp->inputMethod(), &QInputMethod::visibleChanged, this, &QWaylandQtTextInputMethod::sendVisibleChanged);
158 connect(qGuiApp->inputMethod(), &QInputMethod::keyboardRectangleChanged, this, &QWaylandQtTextInputMethod::sendKeyboardRectangleChanged);
159 connect(qGuiApp->inputMethod(), &QInputMethod::inputDirectionChanged, this, &QWaylandQtTextInputMethod::sendInputDirectionChanged);
160 connect(qGuiApp->inputMethod(), &QInputMethod::localeChanged, this, &QWaylandQtTextInputMethod::sendLocaleChanged);
161}
162
163
167
168void QWaylandQtTextInputMethod::focusSurfaceDestroyed()
169{
171 d->focusDestroyListener.reset();
172 d->waitingForSync = false;
173 d->resource = nullptr;
174 d->focusedSurface = nullptr;
175}
176
178{
179 Q_D(const QWaylandQtTextInputMethod);
180 return d->focusedSurface;
181}
182
184{
185 Q_D(const QWaylandQtTextInputMethod);
186 switch (property) {
187 case Qt::ImHints:
188 return int(d->hints);
190 return d->cursorRectangle;
192 return d->cursorPosition;
194 return d->surroundingText;
196 return d->absolutePosition;
198 return d->surroundingText.mid(qMin(d->cursorPosition, d->anchorPosition),
199 qAbs(d->anchorPosition - d->cursorPosition));
201 return d->anchorPosition;
203 if (argument.isValid())
204 return d->surroundingText.mid(d->cursorPosition, argument.toInt());
205 return d->surroundingText.mid(d->cursorPosition);
207 if (argument.isValid())
208 return d->surroundingText.left(d->cursorPosition).right(argument.toInt());
209 return d->surroundingText.left(d->cursorPosition);
211 return d->preferredLanguage;
212
213 default:
214 return QVariant();
215 }
216}
217
219{
221 if (d->resource == nullptr || d->resource->handle == nullptr)
222 return;
223
224 d->send_key(d->resource->handle,
225 int(event->type()),
226 event->key(),
227 event->modifiers(),
228 event->isAutoRepeat(),
229 event->count(),
230 event->nativeScanCode(),
231 event->nativeVirtualKey(),
232 event->nativeModifiers(),
233 event->text());
234}
235
237{
239 if (d->resource == nullptr || d->resource->handle == nullptr || d->compositor == nullptr)
240 return;
241
242 if (d->updatingQueries != 0) {
243 qCWarning(qLcWaylandCompositorInputMethods) << "Input method event sent while client is updating. Ignored.";
244 return;
245 }
246
247 Q_ASSERT(!d->waitingForSync);
248
249 QString oldSurroundText = d->surroundingText;
250 int oldCursorPosition = d->cursorPosition;
251 int oldAnchorPosition = d->anchorPosition;
252 int oldAbsolutePosition = d->absolutePosition;
253 QRect oldCursorRectangle = d->cursorRectangle;
254 QString oldPreferredLanguage = d->preferredLanguage;
255 Qt::InputMethodHints oldHints = d->hints;
256
257 uint serial = d->compositor->nextSerial(); // ### Not needed if we block on this?
258 d->send_start_input_method_event(d->resource->handle, serial, d->surroundingTextOffset);
259 for (const QInputMethodEvent::Attribute &attribute : event->attributes()) {
260 switch (attribute.type) {
262 {
263 auto properties = attribute.value.value<QTextFormat>().properties();
264 if (properties.size() != 2 || properties.firstKey() != QTextFormat::FontUnderline || properties.lastKey() != QTextFormat::TextUnderlineStyle) {
265 qCWarning(qLcWaylandCompositorInputMethods()) << "Only underline text formats currently supported";
266 }
267
268 d->send_input_method_event_attribute(d->resource->handle,
269 serial,
270 attribute.type,
271 attribute.start,
272 attribute.length,
273 QString());
274 break;
275 }
277 d->cursorPosition = attribute.start;
278 d->send_input_method_event_attribute(d->resource->handle,
279 serial,
280 attribute.type,
281 attribute.start,
282 attribute.length,
283 attribute.value.typeId() == QMetaType::QColor ? attribute.value.value<QColor>().name() : QString());
284 break;
285 case QInputMethodEvent::Language: // ### What is the type of value? Is it string?
288 d->send_input_method_event_attribute(d->resource->handle,
289 serial,
290 attribute.type,
291 attribute.start,
292 attribute.length,
293 attribute.value.toString());
294 break;
296 d->send_input_method_event_attribute(d->resource->handle,
297 serial,
298 attribute.type,
299 attribute.start,
300 attribute.length,
301 QString());
302 break;
303 }
304 }
305
306 d->waitingForSync = true;
307 d->send_end_input_method_event(d->resource->handle,
308 serial,
309 event->commitString(),
310 event->preeditString(),
311 event->replacementStart(),
312 event->replacementLength());
313
314 while (d->waitingForSync)
315 d->compositor->processWaylandEvents();
316
317 Qt::InputMethodQueries queries;
318 if (d->surroundingText != oldSurroundText)
319 queries |= Qt::ImSurroundingText;
320 if (d->cursorPosition != oldCursorPosition)
321 queries |= Qt::ImCursorPosition;
322 if (d->anchorPosition != oldAnchorPosition)
323 queries |= Qt::ImAnchorPosition;
324 if (d->absolutePosition != oldAbsolutePosition)
325 queries |= Qt::ImAbsolutePosition;
326 if (d->cursorRectangle != oldCursorRectangle)
327 queries |= Qt::ImCursorRectangle;
328 if (d->preferredLanguage != oldPreferredLanguage)
329 queries |= Qt::ImPreferredLanguage;
330 if (d->hints != oldHints)
331 queries |= Qt::ImHints;
332 if (queries != 0)
333 emit updateInputMethod(queries);
334}
335
337{
338 Q_D(const QWaylandQtTextInputMethod);
339 return d->enabledSurfaces.values().contains(surface);
340}
341
343{
345
346 QWaylandQtTextInputMethodPrivate::Resource *resource = surface != nullptr ? d->resourceMap().value(surface->waylandClient()) : nullptr;
347 if (d->resource == resource)
348 return;
349
350 if (d->resource != nullptr && d->focusedSurface != nullptr) {
351 d->send_leave(d->resource->handle, d->focusedSurface->resource());
352 d->focusDestroyListener.reset();
353 }
354
355 d->resource = resource;
356 d->focusedSurface = surface;
357
358 if (d->resource != nullptr && d->focusedSurface != nullptr) {
359 d->surroundingText.clear();
360 d->cursorPosition = 0;
361 d->anchorPosition = 0;
362 d->absolutePosition = 0;
363 d->cursorRectangle = QRect();
364 d->preferredLanguage.clear();
365 d->hints = Qt::InputMethodHints();
366 d->send_enter(d->resource->handle, d->focusedSurface->resource());
367 sendInputDirectionChanged();
368 sendLocaleChanged();
369 sendInputDirectionChanged();
370 d->focusDestroyListener.listenForDestruction(surface->resource());
371 if (d->inputPanelVisible && d->enabledSurfaces.values().contains(surface))
372 qGuiApp->inputMethod()->show();
373 }
374}
375
376void QWaylandQtTextInputMethod::sendLocaleChanged()
377{
379 if (d->resource == nullptr || d->resource->handle == nullptr)
380 return;
381
382 d->send_locale_changed(d->resource->handle, qGuiApp->inputMethod()->locale().bcp47Name());
383}
384
385void QWaylandQtTextInputMethod::sendInputDirectionChanged()
386{
388 if (d->resource == nullptr || d->resource->handle == nullptr)
389 return;
390
391 d->send_input_direction_changed(d->resource->handle, int(qGuiApp->inputMethod()->inputDirection()));
392}
393
394void QWaylandQtTextInputMethod::sendKeyboardRectangleChanged()
395{
397 if (d->resource == nullptr || d->resource->handle == nullptr)
398 return;
399
400 QRectF keyboardRectangle = qGuiApp->inputMethod()->keyboardRectangle();
401 d->send_keyboard_rectangle_changed(d->resource->handle,
402 wl_fixed_from_double(keyboardRectangle.x()),
403 wl_fixed_from_double(keyboardRectangle.y()),
404 wl_fixed_from_double(keyboardRectangle.width()),
405 wl_fixed_from_double(keyboardRectangle.height()));
406}
407
408void QWaylandQtTextInputMethod::sendVisibleChanged()
409{
411 if (d->resource == nullptr || d->resource->handle == nullptr)
412 return;
413
414 d->send_visible_changed(d->resource->handle, int(qGuiApp->inputMethod()->isVisible()));
415}
416
417void QWaylandQtTextInputMethod::add(::wl_client *client, uint32_t id, int version)
418{
420 d->add(client, id, version);
421}
422
423const struct wl_interface *QWaylandQtTextInputMethod::interface()
424{
425 return QWaylandQtTextInputMethodPrivate::interface();
426}
427
429{
430 return QWaylandQtTextInputMethodPrivate::interfaceName();
431}
432
434
435#include "moc_qwaylandqttextinputmethod.cpp"
\inmodule QtCore
Definition qbytearray.h:57
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
QString name(NameFormat format=HexRgb) const
Definition qcolor.cpp:834
T take(const Key &key)
Removes the item with the key from the hash and returns the value associated with it.
Definition qhash.h:985
The QInputMethodEvent class provides parameters for input method events.
Definition qevent.h:625
Action
Indicates the kind of action performed by the user.
void inputDirectionChanged(Qt::LayoutDirection newDirection)
void visibleChanged()
void keyboardRectangleChanged()
void localeChanged()
The QKeyEvent class describes a key event.
Definition qevent.h:424
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:672
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:732
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:729
constexpr qreal x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:669
\inmodule QtCore\reentrant
Definition qrect.h:30
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\reentrant
Definition qtextformat.h:90
\inmodule QtCore
Definition qvariant.h:65
\qmltype WaylandCompositor \instantiates QWaylandCompositor \inqmlmodule QtWayland....
void fired(void *data)
\inmodule QtWaylandCompositor
void text_input_method_v1_invoke_action(Resource *resource, int32_t type, int32_t cursorPosition) override
QHash< Resource *, QWaylandSurface * > enabledSurfaces
void text_input_method_v1_commit(Resource *resource) override
void text_input_method_v1_update_cursor_rectangle(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) override
void text_input_method_v1_update_anchor_position(Resource *resource, int32_t anchorPosition) override
void text_input_method_v1_hide_input_panel(Resource *resource) override
void text_input_method_v1_update_hints(Resource *resource, int32_t hints) override
void text_input_method_v1_update_surrounding_text(Resource *resource, const QString &surroundingText, int32_t surroundingTextOffset) override
void text_input_method_v1_reset(Resource *resource) override
void text_input_method_v1_disable(Resource *resource, struct ::wl_resource *surface) override
void text_input_method_v1_update_absolute_position(Resource *resource, int32_t absolutePosition) override
void text_input_method_v1_update_cursor_position(Resource *resource, int32_t cursorPosition) override
void text_input_method_v1_destroy(Resource *resource) override
void text_input_method_v1_end_update(Resource *resource) override
QWaylandQtTextInputMethodPrivate(QWaylandCompositor *compositor)
void text_input_method_v1_enable(Resource *resource, struct ::wl_resource *surface) override
void text_input_method_v1_start_update(Resource *resource, int32_t queries) override
void text_input_method_v1_update_preferred_language(Resource *resource, const QString &preferredLanguage) override
void text_input_method_v1_acknowledge_input_method(Resource *resource) override
void text_input_method_v1_show_input_panel(Resource *resource) override
static const struct wl_interface * interface()
void updateInputMethod(Qt::InputMethodQueries queries)
bool isSurfaceEnabled(QWaylandSurface *surface) const
void setFocus(QWaylandSurface *surface)
void add(::wl_client *client, uint32_t id, int version)
QVariant inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const
QWaylandSurface * focusedSurface() const
void sendInputMethodEvent(QInputMethodEvent *event)
QWaylandQtTextInputMethod(QWaylandObject *container, QWaylandCompositor *compositor)
\qmltype WaylandSurface \instantiates QWaylandSurface \inqmlmodule QtWayland.Compositor
struct wl_resource * resource() const
Returns the Wayland resource corresponding to this QWaylandSurface.
::wl_client * waylandClient() const
Holds the wl_client using this QWaylandSurface.
static QWaylandSurface * fromResource(::wl_resource *resource)
Returns the QWaylandSurface corresponding to the Wayland resource resource.
Combined button and popup list for selecting options.
InputMethodQuery
@ ImTextBeforeCursor
@ ImSurroundingText
@ ImCursorPosition
@ ImCurrentSelection
@ ImAbsolutePosition
@ ImPreferredLanguage
@ ImAnchorPosition
@ ImCursorRectangle
@ ImHints
@ ImTextAfterCursor
#define Q_FALLTHROUGH()
#define Q_UNLIKELY(x)
#define qApp
static const QCssKnownValue properties[NumProperties - 1]
EGLOutputLayerEXT EGLint attribute
#define qGuiApp
#define qCWarning(category,...)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
static QOpenGLCompositor * compositor
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei height
GLint GLsizei width
GLenum type
GLint y
struct _cl_event * event
const GLubyte * c
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define emit
unsigned int uint
Definition qtypes.h:34
const char property[13]
Definition qwizard.cpp:101
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QDBusArgument argument