diff options
author | Inho Lee <inho.lee@qt.io> | 2021-06-19 06:27:22 +0200 |
---|---|---|
committer | Inho Lee <inho.lee@qt.io> | 2021-11-19 10:33:31 +0100 |
commit | 0cec50bece2dcd69127f19c87a3062e4b13f3723 (patch) | |
tree | 8ec11248518b1edfede9538a07ee5e0b0aa5624e /src/shared | |
parent | 6f195a592b26ad8416a6f02d6bd7258ab3fadf65 (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.cpp | 149 | ||||
-rw-r--r-- | src/shared/qwaylandinputmethodeventbuilder_p.h | 7 |
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); }; |