48void QWaylandInputMethodEventBuilder::addPreeditStyling(uint32_t index, uint32_t length, uint32_t style)
50 QTextCharFormat format;
53 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_NONE:
55 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_DEFAULT:
56 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_UNDERLINE:
57 format.setFontUnderline(
true);
58 format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
59 m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
61 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_ACTIVE:
62 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_INACTIVE:
63 format.setFontWeight(QFont::Bold);
64 format.setFontUnderline(
true);
65 format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
66 m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
68 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_HIGHLIGHT:
69 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_SELECTION:
71 format.setFontUnderline(
true);
72 format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
73 QPalette palette = qApp->palette();
74 format.setBackground(QBrush(palette.color(QPalette::Active, QPalette::Highlight)));
75 format.setForeground(QBrush(palette.color(QPalette::Active, QPalette::HighlightedText)));
76 m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
79 case ZWP_TEXT_INPUT_V2_PREEDIT_STYLE_INCORRECT:
80 format.setFontUnderline(
true);
81 format.setUnderlineStyle(QTextCharFormat::WaveUnderline);
82 format.setUnderlineColor(QColor(Qt::red));
83 m_preeditStyles.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, index, length, format));
95QInputMethodEvent *QWaylandInputMethodEventBuilder::buildCommit(
const QString &text)
97 QList<QInputMethodEvent::Attribute> attributes;
99 const std::pair<
int,
int> replacement = replacementForDeleteSurrounding();
101 if (m_cursor != 0 || m_anchor != 0) {
102 QString surrounding = QInputMethod::queryFocusObject(Qt::ImSurroundingText, QVariant()).toString();
103 const int cursor = QInputMethod::queryFocusObject(Qt::ImCursorPosition, QVariant()).toInt();
104 const int anchor = QInputMethod::queryFocusObject(Qt::ImAnchorPosition, QVariant()).toInt();
105 const int absoluteCursor = QInputMethod::queryFocusObject(Qt::ImAbsolutePosition, QVariant()).toInt();
107 const int absoluteOffset = absoluteCursor - cursor;
109 const int cursorAfterCommit = qMin(anchor, cursor) + replacement.first + text.size();
110 surrounding.replace(qMin(anchor, cursor) + replacement.first,
111 qAbs(anchor - cursor) + replacement.second, text);
113 attributes.push_back(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
114 indexFromWayland(surrounding, m_cursor, cursorAfterCommit) + absoluteOffset,
115 indexFromWayland(surrounding, m_anchor, cursorAfterCommit) + absoluteOffset,
119 QInputMethodEvent *event =
new QInputMethodEvent(QString(), attributes);
120 event->setCommitString(text, replacement.first, replacement.second);
125QInputMethodEvent *QWaylandInputMethodEventBuilder::buildPreedit(
const QString &text)
127 QList<QInputMethodEvent::Attribute> attributes;
129 if (m_preeditCursor < 0) {
130 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
132 attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, indexFromWayland(text, m_preeditCursor), 1, QVariant()));
135 for (
const QInputMethodEvent::Attribute &attr : std::as_const(m_preeditStyles)) {
136 int start = indexFromWayland(text, attr.start);
137 int length = indexFromWayland(text, attr.start + attr.length) - start;
138 attributes.append(QInputMethodEvent::Attribute(attr.type, start, length, attr.value));
141 QInputMethodEvent *event =
new QInputMethodEvent(text, attributes);
143 const std::pair<
int,
int> replacement = replacementForDeleteSurrounding();
144 event->setCommitString(QString(), replacement.first, replacement.second);
169 uint32_t hint = ZWP_TEXT_INPUT_V2_CONTENT_HINT_NONE;
170 uint32_t purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NORMAL;
172 if (hints & Qt::ImhHiddenText)
173 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_HIDDEN_TEXT;
174 if (hints & Qt::ImhSensitiveData)
175 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_SENSITIVE_DATA;
176 if ((hints & Qt::ImhNoAutoUppercase) == 0)
177 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CAPITALIZATION;
178 if (hints & Qt::ImhPreferNumbers) {
181 if (hints & Qt::ImhPreferUppercase)
182 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_UPPERCASE;
183 if (hints & Qt::ImhPreferLowercase)
184 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LOWERCASE;
185 if ((hints & Qt::ImhNoPredictiveText) == 0) {
186 hint |= (ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_COMPLETION
187 | ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CORRECTION);
190 if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime) == 0)
191 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATE;
192 else if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime))
193 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATETIME;
194 else if ((hints & Qt::ImhDate) == 0 && (hints & Qt::ImhTime))
195 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_TIME;
197 if (hints & Qt::ImhPreferLatin)
198 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LATIN;
199 if (hints & Qt::ImhMultiLine)
200 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_MULTILINE;
201 if (hints & Qt::ImhDigitsOnly)
202 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DIGITS;
203 if (hints & Qt::ImhFormattedNumbersOnly)
204 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NUMBER;
205 if (hints & Qt::ImhUppercaseOnly)
206 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_UPPERCASE;
207 if (hints & Qt::ImhLowercaseOnly)
208 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LOWERCASE;
209 if (hints & Qt::ImhDialableCharactersOnly)
210 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_PHONE;
211 if (hints & Qt::ImhEmailCharactersOnly)
212 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_EMAIL;
213 if (hints & Qt::ImhUrlCharactersOnly)
214 purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_URL;
215 if (hints & Qt::ImhLatinOnly)
216 hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LATIN;
223 uint32_t hint = ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE;
224 uint32_t purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL;
226 if (hints & Qt::ImhHiddenText)
227 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_HIDDEN_TEXT;
228 if (hints & Qt::ImhSensitiveData)
229 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_SENSITIVE_DATA;
230 if ((hints & Qt::ImhNoAutoUppercase) == 0)
231 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_AUTO_CAPITALIZATION;
232 if (hints & Qt::ImhPreferNumbers) {
235 if (hints & Qt::ImhPreferUppercase)
236 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_UPPERCASE;
237 if (hints & Qt::ImhPreferLowercase)
238 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_LOWERCASE;
239 if ((hints & Qt::ImhNoPredictiveText) == 0) {
240 hint |= (ZWP_TEXT_INPUT_V3_CONTENT_HINT_COMPLETION
241 | ZWP_TEXT_INPUT_V3_CONTENT_HINT_SPELLCHECK);
244 if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime) == 0)
245 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATE;
246 else if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime))
247 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATETIME;
248 else if ((hints & Qt::ImhDate) == 0 && (hints & Qt::ImhTime))
249 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TIME;
250 if (hints & Qt::ImhPreferLatin)
251 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_LATIN;
252 if (hints & Qt::ImhMultiLine)
253 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_MULTILINE;
254 if (hints & Qt::ImhDigitsOnly)
255 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DIGITS;
256 if (hints & Qt::ImhFormattedNumbersOnly)
257 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER;
258 if (hints & Qt::ImhUppercaseOnly)
259 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_UPPERCASE;
260 if (hints & Qt::ImhLowercaseOnly)
261 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_LOWERCASE;
262 if (hints & Qt::ImhDialableCharactersOnly)
263 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE;
264 if (hints & Qt::ImhEmailCharactersOnly)
265 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_EMAIL;
266 if (hints & Qt::ImhUrlCharactersOnly)
267 purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_URL;
268 if (hints & Qt::ImhLatinOnly)
269 hint |= ZWP_TEXT_INPUT_V3_CONTENT_HINT_LATIN;
274int QWaylandInputMethodEventBuilder::indexFromWayland(
const QString &text,
int length,
int base)
280 const QByteArray &utf8 = QStringView{text}.left(base).toUtf8();
281 return QString::fromUtf8(utf8.first(qMax(utf8.size() + length, 0))).size();
283 const QByteArray &utf8 = QStringView{text}.mid(base).toUtf8();
284 return QString::fromUtf8(utf8.first(qMin(length, utf8.size()))).size() + base;
288int QWaylandInputMethodEventBuilder::trimmedIndexFromWayland(
const QString &text,
int length,
int base)
294 const QByteArray &utf8 = QStringView{text}.left(base).toUtf8();
295 const int len = utf8.size();
296 const int start = len + length;
300 for (
int i = 0; i < 4; i++) {
301 if (start + i >= len)
304 const unsigned char ch = utf8.at(start + i);
306 if (ch < 0x80 || ch > 0xbf)
307 return QString::fromUtf8(utf8.left(start + i)).size();
310 const QByteArray &utf8 = QStringView{text}.mid(base).toUtf8();
311 const int len = utf8.size();
312 const int start = length;
314 return base + QString::fromUtf8(utf8).size();
316 for (
int i = 0; i < 4; i++) {
317 const unsigned char ch = utf8.at(start - i);
319 if (ch < 0x80 || ch > 0xbf)
320 return base + QString::fromUtf8(utf8.left(start - i)).size();