31 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
33 Qt::InputMethodQueries queries;
35 if (hints != other.hints)
36 queries |= Qt::ImHints;
37 if (cursorRectangle != other.cursorRectangle)
38 queries |= Qt::ImCursorRectangle;
39 if (surroundingText != other.surroundingText)
40 queries |= Qt::ImSurroundingText | Qt::ImCurrentSelection;
41 if (cursorPosition != other.cursorPosition)
42 queries |= Qt::ImCursorPosition | Qt::ImCurrentSelection;
43 if (anchorPosition != other.anchorPosition)
44 queries |= Qt::ImAnchorPosition | Qt::ImCurrentSelection;
51 Qt::InputMethodQueries queries;
53 if ((other.changedState & Qt::ImHints) && hints != other.hints) {
55 queries |= Qt::ImHints;
58 if ((other.changedState & Qt::ImCursorRectangle) && cursorRectangle != other.cursorRectangle) {
59 cursorRectangle = other.cursorRectangle;
60 queries |= Qt::ImCursorRectangle;
63 if ((other.changedState & Qt::ImSurroundingText) && surroundingText != other.surroundingText) {
64 surroundingText = other.surroundingText;
65 queries |= Qt::ImSurroundingText | Qt::ImCurrentSelection;
68 if ((other.changedState & Qt::ImCursorPosition) && cursorPosition != other.cursorPosition) {
70 queries |= Qt::ImCursorPosition | Qt::ImCurrentSelection;
73 if ((other.changedState & Qt::ImAnchorPosition) && anchorPosition != other.anchorPosition) {
75 queries |= Qt::ImAnchorPosition | Qt::ImCurrentSelection;
88void QWaylandTextInputV3Private::sendInputMethodEvent(QInputMethodEvent *event)
90 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
92 if (!focusResource || !focusResource->handle)
95 bool needsDone =
false;
97 const QString &newPreeditString = event->preeditString();
101 int32_t preeditCursorPos = newPreeditString.toUtf8().size();
103 if (event->replacementLength() > 0) {
104 int replacementStart = event->replacementStart();
105 int replacementLength = event->replacementLength();
106 const int cursorPos = currentState->cursorPosition;
107 if (currentState->cursorPosition < -event->replacementStart()) {
108 qCWarning(qLcWaylandCompositorTextInput)
110 <<
"Invalid replacementStart :" << replacementStart
111 <<
"on the cursorPosition :" << cursorPos;
112 replacementStart = -cursorPos;
114 auto targetText = QStringView{currentState->surroundingText}.sliced(cursorPos + replacementStart);
115 if (targetText.length() < replacementLength) {
116 qCWarning(qLcWaylandCompositorTextInput)
118 <<
"Invalid replacementLength :" << replacementLength
119 <<
"for the surrounding text :" << targetText;
120 replacementLength = targetText.length();
122 const int before = targetText.first(-replacementStart).toUtf8().size();
123 const int after = targetText.first(replacementLength).toUtf8().size() - before;
125 send_delete_surrounding_text(focusResource->handle, before, after);
129 currentState->surroundingText.replace(cursorPos + replacementStart,
131 event->commitString());
132 currentState->cursorPosition = cursorPos + replacementStart + event->commitString().length();
133 currentState->anchorPosition = cursorPos + replacementStart + event->commitString().length();
134 qApp->inputMethod()->update(Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition);
137 if (currentPreeditString != newPreeditString) {
138 currentPreeditString = newPreeditString;
139 send_preedit_string(focusResource->handle, currentPreeditString, preeditCursorPos, preeditCursorPos);
142 if (!event->commitString().isEmpty()) {
143 send_commit_string(focusResource->handle, event->commitString());
148 send_done(focusResource->handle, serials[focusResource]);
152void QWaylandTextInputV3Private::sendKeyEvent(QKeyEvent *event)
154 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
156 if (!focusResource || !focusResource->handle)
159 send_commit_string(focusResource->handle, event->text());
161 send_done(focusResource->handle, serials[focusResource]);
164QVariant QWaylandTextInputV3Private::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument)
const
166 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << property;
170 return QVariant(
static_cast<
int>(currentState->hints));
171 case Qt::ImCursorRectangle:
172 return currentState->cursorRectangle;
176 case Qt::ImCursorPosition:
177 qCDebug(qLcWaylandCompositorTextInput) << currentState->cursorPosition;
178 return currentState->cursorPosition;
179 case Qt::ImSurroundingText:
180 qCDebug(qLcWaylandCompositorTextInput) << currentState->surroundingText;
181 return currentState->surroundingText;
182 case Qt::ImCurrentSelection:
183 return currentState->surroundingText.mid(qMin(currentState->cursorPosition, currentState->anchorPosition),
184 qAbs(currentState->anchorPosition - currentState->cursorPosition));
185 case Qt::ImMaximumTextLength:
188 case Qt::ImAnchorPosition:
189 qCDebug(qLcWaylandCompositorTextInput) << currentState->anchorPosition;
190 return currentState->anchorPosition;
191 case Qt::ImAbsolutePosition:
193 return currentState->cursorPosition;
194 case Qt::ImTextAfterCursor:
195 if (argument.isValid())
196 return currentState->surroundingText.mid(currentState->cursorPosition, argument.toInt());
197 return currentState->surroundingText.mid(currentState->cursorPosition);
198 case Qt::ImTextBeforeCursor:
199 if (argument.isValid())
200 return currentState->surroundingText.left(currentState->cursorPosition).right(argument.toInt());
201 return currentState->surroundingText.left(currentState->cursorPosition);
208void QWaylandTextInputV3Private::setFocus(QWaylandSurface *surface)
210 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << surface;
212 if (focusResource && focus) {
213 qApp->inputMethod()->commit();
214 qApp->inputMethod()->hide();
215 inputPanelVisible =
false;
216 send_leave(focusResource->handle, focus->resource());
217 currentPreeditString.clear();
220 if (focus != surface)
221 focusDestroyListener.reset();
223 Resource *resource = surface ? resourceMap().value(surface->waylandClient()) : 0;
224 if (resource && surface) {
225 send_enter(resource->handle, surface->resource());
227 if (focus != surface)
228 focusDestroyListener.listenForDestruction(surface->resource());
232 focusResource = resource;
258void QWaylandTextInputV3Private::zwp_text_input_v3_enable(Resource *resource)
260 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
262 Q_Q(QWaylandTextInputV3);
264 pendingState.reset(
new QWaylandTextInputV3ClientState);
266 enabledSurfaces.insert(resource, focus);
267 emit q->surfaceEnabled(focus);
269 inputPanelVisible =
true;
270 qApp->inputMethod()->show();
273void QWaylandTextInputV3Private::zwp_text_input_v3_disable(QtWaylandServer::zwp_text_input_v3::Resource *resource)
275 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
277 Q_Q(QWaylandTextInputV3);
279 QWaylandSurface *s = enabledSurfaces.take(resource);
280 emit q->surfaceDisabled(s);
283 qApp->inputMethod()->commit();
285 qApp->inputMethod()->reset();
286 pendingState.reset(
new QWaylandTextInputV3ClientState);
289void QWaylandTextInputV3Private::zwp_text_input_v3_set_cursor_rectangle(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
291 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << x << y << width << height;
293 if (resource != focusResource)
296 pendingState->cursorRectangle = QRect(x, y, width, height);
298 pendingState->changedState |= Qt::ImCursorRectangle;
301void QWaylandTextInputV3Private::zwp_text_input_v3_commit(Resource *resource)
303 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
305 serials[resource] = serials[resource] < UINT_MAX ? serials[resource] + 1U : 0U;
308 if (!pendingState->changedState) {
309 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO <<
"pendingState is not changed";
316 if ((currentState->cursorPosition == currentState->anchorPosition)
317 && (pendingState->cursorPosition != pendingState->anchorPosition))
318 qApp->inputMethod()->reset();
322 if (currentState->surroundingText == pendingState->surroundingText && currentState->cursorPosition != pendingState->cursorPosition)
323 qApp->inputMethod()->invokeAction(QInputMethod::Click, pendingState->cursorPosition);
325 Qt::InputMethodQueries queries = currentState->mergeChanged(*pendingState.data());
326 pendingState.reset(
new QWaylandTextInputV3ClientState);
329 qCDebug(qLcWaylandCompositorTextInput) <<
"QInputMethod::update() after commit with" << queries;
331 qApp->inputMethod()->update(queries);
335void QWaylandTextInputV3Private::zwp_text_input_v3_set_content_type(Resource *resource, uint32_t hint, uint32_t purpose)
337 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << hint << purpose;
339 if (resource != focusResource)
342 pendingState->hints = Qt::ImhNone;
344 if ((hint & content_hint_completion) == 0)
345 pendingState->hints |= Qt::ImhNoPredictiveText;
346 if ((hint & content_hint_auto_capitalization) == 0)
347 pendingState->hints |= Qt::ImhNoAutoUppercase;
348 if ((hint & content_hint_lowercase) != 0)
349 pendingState->hints |= Qt::ImhPreferLowercase;
350 if ((hint & content_hint_uppercase) != 0)
351 pendingState->hints |= Qt::ImhPreferUppercase;
352 if ((hint & content_hint_hidden_text) != 0)
353 pendingState->hints |= Qt::ImhHiddenText;
354 if ((hint & content_hint_sensitive_data) != 0)
355 pendingState->hints |= Qt::ImhSensitiveData;
356 if ((hint & content_hint_latin) != 0)
357 pendingState->hints |= Qt::ImhLatinOnly;
358 if ((hint & content_hint_multiline) != 0)
359 pendingState->hints |= Qt::ImhMultiLine;
362 case content_purpose_normal:
364 case content_purpose_alpha:
365 pendingState->hints |= Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly;
367 case content_purpose_digits:
368 pendingState->hints |= Qt::ImhDigitsOnly;
370 case content_purpose_number:
371 pendingState->hints |= Qt::ImhFormattedNumbersOnly;
373 case content_purpose_phone:
374 pendingState->hints |= Qt::ImhDialableCharactersOnly;
376 case content_purpose_url:
377 pendingState->hints |= Qt::ImhUrlCharactersOnly;
379 case content_purpose_email:
380 pendingState->hints |= Qt::ImhEmailCharactersOnly;
382 case content_purpose_name:
383 case content_purpose_password:
385 case content_purpose_date:
386 pendingState->hints |= Qt::ImhDate;
388 case content_purpose_time:
389 pendingState->hints |= Qt::ImhTime;
391 case content_purpose_datetime:
392 pendingState->hints |= Qt::ImhDate | Qt::ImhTime;
394 case content_purpose_terminal:
399 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << pendingState->hints;
401 pendingState->changedState |= Qt::ImHints;
404void QWaylandTextInputV3Private::zwp_text_input_v3_set_surrounding_text(Resource *resource,
const QString &text, int32_t cursor, int32_t anchor)
406 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << text << cursor << anchor;
408 if (resource != focusResource)
411 pendingState->surroundingText = text;
412 pendingState->cursorPosition = QWaylandInputMethodEventBuilder::indexFromWayland(text, cursor);
413 pendingState->anchorPosition = QWaylandInputMethodEventBuilder::indexFromWayland(text, anchor);
415 pendingState->changedState |= Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition;
427 : QWaylandCompositorExtensionTemplate(container, *
new QWaylandTextInputV3Private(compositor))
429 connect(&d_func()->focusDestroyListener, &QWaylandDestroyListener::fired,
495 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << client << id << version;
497 Q_D(QWaylandTextInputV3);
499 d->add(client, id, version);