30 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
32 Qt::InputMethodQueries queries;
34 if (hints != other.hints)
35 queries |= Qt::ImHints;
36 if (cursorRectangle != other.cursorRectangle)
37 queries |= Qt::ImCursorRectangle;
38 if (surroundingText != other.surroundingText)
39 queries |= Qt::ImSurroundingText | Qt::ImCurrentSelection;
40 if (cursorPosition != other.cursorPosition)
41 queries |= Qt::ImCursorPosition | Qt::ImCurrentSelection;
42 if (anchorPosition != other.anchorPosition)
43 queries |= Qt::ImAnchorPosition | Qt::ImCurrentSelection;
50 Qt::InputMethodQueries queries;
52 if ((other.changedState & Qt::ImHints) && hints != other.hints) {
54 queries |= Qt::ImHints;
57 if ((other.changedState & Qt::ImCursorRectangle) && cursorRectangle != other.cursorRectangle) {
58 cursorRectangle = other.cursorRectangle;
59 queries |= Qt::ImCursorRectangle;
62 if ((other.changedState & Qt::ImSurroundingText) && surroundingText != other.surroundingText) {
63 surroundingText = other.surroundingText;
64 queries |= Qt::ImSurroundingText | Qt::ImCurrentSelection;
67 if ((other.changedState & Qt::ImCursorPosition) && cursorPosition != other.cursorPosition) {
69 queries |= Qt::ImCursorPosition | Qt::ImCurrentSelection;
72 if ((other.changedState & Qt::ImAnchorPosition) && anchorPosition != other.anchorPosition) {
74 queries |= Qt::ImAnchorPosition | Qt::ImCurrentSelection;
87void QWaylandTextInputV3Private::sendInputMethodEvent(QInputMethodEvent *event)
89 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
91 if (!focusResource || !focusResource->handle)
94 bool needsDone =
false;
96 const QString &newPreeditString = event->preeditString();
100 int32_t preeditCursorPos = newPreeditString.toUtf8().size();
102 if (event->replacementLength() > 0) {
103 int replacementStart = event->replacementStart();
104 int replacementLength = event->replacementLength();
105 const int cursorPos = currentState->cursorPosition;
106 if (currentState->cursorPosition < -event->replacementStart()) {
107 qCWarning(qLcWaylandCompositorTextInput)
109 <<
"Invalid replacementStart :" << replacementStart
110 <<
"on the cursorPosition :" << cursorPos;
111 replacementStart = -cursorPos;
113 auto targetText = QStringView{currentState->surroundingText}.sliced(cursorPos + replacementStart);
114 if (targetText.length() < replacementLength) {
115 qCWarning(qLcWaylandCompositorTextInput)
117 <<
"Invalid replacementLength :" << replacementLength
118 <<
"for the surrounding text :" << targetText;
119 replacementLength = targetText.length();
121 const int before = targetText.first(-replacementStart).toUtf8().size();
122 const int after = targetText.first(replacementLength).toUtf8().size() - before;
124 send_delete_surrounding_text(focusResource->handle, before, after);
128 currentState->surroundingText.replace(cursorPos + replacementStart,
130 event->commitString());
131 currentState->cursorPosition = cursorPos + replacementStart + event->commitString().length();
132 currentState->anchorPosition = cursorPos + replacementStart + event->commitString().length();
133 qApp->inputMethod()->update(Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition);
136 if (currentPreeditString != newPreeditString) {
137 currentPreeditString = newPreeditString;
138 send_preedit_string(focusResource->handle, currentPreeditString, preeditCursorPos, preeditCursorPos);
141 if (!event->commitString().isEmpty()) {
142 send_commit_string(focusResource->handle, event->commitString());
147 send_done(focusResource->handle, serials[focusResource]);
151void QWaylandTextInputV3Private::sendKeyEvent(QKeyEvent *event)
153 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
155 if (!focusResource || !focusResource->handle)
158 send_commit_string(focusResource->handle, event->text());
160 send_done(focusResource->handle, serials[focusResource]);
163QVariant QWaylandTextInputV3Private::inputMethodQuery(Qt::InputMethodQuery property, QVariant argument)
const
165 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << property;
169 return QVariant(
static_cast<
int>(currentState->hints));
170 case Qt::ImCursorRectangle:
171 return currentState->cursorRectangle;
175 case Qt::ImCursorPosition:
176 qCDebug(qLcWaylandCompositorTextInput) << currentState->cursorPosition;
177 return currentState->cursorPosition;
178 case Qt::ImSurroundingText:
179 qCDebug(qLcWaylandCompositorTextInput) << currentState->surroundingText;
180 return currentState->surroundingText;
181 case Qt::ImCurrentSelection:
182 return currentState->surroundingText.mid(qMin(currentState->cursorPosition, currentState->anchorPosition),
183 qAbs(currentState->anchorPosition - currentState->cursorPosition));
184 case Qt::ImMaximumTextLength:
187 case Qt::ImAnchorPosition:
188 qCDebug(qLcWaylandCompositorTextInput) << currentState->anchorPosition;
189 return currentState->anchorPosition;
190 case Qt::ImAbsolutePosition:
192 return currentState->cursorPosition;
193 case Qt::ImTextAfterCursor:
194 if (argument.isValid())
195 return currentState->surroundingText.mid(currentState->cursorPosition, argument.toInt());
196 return currentState->surroundingText.mid(currentState->cursorPosition);
197 case Qt::ImTextBeforeCursor:
198 if (argument.isValid())
199 return currentState->surroundingText.left(currentState->cursorPosition).right(argument.toInt());
200 return currentState->surroundingText.left(currentState->cursorPosition);
207void QWaylandTextInputV3Private::setFocus(QWaylandSurface *surface)
209 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << surface;
211 if (focusResource && focus) {
212 qApp->inputMethod()->commit();
213 qApp->inputMethod()->hide();
214 inputPanelVisible =
false;
215 send_leave(focusResource->handle, focus->resource());
216 currentPreeditString.clear();
219 if (focus != surface)
220 focusDestroyListener.reset();
222 Resource *resource = surface ? resourceMap().value(surface->waylandClient()) : 0;
223 if (resource && surface) {
224 send_enter(resource->handle, surface->resource());
226 if (focus != surface)
227 focusDestroyListener.listenForDestruction(surface->resource());
231 focusResource = resource;
257void QWaylandTextInputV3Private::zwp_text_input_v3_enable(Resource *resource)
259 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
261 Q_Q(QWaylandTextInputV3);
263 pendingState.reset(
new QWaylandTextInputV3ClientState);
265 enabledSurfaces.insert(resource, focus);
266 emit q->surfaceEnabled(focus);
268 inputPanelVisible =
true;
269 qApp->inputMethod()->show();
272void QWaylandTextInputV3Private::zwp_text_input_v3_disable(QtWaylandServer::zwp_text_input_v3::Resource *resource)
274 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
276 Q_Q(QWaylandTextInputV3);
278 QWaylandSurface *s = enabledSurfaces.take(resource);
279 emit q->surfaceDisabled(s);
282 qApp->inputMethod()->commit();
284 qApp->inputMethod()->reset();
285 pendingState.reset(
new QWaylandTextInputV3ClientState);
288void QWaylandTextInputV3Private::zwp_text_input_v3_set_cursor_rectangle(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
290 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << x << y << width << height;
292 if (resource != focusResource)
295 pendingState->cursorRectangle = QRect(x, y, width, height);
297 pendingState->changedState |= Qt::ImCursorRectangle;
300void QWaylandTextInputV3Private::zwp_text_input_v3_commit(Resource *resource)
302 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO;
304 serials[resource] = serials[resource] < UINT_MAX ? serials[resource] + 1U : 0U;
307 if (!pendingState->changedState) {
308 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO <<
"pendingState is not changed";
315 if ((currentState->cursorPosition == currentState->anchorPosition)
316 && (pendingState->cursorPosition != pendingState->anchorPosition))
317 qApp->inputMethod()->reset();
321 if (currentState->surroundingText == pendingState->surroundingText && currentState->cursorPosition != pendingState->cursorPosition)
322 qApp->inputMethod()->invokeAction(QInputMethod::Click, pendingState->cursorPosition);
324 Qt::InputMethodQueries queries = currentState->mergeChanged(*pendingState.data());
325 pendingState.reset(
new QWaylandTextInputV3ClientState);
328 qCDebug(qLcWaylandCompositorTextInput) <<
"QInputMethod::update() after commit with" << queries;
330 qApp->inputMethod()->update(queries);
334void QWaylandTextInputV3Private::zwp_text_input_v3_set_content_type(Resource *resource, uint32_t hint, uint32_t purpose)
336 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << hint << purpose;
338 if (resource != focusResource)
341 pendingState->hints = Qt::ImhNone;
343 if ((hint & content_hint_completion) == 0)
344 pendingState->hints |= Qt::ImhNoPredictiveText;
345 if ((hint & content_hint_auto_capitalization) == 0)
346 pendingState->hints |= Qt::ImhNoAutoUppercase;
347 if ((hint & content_hint_lowercase) != 0)
348 pendingState->hints |= Qt::ImhPreferLowercase;
349 if ((hint & content_hint_uppercase) != 0)
350 pendingState->hints |= Qt::ImhPreferUppercase;
351 if ((hint & content_hint_hidden_text) != 0)
352 pendingState->hints |= Qt::ImhHiddenText;
353 if ((hint & content_hint_sensitive_data) != 0)
354 pendingState->hints |= Qt::ImhSensitiveData;
355 if ((hint & content_hint_latin) != 0)
356 pendingState->hints |= Qt::ImhLatinOnly;
357 if ((hint & content_hint_multiline) != 0)
358 pendingState->hints |= Qt::ImhMultiLine;
361 case content_purpose_normal:
363 case content_purpose_alpha:
364 pendingState->hints |= Qt::ImhUppercaseOnly | Qt::ImhLowercaseOnly;
366 case content_purpose_digits:
367 pendingState->hints |= Qt::ImhDigitsOnly;
369 case content_purpose_number:
370 pendingState->hints |= Qt::ImhFormattedNumbersOnly;
372 case content_purpose_phone:
373 pendingState->hints |= Qt::ImhDialableCharactersOnly;
375 case content_purpose_url:
376 pendingState->hints |= Qt::ImhUrlCharactersOnly;
378 case content_purpose_email:
379 pendingState->hints |= Qt::ImhEmailCharactersOnly;
381 case content_purpose_name:
382 case content_purpose_password:
384 case content_purpose_date:
385 pendingState->hints |= Qt::ImhDate;
387 case content_purpose_time:
388 pendingState->hints |= Qt::ImhTime;
390 case content_purpose_datetime:
391 pendingState->hints |= Qt::ImhDate | Qt::ImhTime;
393 case content_purpose_terminal:
398 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << pendingState->hints;
400 pendingState->changedState |= Qt::ImHints;
403void QWaylandTextInputV3Private::zwp_text_input_v3_set_surrounding_text(Resource *resource,
const QString &text, int32_t cursor, int32_t anchor)
405 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << text << cursor << anchor;
407 if (resource != focusResource)
410 pendingState->surroundingText = text;
411 pendingState->cursorPosition = QWaylandInputMethodEventBuilder::indexFromWayland(text, cursor);
412 pendingState->anchorPosition = QWaylandInputMethodEventBuilder::indexFromWayland(text, anchor);
414 pendingState->changedState |= Qt::ImSurroundingText | Qt::ImCursorPosition | Qt::ImAnchorPosition;
426 : QWaylandCompositorExtensionTemplate(container, *
new QWaylandTextInputV3Private(compositor))
428 connect(&d_func()->focusDestroyListener, &QWaylandDestroyListener::fired,
429 this, &QWaylandTextInputV3::focusSurfaceDestroyed);
494 qCDebug(qLcWaylandCompositorTextInput) << Q_FUNC_INFO << client << id << version;
496 Q_D(QWaylandTextInputV3);
498 d->add(client, id, version);