summaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
authorInho Lee <inho.lee@qt.io>2021-06-19 06:27:22 +0200
committerInho Lee <inho.lee@qt.io>2021-11-19 10:33:31 +0100
commit0cec50bece2dcd69127f19c87a3062e4b13f3723 (patch)
tree8ec11248518b1edfede9538a07ee5e0b0aa5624e /src/shared
parent6f195a592b26ad8416a6f02d6bd7258ab3fadf65 (diff)
Support text-input-unstable-v4-wip
This feature can be enabled by -feature-wayland-text-input-v4-wip. It is disabled by default. TextInputManagerV4 is available in a compositor. zwp_text_input_v4 is available for QT_WAYLAND_TEXT_INPUT_PROTOCOL in a client It supports Hangul(Korean) with a qtvirtualkeyboard patchset (refs/changes/02/357902/3) It includes some workarounds for ibus because each ibus module has its own policy for focus-in/focus-out. enter/leave will synchronize with enable/disable and they will happen whenever focus-in/focus-out happen. Cursor/anchor positions are byte offsets. Surrounding text will be trimmed when it is over 4000 byte. For debugging, uses "qt.waylandcompositor.textinput" in a compositor side uses "qt.qpa.wayland.textinput" in a client side Tested on qtvirtualkeyboard and ibus TODO : * QTBUG-97248 - event:preedit_commit_mode is not implemented yet. Current preedit_commit_mode is 'commit'. * request:set_text_change_cause is not implemented. Task-number: QTBUG-94327 Change-Id: I72644893f40f30c4b03cd6a7d05483d12bde1070 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/qwaylandinputmethodeventbuilder.cpp149
-rw-r--r--src/shared/qwaylandinputmethodeventbuilder_p.h7
2 files changed, 118 insertions, 38 deletions
diff --git a/src/shared/qwaylandinputmethodeventbuilder.cpp b/src/shared/qwaylandinputmethodeventbuilder.cpp
index 00e3ae14e..cfc4a99f8 100644
--- a/src/shared/qwaylandinputmethodeventbuilder.cpp
+++ b/src/shared/qwaylandinputmethodeventbuilder.cpp
@@ -44,8 +44,10 @@
#ifdef QT_BUILD_WAYLANDCOMPOSITOR_LIB
#include <QtWaylandCompositor/private/qwayland-server-text-input-unstable-v2.h>
+#include <QtWaylandCompositor/private/qwayland-server-text-input-unstable-v4-wip.h>
#else
#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
+#include <QtWaylandClient/private/qwayland-text-input-unstable-v4-wip.h>
#endif
QT_BEGIN_NAMESPACE
@@ -194,68 +196,105 @@ QWaylandInputMethodContentType QWaylandInputMethodContentType::convert(Qt::Input
uint32_t hint = ZWP_TEXT_INPUT_V2_CONTENT_HINT_NONE;
uint32_t purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NORMAL;
- if (hints & Qt::ImhHiddenText) {
+ if (hints & Qt::ImhHiddenText)
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_HIDDEN_TEXT;
- }
- if (hints & Qt::ImhSensitiveData) {
+ if (hints & Qt::ImhSensitiveData)
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_SENSITIVE_DATA;
- }
- if ((hints & Qt::ImhNoAutoUppercase) == 0) {
+ if ((hints & Qt::ImhNoAutoUppercase) == 0)
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CAPITALIZATION;
- }
if (hints & Qt::ImhPreferNumbers) {
// Nothing yet
}
- if (hints & Qt::ImhPreferUppercase) {
+ if (hints & Qt::ImhPreferUppercase)
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_UPPERCASE;
- }
- if (hints & Qt::ImhPreferLowercase) {
+ if (hints & Qt::ImhPreferLowercase)
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LOWERCASE;
- }
if ((hints & Qt::ImhNoPredictiveText) == 0) {
- hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_COMPLETION | ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CORRECTION;
+ hint |= (ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_COMPLETION
+ | ZWP_TEXT_INPUT_V2_CONTENT_HINT_AUTO_CORRECTION);
}
- if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime) == 0) {
+ if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime) == 0)
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATE;
- } else if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime)) {
+ else if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime))
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DATETIME;
- } else if ((hints & Qt::ImhDate) == 0 && (hints & Qt::ImhTime)) {
+ else if ((hints & Qt::ImhDate) == 0 && (hints & Qt::ImhTime))
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_TIME;
- }
- if (hints & Qt::ImhPreferLatin) {
+ if (hints & Qt::ImhPreferLatin)
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LATIN;
- }
-
- if (hints & Qt::ImhMultiLine) {
+ if (hints & Qt::ImhMultiLine)
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_MULTILINE;
- }
-
- if (hints & Qt::ImhDigitsOnly) {
+ if (hints & Qt::ImhDigitsOnly)
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_DIGITS;
- }
- if (hints & Qt::ImhFormattedNumbersOnly) {
+ if (hints & Qt::ImhFormattedNumbersOnly)
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_NUMBER;
- }
- if (hints & Qt::ImhUppercaseOnly) {
+ if (hints & Qt::ImhUppercaseOnly)
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_UPPERCASE;
- }
- if (hints & Qt::ImhLowercaseOnly) {
+ if (hints & Qt::ImhLowercaseOnly)
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LOWERCASE;
- }
- if (hints & Qt::ImhDialableCharactersOnly) {
+ if (hints & Qt::ImhDialableCharactersOnly)
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_PHONE;
- }
- if (hints & Qt::ImhEmailCharactersOnly) {
+ if (hints & Qt::ImhEmailCharactersOnly)
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_EMAIL;
- }
- if (hints & Qt::ImhUrlCharactersOnly) {
+ if (hints & Qt::ImhUrlCharactersOnly)
purpose = ZWP_TEXT_INPUT_V2_CONTENT_PURPOSE_URL;
- }
- if (hints & Qt::ImhLatinOnly) {
+ if (hints & Qt::ImhLatinOnly)
hint |= ZWP_TEXT_INPUT_V2_CONTENT_HINT_LATIN;
+
+ return QWaylandInputMethodContentType{hint, purpose};
+}
+
+QWaylandInputMethodContentType QWaylandInputMethodContentType::convertV4(Qt::InputMethodHints hints)
+{
+ uint32_t hint = ZWP_TEXT_INPUT_V4_CONTENT_HINT_NONE;
+ uint32_t purpose = ZWP_TEXT_INPUT_V4_CONTENT_PURPOSE_NORMAL;
+
+ if (hints & Qt::ImhHiddenText)
+ hint |= ZWP_TEXT_INPUT_V4_CONTENT_HINT_HIDDEN_TEXT;
+ if (hints & Qt::ImhSensitiveData)
+ hint |= ZWP_TEXT_INPUT_V4_CONTENT_HINT_SENSITIVE_DATA;
+ if ((hints & Qt::ImhNoAutoUppercase) == 0)
+ hint |= ZWP_TEXT_INPUT_V4_CONTENT_HINT_AUTO_CAPITALIZATION;
+ if (hints & Qt::ImhPreferNumbers) {
+ // Nothing yet
+ }
+ if (hints & Qt::ImhPreferUppercase)
+ hint |= ZWP_TEXT_INPUT_V4_CONTENT_HINT_UPPERCASE;
+ if (hints & Qt::ImhPreferLowercase)
+ hint |= ZWP_TEXT_INPUT_V4_CONTENT_HINT_LOWERCASE;
+ if ((hints & Qt::ImhNoPredictiveText) == 0) {
+ hint |= (ZWP_TEXT_INPUT_V4_CONTENT_HINT_COMPLETION
+ | ZWP_TEXT_INPUT_V4_CONTENT_HINT_SPELLCHECK);
}
+
+ if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime) == 0)
+ purpose = ZWP_TEXT_INPUT_V4_CONTENT_PURPOSE_DATE;
+ else if ((hints & Qt::ImhDate) && (hints & Qt::ImhTime))
+ purpose = ZWP_TEXT_INPUT_V4_CONTENT_PURPOSE_DATETIME;
+ else if ((hints & Qt::ImhDate) == 0 && (hints & Qt::ImhTime))
+ purpose = ZWP_TEXT_INPUT_V4_CONTENT_PURPOSE_TIME;
+ if (hints & Qt::ImhPreferLatin)
+ hint |= ZWP_TEXT_INPUT_V4_CONTENT_HINT_LATIN;
+ if (hints & Qt::ImhMultiLine)
+ hint |= ZWP_TEXT_INPUT_V4_CONTENT_HINT_MULTILINE;
+ if (hints & Qt::ImhDigitsOnly)
+ purpose = ZWP_TEXT_INPUT_V4_CONTENT_PURPOSE_DIGITS;
+ if (hints & Qt::ImhFormattedNumbersOnly)
+ purpose = ZWP_TEXT_INPUT_V4_CONTENT_PURPOSE_NUMBER;
+ if (hints & Qt::ImhUppercaseOnly)
+ hint |= ZWP_TEXT_INPUT_V4_CONTENT_HINT_UPPERCASE;
+ if (hints & Qt::ImhLowercaseOnly)
+ hint |= ZWP_TEXT_INPUT_V4_CONTENT_HINT_LOWERCASE;
+ if (hints & Qt::ImhDialableCharactersOnly)
+ purpose = ZWP_TEXT_INPUT_V4_CONTENT_PURPOSE_PHONE;
+ if (hints & Qt::ImhEmailCharactersOnly)
+ purpose = ZWP_TEXT_INPUT_V4_CONTENT_PURPOSE_EMAIL;
+ if (hints & Qt::ImhUrlCharactersOnly)
+ purpose = ZWP_TEXT_INPUT_V4_CONTENT_PURPOSE_URL;
+ if (hints & Qt::ImhLatinOnly)
+ hint |= ZWP_TEXT_INPUT_V4_CONTENT_HINT_LATIN;
+
return QWaylandInputMethodContentType{hint, purpose};
}
@@ -273,6 +312,44 @@ int QWaylandInputMethodEventBuilder::indexFromWayland(const QString &text, int l
}
}
+int QWaylandInputMethodEventBuilder::trimmedIndexFromWayland(const QString &text, int length, int base)
+{
+ if (length == 0)
+ return base;
+
+ if (length < 0) {
+ const QByteArray &utf8 = QStringView{text}.left(base).toUtf8();
+ const int len = utf8.size();
+ const int start = len + length;
+ if (start <= 0)
+ return 0;
+
+ for (int i = 0; i < 4; i++) {
+ if (start + i >= len)
+ return base;
+
+ const unsigned char ch = utf8.at(start + i);
+ // check if current character is a utf8's initial character.
+ if (ch < 0x80 || ch > 0xbf)
+ return QString::fromUtf8(utf8.left(start + i)).length();
+ }
+ } else {
+ const QByteArray &utf8 = QStringView{text}.mid(base).toUtf8();
+ const int len = utf8.size();
+ const int start = length;
+ if (start >= len)
+ return base + QString::fromUtf8(utf8).length();
+
+ for (int i = 0; i < 4; i++) {
+ const unsigned char ch = utf8.at(start - i);
+ // check if current character is a utf8's initial character.
+ if (ch < 0x80 || ch > 0xbf)
+ return base + QString::fromUtf8(utf8.left(start - i)).length();
+ }
+ }
+ return -1;
+}
+
int QWaylandInputMethodEventBuilder::indexToWayland(const QString &text, int length, int base)
{
return QStringView{text}.mid(base, length).toUtf8().size();
diff --git a/src/shared/qwaylandinputmethodeventbuilder_p.h b/src/shared/qwaylandinputmethodeventbuilder_p.h
index 2499a563f..f362562fa 100644
--- a/src/shared/qwaylandinputmethodeventbuilder_p.h
+++ b/src/shared/qwaylandinputmethodeventbuilder_p.h
@@ -63,6 +63,8 @@ public:
static int indexFromWayland(const QString &text, int length, int base = 0);
static int indexToWayland(const QString &text, int length, int base = 0);
+
+ static int trimmedIndexFromWayland(const QString &text, int length, int base = 0);
private:
QPair<int, int> replacementForDeleteSurrounding();
@@ -76,10 +78,11 @@ private:
};
struct QWaylandInputMethodContentType {
- uint32_t hint;
- uint32_t purpose;
+ uint32_t hint = 0;
+ uint32_t purpose = 0;
static QWaylandInputMethodContentType convert(Qt::InputMethodHints hints);
+ static QWaylandInputMethodContentType convertV4(Qt::InputMethodHints hints);
};