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
qwasmevent.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qwasmevent.h"
5
7
8#include <QtCore/private/qmakearray_p.h>
9#include <QtCore/private/qstringiterator_p.h>
10#include <QtCore/qregularexpression.h>
11
13
14namespace {
15constexpr std::string_view WebDeadKeyValue = "Dead";
16
17bool isDeadKeyEvent(const char *key)
18{
19 return qstrncmp(key, WebDeadKeyValue.data(), WebDeadKeyValue.size()) == 0;
20}
21
22Qt::Key getKeyFromCode(const std::string &code)
23{
25 return *mapping;
26
27 static QRegularExpression regex(QString(QStringLiteral(R"re((?:Key|Digit)(\w))re")));
28 const auto codeQString = QString::fromStdString(code);
29 const auto match = regex.match(codeQString);
30
31 if (!match.hasMatch())
32 return Qt::Key_unknown;
33
34 constexpr size_t CharacterIndex = 1;
35 return static_cast<Qt::Key>(match.capturedView(CharacterIndex).at(0).toLatin1());
36}
37
38Qt::Key webKeyToQtKey(const std::string &code, const std::string &key, bool isDeadKey,
39 QFlags<Qt::KeyboardModifier> modifiers)
40{
41 if (isDeadKey) {
42 auto mapped = getKeyFromCode(code);
43 switch (mapped) {
44 case Qt::Key_U:
46 case Qt::Key_E:
47 return Qt::Key_Dead_Acute;
48 case Qt::Key_I:
50 case Qt::Key_N:
51 return Qt::Key_Dead_Tilde;
54 case Qt::Key_6:
60 return Qt::Key_Dead_Tilde;
61 default:
62 return Qt::Key_unknown;
63 }
64 } else if (auto mapping = QWasmKeyTranslator::mapWebKeyTextToQtKey(key.c_str())) {
65 return *mapping;
66 }
67
68 // cast to unicode key
69 QString str = QString::fromUtf8(key.c_str()).toUpper();
70 if (str.length() > 1)
71 return Qt::Key_unknown;
72
74 return static_cast<Qt::Key>(i.next(0));
75}
76} // namespace
77
79{
80template <>
81QFlags<Qt::KeyboardModifier> getForEvent<EmscriptenKeyboardEvent>(
82 const EmscriptenKeyboardEvent& event)
83{
85 (event.location == DOM_KEY_LOCATION_NUMPAD ? Qt::KeypadModifier : Qt::NoModifier);
86}
87} // namespace KeyboardModifier
88
89Event::Event(EventType type, emscripten::val webEvent)
90 : webEvent(webEvent), type(type)
91{
92}
93
94Event::~Event() = default;
95
96Event::Event(const Event &other) = default;
97
98Event::Event(Event &&other) = default;
99
100Event &Event::operator=(const Event &other) = default;
101
102Event &Event::operator=(Event &&other) = default;
103
105{
106 const auto code = event["code"].as<std::string>();
107 const auto webKey = event["key"].as<std::string>();
108 deadKey = isDeadKeyEvent(webKey.c_str());
109
111 key = webKeyToQtKey(code, webKey, deadKey, modifiers);
112
113 text = QString::fromUtf8(webKey);
114 if (text.size() > 1)
115 text.clear();
116
117 if (key == Qt::Key_Tab)
118 text = "\t";
119}
120
121KeyEvent::~KeyEvent() = default;
122
123KeyEvent::KeyEvent(const KeyEvent &other) = default;
124
126
127KeyEvent &KeyEvent::operator=(const KeyEvent &other) = default;
128
130
131std::optional<KeyEvent> KeyEvent::fromWebWithDeadKeyTranslation(emscripten::val event,
132 QWasmDeadKeySupport *deadKeySupport)
133{
134 const auto eventType = ([&event]() -> std::optional<EventType> {
135 const auto eventTypeString = event["type"].as<std::string>();
136
137 if (eventTypeString == "keydown")
138 return EventType::KeyDown;
139 else if (eventTypeString == "keyup")
140 return EventType::KeyUp;
141 return std::nullopt;
142 })();
143 if (!eventType)
144 return std::nullopt;
145
146 auto result = KeyEvent(*eventType, event);
147 deadKeySupport->applyDeadKeyTranslations(&result);
148
149 return result;
150}
151
153{
154 mouseButton = MouseEvent::buttonFromWeb(event["button"].as<int>());
155 mouseButtons = MouseEvent::buttonsFromWeb(event["buttons"].as<unsigned short>());
156 // The current button state (event.buttons) may be out of sync for some PointerDown
157 // events where the "down" state is very brief, for example taps on Apple trackpads.
158 // Qt expects that the current button state is in sync with the event, so we sync
159 // it up here.
162 localPoint = QPointF(event["offsetX"].as<qreal>(), event["offsetY"].as<qreal>());
163 pointInPage = QPointF(event["pageX"].as<qreal>(), event["pageY"].as<qreal>());
164 pointInViewport = QPointF(event["clientX"].as<qreal>(), event["clientY"].as<qreal>());
166}
167
168MouseEvent::~MouseEvent() = default;
169
170MouseEvent::MouseEvent(const MouseEvent &other) = default;
171
173
175
177
179{
180 pointerId = event["pointerId"].as<int>();
181 pointerType = ([type = event["pointerType"].as<std::string>()]() {
182 if (type == "mouse")
183 return PointerType::Mouse;
184 if (type == "touch")
185 return PointerType::Touch;
186 if (type == "pen")
187 return PointerType::Pen;
188 return PointerType::Other;
189 })();
190 width = event["width"].as<qreal>();
191 height = event["height"].as<qreal>();
192 pressure = event["pressure"].as<qreal>();
193 tiltX = event["tiltX"].as<qreal>();
194 tiltY = event["tiltY"].as<qreal>();
195 tangentialPressure = event["tangentialPressure"].as<qreal>();
196 twist = event["twist"].as<qreal>();
197 isPrimary = event["isPrimary"].as<bool>();
198}
199
201
203
205
207
209
210std::optional<PointerEvent> PointerEvent::fromWeb(emscripten::val event)
211{
212 const auto eventType = ([&event]() -> std::optional<EventType> {
213 const auto eventTypeString = event["type"].as<std::string>();
214
215 if (eventTypeString == "pointermove")
217 else if (eventTypeString == "pointerup")
219 else if (eventTypeString == "pointerdown")
221 else if (eventTypeString == "pointerenter")
223 else if (eventTypeString == "pointerleave")
225 return std::nullopt;
226 })();
227 if (!eventType)
228 return std::nullopt;
229
230 return PointerEvent(*eventType, event);
231}
232
234 : MouseEvent(type, event), dataTransfer(event["dataTransfer"]), targetWindow(window)
235{
236 dropAction = ([event]() {
237 const std::string effect = event["dataTransfer"]["dropEffect"].as<std::string>();
238
239 if (effect == "copy")
240 return Qt::CopyAction;
241 else if (effect == "move")
242 return Qt::MoveAction;
243 else if (effect == "link")
244 return Qt::LinkAction;
245 return Qt::IgnoreAction;
246 })();
247}
248
249DragEvent::~DragEvent() = default;
250
251DragEvent::DragEvent(const DragEvent &other) = default;
252
254
256
258
259std::optional<DragEvent> DragEvent::fromWeb(emscripten::val event, QWindow *targetWindow)
260{
261 const auto eventType = ([&event]() -> std::optional<EventType> {
262 const auto eventTypeString = event["type"].as<std::string>();
263
264 if (eventTypeString == "dragend")
265 return EventType::DragEnd;
266 if (eventTypeString == "dragover")
267 return EventType::DragOver;
268 if (eventTypeString == "dragstart")
270 if (eventTypeString == "drop")
271 return EventType::Drop;
272 return std::nullopt;
273 })();
274 if (!eventType)
275 return std::nullopt;
276 return DragEvent(*eventType, event, targetWindow);
277}
278
280{
281 Q_ASSERT_X(type == EventType::DragStart, Q_FUNC_INFO, "Only supported for DragStart");
282 webEvent.call<void>("preventDefault");
283}
284
286{
287 Q_ASSERT_X(type == EventType::DragOver, Q_FUNC_INFO, "Only supported for DragOver");
288 webEvent.call<void>("preventDefault");
289}
290
292{
293 Q_ASSERT_X(type == EventType::Drop, Q_FUNC_INFO, "Only supported for Drop");
294 webEvent.call<void>("preventDefault");
295}
296
298{
299 deltaMode = ([event]() {
300 const int deltaMode = event["deltaMode"].as<int>();
301 const auto jsWheelEventType = emscripten::val::global("WheelEvent");
302 if (deltaMode == jsWheelEventType["DOM_DELTA_PIXEL"].as<int>())
303 return DeltaMode::Pixel;
304 else if (deltaMode == jsWheelEventType["DOM_DELTA_LINE"].as<int>())
305 return DeltaMode::Line;
306 return DeltaMode::Page;
307 })();
308
309 delta = QPointF(event["deltaX"].as<qreal>(), event["deltaY"].as<qreal>());
310
311 webkitDirectionInvertedFromDevice = event["webkitDirectionInvertedFromDevice"].as<bool>();
312}
313
314WheelEvent::~WheelEvent() = default;
315
316WheelEvent::WheelEvent(const WheelEvent &other) = default;
317
319
321
323
324std::optional<WheelEvent> WheelEvent::fromWeb(emscripten::val event)
325{
326 const auto eventType = ([&event]() -> std::optional<EventType> {
327 const auto eventTypeString = event["type"].as<std::string>();
328
329 if (eventTypeString == "wheel")
330 return EventType::Wheel;
331 return std::nullopt;
332 })();
333 if (!eventType)
334 return std::nullopt;
335 return WheelEvent(*eventType, event);
336}
337
\inmodule QtCore\reentrant
Definition qpoint.h:217
\inmodule QtCore \reentrant
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromStdString(const std::string &s)
Definition qstring.h:1447
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
qsizetype length() const noexcept
Returns the number of characters in this string.
Definition qstring.h:191
void applyDeadKeyTranslations(KeyEvent *event)
\inmodule QtGui
Definition qwindow.h:63
EGLImageKHR int int EGLuint64KHR * modifiers
QString str
[2]
QFlags< Qt::KeyboardModifier > getForEvent< EmscriptenKeyboardEvent >(const EmscriptenKeyboardEvent &event)
QFlags< Qt::KeyboardModifier > getForEvent(const Event &event)
Definition qwasmevent.h:115
Combined button and popup list for selecting options.
constexpr std::string_view WebDeadKeyValue
bool isDeadKeyEvent(const char *key)
Qt::Key getKeyFromCode(const std::string &code)
std::optional< Qt::Key > mapWebKeyTextToQtKey(const char *toFind)
@ Key_Tab
Definition qnamespace.h:664
@ Key_QuoteLeft
Definition qnamespace.h:578
@ Key_I
Definition qnamespace.h:555
@ Key_U
Definition qnamespace.h:567
@ Key_Dead_Circumflex
Definition qnamespace.h:797
@ Key_Dead_Grave
Definition qnamespace.h:795
@ Key_Dead_Acute
Definition qnamespace.h:796
@ Key_6
Definition qnamespace.h:536
@ Key_AsciiTilde
Definition qnamespace.h:582
@ Key_N
Definition qnamespace.h:560
@ Key_Dead_Tilde
Definition qnamespace.h:798
@ Key_E
Definition qnamespace.h:551
@ Key_Apostrophe
Definition qnamespace.h:521
@ Key_unknown
@ Key_Dead_Diaeresis
Definition qnamespace.h:802
@ ShiftModifier
@ KeypadModifier
@ NoModifier
@ CopyAction
@ IgnoreAction
@ MoveAction
@ LinkAction
int qstrncmp(const char *str1, const char *str2, size_t len)
#define Q_FUNC_INFO
GLuint64 key
GLint GLsizei GLsizei height
GLint GLsizei width
GLenum type
struct _cl_event * event
GLuint64EXT * result
[6]
GLenum GLenum GLenum GLenum mapping
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
#define QStringLiteral(str)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
double qreal
Definition qtypes.h:187
EventType
Definition qwasmevent.h:24
QSharedPointer< T > other(t)
[5]
QGraphicsOpacityEffect * effect
the effect attached to this item
aWidget window() -> setWindowTitle("New Window Title")
[2]
DragEvent & operator=(const DragEvent &other)
DragEvent(EventType type, emscripten::val webEvent, QWindow *targetQWindow)
void acceptDrop()
void acceptDragOver()
void cancelDragStart()
QWindow * targetWindow
Definition qwasmevent.h:250
static std::optional< DragEvent > fromWeb(emscripten::val webEvent, QWindow *targetQWindow)
Qt::DropAction dropAction
Definition qwasmevent.h:248
emscripten::val webEvent
Definition qwasmevent.h:135
Event & operator=(const Event &other)
Event(EventType type, emscripten::val webEvent)
KeyEvent & operator=(const KeyEvent &other)
bool deadKey
Definition qwasmevent.h:154
QString text
Definition qwasmevent.h:155
static std::optional< KeyEvent > fromWebWithDeadKeyTranslation(emscripten::val webEvent, QWasmDeadKeySupport *deadKeySupport)
KeyEvent(EventType type, emscripten::val webEvent)
static constexpr Qt::MouseButton buttonFromWeb(int webButton)
Definition qwasmevent.h:167
QPointF localPoint
Definition qwasmevent.h:202
QPointF pointInViewport
Definition qwasmevent.h:204
Qt::MouseButton mouseButton
Definition qwasmevent.h:205
static constexpr Qt::MouseButtons buttonsFromWeb(unsigned short webButtons)
Definition qwasmevent.h:180
Qt::MouseButtons mouseButtons
Definition qwasmevent.h:206
QPointF pointInPage
Definition qwasmevent.h:203
MouseEvent(EventType type, emscripten::val webEvent)
MouseEvent & operator=(const MouseEvent &other)
PointerType pointerType
Definition qwasmevent.h:221
PointerEvent(EventType type, emscripten::val webEvent)
static std::optional< PointerEvent > fromWeb(emscripten::val webEvent)
qreal tangentialPressure
Definition qwasmevent.h:226
PointerEvent & operator=(const PointerEvent &other)
static std::optional< WheelEvent > fromWeb(emscripten::val webEvent)
DeltaMode deltaMode
Definition qwasmevent.h:264
WheelEvent(EventType type, emscripten::val webEvent)
bool webkitDirectionInvertedFromDevice
Definition qwasmevent.h:265
WheelEvent & operator=(const WheelEvent &other)
QPointF delta
Definition qwasmevent.h:266