49void QWaylandInputMethodEventBuilder::addPreeditStyling(uint32_t index, uint32_t length, uint32_t style)
51 QTextCharFormat format;
54 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_NONE:
56 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_DEFAULT:
57 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_UNDERLINE:
58 format.setFontUnderline(
true);
59 format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
60 m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
62 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_ACTIVE:
63 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_INACTIVE:
64 format.setFontWeight(QFont::Bold);
65 format.setFontUnderline(
true);
66 format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
67 m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
69 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_HIGHLIGHT:
70 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_SELECTION:
72 format.setFontUnderline(
true);
73 format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
74 QPalette palette = qApp->palette();
75 format.setBackground(QBrush(palette.color(QPalette::Active, QPalette::Highlight)));
76 format.setForeground(QBrush(palette.color(QPalette::Active, QPalette::HighlightedText)));
77 m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
80 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_INCORRECT:
81 format.setFontUnderline(
true);
82 format.setUnderlineStyle(QTextCharFormat::WaveUnderline);
83 format.setUnderlineColor(QColor(Qt::red));
84 m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
96QInputMethodEvent *QWaylandInputMethodEventBuilder::buildCommit(
const QString &text)
98 QList<QInputMethodEvent::Attribute> attributes;
100 const std::pair<
int,
int> replacement = replacementForDeleteSurrounding();
102 if (m_cursor != 0 || m_anchor != 0) {
103 QString surrounding = QInputMethod::queryFocusObject(Qt::ImSurroundingText, QVariant()).toString();
104 const int cursor = QInputMethod::queryFocusObject(Qt::ImCursorPosition, QVariant()).toInt();
105 const int anchor = QInputMethod::queryFocusObject(Qt::ImAnchorPosition, QVariant()).toInt();
106 const int absoluteCursor = QInputMethod::queryFocusObject(Qt::ImAbsolutePosition, QVariant()).toInt();
108 const int absoluteOffset = absoluteCursor - cursor;
110 const int cursorAfterCommit = qMin(anchor, cursor) + replacement.first + text.size();
111 surrounding.replace(qMin(anchor, cursor) + replacement.first,
112 qAbs(anchor - cursor) + replacement.second, text);
114 attributes.push_back(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
115 indexFromWayland(surrounding, m_cursor, cursorAfterCommit) + absoluteOffset,
116 indexFromWayland(surrounding, m_anchor, cursorAfterCommit) + absoluteOffset,
120 QInputMethodEvent *event =
new QInputMethodEvent(QString(), attributes);
121 event->setCommitString(text, replacement.first, replacement.second);
126QInputMethodEvent *QWaylandInputMethodEventBuilder::buildPreedit(
const QString &text)
128 QList<QInputMethodEvent::Attribute> attributes;
130 if (m_preeditCursor < 0) {
131 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
133 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, indexFromWayland(text, m_preeditCursor), 1, QVariant()));
136 for (
const QInputMethodEvent::Attribute &attr : std::as_const(m_preeditStyles)) {
137 int start = indexFromWayland(text, attr.start);
138 int length = indexFromWayland(text, attr.start + attr.length) - start;
139 attributes.append(QInputMethodEvent::Attribute(attr.type, start, length, attr.value));
142 QInputMethodEvent *event =
new QInputMethodEvent(text, attributes);
144 const std::pair<
int,
int> replacement = replacementForDeleteSurrounding();
145 event->setCommitString(QString(), replacement.first, replacement.second);
170 uint32_t hint = ZWP_TEXT_INPUT_V2_CONTENT_HINT_NONE;
171 uint32_t purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NORMAL;
173 if (hints & Qt::ImhHiddenText)
174 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_HIDDEN_TEXT;
175 if (hints & Qt::ImhSensitiveData)
176 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_SENSITIVE_DATA;
177 if ((hints & Qt::ImhNoAutoUppercase) == 0)
178 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CAPITALIZATION;
179 if (hints & Qt::ImhPreferNumbers) {
182 if (hints & Qt::ImhPreferUppercase)
183 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_UPPERCASE;
184 if (hints & Qt::ImhPreferLowercase)
185 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LOWERCASE;
186 if ((hints & Qt::ImhNoPredictiveText) == 0) {
187 hint |= (ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_COMPLETION
188 | ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CORRECTION);
191 if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime) == 0)
192 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATE;
193 else if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime))
194 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATETIME;
195 else if ((hints & Qt::ImhDate) == 0 && (hints & Qt::ImhTime))
196 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_TIME;
198 if (hints & Qt::ImhPreferLatin)
199 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LATIN;
200 if (hints & Qt::ImhMultiLine)
201 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_MULTILINE;
202 if (hints & Qt::ImhDigitsOnly)
203 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DIGITS;
204 if (hints & Qt::ImhFormattedNumbersOnly)
205 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NUMBER;
206 if (hints & Qt::ImhUppercaseOnly)
207 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_UPPERCASE;
208 if (hints & Qt::ImhLowercaseOnly)
209 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LOWERCASE;
210 if (hints & Qt::ImhDialableCharactersOnly)
211 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_PHONE;
212 if (hints & Qt::ImhEmailCharactersOnly)
213 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_EMAIL;
214 if (hints & Qt::ImhUrlCharactersOnly)
215 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_URL;
216 if (hints & Qt::ImhLatinOnly)
217 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LATIN;
224 uint32_t hint = ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE;
225 uint32_t purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL;
227 if (hints & Qt::ImhHiddenText)
228 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_HIDDEN_TEXT;
229 if (hints & Qt::ImhSensitiveData)
230 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_SENSITIVE_DATA;
231 if ((hints & Qt::ImhNoAutoUppercase) == 0)
232 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_AUTO_CAPITALIZATION;
233 if (hints & Qt::ImhPreferNumbers) {
236 if (hints & Qt::ImhPreferUppercase)
237 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_UPPERCASE;
238 if (hints & Qt::ImhPreferLowercase)
239 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_LOWERCASE;
240 if ((hints & Qt::ImhNoPredictiveText) == 0) {
241 hint |= (ZWP_TEXT_INPUT_V3_CONTENT_HINT_COMPLETION
242 | ZWP_TEXT_INPUT_V3_CONTENT_HINT_SPELLCHECK);
245 if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime) == 0)
246 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATE;
247 else if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime))
248 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATETIME;
249 else if ((hints & Qt::ImhDate) == 0 && (hints & Qt::ImhTime))
250 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TIME;
251 if (hints & Qt::ImhPreferLatin)
252 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_LATIN;
253 if (hints & Qt::ImhMultiLine)
254 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_MULTILINE;
255 if (hints & Qt::ImhDigitsOnly)
256 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DIGITS;
257 if (hints & Qt::ImhFormattedNumbersOnly)
258 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER;
259 if (hints & Qt::ImhUppercaseOnly)
260 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_UPPERCASE;
261 if (hints & Qt::ImhLowercaseOnly)
262 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_LOWERCASE;
263 if (hints & Qt::ImhDialableCharactersOnly)
264 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE;
265 if (hints & Qt::ImhEmailCharactersOnly)
266 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_EMAIL;
267 if (hints & Qt::ImhUrlCharactersOnly)
268 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_URL;
269 if (hints & Qt::ImhLatinOnly)
270 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_LATIN;
275int QWaylandInputMethodEventBuilder::indexFromWayland(
const QString &text,
int length,
int base)
281 const QByteArray &utf8 = QStringView{text}.left(base).toUtf8();
282 return QString::fromUtf8(utf8.first(qMax(utf8.size() + length, 0))).size();
284 const QByteArray &utf8 = QStringView{text}.mid(base).toUtf8();
285 return QString::fromUtf8(utf8.first(qMin(length, utf8.size()))).size() + base;
289int QWaylandInputMethodEventBuilder::trimmedIndexFromWayland(
const QString &text,
int length,
int base)
295 const QByteArray &utf8 = QStringView{text}.left(base).toUtf8();
296 const int len = utf8.size();
297 const int start = len + length;
301 for (
int i = 0; i < 4; i++) {
302 if (start + i >= len)
305 const unsigned char ch = utf8.at(start + i);
307 if (ch < 0x80 || ch > 0xbf)
308 return QString::fromUtf8(utf8.left(start + i)).size();
311 const QByteArray &utf8 = QStringView{text}.mid(base).toUtf8();
312 const int len = utf8.size();
313 const int start = length;
315 return base + QString::fromUtf8(utf8).size();
317 for (
int i = 0; i < 4; i++) {
318 const unsigned char ch = utf8.at(start - i);
320 if (ch < 0x80 || ch > 0xbf)
321 return base + QString::fromUtf8(utf8.left(start - i)).size();