summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/wasm/qwasmeventtranslator.cpp')
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.cpp779
1 files changed, 578 insertions, 201 deletions
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
index cc48c15b64..f4ca49997a 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
@@ -31,6 +31,7 @@
#include "qwasmeventdispatcher.h"
#include "qwasmcompositor.h"
#include "qwasmintegration.h"
+#include "qwasmclipboard.h"
#include <QtGui/qevent.h>
#include <qpa/qwindowsysteminterface.h>
@@ -39,6 +40,9 @@
#include <QtCore/qobject.h>
#include <QtCore/qdeadlinetimer.h>
+#include <private/qmakearray_p.h>
+#include <QtCore/qnamespace.h>
+
#include <emscripten/bind.h>
#include <iostream>
@@ -46,70 +50,336 @@
QT_BEGIN_NAMESPACE
using namespace emscripten;
+typedef struct emkb2qt {
+ const char *em;
+ unsigned int qt;
+
+ constexpr bool operator <=(const emkb2qt &that) const noexcept
+ {
+ return !(strcmp(that) > 0);
+ }
+
+ bool operator <(const emkb2qt &that) const noexcept
+ {
+ return ::strcmp(em, that.em) < 0;
+ }
+ constexpr int strcmp(const emkb2qt &that, const int i = 0) const
+ {
+ return em[i] == 0 && that.em[i] == 0 ? 0
+ : em[i] == 0 ? -1
+ : that.em[i] == 0 ? 1
+ : em[i] < that.em[i] ? -1
+ : em[i] > that.em[i] ? 1
+ : strcmp(that, i + 1);
+ }
+} emkb2qt_t;
+
+template<unsigned int Qt, char ... EmChar>
+struct Emkb2Qt
+{
+ static constexpr const char storage[sizeof ... (EmChar) + 1] = {EmChar..., '\0'};
+ using Type = emkb2qt_t;
+ static constexpr Type data() noexcept { return Type{storage, Qt}; }
+};
+
+template<unsigned int Qt, char ... EmChar> constexpr char Emkb2Qt<Qt, EmChar...>::storage[];
+
+static constexpr const auto KeyTbl = qMakeArray(
+ QSortedData<
+ Emkb2Qt< Qt::Key_Escape, 'E','s','c','a','p','e' >,
+ Emkb2Qt< Qt::Key_Tab, 'T','a','b' >,
+ Emkb2Qt< Qt::Key_Backspace, 'B','a','c','k','s','p','a','c','e' >,
+ Emkb2Qt< Qt::Key_Return, 'E','n','t','e','r' >,
+ Emkb2Qt< Qt::Key_Insert, 'I','n','s','e','r','t' >,
+ Emkb2Qt< Qt::Key_Delete, 'D','e','l','e','t','e' >,
+ Emkb2Qt< Qt::Key_Pause, 'P','a','u','s','e' >,
+ Emkb2Qt< Qt::Key_Pause, 'C','l','e','a','r' >,
+ Emkb2Qt< Qt::Key_Home, 'H','o','m','e' >,
+ Emkb2Qt< Qt::Key_End, 'E','n','d' >,
+ Emkb2Qt< Qt::Key_Left, 'A','r','r','o','w','L','e','f','t' >,
+ Emkb2Qt< Qt::Key_Up, 'A','r','r','o','w','U','p' >,
+ Emkb2Qt< Qt::Key_Right, 'A','r','r','o','w','R','i','g','h','t' >,
+ Emkb2Qt< Qt::Key_Down, 'A','r','r','o','w','D','o','w','n' >,
+ Emkb2Qt< Qt::Key_PageUp, 'P','a','g','e','U','p' >,
+ Emkb2Qt< Qt::Key_PageDown, 'P','a','g','e','D','o','w','n' >,
+ Emkb2Qt< Qt::Key_Shift, 'S','h','i','f','t' >,
+ Emkb2Qt< Qt::Key_Control, 'C','o','n','t','r','o','l' >,
+ Emkb2Qt< Qt::Key_Meta, 'O','S'>,
+ Emkb2Qt< Qt::Key_Alt, 'A','l','t','L','e','f','t' >,
+ Emkb2Qt< Qt::Key_Alt, 'A','l','t' >,
+ Emkb2Qt< Qt::Key_CapsLock, 'C','a','p','s','L','o','c','k' >,
+ Emkb2Qt< Qt::Key_NumLock, 'N','u','m','L','o','c','k' >,
+ Emkb2Qt< Qt::Key_ScrollLock, 'S','c','r','o','l','l','L','o','c','k' >,
+ Emkb2Qt< Qt::Key_F1, 'F','1' >,
+ Emkb2Qt< Qt::Key_F2, 'F','2' >,
+ Emkb2Qt< Qt::Key_F3, 'F','3' >,
+ Emkb2Qt< Qt::Key_F4, 'F','4' >,
+ Emkb2Qt< Qt::Key_F5, 'F','5' >,
+ Emkb2Qt< Qt::Key_F6, 'F','6' >,
+ Emkb2Qt< Qt::Key_F7, 'F','7' >,
+ Emkb2Qt< Qt::Key_F8, 'F','8' >,
+ Emkb2Qt< Qt::Key_F9, 'F','9' >,
+ Emkb2Qt< Qt::Key_F10, 'F','1','0' >,
+ Emkb2Qt< Qt::Key_F11, 'F','1','1' >,
+ Emkb2Qt< Qt::Key_F12, 'F','1','2' >,
+ Emkb2Qt< Qt::Key_F13, 'F','1','3' >,
+ Emkb2Qt< Qt::Key_F14, 'F','1','4' >,
+ Emkb2Qt< Qt::Key_F15, 'F','1','5' >,
+ Emkb2Qt< Qt::Key_F16, 'F','1','6' >,
+ Emkb2Qt< Qt::Key_F17, 'F','1','7' >,
+ Emkb2Qt< Qt::Key_F18, 'F','1','8' >,
+ Emkb2Qt< Qt::Key_F19, 'F','1','9' >,
+ Emkb2Qt< Qt::Key_F20, 'F','2','0' >,
+ Emkb2Qt< Qt::Key_F21, 'F','2','1' >,
+ Emkb2Qt< Qt::Key_F22, 'F','2','2' >,
+ Emkb2Qt< Qt::Key_F23, 'F','2','3' >,
+ Emkb2Qt< Qt::Key_Space, ' ' >,
+ Emkb2Qt< Qt::Key_Comma, ',' >,
+ Emkb2Qt< Qt::Key_Minus, '-' >,
+ Emkb2Qt< Qt::Key_Period, '.' >,
+ Emkb2Qt< Qt::Key_Slash, '/' >,
+ Emkb2Qt< Qt::Key_0, '0' >,
+ Emkb2Qt< Qt::Key_1, '1' >,
+ Emkb2Qt< Qt::Key_2, '2' >,
+ Emkb2Qt< Qt::Key_3, '3' >,
+ Emkb2Qt< Qt::Key_4, '4' >,
+ Emkb2Qt< Qt::Key_5, '5' >,
+ Emkb2Qt< Qt::Key_6, '6' >,
+ Emkb2Qt< Qt::Key_7, '7' >,
+ Emkb2Qt< Qt::Key_8, '8' >,
+ Emkb2Qt< Qt::Key_9, '9' >,
+ Emkb2Qt< Qt::Key_Semicolon, ';' >,
+ Emkb2Qt< Qt::Key_Equal, '=' >,
+ Emkb2Qt< Qt::Key_A, 'K','e','y','A' >,
+ Emkb2Qt< Qt::Key_B, 'K','e','y','B' >,
+ Emkb2Qt< Qt::Key_C, 'K','e','y','C' >,
+ Emkb2Qt< Qt::Key_D, 'K','e','y','D' >,
+ Emkb2Qt< Qt::Key_E, 'K','e','y','E' >,
+ Emkb2Qt< Qt::Key_F, 'K','e','y','F' >,
+ Emkb2Qt< Qt::Key_G, 'K','e','y','G' >,
+ Emkb2Qt< Qt::Key_H, 'K','e','y','H' >,
+ Emkb2Qt< Qt::Key_I, 'K','e','y','I' >,
+ Emkb2Qt< Qt::Key_J, 'K','e','y','J' >,
+ Emkb2Qt< Qt::Key_K, 'K','e','y','K' >,
+ Emkb2Qt< Qt::Key_L, 'K','e','y','L' >,
+ Emkb2Qt< Qt::Key_M, 'K','e','y','M' >,
+ Emkb2Qt< Qt::Key_N, 'K','e','y','N' >,
+ Emkb2Qt< Qt::Key_O, 'K','e','y','O' >,
+ Emkb2Qt< Qt::Key_P, 'K','e','y','P' >,
+ Emkb2Qt< Qt::Key_Q, 'K','e','y','Q' >,
+ Emkb2Qt< Qt::Key_R, 'K','e','y','R' >,
+ Emkb2Qt< Qt::Key_S, 'K','e','y','S' >,
+ Emkb2Qt< Qt::Key_T, 'K','e','y','T' >,
+ Emkb2Qt< Qt::Key_U, 'K','e','y','U' >,
+ Emkb2Qt< Qt::Key_V, 'K','e','y','V' >,
+ Emkb2Qt< Qt::Key_W, 'K','e','y','W' >,
+ Emkb2Qt< Qt::Key_X, 'K','e','y','X' >,
+ Emkb2Qt< Qt::Key_Y, 'K','e','y','Y' >,
+ Emkb2Qt< Qt::Key_Z, 'K','e','y','Z' >,
+ Emkb2Qt< Qt::Key_BracketLeft, '[' >,
+ Emkb2Qt< Qt::Key_Backslash, '\\' >,
+ Emkb2Qt< Qt::Key_BracketRight, ']' >,
+ Emkb2Qt< Qt::Key_Apostrophe, '\'' >,
+ Emkb2Qt< Qt::Key_QuoteLeft, 'B','a','c','k','q','u','o','t','e' >,
+ Emkb2Qt< Qt::Key_multiply, 'N','u','m','p','a','d','M','u','l','t','i','p','l','y' >,
+ Emkb2Qt< Qt::Key_Minus, 'N','u','m','p','a','d','S','u','b','t','r','a','c','t' >,
+ Emkb2Qt< Qt::Key_Period, 'N','u','m','p','a','d','D','e','c','i','m','a','l' >,
+ Emkb2Qt< Qt::Key_Plus, 'N','u','m','p','a','d','A','d','d' >,
+ Emkb2Qt< Qt::Key_division, 'N','u','m','p','a','d','D','i','v','i','d','e' >,
+ Emkb2Qt< Qt::Key_Equal, 'N','u','m','p','a','d','E','q','u','a','l' >,
+ Emkb2Qt< Qt::Key_0, 'N','u','m','p','a','d','0' >,
+ Emkb2Qt< Qt::Key_1, 'N','u','m','p','a','d','1' >,
+ Emkb2Qt< Qt::Key_2, 'N','u','m','p','a','d','2' >,
+ Emkb2Qt< Qt::Key_3, 'N','u','m','p','a','d','3' >,
+ Emkb2Qt< Qt::Key_4, 'N','u','m','p','a','d','4' >,
+ Emkb2Qt< Qt::Key_5, 'N','u','m','p','a','d','5' >,
+ Emkb2Qt< Qt::Key_6, 'N','u','m','p','a','d','6' >,
+ Emkb2Qt< Qt::Key_7, 'N','u','m','p','a','d','7' >,
+ Emkb2Qt< Qt::Key_8, 'N','u','m','p','a','d','8' >,
+ Emkb2Qt< Qt::Key_9, 'N','u','m','p','a','d','9' >,
+ Emkb2Qt< Qt::Key_Comma, 'N','u','m','p','a','d','C','o','m','m','a' >,
+ Emkb2Qt< Qt::Key_Enter, 'N','u','m','p','a','d','E','n','t','e','r' >,
+ Emkb2Qt< Qt::Key_Paste, 'P','a','s','t','e' >,
+ Emkb2Qt< Qt::Key_AltGr, 'A','l','t','R','i','g','h','t' >,
+ Emkb2Qt< Qt::Key_Help, 'H','e','l','p' >,
+ Emkb2Qt< Qt::Key_Equal, '=' >,
+ Emkb2Qt< Qt::Key_yen, 'I','n','t','l','Y','e','n' >,
+
+ Emkb2Qt< Qt::Key_Exclam, '\x21' >,
+ Emkb2Qt< Qt::Key_QuoteDbl, '\x22' >,
+ Emkb2Qt< Qt::Key_NumberSign, '\x23' >,
+ Emkb2Qt< Qt::Key_Dollar, '\x24' >,
+ Emkb2Qt< Qt::Key_Percent, '\x25' >,
+ Emkb2Qt< Qt::Key_Ampersand, '\x26' >,
+ Emkb2Qt< Qt::Key_ParenLeft, '\x28' >,
+ Emkb2Qt< Qt::Key_ParenRight, '\x29' >,
+ Emkb2Qt< Qt::Key_Asterisk, '\x2a' >,
+ Emkb2Qt< Qt::Key_Plus, '\x2b' >,
+ Emkb2Qt< Qt::Key_Colon, '\x3a' >,
+ Emkb2Qt< Qt::Key_Semicolon, '\x3b' >,
+ Emkb2Qt< Qt::Key_Less, '\x3c' >,
+ Emkb2Qt< Qt::Key_Equal, '\x3d' >,
+ Emkb2Qt< Qt::Key_Greater, '\x3e' >,
+ Emkb2Qt< Qt::Key_Question, '\x3f' >,
+ Emkb2Qt< Qt::Key_At, '\x40' >,
+ Emkb2Qt< Qt::Key_BracketLeft, '\x5b' >,
+ Emkb2Qt< Qt::Key_Backslash, '\x5c' >,
+ Emkb2Qt< Qt::Key_BracketRight, '\x5d' >,
+ Emkb2Qt< Qt::Key_AsciiCircum, '\x5e' >,
+ Emkb2Qt< Qt::Key_Underscore, '\x5f' >,
+ Emkb2Qt< Qt::Key_QuoteLeft, '\x60'>,
+ Emkb2Qt< Qt::Key_BraceLeft, '\x7b'>,
+ Emkb2Qt< Qt::Key_Bar, '\x7c'>,
+ Emkb2Qt< Qt::Key_BraceRight, '\x7d'>,
+ Emkb2Qt< Qt::Key_AsciiTilde, '\x7e'>,
+ Emkb2Qt< Qt::Key_Space, '\x20' >,
+ Emkb2Qt< Qt::Key_Comma, '\x2c' >,
+ Emkb2Qt< Qt::Key_Minus, '\x2d' >,
+ Emkb2Qt< Qt::Key_Period, '\x2e' >,
+ Emkb2Qt< Qt::Key_Slash, '\x2f' >,
+ Emkb2Qt< Qt::Key_Apostrophe, '\x27' >,
+ Emkb2Qt< Qt::Key_Menu, 'C','o','n','t','e','x','t','M','e','n','u' >,
+
+ Emkb2Qt< Qt::Key_Agrave, '\xc3','\xa0' >,
+ Emkb2Qt< Qt::Key_Aacute, '\xc3','\xa1' >,
+ Emkb2Qt< Qt::Key_Acircumflex, '\xc3','\xa2' >,
+ Emkb2Qt< Qt::Key_Adiaeresis, '\xc3','\xa4' >,
+ Emkb2Qt< Qt::Key_AE, '\xc3','\xa6' >,
+ Emkb2Qt< Qt::Key_Atilde, '\xc3','\xa3' >,
+ Emkb2Qt< Qt::Key_Aring, '\xc3','\xa5' >,
+ Emkb2Qt< Qt::Key_Ccedilla, '\xc3','\xa7' >,
+ Emkb2Qt< Qt::Key_Egrave, '\xc3','\xa8' >,
+ Emkb2Qt< Qt::Key_Eacute, '\xc3','\xa9' >,
+ Emkb2Qt< Qt::Key_Ecircumflex, '\xc3','\xaa' >,
+ Emkb2Qt< Qt::Key_Ediaeresis, '\xc3','\xab' >,
+ Emkb2Qt< Qt::Key_Icircumflex, '\xc3','\xae' >,
+ Emkb2Qt< Qt::Key_Idiaeresis, '\xc3','\xaf' >,
+ Emkb2Qt< Qt::Key_Ocircumflex, '\xc3','\xb4' >,
+ Emkb2Qt< Qt::Key_Odiaeresis, '\xc3','\xb6' >,
+ Emkb2Qt< Qt::Key_Ograve, '\xc3','\xb2' >,
+ Emkb2Qt< Qt::Key_Oacute, '\xc3','\xb3' >,
+ Emkb2Qt< Qt::Key_Ooblique, '\xc3','\xb8' >,
+ Emkb2Qt< Qt::Key_Otilde, '\xc3','\xb5' >,
+ Emkb2Qt< Qt::Key_Ucircumflex, '\xc3','\xbb' >,
+ Emkb2Qt< Qt::Key_Udiaeresis, '\xc3','\xbc' >,
+ Emkb2Qt< Qt::Key_Ugrave, '\xc3','\xb9' >,
+ Emkb2Qt< Qt::Key_Uacute, '\xc3','\xba' >,
+ Emkb2Qt< Qt::Key_Ntilde, '\xc3','\xb1' >,
+ Emkb2Qt< Qt::Key_ydiaeresis, '\xc3','\xbf' >
+ >::Data{}
+ );
+
+static constexpr const auto DeadKeyShiftTbl = qMakeArray(
+ QSortedData<
+ // shifted
+ Emkb2Qt< Qt::Key_Agrave, '\xc3','\x80' >,
+ Emkb2Qt< Qt::Key_Aacute, '\xc3','\x81' >,
+ Emkb2Qt< Qt::Key_Acircumflex, '\xc3','\x82' >,
+ Emkb2Qt< Qt::Key_Adiaeresis, '\xc3','\x84' >,
+ Emkb2Qt< Qt::Key_AE, '\xc3','\x86' >,
+ Emkb2Qt< Qt::Key_Atilde, '\xc3','\x83' >,
+ Emkb2Qt< Qt::Key_Aring, '\xc3','\x85' >,
+ Emkb2Qt< Qt::Key_Egrave, '\xc3','\x88' >,
+ Emkb2Qt< Qt::Key_Eacute, '\xc3','\x89' >,
+ Emkb2Qt< Qt::Key_Ecircumflex, '\xc3','\x8a' >,
+ Emkb2Qt< Qt::Key_Ediaeresis, '\xc3','\x8b' >,
+ Emkb2Qt< Qt::Key_Icircumflex, '\xc3','\x8e' >,
+ Emkb2Qt< Qt::Key_Idiaeresis, '\xc3','\x8f' >,
+ Emkb2Qt< Qt::Key_Ocircumflex, '\xc3','\x94' >,
+ Emkb2Qt< Qt::Key_Odiaeresis, '\xc3','\x96' >,
+ Emkb2Qt< Qt::Key_Ograve, '\xc3','\x92' >,
+ Emkb2Qt< Qt::Key_Oacute, '\xc3','\x93' >,
+ Emkb2Qt< Qt::Key_Ooblique, '\xc3','\x98' >,
+ Emkb2Qt< Qt::Key_Otilde, '\xc3','\x95' >,
+ Emkb2Qt< Qt::Key_Ucircumflex, '\xc3','\x9b' >,
+ Emkb2Qt< Qt::Key_Udiaeresis, '\xc3','\x9c' >,
+ Emkb2Qt< Qt::Key_Ugrave, '\xc3','\x99' >,
+ Emkb2Qt< Qt::Key_Uacute, '\xc3','\x9a' >,
+ Emkb2Qt< Qt::Key_Ntilde, '\xc3','\x91' >,
+ Emkb2Qt< Qt::Key_Ccedilla, '\xc3','\x87' >,
+ Emkb2Qt< Qt::Key_ydiaeresis, '\xc3','\x8f' >
+ >::Data{}
+);
+
// macOS CTRL <-> META switching. We most likely want to enable
// the existing switching code in QtGui, but for now do it here.
static bool g_usePlatformMacCtrlMetaSwitching = false;
-bool g_useNaturalScrolling = false;
+bool g_useNaturalScrolling = true; // natural scrolling is default on linux/windows
+
+static void mouseWheelEvent(emscripten::val event) {
+
+ emscripten::val wheelInterted = event["webkitDirectionInvertedFromDevice"];
-void setNaturalScrolling(bool use) {
- g_useNaturalScrolling = use;
+ if (wheelInterted.as<bool>()) {
+ g_useNaturalScrolling = true;
+ }
}
-EMSCRIPTEN_BINDINGS(mouse_module) {
- function("setNaturalScrolling", &setNaturalScrolling);
+EMSCRIPTEN_BINDINGS(qtMouseModule) {
+ function("qtMouseWheelEvent", &mouseWheelEvent);
}
-QWasmEventTranslator::QWasmEventTranslator(QObject *parent)
- : QObject(parent)
+QWasmEventTranslator::QWasmEventTranslator(QWasmScreen *screen)
+ : QObject(screen)
, draggedWindow(nullptr)
+ , lastWindow(nullptr)
, pressedButtons(Qt::NoButton)
, resizeMode(QWasmWindow::ResizeNone)
{
- emscripten_set_keydown_callback(0, (void *)this, 1, &keyboard_cb);
- emscripten_set_keyup_callback(0, (void *)this, 1, &keyboard_cb);
-
- emscripten_set_mousedown_callback(0, (void *)this, 1, &mouse_cb);
- emscripten_set_mouseup_callback(0, (void *)this, 1, &mouse_cb);
- emscripten_set_mousemove_callback(0, (void *)this, 1, &mouse_cb);
-
- emscripten_set_focus_callback(0, (void *)this, 1, &focus_cb);
-
- emscripten_set_wheel_callback(0, (void *)this, 1, &wheel_cb);
-
touchDevice = new QTouchDevice;
touchDevice->setType(QTouchDevice::TouchScreen);
touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition);
QWindowSystemInterface::registerTouchDevice(touchDevice);
- emscripten_set_touchstart_callback("#canvas", (void *)this, 1, &touchCallback);
- emscripten_set_touchend_callback("#canvas", (void *)this, 1, &touchCallback);
- emscripten_set_touchmove_callback("#canvas", (void *)this, 1, &touchCallback);
- emscripten_set_touchcancel_callback("#canvas", (void *)this, 1, &touchCallback);
+ initEventHandlers();
+}
+
+void QWasmEventTranslator::initEventHandlers()
+{
+ qDebug() << "QWasmEventTranslator::initEventHandlers";
+
+ QByteArray _canvasId = screen()->canvasId().toUtf8();
+ const char *canvasId = _canvasId.constData();
// The Platform Detect: expand coverage and move as needed
enum Platform {
GenericPlatform,
MacOSPlatform
};
- Platform platform =
- Platform(EM_ASM_INT("if (navigator.platform.includes(\"Mac\")) return 1; return 0;"));
-
+ Platform platform = Platform(emscripten::val::global("navigator")["platform"]
+ .call<bool>("includes", emscripten::val("Mac")));
g_usePlatformMacCtrlMetaSwitching = (platform == MacOSPlatform);
if (platform == MacOSPlatform) {
- g_useNaturalScrolling = true; //make this default on macOS
- EM_ASM(
- if (window.safari !== undefined) {//this only works on safari
- Module["canvas"].addEventListener('wheel', mouseWheelEvent);
- function mouseWheelEvent(e) {
- if (event.webkitDirectionInvertedFromDevice) {
- Module.setNaturalScrolling(event.webkitDirectionInvertedFromDevice);
- }
- }
- }
- );
+ g_useNaturalScrolling = false; // make this !default on macOS
+
+ if (emscripten::val::global("window")["safari"].isUndefined()) {
+
+ emscripten::val::global(canvasId).call<void>("addEventListener",
+ std::string("wheel"),
+ val::module_property("qtMouseWheelEvent"));
+ }
}
+
+ emscripten_set_keydown_callback(canvasId, (void *)this, 1, &keyboard_cb);
+ emscripten_set_keyup_callback(canvasId, (void *)this, 1, &keyboard_cb);
+
+ emscripten_set_mousedown_callback(canvasId, (void *)this, 1, &mouse_cb);
+ emscripten_set_mouseup_callback(canvasId, (void *)this, 1, &mouse_cb);
+ emscripten_set_mousemove_callback(canvasId, (void *)this, 1, &mouse_cb);
+
+ emscripten_set_focus_callback(canvasId, (void *)this, 1, &focus_cb);
+
+ emscripten_set_wheel_callback(canvasId, (void *)this, 1, &wheel_cb);
+
+ emscripten_set_touchstart_callback(canvasId, (void *)this, 1, &touchCallback);
+ emscripten_set_touchend_callback(canvasId, (void *)this, 1, &touchCallback);
+ emscripten_set_touchmove_callback(canvasId, (void *)this, 1, &touchCallback);
+ emscripten_set_touchcancel_callback(canvasId, (void *)this, 1, &touchCallback);
+
+ emscripten_set_resize_callback(nullptr, (void *)this, 1, uiEvent_cb); // Note: handles browser window resize
+
}
template <typename Event>
@@ -152,132 +422,49 @@ QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateMouseEventModifier(c
int QWasmEventTranslator::keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
{
- Q_UNUSED(userData)
-
- bool alphanumeric;
- Qt::Key qtKey = translateEmscriptKey(keyEvent, &alphanumeric);
-
- QEvent::Type keyType = QEvent::None;
- switch (eventType) {
- case EMSCRIPTEN_EVENT_KEYPRESS:
- case EMSCRIPTEN_EVENT_KEYDOWN: //down
- keyType = QEvent::KeyPress;
- break;
- case EMSCRIPTEN_EVENT_KEYUP: //up
- keyType = QEvent::KeyRelease;
- break;
- default:
- break;
- };
+ QWasmEventTranslator *wasmTranslator = reinterpret_cast<QWasmEventTranslator *>(userData);
+ bool accepted = wasmTranslator->processKeyboard(eventType, keyEvent);
- if (keyType == QEvent::None)
- return 0;
-
- QString keyText = alphanumeric ? QString(keyEvent->key) : QString();
- bool accepted = QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(
- 0, keyType, qtKey, translateKeyboardEventModifier(keyEvent), keyText);
- QWasmEventDispatcher::maintainTimers();
return accepted ? 1 : 0;
}
-Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey, bool *outAlphanumeric)
+QWasmScreen *QWasmEventTranslator::screen()
{
- Qt::Key qtKey;
- if (outAlphanumeric)
- *outAlphanumeric = false;
-
- switch (emscriptKey->keyCode) {
- case KeyMultiply: qtKey = Qt::Key_Asterisk; *outAlphanumeric = true; break;
- case KeyAdd: qtKey = Qt::Key_Plus; *outAlphanumeric = true; break;
- case KeyMinus: qtKey = Qt::Key_Minus; *outAlphanumeric = true; break;
- case KeySubtract: qtKey = Qt::Key_Minus; *outAlphanumeric = true; break;
- case KeyDecimal: qtKey = Qt::Key_Period; *outAlphanumeric = true; break;
- case KeyDivide: qtKey = Qt::Key_Slash; *outAlphanumeric = true; break;
- case KeyNumPad0: qtKey = Qt::Key_0; *outAlphanumeric = true; break;
- case KeyNumPad1: qtKey = Qt::Key_1; *outAlphanumeric = true; break;
- case KeyNumPad2: qtKey = Qt::Key_2; *outAlphanumeric = true; break;
- case KeyNumPad3: qtKey = Qt::Key_3; *outAlphanumeric = true; break;
- case KeyNumPad4: qtKey = Qt::Key_4; *outAlphanumeric = true; break;
- case KeyNumPad5: qtKey = Qt::Key_5; *outAlphanumeric = true; break;
- case KeyNumPad6: qtKey = Qt::Key_6; *outAlphanumeric = true; break;
- case KeyNumPad7: qtKey = Qt::Key_7; *outAlphanumeric = true; break;
- case KeyNumPad8: qtKey = Qt::Key_8; *outAlphanumeric = true; break;
- case KeyNumPad9: qtKey = Qt::Key_9; *outAlphanumeric = true; break;
- case KeyComma: qtKey = Qt::Key_Comma; *outAlphanumeric = true; break;
- case KeyPeriod: qtKey = Qt::Key_Period; *outAlphanumeric = true; break;
- case KeySlash: qtKey = Qt::Key_Slash; *outAlphanumeric = true; break;
- case KeySemiColon: qtKey = Qt::Key_Semicolon; *outAlphanumeric = true; break;
- case KeyEquals: qtKey = Qt::Key_Equal; *outAlphanumeric = true; break;
- case KeyOpenBracket: qtKey = Qt::Key_BracketLeft; *outAlphanumeric = true; break;
- case KeyCloseBracket: qtKey = Qt::Key_BracketRight; *outAlphanumeric = true; break;
- case KeyBackSlash: qtKey = Qt::Key_Backslash; *outAlphanumeric = true; break;
- case KeyMeta:
- Q_FALLTHROUGH();
- case KeyMetaRight:
- qtKey = Qt::Key_Meta;
- break;
- case KeyTab: qtKey = Qt::Key_Tab; break;
- case KeyClear: qtKey = Qt::Key_Clear; break;
- case KeyBackSpace: qtKey = Qt::Key_Backspace; break;
- case KeyEnter: qtKey = Qt::Key_Return; break;
- case KeyShift: qtKey = Qt::Key_Shift; break;
- case KeyControl: qtKey = Qt::Key_Control; break;
- case KeyAlt: qtKey = Qt::Key_Alt; break;
- case KeyCapsLock: qtKey = Qt::Key_CapsLock; break;
- case KeyEscape: qtKey = Qt::Key_Escape; break;
- case KeyPageUp: qtKey = Qt::Key_PageUp; break;
- case KeyPageDown: qtKey = Qt::Key_PageDown; break;
- case KeyEnd: qtKey = Qt::Key_End; break;
- case KeyHome: qtKey = Qt::Key_Home; break;
- case KeyLeft: qtKey = Qt::Key_Left; break;
- case KeyUp: qtKey = Qt::Key_Up; break;
- case KeyRight: qtKey = Qt::Key_Right; break;
- case KeyDown: qtKey = Qt::Key_Down; break;
- case KeyBrightnessDown: qtKey = Qt::Key_MonBrightnessDown; break;
- case KeyBrightnessUp: qtKey = Qt::Key_MonBrightnessUp; break;
- case KeyMediaTrackPrevious: qtKey = Qt::Key_MediaPrevious; break;
- case KeyMediaPlayPause: qtKey = Qt::Key_MediaTogglePlayPause; break;
- case KeyMediaTrackNext: qtKey = Qt::Key_MediaNext; break;
- case KeyAudioVolumeMute: qtKey = Qt::Key_VolumeMute; break;
- case KeyAudioVolumeDown: qtKey = Qt::Key_VolumeDown; break;
- case KeyAudioVolumeUp: qtKey = Qt::Key_VolumeUp; break;
- case KeyDelete: qtKey = Qt::Key_Delete; break;
-
- case KeyF1: qtKey = Qt::Key_F1; break;
- case KeyF2: qtKey = Qt::Key_F2; break;
- case KeyF3: qtKey = Qt::Key_F3; break;
- case KeyF4: qtKey = Qt::Key_F4; break;
- case KeyF5: qtKey = Qt::Key_F5; break;
- case KeyF6: qtKey = Qt::Key_F6; break;
- case KeyF7: qtKey = Qt::Key_F7; break;
- case KeyF8: qtKey = Qt::Key_F8; break;
- case KeyF9: qtKey = Qt::Key_F9; break;
- case KeyF10: qtKey = Qt::Key_F10; break;
- case KeyF11: qtKey = Qt::Key_F11; break;
- case KeyF12: qtKey = Qt::Key_F12; break;
- case 124: qtKey = Qt::Key_F13; break;
- case 125: qtKey = Qt::Key_F14; break;
-
- case KeySpace:
- default:
- if (outAlphanumeric)
- *outAlphanumeric = true;
- qtKey = static_cast<Qt::Key>(emscriptKey->keyCode);
- break;
- }
+ return static_cast<QWasmScreen *>(parent());
+}
- // Handle Mac command key. Using event->keyCode as above is
- // no reliable since the codes differ between browsers.
- if (qstrncmp(emscriptKey->key, "Meta", 4) == 0) {
- qtKey = Qt::Key_Meta;
- *outAlphanumeric = false;
+Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey)
+{
+ Qt::Key qtKey = Qt::Key_unknown;
+
+ if (qstrncmp(emscriptKey->code, "Key", 3) == 0 || qstrncmp(emscriptKey->code, "Numpad", 6) == 0) {
+
+ emkb2qt_t searchKey{emscriptKey->code, 0}; // search emcsripten code
+ auto it1 = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
+ if (it1 != KeyTbl.end() && !(searchKey < *it1)) {
+ qtKey = static_cast<Qt::Key>(it1->qt);
+ }
+ } else if (qstrncmp(emscriptKey->key, "Dead", 4) == 0 ) {
+ emkb2qt_t searchKey1{emscriptKey->code, 0};
+ for (auto it1 = KeyTbl.cbegin(); it1 != KeyTbl.end(); ++it1)
+ if (it1 != KeyTbl.end() && (qstrcmp(searchKey1.em, it1->em) == 0)) {
+ qtKey = static_cast<Qt::Key>(it1->qt);
+ }
}
- if (g_usePlatformMacCtrlMetaSwitching) {
- if (qtKey == Qt::Key_Meta)
- qtKey = Qt::Key_Control;
- else if (qtKey == Qt::Key_Control)
- qtKey = Qt::Key_Meta;
+ if (qtKey == Qt::Key_unknown) {
+ emkb2qt_t searchKey{emscriptKey->key, 0}; // search unicode key
+ auto it1 = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
+ if (it1 != KeyTbl.end() && !(searchKey < *it1)) {
+ qtKey = static_cast<Qt::Key>(it1->qt);
+ }
+ }
+ if (qtKey == Qt::Key_unknown) {//try harder with shifted number keys
+ emkb2qt_t searchKey1{emscriptKey->key, 0};
+ for (auto it1 = KeyTbl.cbegin(); it1 != KeyTbl.end(); ++it1)
+ if (it1 != KeyTbl.end() && (qstrcmp(searchKey1.em, it1->em) == 0)) {
+ qtKey = static_cast<Qt::Key>(it1->qt);
+ }
}
return qtKey;
@@ -362,26 +549,30 @@ void resizeWindow(QWindow *window, QWasmWindow::ResizeMode mode,
void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent)
{
auto timestamp = mouseEvent->timestamp;
- QPoint point(mouseEvent->canvasX, mouseEvent->canvasY);
+ QPoint targetPoint(mouseEvent->targetX, mouseEvent->targetY);
+ QPoint globalPoint = screen()->geometry().topLeft() + targetPoint;
QEvent::Type buttonEventType = QEvent::None;
-
Qt::MouseButton button = translateMouseButton(mouseEvent->button);
Qt::KeyboardModifiers modifiers = translateMouseEventModifier(mouseEvent);
- QWindow *window2 = QWasmIntegration::get()->compositor()->windowAt(point, 5);
- QWasmWindow *htmlWindow = static_cast<QWasmWindow*>(window2->handle());
- bool onFrame = false;
- if (window2 && !window2->geometry().contains(point))
- onFrame = true;
+ QWindow *window2 = screen()->compositor()->windowAt(globalPoint, 5);
+ if (window2 == nullptr)
+ return;
+ lastWindow = window2;
- QPoint localPoint(point.x() - window2->geometry().x(), point.y() - window2->geometry().y());
+ QPoint localPoint = window2->mapFromGlobal(globalPoint);
+ bool interior = window2->geometry().contains(globalPoint);
+ QWasmWindow *htmlWindow = static_cast<QWasmWindow*>(window2->handle());
switch (eventType) {
- case 5: //down
+ case EMSCRIPTEN_EVENT_MOUSEDOWN:
{
- if (window2)
+ if (window2) {
window2->raise();
+ if (!window2->isActive())
+ window2->requestActivate();
+ }
pressedButtons.setFlag(button);
@@ -389,21 +580,21 @@ void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEven
pressedWindow = window2;
buttonEventType = QEvent::MouseButtonPress;
if (!(htmlWindow->m_windowState & Qt::WindowFullScreen) && !(htmlWindow->m_windowState & Qt::WindowMaximized)) {
- if (htmlWindow && window2->flags().testFlag(Qt::WindowTitleHint) && htmlWindow->isPointOnTitle(point))
+ if (htmlWindow && window2->flags().testFlag(Qt::WindowTitleHint) && htmlWindow->isPointOnTitle(globalPoint))
draggedWindow = window2;
- else if (htmlWindow && htmlWindow->isPointOnResizeRegion(point)) {
+ else if (htmlWindow && htmlWindow->isPointOnResizeRegion(globalPoint)) {
draggedWindow = window2;
- resizeMode = htmlWindow->resizeModeAtPoint(point);
- resizePoint = point;
+ resizeMode = htmlWindow->resizeModeAtPoint(globalPoint);
+ resizePoint = globalPoint;
resizeStartRect = window2->geometry();
}
}
}
- htmlWindow->injectMousePressed(localPoint, point, button, modifiers);
+ htmlWindow->injectMousePressed(localPoint, globalPoint, button, modifiers);
break;
}
- case 6: //up
+ case EMSCRIPTEN_EVENT_MOUSEUP:
{
pressedButtons.setFlag(translateMouseButton(mouseEvent->button), false);
buttonEventType = QEvent::MouseButtonRelease;
@@ -414,17 +605,16 @@ void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEven
pressedWindow = nullptr;
}
-
if (mouseEvent->button == 0) {
draggedWindow = nullptr;
resizeMode = QWasmWindow::ResizeNone;
}
if (oldWindow)
- oldWindow->injectMouseReleased(localPoint, point, button, modifiers);
+ oldWindow->injectMouseReleased(localPoint, globalPoint, button, modifiers);
break;
}
- case 8://move //drag event
+ case EMSCRIPTEN_EVENT_MOUSEMOVE: // drag event
{
buttonEventType = QEvent::MouseMove;
if (!(htmlWindow->m_windowState & Qt::WindowFullScreen) && !(htmlWindow->m_windowState & Qt::WindowMaximized)) {
@@ -440,13 +630,17 @@ void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEven
}
break;
}
- default:
+ default: // MOUSELEAVE MOUSEENTER
break;
};
-
- if (window2 && !onFrame) {
+ if (!window2 && buttonEventType == QEvent::MouseButtonRelease) {
+ window2 = lastWindow;
+ lastWindow = nullptr;
+ interior = true;
+ }
+ if (window2 && interior) {
QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(
- window2, timestamp, localPoint, point, pressedButtons, button, buttonEventType, modifiers);
+ window2, timestamp, localPoint, globalPoint, pressedButtons, button, buttonEventType, modifiers);
}
}
@@ -458,8 +652,8 @@ int QWasmEventTranslator::focus_cb(int /*eventType*/, const EmscriptenFocusEvent
int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
{
Q_UNUSED(eventType)
- Q_UNUSED(userData)
+ QWasmEventTranslator *eventTranslator = static_cast<QWasmEventTranslator *>(userData);
EmscriptenMouseEvent mouseEvent = wheelEvent->mouse;
int scrollFactor = 0;
@@ -478,25 +672,37 @@ int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wh
if (g_useNaturalScrolling) //macOS platform has document oriented scrolling
scrollFactor = -scrollFactor;
- Qt::KeyboardModifiers modifiers = translateMouseEventModifier(&mouseEvent);
+ QWasmEventTranslator *translator = (QWasmEventTranslator*)userData;
+ Qt::KeyboardModifiers modifiers = translator->translateMouseEventModifier(&mouseEvent);
auto timestamp = mouseEvent.timestamp;
- QPoint globalPoint(mouseEvent.canvasX, mouseEvent.canvasY);
+ QPoint targetPoint(mouseEvent.targetX, mouseEvent.targetY);
+ QPoint globalPoint = eventTranslator->screen()->geometry().topLeft() + targetPoint;
- QWindow *window2 = QWasmIntegration::get()->compositor()->windowAt(globalPoint, 5);
-
- QPoint localPoint(globalPoint.x() - window2->geometry().x(), globalPoint.y() - window2->geometry().y());
+ QWindow *window2 = eventTranslator->screen()->compositor()->windowAt(globalPoint, 5);
+ if (!window2)
+ return 0;
+ QPoint localPoint = window2->mapFromGlobal(globalPoint);
QPoint pixelDelta;
if (wheelEvent->deltaY != 0) pixelDelta.setY(wheelEvent->deltaY * scrollFactor);
if (wheelEvent->deltaX != 0) pixelDelta.setX(wheelEvent->deltaX * scrollFactor);
- QWindowSystemInterface::handleWheelEvent(window2, timestamp, localPoint, globalPoint, QPoint(), pixelDelta, modifiers);
+ QWindowSystemInterface::handleWheelEvent(window2, timestamp, localPoint,
+ globalPoint, QPoint(), pixelDelta, modifiers);
+ QWasmEventDispatcher::maintainTimers();
+
return 1;
}
int QWasmEventTranslator::touchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
{
+ auto translator = reinterpret_cast<QWasmEventTranslator*>(userData);
+ return translator->handleTouch(eventType, touchEvent);
+}
+
+int QWasmEventTranslator::handleTouch(int eventType, const EmscriptenTouchEvent *touchEvent)
+{
QList<QWindowSystemInterface::TouchPoint> touchPointList;
touchPointList.reserve(touchEvent->numTouches);
QWindow *window2;
@@ -505,46 +711,72 @@ int QWasmEventTranslator::touchCallback(int eventType, const EmscriptenTouchEven
const EmscriptenTouchPoint *touches = &touchEvent->touches[i];
- QPoint point(touches->canvasX, touches->canvasY);
- window2 = QWasmIntegration::get()->compositor()->windowAt(point, 5);
+ QPoint targetPoint(touches->targetX, touches->targetY);
+ QPoint globalPoint = screen()->geometry().topLeft() + targetPoint;
+
+ window2 = this->screen()->compositor()->windowAt(globalPoint, 5);
+ if (window2 == nullptr)
+ continue;
QWindowSystemInterface::TouchPoint touchPoint;
- auto cX = point.x();
- auto cY = point.y();
touchPoint.area = QRect(0, 0, 8, 8);
- touchPoint.area.moveCenter(QPointF(cX,cY)); // simulate area
-
touchPoint.id = touches->identifier;
- touchPoint.normalPosition = QPointF(cX / window2->width(), cY / window2->height());
+ touchPoint.pressure = 1.0;
+
+ touchPoint.area.moveCenter(globalPoint);
+
+ const auto tp = pressedTouchIds.constFind(touchPoint.id);
+ if (tp != pressedTouchIds.constEnd())
+ touchPoint.normalPosition = tp.value();
+
+ QPointF localPoint = QPointF(window2->mapFromGlobal(globalPoint));
+ QPointF normalPosition(localPoint.x() / window2->width(),
+ localPoint.y() / window2->height());
+
+ const bool stationaryTouchPoint = (normalPosition == touchPoint.normalPosition);
+ touchPoint.normalPosition = normalPosition;
switch (eventType) {
case EMSCRIPTEN_EVENT_TOUCHSTART:
- touchPoint.state = Qt::TouchPointPressed;
+ if (tp != pressedTouchIds.constEnd()) {
+ touchPoint.state = (stationaryTouchPoint
+ ? Qt::TouchPointStationary
+ : Qt::TouchPointMoved);
+ } else {
+ touchPoint.state = Qt::TouchPointPressed;
+ }
+ pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
+
break;
case EMSCRIPTEN_EVENT_TOUCHEND:
touchPoint.state = Qt::TouchPointReleased;
+ pressedTouchIds.remove(touchPoint.id);
break;
case EMSCRIPTEN_EVENT_TOUCHMOVE:
- touchPoint.state = Qt::TouchPointMoved;
+ touchPoint.state = (stationaryTouchPoint
+ ? Qt::TouchPointStationary
+ : Qt::TouchPointMoved);
+
+ pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
break;
default:
- Q_UNREACHABLE();
+ break;
}
touchPointList.append(touchPoint);
}
- QWasmEventTranslator *wasmEventTranslator = (QWasmEventTranslator*)userData;
QFlags<Qt::KeyboardModifier> keyModifier = translatKeyModifier(touchEvent);
- if (eventType != EMSCRIPTEN_EVENT_TOUCHCANCEL)
- QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(window2, wasmEventTranslator->getTimestamp(), wasmEventTranslator->touchDevice, touchPointList, keyModifier);
- else
- QWindowSystemInterface::handleTouchCancelEvent(window2, wasmEventTranslator->getTimestamp(), wasmEventTranslator->touchDevice, keyModifier);
+ QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(
+ window2, getTimestamp(), touchDevice, touchPointList, keyModifier);
- QCoreApplication::processEvents();
- return 1;
+ if (eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL)
+ QWindowSystemInterface::handleTouchCancelEvent(window2, getTimestamp(), touchDevice, keyModifier);
+
+ QWasmEventDispatcher::maintainTimers();
+ return 0;
}
quint64 QWasmEventTranslator::getTimestamp()
@@ -552,4 +784,149 @@ quint64 QWasmEventTranslator::getTimestamp()
return QDeadlineTimer::current().deadlineNSecs() / 1000;
}
+Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey)
+{
+ Qt::Key wasmKey = Qt::Key_unknown;
+ switch (deadKey) {
+#ifdef Q_OS_MACOS
+ case Qt::Key_QuoteLeft: // ` macOS: Key_Dead_Grave
+#else
+ case Qt::Key_O: // ´ Key_Dead_Grave
+#endif
+ wasmKey = graveKeyTable.value(accentBaseKey);
+ break;
+ case Qt::Key_E: // ´ Key_Dead_Acute
+ wasmKey = acuteKeyTable.value(accentBaseKey);
+ break;
+ case Qt::Key_AsciiTilde:
+ case Qt::Key_N:// Key_Dead_Tilde
+ wasmKey = tildeKeyTable.value(accentBaseKey);
+ break;
+#ifndef Q_OS_MACOS
+ case Qt::Key_QuoteLeft:
+#endif
+ case Qt::Key_U:// ¨ Key_Dead_Diaeresis
+ wasmKey = diaeresisKeyTable.value(accentBaseKey);
+ break;
+ case Qt::Key_I:// macOS Key_Dead_Circumflex
+ case Qt::Key_6:// linux
+ case Qt::Key_Apostrophe:// linux
+ wasmKey = circumflexKeyTable.value(accentBaseKey);
+ break;
+ break;
+ default:
+ break;
+ };
+
+ return wasmKey;
+}
+
+bool QWasmEventTranslator::processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent)
+{
+ Qt::Key qtKey = translateEmscriptKey(keyEvent);
+
+ Qt::KeyboardModifiers modifiers = translateKeyboardEventModifier(keyEvent);
+
+ QString keyText;
+ QEvent::Type keyType = QEvent::None;
+ switch (eventType) {
+ case EMSCRIPTEN_EVENT_KEYPRESS:
+ case EMSCRIPTEN_EVENT_KEYDOWN: // down
+ keyType = QEvent::KeyPress;
+
+ if (m_emDeadKey != Qt::Key_unknown) {
+
+ Qt::Key transformedKey = translateDeadKey(m_emDeadKey, qtKey);
+
+ if (transformedKey != Qt::Key_unknown)
+ qtKey = transformedKey;
+
+ if (keyEvent->shiftKey == 0) {
+ for (auto it = KeyTbl.cbegin(); it != KeyTbl.end(); ++it) {
+ if (it != KeyTbl.end() && (qtKey == static_cast<Qt::Key>(it->qt))) {
+ keyText = it->em;
+ m_emDeadKey = Qt::Key_unknown;
+ break;
+ }
+ }
+ } else {
+ for (auto it = DeadKeyShiftTbl.cbegin(); it != DeadKeyShiftTbl.end(); ++it) {
+ if (it != DeadKeyShiftTbl.end() && (qtKey == static_cast<Qt::Key>(it->qt))) {
+ keyText = it->em;
+ m_emDeadKey = Qt::Key_unknown;
+ break;
+ }
+ }
+ }
+ }
+ if (qstrncmp(keyEvent->key, "Dead", 4) == 0 || qtKey == Qt::Key_AltGr) {
+ qtKey = translateEmscriptKey(keyEvent);
+ m_emStickyDeadKey = true;
+ if (keyEvent->shiftKey == 1 && qtKey == Qt::Key_QuoteLeft)
+ qtKey = Qt::Key_AsciiTilde;
+ m_emDeadKey = qtKey;
+ }
+ break;
+ case EMSCRIPTEN_EVENT_KEYUP: // up
+ keyType = QEvent::KeyRelease;
+ if (m_emStickyDeadKey && qtKey != Qt::Key_Alt) {
+ m_emStickyDeadKey = false;
+ }
+ break;
+ default:
+ break;
+ };
+
+ if (keyType == QEvent::None)
+ return 0;
+
+ QFlags<Qt::KeyboardModifier> mods = translateKeyboardEventModifier(keyEvent);
+
+ // Clipboard fallback path: cut/copy/paste are handled by clipboard event
+ // handlers if direct clipboard access is not available.
+ if (!QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi && modifiers & Qt::ControlModifier &&
+ (qtKey == Qt::Key_X || qtKey == Qt::Key_C || qtKey == Qt::Key_V)) {
+ return 0;
+ }
+
+ bool accepted = false;
+
+ if (keyType == QEvent::KeyPress &&
+ mods.testFlag(Qt::ControlModifier)
+ && qtKey == Qt::Key_V) {
+ QWasmIntegration::get()->getWasmClipboard()->readTextFromClipboard();
+ } else {
+ if (keyText.isEmpty())
+ keyText = QString(keyEvent->key);
+ if (keyText.size() > 1)
+ keyText.clear();
+ accepted = QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(
+ 0, keyType, qtKey, modifiers, keyText);
+ }
+ if (keyType == QEvent::KeyPress &&
+ mods.testFlag(Qt::ControlModifier)
+ && qtKey == Qt::Key_C) {
+ QWasmIntegration::get()->getWasmClipboard()->writeTextToClipboard();
+ }
+
+ QWasmEventDispatcher::maintainTimers();
+
+ return accepted;
+}
+
+int QWasmEventTranslator::uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData)
+{
+ Q_UNUSED(e)
+ QWasmEventTranslator *eventTranslator = static_cast<QWasmEventTranslator *>(userData);
+
+ if (eventType == EMSCRIPTEN_EVENT_RESIZE) {
+ // This resize event is called when the HTML window is resized. Depending
+ // on the page layout the the canvas might also have been resized, so we
+ // update the Qt screen size (and canvas render size).
+ eventTranslator->screen()->updateQScreenAndCanvasRenderSize();
+ }
+
+ return 0;
+}
+
QT_END_NAMESPACE