1 /****************************************************************************
2 **
3 ** Copyright (C) 2017-2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 or (at your option) any later version
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
26 ** $QT_END_LICENSE$
27 **
28 ****************************************************************************/
29
30 #include "qwaylandtextinput.h"
31 #include "qwaylandtextinput_p.h"
32
33 #include <QtWaylandCompositor/QWaylandCompositor>
34 #include <QtWaylandCompositor/private/qwaylandseat_p.h>
35
36 #include "qwaylandsurface.h"
37 #include "qwaylandview.h"
38 #include "qwaylandinputmethodeventbuilder_p.h"
39
40 #include <QGuiApplication>
41 #include <QInputMethodEvent>
42
43 #if QT_CONFIG(xkbcommon)
44 #include <QtXkbCommonSupport/private/qxkbcommon_p.h>
45 #endif
46
47 QT_BEGIN_NAMESPACE
48
QWaylandTextInputClientState()49 QWaylandTextInputClientState::QWaylandTextInputClientState()
50 {
51 }
52
updatedQueries(const QWaylandTextInputClientState & other) const53 Qt::InputMethodQueries QWaylandTextInputClientState::updatedQueries(const QWaylandTextInputClientState &other) const
54 {
55 Qt::InputMethodQueries queries;
56
57 if (hints != other.hints)
58 queries |= Qt::ImHints;
59 if (cursorRectangle != other.cursorRectangle)
60 queries |= Qt::ImCursorRectangle;
61 if (surroundingText != other.surroundingText)
62 queries |= Qt::ImSurroundingText | Qt::ImCurrentSelection;
63 if (cursorPosition != other.cursorPosition)
64 queries |= Qt::ImCursorPosition | Qt::ImCurrentSelection;
65 if (anchorPosition != other.anchorPosition)
66 queries |= Qt::ImAnchorPosition | Qt::ImCurrentSelection;
67 if (preferredLanguage != other.preferredLanguage)
68 queries |= Qt::ImPreferredLanguage;
69
70 return queries;
71 }
72
mergeChanged(const QWaylandTextInputClientState & other)73 Qt::InputMethodQueries QWaylandTextInputClientState::mergeChanged(const QWaylandTextInputClientState &other) {
74 Qt::InputMethodQueries queries;
75
76 if ((other.changedState & Qt::ImHints) && hints != other.hints) {
77 hints = other.hints;
78 queries |= Qt::ImHints;
79 }
80
81 if ((other.changedState & Qt::ImCursorRectangle) && cursorRectangle != other.cursorRectangle) {
82 cursorRectangle = other.cursorRectangle;
83 queries |= Qt::ImCursorRectangle;
84 }
85
86 if ((other.changedState & Qt::ImSurroundingText) && surroundingText != other.surroundingText) {
87 surroundingText = other.surroundingText;
88 queries |= Qt::ImSurroundingText | Qt::ImCurrentSelection;
89 }
90
91 if ((other.changedState & Qt::ImCursorPosition) && cursorPosition != other.cursorPosition) {
92 cursorPosition = other.cursorPosition;
93 queries |= Qt::ImCursorPosition | Qt::ImCurrentSelection;
94 }
95
96 if ((other.changedState & Qt::ImAnchorPosition) && anchorPosition != other.anchorPosition) {
97 anchorPosition = other.anchorPosition;
98 queries |= Qt::ImAnchorPosition | Qt::ImCurrentSelection;
99 }
100
101 if ((other.changedState & Qt::ImPreferredLanguage) && preferredLanguage != other.preferredLanguage) {
102 preferredLanguage = other.preferredLanguage;
103 queries |= Qt::ImPreferredLanguage;
104 }
105
106 return queries;
107 }
108
QWaylandTextInputPrivate(QWaylandCompositor * compositor)109 QWaylandTextInputPrivate::QWaylandTextInputPrivate(QWaylandCompositor *compositor)
110 : compositor(compositor)
111 , currentState(new QWaylandTextInputClientState)
112 , pendingState(new QWaylandTextInputClientState)
113 {
114 }
115
sendInputMethodEvent(QInputMethodEvent * event)116 void QWaylandTextInputPrivate::sendInputMethodEvent(QInputMethodEvent *event)
117 {
118 Q_Q(QWaylandTextInput);
119
120 if (!focusResource || !focusResource->handle)
121 return;
122
123 QWaylandTextInputClientState afterCommit;
124
125 afterCommit.surroundingText = currentState->surroundingText;
126 afterCommit.cursorPosition = qMin(currentState->cursorPosition, currentState->anchorPosition);
127
128 // Remove selection
129 afterCommit.surroundingText.remove(afterCommit.cursorPosition, qAbs(currentState->cursorPosition - currentState->anchorPosition));
130
131 if (event->replacementLength() > 0 || event->replacementStart() != 0) {
132 // Remove replacement
133 afterCommit.cursorPosition = qBound(0, afterCommit.cursorPosition + event->replacementStart(), afterCommit.surroundingText.length());
134 afterCommit.surroundingText.remove(afterCommit.cursorPosition,
135 qMin(event->replacementLength(),
136 afterCommit.surroundingText.length() - afterCommit.cursorPosition));
137
138 if (event->replacementStart() <= 0 && (event->replacementLength() >= -event->replacementStart())) {
139 const int selectionStart = qMin(currentState->cursorPosition, currentState->anchorPosition);
140 const int selectionEnd = qMax(currentState->cursorPosition, currentState->anchorPosition);
141 const int before = QWaylandInputMethodEventBuilder::indexToWayland(currentState->surroundingText, -event->replacementStart(), selectionStart + event->replacementStart());
142 const int after = QWaylandInputMethodEventBuilder::indexToWayland(currentState->surroundingText, event->replacementLength() + event->replacementStart(), selectionEnd);
143 send_delete_surrounding_text(focusResource->handle, before, after);
144 } else {
145 // TODO: Implement this case
146 qWarning() << "Not yet supported case of replacement. Start:" << event->replacementStart() << "length:" << event->replacementLength();
147 }
148 }
149
150 // Insert commit string
151 afterCommit.surroundingText.insert(afterCommit.cursorPosition, event->commitString());
152 afterCommit.cursorPosition += event->commitString().length();
153 afterCommit.anchorPosition = afterCommit.cursorPosition;
154
155 for (const QInputMethodEvent::Attribute &attribute : event->attributes()) {
156 if (attribute.type == QInputMethodEvent::Selection) {
157 afterCommit.cursorPosition = attribute.start;
158 afterCommit.anchorPosition = attribute.length;
159 int cursor = QWaylandInputMethodEventBuilder::indexToWayland(afterCommit.surroundingText, qAbs(attribute.start - afterCommit.cursorPosition), qMin(attribute.start, afterCommit.cursorPosition));
160 int anchor = QWaylandInputMethodEventBuilder::indexToWayland(afterCommit.surroundingText, qAbs(attribute.length - afterCommit.cursorPosition), qMin(attribute.length, afterCommit.cursorPosition));
161 send_cursor_position(focusResource->handle,
162 attribute.start < afterCommit.cursorPosition ? -cursor : cursor,
163 attribute.length < afterCommit.cursorPosition ? -anchor : anchor);
164 }
165 }
166 send_commit_string(focusResource->handle, event->commitString());
167 for (const QInputMethodEvent::Attribute &attribute : event->attributes()) {
168 if (attribute.type == QInputMethodEvent::Cursor) {
169 int index = QWaylandInputMethodEventBuilder::indexToWayland(event->preeditString(), attribute.start);
170 send_preedit_cursor(focusResource->handle, index);
171 } else if (attribute.type == QInputMethodEvent::TextFormat) {
172 int start = QWaylandInputMethodEventBuilder::indexToWayland(event->preeditString(), attribute.start);
173 int length = QWaylandInputMethodEventBuilder::indexToWayland(event->preeditString(), attribute.length, attribute.start);
174 // TODO add support for different stylesQWaylandTextInput
175 send_preedit_styling(focusResource->handle, start, length, preedit_style_default);
176 }
177 }
178 send_preedit_string(focusResource->handle, event->preeditString(), event->preeditString());
179
180 Qt::InputMethodQueries queries = currentState->updatedQueries(afterCommit);
181 currentState->surroundingText = afterCommit.surroundingText;
182 currentState->cursorPosition = afterCommit.cursorPosition;
183 currentState->anchorPosition = afterCommit.anchorPosition;
184
185 if (queries) {
186 qCDebug(qLcWaylandCompositorInputMethods) << "QInputMethod::update() after QInputMethodEvent" << queries;
187
188 emit q->updateInputMethod(queries);
189 }
190 }
191
sendKeyEvent(QKeyEvent * event)192 void QWaylandTextInputPrivate::sendKeyEvent(QKeyEvent *event)
193 {
194 if (!focusResource || !focusResource->handle)
195 return;
196
197 // TODO add support for modifiers
198
199 #if QT_CONFIG(xkbcommon)
200 for (xkb_keysym_t keysym : QXkbCommon::toKeysym(event)) {
201 send_keysym(focusResource->handle, event->timestamp(), keysym,
202 event->type() == QEvent::KeyPress ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED,
203 0);
204 }
205 #else
206 Q_UNUSED(event);
207 #endif
208 }
209
sendInputPanelState()210 void QWaylandTextInputPrivate::sendInputPanelState()
211 {
212 if (!focusResource || !focusResource->handle)
213 return;
214
215 QInputMethod *inputMethod = qApp->inputMethod();
216 const QRectF& keyboardRect = inputMethod->keyboardRectangle();
217 const QRectF& sceneInputRect = inputMethod->inputItemTransform().mapRect(inputMethod->inputItemRectangle());
218 const QRectF& localRect = sceneInputRect.intersected(keyboardRect).translated(-sceneInputRect.topLeft());
219
220 send_input_panel_state(focusResource->handle,
221 inputMethod->isVisible() ? input_panel_visibility_visible : input_panel_visibility_hidden,
222 localRect.x(), localRect.y(), localRect.width(), localRect.height());
223 }
224
sendTextDirection()225 void QWaylandTextInputPrivate::sendTextDirection()
226 {
227 if (!focusResource || !focusResource->handle)
228 return;
229
230 const Qt::LayoutDirection direction = qApp->inputMethod()->inputDirection();
231 send_text_direction(focusResource->handle,
232 (direction == Qt::LeftToRight) ? text_direction_ltr :
233 (direction == Qt::RightToLeft) ? text_direction_rtl : text_direction_auto);
234 }
235
sendLocale()236 void QWaylandTextInputPrivate::sendLocale()
237 {
238 if (!focusResource || !focusResource->handle)
239 return;
240
241 const QLocale locale = qApp->inputMethod()->locale();
242 send_language(focusResource->handle, locale.bcp47Name());
243 }
244
inputMethodQuery(Qt::InputMethodQuery property,QVariant argument) const245 QVariant QWaylandTextInputPrivate::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const
246 {
247 switch (property) {
248 case Qt::ImHints:
249 return QVariant(static_cast<int>(currentState->hints));
250 case Qt::ImCursorRectangle:
251 return currentState->cursorRectangle;
252 case Qt::ImFont:
253 // Not supported
254 return QVariant();
255 case Qt::ImCursorPosition:
256 return currentState->cursorPosition;
257 case Qt::ImSurroundingText:
258 return currentState->surroundingText;
259 case Qt::ImCurrentSelection:
260 return currentState->surroundingText.mid(qMin(currentState->cursorPosition, currentState->anchorPosition),
261 qAbs(currentState->anchorPosition - currentState->cursorPosition));
262 case Qt::ImMaximumTextLength:
263 // Not supported
264 return QVariant();
265 case Qt::ImAnchorPosition:
266 return currentState->anchorPosition;
267 case Qt::ImAbsolutePosition:
268 // We assume the surrounding text is our whole document for now
269 return currentState->cursorPosition;
270 case Qt::ImTextAfterCursor:
271 if (argument.isValid())
272 return currentState->surroundingText.mid(currentState->cursorPosition, argument.toInt());
273 return currentState->surroundingText.mid(currentState->cursorPosition);
274 case Qt::ImTextBeforeCursor:
275 if (argument.isValid())
276 return currentState->surroundingText.left(currentState->cursorPosition).right(argument.toInt());
277 return currentState->surroundingText.left(currentState->cursorPosition);
278 case Qt::ImPreferredLanguage:
279 return currentState->preferredLanguage;
280
281 default:
282 return QVariant();
283 }
284 }
285
setFocus(QWaylandSurface * surface)286 void QWaylandTextInputPrivate::setFocus(QWaylandSurface *surface)
287 {
288 Q_Q(QWaylandTextInput);
289
290 if (focusResource && focus != surface) {
291 uint32_t serial = compositor->nextSerial();
292 send_leave(focusResource->handle, serial, focus->resource());
293 focusDestroyListener.reset();
294 }
295
296 Resource *resource = surface ? resourceMap().value(surface->waylandClient()) : 0;
297
298 if (resource && (focus != surface || focusResource != resource)) {
299 uint32_t serial = compositor->nextSerial();
300 currentState.reset(new QWaylandTextInputClientState);
301 pendingState.reset(new QWaylandTextInputClientState);
302 send_enter(resource->handle, serial, surface->resource());
303 focusResource = resource;
304 sendInputPanelState();
305 sendLocale();
306 sendTextDirection();
307 focusDestroyListener.listenForDestruction(surface->resource());
308 if (inputPanelVisible && q->isSurfaceEnabled(surface))
309 qApp->inputMethod()->show();
310 }
311
312 focusResource = resource;
313 focus = surface;
314 }
315
zwp_text_input_v2_bind_resource(Resource * resource)316 void QWaylandTextInputPrivate::zwp_text_input_v2_bind_resource(Resource *resource)
317 {
318 send_modifiers_map(resource->handle, QByteArray(""));
319 }
320
zwp_text_input_v2_destroy_resource(Resource * resource)321 void QWaylandTextInputPrivate::zwp_text_input_v2_destroy_resource(Resource *resource)
322 {
323 if (focusResource == resource)
324 focusResource = nullptr;
325 }
326
zwp_text_input_v2_destroy(Resource * resource)327 void QWaylandTextInputPrivate::zwp_text_input_v2_destroy(Resource *resource)
328 {
329 wl_resource_destroy(resource->handle);
330 }
331
zwp_text_input_v2_enable(Resource * resource,wl_resource * surface)332 void QWaylandTextInputPrivate::zwp_text_input_v2_enable(Resource *resource, wl_resource *surface)
333 {
334 Q_Q(QWaylandTextInput);
335
336 QWaylandSurface *s = QWaylandSurface::fromResource(surface);
337 enabledSurfaces.insert(resource, s);
338 emit q->surfaceEnabled(s);
339 }
340
zwp_text_input_v2_disable(QtWaylandServer::zwp_text_input_v2::Resource * resource,wl_resource *)341 void QWaylandTextInputPrivate::zwp_text_input_v2_disable(QtWaylandServer::zwp_text_input_v2::Resource *resource, wl_resource *)
342 {
343 Q_Q(QWaylandTextInput);
344
345 QWaylandSurface *s = enabledSurfaces.take(resource);
346 emit q->surfaceDisabled(s);
347 }
348
zwp_text_input_v2_show_input_panel(Resource *)349 void QWaylandTextInputPrivate::zwp_text_input_v2_show_input_panel(Resource *)
350 {
351 inputPanelVisible = true;
352
353 qApp->inputMethod()->show();
354 }
355
zwp_text_input_v2_hide_input_panel(Resource *)356 void QWaylandTextInputPrivate::zwp_text_input_v2_hide_input_panel(Resource *)
357 {
358 inputPanelVisible = false;
359
360 qApp->inputMethod()->hide();
361 }
362
zwp_text_input_v2_set_cursor_rectangle(Resource * resource,int32_t x,int32_t y,int32_t width,int32_t height)363 void QWaylandTextInputPrivate::zwp_text_input_v2_set_cursor_rectangle(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
364 {
365 if (resource != focusResource)
366 return;
367
368 pendingState->cursorRectangle = QRect(x, y, width, height);
369
370 pendingState->changedState |= Qt::ImCursorRectangle;
371 }
372
zwp_text_input_v2_update_state(Resource * resource,uint32_t serial,uint32_t flags)373 void QWaylandTextInputPrivate::zwp_text_input_v2_update_state(Resource *resource, uint32_t serial, uint32_t flags)
374 {
375 Q_Q(QWaylandTextInput);
376
377 qCDebug(qLcWaylandCompositorInputMethods) << "update_state" << serial << flags;
378
379 if (resource != focusResource)
380 return;
381
382 if (flags == update_state_reset || flags == update_state_enter) {
383 qCDebug(qLcWaylandCompositorInputMethods) << "QInputMethod::reset()";
384 qApp->inputMethod()->reset();
385 }
386
387 this->serial = serial;
388
389 Qt::InputMethodQueries queries;
390 if (flags == update_state_change) {
391 queries = currentState->mergeChanged(*pendingState.data());
392 } else {
393 queries = pendingState->updatedQueries(*currentState.data());
394 currentState.swap(pendingState);
395 }
396
397 pendingState.reset(new QWaylandTextInputClientState);
398
399 if (queries) {
400 qCDebug(qLcWaylandCompositorInputMethods) << "QInputMethod::update()" << queries;
401
402 emit q->updateInputMethod(queries);
403 }
404 }
405
zwp_text_input_v2_set_content_type(Resource * resource,uint32_t hint,uint32_t purpose)406 void QWaylandTextInputPrivate::zwp_text_input_v2_set_content_type(Resource *resource, uint32_t hint, uint32_t purpose)
407 {
408 if (resource != focusResource)
409 return;
410
411 pendingState->hints = Qt::ImhNone;
412
413 if ((hint & content_hint_auto_completion) == 0
414 && (hint & content_hint_auto_correction) == 0)
415 pendingState->hints |= Qt::ImhNoPredictiveText;
416 if ((hint & content_hint_auto_capitalization) == 0)
417 pendingState->hints |= Qt::ImhNoAutoUppercase;
418 if ((hint & content_hint_lowercase) != 0)
419 pendingState->hints |= Qt::ImhPreferLowercase;
420 if ((hint & content_hint_uppercase) != 0)
421 pendingState->hints |= Qt::ImhPreferUppercase;
422 if ((hint & content_hint_hidden_text) != 0)
423 pendingState->hints |= Qt::ImhHiddenText;
424 if ((hint & content_hint_sensitive_data) != 0)
425 pendingState->hints |= Qt::ImhSensitiveData;
426 if ((hint & content_hint_latin) != 0)
427 pendingState->hints |= Qt::ImhLatinOnly;
428 if ((hint & content_hint_multiline) != 0)
429 pendingState->hints |= Qt::ImhMultiLine;
430
431 switch (purpose) {
432 case content_purpose_normal:
433 break;
434 case content_purpose_alpha:
435 pendingState->hints |= Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly;
436 break;
437 case content_purpose_digits:
438 pendingState->hints |= Qt::ImhDigitsOnly;
439 break;
440 case content_purpose_number:
441 pendingState->hints |= Qt::ImhFormattedNumbersOnly;
442 break;
443 case content_purpose_phone:
444 pendingState->hints |= Qt::ImhDialableCharactersOnly;
445 break;
446 case content_purpose_url:
447 pendingState->hints |= Qt::ImhUrlCharactersOnly;
448 break;
449 case content_purpose_email:
450 pendingState->hints |= Qt::ImhEmailCharactersOnly;
451 break;
452 case content_purpose_name:
453 case content_purpose_password:
454 break;
455 case content_purpose_date:
456 pendingState->hints |= Qt::ImhDate;
457 break;
458 case content_purpose_time:
459 pendingState->hints |= Qt::ImhTime;
460 break;
461 case content_purpose_datetime:
462 pendingState->hints |= Qt::ImhDate | Qt::ImhTime;
463 break;
464 case content_purpose_terminal:
465 default:
466 break;
467 }
468
469 pendingState->changedState |= Qt::ImHints;
470 }
471
zwp_text_input_v2_set_preferred_language(Resource * resource,const QString & language)472 void QWaylandTextInputPrivate::zwp_text_input_v2_set_preferred_language(Resource *resource, const QString &language)
473 {
474 if (resource != focusResource)
475 return;
476
477 pendingState->preferredLanguage = language;
478
479 pendingState->changedState |= Qt::ImPreferredLanguage;
480 }
481
zwp_text_input_v2_set_surrounding_text(Resource * resource,const QString & text,int32_t cursor,int32_t anchor)482 void QWaylandTextInputPrivate::zwp_text_input_v2_set_surrounding_text(Resource *resource, const QString &text, int32_t cursor, int32_t anchor)
483 {
484 if (resource != focusResource)
485 return;
486
487 pendingState->surroundingText = text;
488 pendingState->cursorPosition = QWaylandInputMethodEventBuilder::indexFromWayland(text, cursor);
489 pendingState->anchorPosition = QWaylandInputMethodEventBuilder::indexFromWayland(text, anchor);
490
491 pendingState->changedState |= Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition;
492 }
493
QWaylandTextInput(QWaylandObject * container,QWaylandCompositor * compositor)494 QWaylandTextInput::QWaylandTextInput(QWaylandObject *container, QWaylandCompositor *compositor)
495 : QWaylandCompositorExtensionTemplate(container, *new QWaylandTextInputPrivate(compositor))
496 {
497 connect(&d_func()->focusDestroyListener, &QWaylandDestroyListener::fired,
498 this, &QWaylandTextInput::focusSurfaceDestroyed);
499
500 connect(qApp->inputMethod(), &QInputMethod::visibleChanged,
501 this, &QWaylandTextInput::sendInputPanelState);
502 connect(qApp->inputMethod(), &QInputMethod::keyboardRectangleChanged,
503 this, &QWaylandTextInput::sendInputPanelState);
504 connect(qApp->inputMethod(), &QInputMethod::inputDirectionChanged,
505 this, &QWaylandTextInput::sendTextDirection);
506 connect(qApp->inputMethod(), &QInputMethod::localeChanged,
507 this, &QWaylandTextInput::sendLocale);
508 }
509
~QWaylandTextInput()510 QWaylandTextInput::~QWaylandTextInput()
511 {
512 }
513
sendInputMethodEvent(QInputMethodEvent * event)514 void QWaylandTextInput::sendInputMethodEvent(QInputMethodEvent *event)
515 {
516 Q_D(QWaylandTextInput);
517
518 d->sendInputMethodEvent(event);
519 }
520
sendKeyEvent(QKeyEvent * event)521 void QWaylandTextInput::sendKeyEvent(QKeyEvent *event)
522 {
523 Q_D(QWaylandTextInput);
524
525 d->sendKeyEvent(event);
526 }
527
sendInputPanelState()528 void QWaylandTextInput::sendInputPanelState()
529 {
530 Q_D(QWaylandTextInput);
531
532 d->sendInputPanelState();
533 }
534
sendTextDirection()535 void QWaylandTextInput::sendTextDirection()
536 {
537 Q_D(QWaylandTextInput);
538
539 d->sendTextDirection();
540 }
541
sendLocale()542 void QWaylandTextInput::sendLocale()
543 {
544 Q_D(QWaylandTextInput);
545
546 d->sendLocale();
547 }
548
inputMethodQuery(Qt::InputMethodQuery property,QVariant argument) const549 QVariant QWaylandTextInput::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument) const
550 {
551 const Q_D(QWaylandTextInput);
552
553 return d->inputMethodQuery(property, argument);
554 }
555
focus() const556 QWaylandSurface *QWaylandTextInput::focus() const
557 {
558 const Q_D(QWaylandTextInput);
559
560 return d->focus;
561 }
562
setFocus(QWaylandSurface * surface)563 void QWaylandTextInput::setFocus(QWaylandSurface *surface)
564 {
565 Q_D(QWaylandTextInput);
566
567 d->setFocus(surface);
568 }
569
focusSurfaceDestroyed(void *)570 void QWaylandTextInput::focusSurfaceDestroyed(void *)
571 {
572 Q_D(QWaylandTextInput);
573
574 d->focusDestroyListener.reset();
575
576 d->focus = nullptr;
577 d->focusResource = nullptr;
578 }
579
isSurfaceEnabled(QWaylandSurface * surface) const580 bool QWaylandTextInput::isSurfaceEnabled(QWaylandSurface *surface) const
581 {
582 const Q_D(QWaylandTextInput);
583
584 return d->enabledSurfaces.values().contains(surface);
585 }
586
add(::wl_client * client,uint32_t id,int version)587 void QWaylandTextInput::add(::wl_client *client, uint32_t id, int version)
588 {
589 Q_D(QWaylandTextInput);
590
591 d->add(client, id, version);
592 }
593
interface()594 const wl_interface *QWaylandTextInput::interface()
595 {
596 return QWaylandTextInputPrivate::interface();
597 }
598
interfaceName()599 QByteArray QWaylandTextInput::interfaceName()
600 {
601 return QWaylandTextInputPrivate::interfaceName();
602 }
603
604 QT_END_NAMESPACE
605