Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwasmkeytranslator.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
5#include "qwasmevent.h"
6
7#include <QtCore/private/qmakearray_p.h>
8#include <QtCore/qglobal.h>
9#include <QtCore/qobject.h>
10
11#include <algorithm>
12
14
15namespace {
17{
18 static constexpr char StringTerminator = '\0';
19
20 const char *web;
21 unsigned int qt;
22
23 constexpr bool operator<=(const WebKb2QtData &that) const noexcept
24 {
25 return !(strcmp(that) > 0);
26 }
27
28 bool operator<(const WebKb2QtData &that) const noexcept { return ::strcmp(web, that.web) < 0; }
29
30 constexpr bool operator==(const WebKb2QtData &that) const noexcept { return strcmp(that) == 0; }
31
32 constexpr int strcmp(const WebKb2QtData &that, const int i = 0) const
33 {
34 return web[i] == StringTerminator && that.web[i] == StringTerminator ? 0
35 : web[i] == StringTerminator ? -1
36 : that.web[i] == StringTerminator ? 1
37 : web[i] < that.web[i] ? -1
38 : web[i] > that.web[i] ? 1
39 : strcmp(that, i + 1);
40 }
41};
42
43template<unsigned int Qt, char... WebChar>
44struct Web2Qt
45{
46 static constexpr const char storage[sizeof...(WebChar) + 1] = { WebChar..., '\0' };
48 static constexpr Type data() noexcept { return Type{ storage, Qt }; }
49};
50
51template<unsigned int Qt, char... WebChar>
52constexpr char Web2Qt<Qt, WebChar...>::storage[];
53
54static constexpr const auto WebToQtKeyCodeMappings = qMakeArray(
55 QSortedData<Web2Qt<Qt::Key_Alt, 'A', 'l', 't', 'L', 'e', 'f', 't'>,
56 Web2Qt<Qt::Key_Alt, 'A', 'l', 't'>,
57 Web2Qt<Qt::Key_AltGr, 'A', 'l', 't', 'R', 'i', 'g', 'h', 't'>,
58 Web2Qt<Qt::Key_Apostrophe, 'Q', 'u', 'o', 't', 'e'>,
59 Web2Qt<Qt::Key_Backspace, 'B', 'a', 'c', 'k', 's', 'p', 'a', 'c', 'e'>,
60 Web2Qt<Qt::Key_CapsLock, 'C', 'a', 'p', 's', 'L', 'o', 'c', 'k'>,
61 Web2Qt<Qt::Key_Control, 'C', 'o', 'n', 't', 'r', 'o', 'l'>,
62 Web2Qt<Qt::Key_Delete, 'D', 'e', 'l', 'e', 't', 'e'>,
63 Web2Qt<Qt::Key_Down, 'A', 'r', 'r', 'o', 'w', 'D', 'o', 'w', 'n'>,
64 Web2Qt<Qt::Key_Escape, 'E', 's', 'c', 'a', 'p', 'e'>,
65 Web2Qt<Qt::Key_F1, 'F', '1'>, Web2Qt<Qt::Key_F2, 'F', '2'>,
66 Web2Qt<Qt::Key_F11, 'F', '1', '1'>, Web2Qt<Qt::Key_F12, 'F', '1', '2'>,
67 Web2Qt<Qt::Key_F13, 'F', '1', '3'>, Web2Qt<Qt::Key_F14, 'F', '1', '4'>,
68 Web2Qt<Qt::Key_F15, 'F', '1', '5'>, Web2Qt<Qt::Key_F16, 'F', '1', '6'>,
69 Web2Qt<Qt::Key_F17, 'F', '1', '7'>, Web2Qt<Qt::Key_F18, 'F', '1', '8'>,
70 Web2Qt<Qt::Key_F19, 'F', '1', '9'>, Web2Qt<Qt::Key_F20, 'F', '2', '0'>,
71 Web2Qt<Qt::Key_F21, 'F', '2', '1'>, Web2Qt<Qt::Key_F22, 'F', '2', '2'>,
72 Web2Qt<Qt::Key_F23, 'F', '2', '3'>,
73 Web2Qt<Qt::Key_F3, 'F', '3'>, Web2Qt<Qt::Key_F4, 'F', '4'>,
74 Web2Qt<Qt::Key_F5, 'F', '5'>, Web2Qt<Qt::Key_F6, 'F', '6'>,
75 Web2Qt<Qt::Key_F7, 'F', '7'>, Web2Qt<Qt::Key_F8, 'F', '8'>,
76 Web2Qt<Qt::Key_F9, 'F', '9'>, Web2Qt<Qt::Key_F10, 'F', '1', '0'>,
77 Web2Qt<Qt::Key_Help, 'H', 'e', 'l', 'p'>,
78 Web2Qt<Qt::Key_Home, 'H', 'o', 'm', 'e'>, Web2Qt<Qt::Key_End, 'E', 'n', 'd'>,
79 Web2Qt<Qt::Key_Insert, 'I', 'n', 's', 'e', 'r', 't'>,
80 Web2Qt<Qt::Key_Left, 'A', 'r', 'r', 'o', 'w', 'L', 'e', 'f', 't'>,
81 Web2Qt<Qt::Key_Meta, 'M', 'e', 't', 'a'>, Web2Qt<Qt::Key_Meta, 'O', 'S'>,
82 Web2Qt<Qt::Key_Menu, 'C', 'o', 'n', 't', 'e', 'x', 't', 'M', 'e', 'n', 'u'>,
83 Web2Qt<Qt::Key_NumLock, 'N', 'u', 'm', 'L', 'o', 'c', 'k'>,
84 Web2Qt<Qt::Key_PageDown, 'P', 'a', 'g', 'e', 'D', 'o', 'w', 'n'>,
85 Web2Qt<Qt::Key_PageUp, 'P', 'a', 'g', 'e', 'U', 'p'>,
86 Web2Qt<Qt::Key_Paste, 'P', 'a', 's', 't', 'e'>,
87 Web2Qt<Qt::Key_Pause, 'C', 'l', 'e', 'a', 'r'>,
88 Web2Qt<Qt::Key_Pause, 'P', 'a', 'u', 's', 'e'>,
89 Web2Qt<Qt::Key_QuoteLeft, 'B', 'a', 'c', 'k', 'q', 'u', 'o', 't', 'e'>,
90 Web2Qt<Qt::Key_QuoteLeft, 'I', 'n', 't', 'l', 'B', 'a', 'c', 'k', 's', 'l', 'a', 's', 'h'>,
91 Web2Qt<Qt::Key_Return, 'E', 'n', 't', 'e', 'r'>,
92 Web2Qt<Qt::Key_Right, 'A', 'r', 'r', 'o', 'w', 'R', 'i', 'g', 'h', 't'>,
93 Web2Qt<Qt::Key_ScrollLock, 'S', 'c', 'r', 'o', 'l', 'l', 'L', 'o', 'c', 'k'>,
94 Web2Qt<Qt::Key_Shift, 'S', 'h', 'i', 'f', 't'>,
95 Web2Qt<Qt::Key_Tab, 'T', 'a', 'b'>,
96 Web2Qt<Qt::Key_Up, 'A', 'r', 'r', 'o', 'w', 'U', 'p'>,
97 Web2Qt<Qt::Key_yen, 'I', 'n', 't', 'l', 'Y', 'e', 'n'>>::Data{});
98
99static constexpr const auto DiacriticalCharsKeyToTextLowercase = qMakeArray(
101 Web2Qt<Qt::Key_Aacute, '\xc3', '\xa1'>,
102 Web2Qt<Qt::Key_Acircumflex, '\xc3', '\xa2'>,
103 Web2Qt<Qt::Key_Adiaeresis, '\xc3', '\xa4'>,
104 Web2Qt<Qt::Key_AE, '\xc3', '\xa6'>,
105 Web2Qt<Qt::Key_Agrave, '\xc3', '\xa0'>,
106 Web2Qt<Qt::Key_Aring, '\xc3', '\xa5'>,
107 Web2Qt<Qt::Key_Atilde, '\xc3', '\xa3'>,
108 Web2Qt<Qt::Key_Ccedilla, '\xc3', '\xa7'>,
109 Web2Qt<Qt::Key_Eacute, '\xc3', '\xa9'>,
110 Web2Qt<Qt::Key_Ecircumflex, '\xc3', '\xaa'>,
111 Web2Qt<Qt::Key_Ediaeresis, '\xc3', '\xab'>,
112 Web2Qt<Qt::Key_Egrave, '\xc3', '\xa8'>,
113 Web2Qt<Qt::Key_Iacute, '\xc3', '\xad'>,
114 Web2Qt<Qt::Key_Icircumflex, '\xc3', '\xae'>,
115 Web2Qt<Qt::Key_Idiaeresis, '\xc3', '\xaf'>,
116 Web2Qt<Qt::Key_Igrave, '\xc3', '\xac'>,
117 Web2Qt<Qt::Key_Ntilde, '\xc3', '\xb1'>,
118 Web2Qt<Qt::Key_Oacute, '\xc3', '\xb3'>,
119 Web2Qt<Qt::Key_Ocircumflex, '\xc3', '\xb4'>,
120 Web2Qt<Qt::Key_Odiaeresis, '\xc3', '\xb6'>,
121 Web2Qt<Qt::Key_Ograve, '\xc3', '\xb2'>,
122 Web2Qt<Qt::Key_Ooblique, '\xc3', '\xb8'>,
123 Web2Qt<Qt::Key_Otilde, '\xc3', '\xb5'>,
124 Web2Qt<Qt::Key_Uacute, '\xc3', '\xba'>,
125 Web2Qt<Qt::Key_Ucircumflex, '\xc3', '\xbb'>,
126 Web2Qt<Qt::Key_Udiaeresis, '\xc3', '\xbc'>,
127 Web2Qt<Qt::Key_Ugrave, '\xc3', '\xb9'>,
128 Web2Qt<Qt::Key_Yacute, '\xc3', '\xbd'>,
129 Web2Qt<Qt::Key_ydiaeresis, '\xc3', '\xbf'>>::Data{});
130
131static constexpr const auto DiacriticalCharsKeyToTextUppercase = qMakeArray(
133 Web2Qt<Qt::Key_Aacute, '\xc3', '\x81'>,
134 Web2Qt<Qt::Key_Acircumflex, '\xc3', '\x82'>,
135 Web2Qt<Qt::Key_Adiaeresis, '\xc3', '\x84'>,
136 Web2Qt<Qt::Key_AE, '\xc3', '\x86'>,
137 Web2Qt<Qt::Key_Agrave, '\xc3', '\x80'>,
138 Web2Qt<Qt::Key_Aring, '\xc3', '\x85'>,
139 Web2Qt<Qt::Key_Atilde, '\xc3', '\x83'>,
140 Web2Qt<Qt::Key_Ccedilla, '\xc3', '\x87'>,
141 Web2Qt<Qt::Key_Eacute, '\xc3', '\x89'>,
142 Web2Qt<Qt::Key_Ecircumflex, '\xc3', '\x8a'>,
143 Web2Qt<Qt::Key_Ediaeresis, '\xc3', '\x8b'>,
144 Web2Qt<Qt::Key_Egrave, '\xc3', '\x88'>,
145 Web2Qt<Qt::Key_Iacute, '\xc3', '\x8d'>,
146 Web2Qt<Qt::Key_Icircumflex, '\xc3', '\x8e'>,
147 Web2Qt<Qt::Key_Idiaeresis, '\xc3', '\x8f'>,
148 Web2Qt<Qt::Key_Igrave, '\xc3', '\x8c'>,
149 Web2Qt<Qt::Key_Ntilde, '\xc3', '\x91'>,
150 Web2Qt<Qt::Key_Oacute, '\xc3', '\x93'>,
151 Web2Qt<Qt::Key_Ocircumflex, '\xc3', '\x94'>,
152 Web2Qt<Qt::Key_Odiaeresis, '\xc3', '\x96'>,
153 Web2Qt<Qt::Key_Ograve, '\xc3', '\x92'>,
154 Web2Qt<Qt::Key_Ooblique, '\xc3', '\x98'>,
155 Web2Qt<Qt::Key_Otilde, '\xc3', '\x95'>,
156 Web2Qt<Qt::Key_Uacute, '\xc3', '\x9a'>,
157 Web2Qt<Qt::Key_Ucircumflex, '\xc3', '\x9b'>,
158 Web2Qt<Qt::Key_Udiaeresis, '\xc3', '\x9c'>,
159 Web2Qt<Qt::Key_Ugrave, '\xc3', '\x99'>,
160 Web2Qt<Qt::Key_Yacute, '\xc3', '\x9d'>,
161 Web2Qt<Qt::Key_ydiaeresis, '\xc5', '\xb8'>>::Data{});
162
163static_assert(DiacriticalCharsKeyToTextLowercase.size()
164 == DiacriticalCharsKeyToTextUppercase.size(),
165 "Add the new key to both arrays");
166
168{
170};
171
173 // ~
177};
200
201static Qt::Key find_impl(const KeyMapping *first, const KeyMapping *last, Qt::Key key) noexcept
202{
203 while (first != last) {
204 if (first->from == key)
205 return first->to;
206 ++first;
207 }
208 return Qt::Key_unknown;
209}
210
211template<size_t N>
212static Qt::Key find(const KeyMapping (&map)[N], Qt::Key key) noexcept
213{
214 return find_impl(map, map + N, key);
215}
216
218{
219 switch (deadKey) {
221 return find(graveKeyTable, accentBaseKey);
223 return find(acuteKeyTable, accentBaseKey);
225 return find(tildeKeyTable, accentBaseKey);
227 return find(diaeresisKeyTable, accentBaseKey);
229 return find(circumflexKeyTable, accentBaseKey);
230 default:
231 return Qt::Key_unknown;
232 };
233}
234
235template<class T>
236std::optional<QString> findKeyTextByKeyId(const T &mappingArray, Qt::Key qtKey)
237{
238 const auto it = std::find_if(mappingArray.cbegin(), mappingArray.cend(),
239 [qtKey](const WebKb2QtData &data) { return data.qt == qtKey; });
240 return it != mappingArray.cend() ? it->web : std::optional<QString>();
241}
242} // namespace
243
244std::optional<Qt::Key> QWasmKeyTranslator::mapWebKeyTextToQtKey(const char *toFind)
245{
246 const WebKb2QtData searchKey{ toFind, 0 };
247 const auto it = std::lower_bound(WebToQtKeyCodeMappings.cbegin(), WebToQtKeyCodeMappings.cend(),
248 searchKey);
249 return it != WebToQtKeyCodeMappings.cend() && searchKey == *it ? static_cast<Qt::Key>(it->qt)
250 : std::optional<Qt::Key>();
251}
252
254
256
258{
259 if (event->deadKey) {
260 m_activeDeadKey = event->key;
261 } else if (m_activeDeadKey != Qt::Key_unknown
262 && (((m_keyModifiedByDeadKeyOnPress == Qt::Key_unknown
263 && event->type == EventType::KeyDown))
264 || (m_keyModifiedByDeadKeyOnPress == event->key
265 && event->type == EventType::KeyUp))) {
266 const Qt::Key baseKey = event->key;
267 const Qt::Key translatedKey = translateBaseKeyUsingDeadKey(baseKey, m_activeDeadKey);
268 if (translatedKey != Qt::Key_unknown) {
269 event->key = translatedKey;
270
271 auto foundText = event->modifiers.testFlag(Qt::ShiftModifier)
272 ? findKeyTextByKeyId(DiacriticalCharsKeyToTextUppercase, event->key)
273 : findKeyTextByKeyId(DiacriticalCharsKeyToTextLowercase, event->key);
274 Q_ASSERT(foundText.has_value());
275 event->text = foundText->size() == 1 ? *foundText : QString();
276 }
277
278 if (!event->text.isEmpty()) {
279 if (event->type == EventType::KeyDown) {
280 // Assume the first keypress with an active dead key is treated as modified,
281 // regardless of whether it has actually been modified or not. Take into account
282 // only events that produce actual key text.
283 if (!event->text.isEmpty())
284 m_keyModifiedByDeadKeyOnPress = baseKey;
285 } else {
287 Q_ASSERT(m_keyModifiedByDeadKeyOnPress == baseKey);
288 m_keyModifiedByDeadKeyOnPress = Qt::Key_unknown;
289 m_activeDeadKey = Qt::Key_unknown;
290 }
291 }
292 }
293}
294
const_iterator cend() const noexcept
Definition qset.h:142
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
void applyDeadKeyTranslations(KeyEvent *event)
QMap< QString, QString > map
[6]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
std::optional< QString > findKeyTextByKeyId(const T &mappingArray, Qt::Key qtKey)
constexpr KeyMapping circumflexKeyTable[]
static Qt::Key find(const KeyMapping(&map)[N], Qt::Key key) noexcept
constexpr KeyMapping graveKeyTable[]
static constexpr const auto DiacriticalCharsKeyToTextLowercase
static constexpr const auto WebToQtKeyCodeMappings
constexpr KeyMapping acuteKeyTable[]
static Qt::Key find_impl(const KeyMapping *first, const KeyMapping *last, Qt::Key key) noexcept
static constexpr const auto DiacriticalCharsKeyToTextUppercase
Qt::Key translateBaseKeyUsingDeadKey(Qt::Key accentBaseKey, Qt::Key deadKey)
constexpr KeyMapping diaeresisKeyTable[]
constexpr KeyMapping tildeKeyTable[]
std::optional< Qt::Key > mapWebKeyTextToQtKey(const char *toFind)
Definition qcompare.h:63
@ Key_ydiaeresis
Definition qnamespace.h:654
@ Key_Escape
Definition qnamespace.h:663
@ Key_AltGr
Definition qnamespace.h:739
@ Key_F20
Definition qnamespace.h:709
@ Key_O
Definition qnamespace.h:561
@ Key_Tab
Definition qnamespace.h:664
@ Key_Iacute
Definition qnamespace.h:634
@ Key_Eacute
Definition qnamespace.h:630
@ Key_Shift
Definition qnamespace.h:683
@ Key_Return
Definition qnamespace.h:667
@ Key_Otilde
Definition qnamespace.h:642
@ Key_Ucircumflex
Definition qnamespace.h:648
@ Key_Ediaeresis
Definition qnamespace.h:632
@ Key_QuoteLeft
Definition qnamespace.h:578
@ Key_Right
Definition qnamespace.h:679
@ Key_F7
Definition qnamespace.h:696
@ Key_PageUp
Definition qnamespace.h:681
@ Key_Aring
Definition qnamespace.h:626
@ Key_F22
Definition qnamespace.h:711
@ Key_F23
Definition qnamespace.h:712
@ Key_Aacute
Definition qnamespace.h:622
@ Key_Acircumflex
Definition qnamespace.h:623
@ Key_I
Definition qnamespace.h:555
@ Key_F17
Definition qnamespace.h:706
@ Key_F21
Definition qnamespace.h:710
@ Key_Odiaeresis
Definition qnamespace.h:643
@ Key_Ograve
Definition qnamespace.h:639
@ Key_Agrave
Definition qnamespace.h:621
@ Key_U
Definition qnamespace.h:567
@ Key_Dead_Circumflex
Definition qnamespace.h:797
@ Key_Backspace
Definition qnamespace.h:666
@ Key_F6
Definition qnamespace.h:695
@ Key_Insert
Definition qnamespace.h:669
@ Key_Left
Definition qnamespace.h:677
@ Key_AE
Definition qnamespace.h:627
@ Key_Ecircumflex
Definition qnamespace.h:631
@ Key_A
Definition qnamespace.h:547
@ Key_Control
Definition qnamespace.h:684
@ Key_F9
Definition qnamespace.h:698
@ Key_Uacute
Definition qnamespace.h:647
@ Key_Alt
Definition qnamespace.h:686
@ Key_Adiaeresis
Definition qnamespace.h:625
@ Key_Idiaeresis
Definition qnamespace.h:636
@ Key_Ocircumflex
Definition qnamespace.h:641
@ Key_F11
Definition qnamespace.h:700
@ Key_Pause
Definition qnamespace.h:671
@ Key_Up
Definition qnamespace.h:678
@ Key_Atilde
Definition qnamespace.h:624
@ Key_Ccedilla
Definition qnamespace.h:628
@ Key_F3
Definition qnamespace.h:692
@ Key_Ooblique
Definition qnamespace.h:645
@ Key_Dead_Grave
Definition qnamespace.h:795
@ Key_F16
Definition qnamespace.h:705
@ Key_Down
Definition qnamespace.h:680
@ Key_F18
Definition qnamespace.h:707
@ Key_Dead_Acute
Definition qnamespace.h:796
@ Key_F4
Definition qnamespace.h:693
@ Key_F2
Definition qnamespace.h:691
@ Key_Delete
Definition qnamespace.h:670
@ Key_NumLock
Definition qnamespace.h:688
@ Key_Meta
Definition qnamespace.h:685
@ Key_Egrave
Definition qnamespace.h:629
@ Key_Help
Definition qnamespace.h:730
@ Key_ScrollLock
Definition qnamespace.h:689
@ Key_F1
Definition qnamespace.h:690
@ Key_F14
Definition qnamespace.h:703
@ Key_Menu
Definition qnamespace.h:727
@ Key_PageDown
Definition qnamespace.h:682
@ Key_yen
Definition qnamespace.h:590
@ Key_Ugrave
Definition qnamespace.h:646
@ Key_Ntilde
Definition qnamespace.h:638
@ Key_F19
Definition qnamespace.h:708
@ Key_Icircumflex
Definition qnamespace.h:635
@ Key_F5
Definition qnamespace.h:694
@ Key_Home
Definition qnamespace.h:675
@ Key_F10
Definition qnamespace.h:699
@ Key_N
Definition qnamespace.h:560
@ Key_F8
Definition qnamespace.h:697
@ Key_Yacute
Definition qnamespace.h:650
@ Key_F13
Definition qnamespace.h:702
@ Key_CapsLock
Definition qnamespace.h:687
@ Key_Y
Definition qnamespace.h:571
@ Key_Dead_Tilde
Definition qnamespace.h:798
@ Key_Paste
Definition qnamespace.h:936
@ Key_Oacute
Definition qnamespace.h:640
@ Key_E
Definition qnamespace.h:551
@ Key_Apostrophe
Definition qnamespace.h:521
@ Key_F12
Definition qnamespace.h:701
@ Key_unknown
@ Key_Udiaeresis
Definition qnamespace.h:649
@ Key_F15
Definition qnamespace.h:704
@ Key_End
Definition qnamespace.h:676
@ Key_Igrave
Definition qnamespace.h:633
@ Key_Dead_Diaeresis
Definition qnamespace.h:802
@ ShiftModifier
constexpr QtPrivate::ArrayType< ManualType, Types... > qMakeArray(Types &&... t) noexcept
GLuint64 key
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint first
struct _cl_event * event
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QString qtKey(CFStringRef cfkey)
QStorageInfo storage
[1]
static constexpr Type data() noexcept
bool operator<(const WebKb2QtData &that) const noexcept
constexpr int strcmp(const WebKb2QtData &that, const int i=0) const
constexpr bool operator==(const WebKb2QtData &that) const noexcept
constexpr bool operator<=(const WebKb2QtData &that) const noexcept