summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Skoland <david.skoland@qt.io>2021-12-07 17:16:36 +0100
committerDavid Skoland <david.skoland@qt.io>2022-01-17 18:23:50 +0100
commit5359d420afda4a4562f27d44251ae8cf764406b8 (patch)
treeea8b1f3ce0a49d0bc8d3852bda48d03ef876885b
parentb99c08dd4ed6c9660e1b2c4d93cb1271e8039e03 (diff)
Move input event logic into QWasmCompositor
Move the window logic and state out of QWasmEventTranslator and into QWasmCompositor. The reasoning for this change is that the state of the windowing system was split between QWasmCompositor (eg. window stack) and QWasmEventTranslator (eg. dragged and pressed windows). This change moves the input handling and state to QWasmCompositor and demotes QWasmEventTranslator to a helper class. In this model, QWC acts as a proper window system / display server and can leverage multiple helper classes which are "owned" by the QWC. Here is a quick diagram illustrating the proposed general architecture around WASM window handling and its difference from typical OSes: https://i.imgur.com/vcBwUPf.png Change-Id: Idca617992b8e1b431e5c71d46b5db61597c99e75 Pick-to: 6.3 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp504
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.h52
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.cpp602
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.h54
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp5
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.h1
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.cpp2
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp20
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.h16
9 files changed, 658 insertions, 598 deletions
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index aa498c8238..048dcfa2fc 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -28,9 +28,11 @@
****************************************************************************/
#include "qwasmcompositor.h"
-#include "qwasmeventdispatcher.h"
-#include "qwasmwindow.h"
#include "qwasmstylepixmaps_p.h"
+#include "qwasmwindow.h"
+#include "qwasmeventtranslator.h"
+#include "qwasmeventdispatcher.h"
+#include "qwasmclipboard.h"
#include <QtOpenGL/qopengltexture.h>
@@ -47,6 +49,10 @@
#include <QtCore/qcoreapplication.h>
#include <QtGui/qguiapplication.h>
+#include <emscripten/bind.h>
+
+using namespace emscripten;
+
Q_GUI_EXPORT int qt_defaultDpiX();
QWasmCompositedWindow::QWasmCompositedWindow()
@@ -57,6 +63,25 @@ QWasmCompositedWindow::QWasmCompositedWindow()
{
}
+// macOS CTRL <-> META switching. We most likely want to enable
+// the existing switching code in QtGui, but for now do it here.
+
+
+bool g_useNaturalScrolling = true; // natural scrolling is default on linux/windows
+
+static void mouseWheelEvent(emscripten::val event) {
+
+ emscripten::val wheelInterted = event["webkitDirectionInvertedFromDevice"];
+
+ if (wheelInterted.as<bool>()) {
+ g_useNaturalScrolling = true;
+ }
+}
+
+EMSCRIPTEN_BINDINGS(qtMouseModule) {
+ function("qtMouseWheelEvent", &mouseWheelEvent);
+}
+
QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
:QObject(screen)
, m_blitter(new QOpenGLTextureBlitter)
@@ -65,16 +90,51 @@ QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
, m_inResize(false)
, m_isEnabled(true)
, m_targetDevicePixelRatio(1)
+ , draggedWindow(nullptr)
+ , lastWindow(nullptr)
+ , pressedButtons(Qt::NoButton)
+ , resizeMode(QWasmCompositor::ResizeNone)
+ , eventTranslator(new QWasmEventTranslator())
{
+ touchDevice = new QPointingDevice(
+ "touchscreen", 1, QInputDevice::DeviceType::TouchScreen,
+ QPointingDevice::PointerType::Finger,
+ QPointingDevice::Capability::Position | QPointingDevice::Capability::Area | QPointingDevice::Capability::NormalizedPosition,
+ 10, 0);
+ QWindowSystemInterface::registerInputDevice(touchDevice);
+
+ initEventHandlers();
}
QWasmCompositor::~QWasmCompositor()
{
if (m_requestAnimationFrameId != -1)
emscripten_cancel_animation_frame(m_requestAnimationFrameId);
+
+ deregisterEventHandlers();
destroy();
}
+void QWasmCompositor::deregisterEventHandlers()
+{
+ QByteArray canvasSelector = "#" + screen()->canvasId().toUtf8();
+ emscripten_set_keydown_callback(canvasSelector.constData(), 0, 0, NULL);
+ emscripten_set_keyup_callback(canvasSelector.constData(), 0, 0, NULL);
+
+ emscripten_set_mousedown_callback(canvasSelector.constData(), 0, 0, NULL);
+ emscripten_set_mouseup_callback(canvasSelector.constData(), 0, 0, NULL);
+ emscripten_set_mousemove_callback(canvasSelector.constData(), 0, 0, NULL);
+
+ emscripten_set_focus_callback(canvasSelector.constData(), 0, 0, NULL);
+
+ emscripten_set_wheel_callback(canvasSelector.constData(), 0, 0, NULL);
+
+ emscripten_set_touchstart_callback(canvasSelector.constData(), 0, 0, NULL);
+ emscripten_set_touchend_callback(canvasSelector.constData(), 0, 0, NULL);
+ emscripten_set_touchmove_callback(canvasSelector.constData(), 0, 0, NULL);
+ emscripten_set_touchcancel_callback(canvasSelector.constData(), 0, 0, NULL);
+}
+
void QWasmCompositor::destroy()
{
// Destroy OpenGL resources. This is done here in a separate function
@@ -96,6 +156,48 @@ void QWasmCompositor::destroy()
m_isEnabled = false; // prevent frame() from creating a new m_context
}
+void QWasmCompositor::initEventHandlers()
+{
+ QByteArray canvasSelector = "#" + screen()->canvasId().toUtf8();
+
+ // The Platform Detect: expand coverage and move as needed
+ enum Platform {
+ GenericPlatform,
+ MacOSPlatform
+ };
+ Platform platform = Platform(emscripten::val::global("navigator")["platform"]
+ .call<bool>("includes", emscripten::val("Mac")));
+
+ eventTranslator->setIsMac(platform == MacOSPlatform);
+
+ if (platform == MacOSPlatform) {
+ g_useNaturalScrolling = false; // make this !default on macOS
+
+ if (!emscripten::val::global("window")["safari"].isUndefined()) {
+ val canvas = screen()->canvas();
+ canvas.call<void>("addEventListener",
+ val("wheel"),
+ val::module_property("qtMouseWheelEvent"));
+ }
+ }
+
+ emscripten_set_keydown_callback(canvasSelector.constData(), (void *)this, 1, &keyboard_cb);
+ emscripten_set_keyup_callback(canvasSelector.constData(), (void *)this, 1, &keyboard_cb);
+
+ emscripten_set_mousedown_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
+ emscripten_set_mouseup_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
+ emscripten_set_mousemove_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
+
+ emscripten_set_focus_callback(canvasSelector.constData(), (void *)this, 1, &focus_cb);
+
+ emscripten_set_wheel_callback(canvasSelector.constData(), (void *)this, 1, &wheel_cb);
+
+ emscripten_set_touchstart_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
+ emscripten_set_touchend_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
+ emscripten_set_touchmove_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
+ emscripten_set_touchcancel_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
+}
+
void QWasmCompositor::setEnabled(bool enabled)
{
m_isEnabled = enabled;
@@ -784,6 +886,62 @@ void QWasmCompositor::frame()
m_context->swapBuffers(someWindow->window());
}
+void QWasmCompositor::resizeWindow(QWindow *window, QWasmCompositor::ResizeMode mode,
+ QRect startRect, QPoint amount)
+{
+ if (mode == QWasmCompositor::ResizeNone)
+ return;
+
+ bool top = mode == QWasmCompositor::ResizeTopLeft ||
+ mode == QWasmCompositor::ResizeTop ||
+ mode == QWasmCompositor::ResizeTopRight;
+
+ bool bottom = mode == QWasmCompositor::ResizeBottomLeft ||
+ mode == QWasmCompositor::ResizeBottom ||
+ mode == QWasmCompositor::ResizeBottomRight;
+
+ bool left = mode == QWasmCompositor::ResizeLeft ||
+ mode == QWasmCompositor::ResizeTopLeft ||
+ mode == QWasmCompositor::ResizeBottomLeft;
+
+ bool right = mode == QWasmCompositor::ResizeRight ||
+ mode == QWasmCompositor::ResizeTopRight ||
+ mode == QWasmCompositor::ResizeBottomRight;
+
+ int x1 = startRect.left();
+ int y1 = startRect.top();
+ int x2 = startRect.right();
+ int y2 = startRect.bottom();
+
+ if (left)
+ x1 += amount.x();
+ if (top)
+ y1 += amount.y();
+ if (right)
+ x2 += amount.x();
+ if (bottom)
+ y2 += amount.y();
+
+ int w = x2-x1;
+ int h = y2-y1;
+
+ if (w < window->minimumWidth()) {
+ if (left)
+ x1 -= window->minimumWidth() - w;
+
+ w = window->minimumWidth();
+ }
+
+ if (h < window->minimumHeight()) {
+ if (top)
+ y1 -= window->minimumHeight() - h;
+
+ h = window->minimumHeight();
+ }
+
+ window->setGeometry(x1, y1, w, h);
+}
+
void QWasmCompositor::notifyTopWindowChanged(QWasmWindow *window)
{
QWindow *modalWindow;
@@ -807,3 +965,345 @@ QOpenGLContext *QWasmCompositor::context()
{
return m_context.data();
}
+
+int QWasmCompositor::keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
+{
+ QWasmCompositor *wasmCompositor = reinterpret_cast<QWasmCompositor *>(userData);
+ bool accepted = wasmCompositor->processKeyboard(eventType, keyEvent);
+
+ return accepted ? 1 : 0;
+}
+
+int QWasmCompositor::mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
+{
+ QWasmCompositor *compositor = (QWasmCompositor*)userData;
+ bool accepted = compositor->processMouse(eventType, mouseEvent);
+ return accepted;
+}
+
+int QWasmCompositor::focus_cb(int /*eventType*/, const EmscriptenFocusEvent */*focusEvent*/, void */*userData*/)
+{
+ return 0;
+}
+
+int QWasmCompositor::wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
+{
+ QWasmCompositor *compositor = (QWasmCompositor *) userData;
+ bool accepted = compositor->processWheel(eventType, wheelEvent);
+ return accepted ? 1 : 0;
+}
+
+int QWasmCompositor::touchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
+{
+ auto compositor = reinterpret_cast<QWasmCompositor*>(userData);
+ return compositor->handleTouch(eventType, touchEvent);
+}
+
+bool QWasmCompositor::processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent)
+{
+ QPoint targetPoint(mouseEvent->targetX, mouseEvent->targetY);
+ QPoint globalPoint = screen()->geometry().topLeft() + targetPoint;
+
+ QEvent::Type buttonEventType = QEvent::None;
+ Qt::MouseButton button = Qt::NoButton;
+ Qt::KeyboardModifiers modifiers = eventTranslator->translateMouseEventModifier(mouseEvent);
+
+ QWindow *window2 = nullptr;
+ if (resizeMode == QWasmCompositor::ResizeNone)
+ window2 = screen()->compositor()->windowAt(globalPoint, 5);
+
+ if (window2 == nullptr) {
+ window2 = lastWindow;
+ } else {
+ lastWindow = window2;
+ }
+
+ QPoint localPoint = window2->mapFromGlobal(globalPoint);
+ bool interior = window2->geometry().contains(globalPoint);
+
+ QWasmWindow *htmlWindow = static_cast<QWasmWindow*>(window2->handle());
+ switch (eventType) {
+ case EMSCRIPTEN_EVENT_MOUSEDOWN:
+ {
+ button = QWasmEventTranslator::translateMouseButton(mouseEvent->button);
+
+ if (window2)
+ window2->requestActivate();
+
+ pressedButtons.setFlag(button);
+
+ pressedWindow = window2;
+ buttonEventType = QEvent::MouseButtonPress;
+
+ // button overview:
+ // 0 = primary mouse button, usually left click
+ // 1 = middle mouse button, usually mouse wheel
+ // 2 = right mouse button, usually right click
+ // from: https://w3c.github.io/uievents/#dom-mouseevent-button
+ if (mouseEvent->button == 0) {
+ if (!(htmlWindow->m_windowState & Qt::WindowFullScreen) && !(htmlWindow->m_windowState & Qt::WindowMaximized)) {
+ if (htmlWindow && window2->flags().testFlag(Qt::WindowTitleHint) && htmlWindow->isPointOnTitle(globalPoint))
+ draggedWindow = window2;
+ else if (htmlWindow && htmlWindow->isPointOnResizeRegion(globalPoint)) {
+ draggedWindow = window2;
+ resizeMode = htmlWindow->resizeModeAtPoint(globalPoint);
+ resizePoint = globalPoint;
+ resizeStartRect = window2->geometry();
+ }
+ }
+ }
+
+ htmlWindow->injectMousePressed(localPoint, globalPoint, button, modifiers);
+ break;
+ }
+ case EMSCRIPTEN_EVENT_MOUSEUP:
+ {
+ button = QWasmEventTranslator::translateMouseButton(mouseEvent->button);
+ pressedButtons.setFlag(button, false);
+ buttonEventType = QEvent::MouseButtonRelease;
+ QWasmWindow *oldWindow = nullptr;
+
+ if (mouseEvent->button == 0 && pressedWindow) {
+ oldWindow = static_cast<QWasmWindow*>(pressedWindow->handle());
+ pressedWindow = nullptr;
+ }
+
+ if (draggedWindow && pressedButtons.testFlag(Qt::NoButton)) {
+ draggedWindow = nullptr;
+ resizeMode = QWasmCompositor::ResizeNone;
+ }
+
+ if (oldWindow)
+ oldWindow->injectMouseReleased(localPoint, globalPoint, button, modifiers);
+ else
+ htmlWindow->injectMouseReleased(localPoint, globalPoint, button, modifiers);
+ break;
+ }
+ case EMSCRIPTEN_EVENT_MOUSEMOVE: // drag event
+ {
+ buttonEventType = QEvent::MouseMove;
+
+ if (htmlWindow && pressedButtons.testFlag(Qt::NoButton)) {
+
+ if (htmlWindow->isPointOnResizeRegion(globalPoint)) {
+ QCursor resizingCursor = eventTranslator->cursorForMode(htmlWindow->resizeModeAtPoint(globalPoint));
+
+ if (resizingCursor != window2->cursor()) {
+ isCursorOverridden = true;
+ QWasmCursor::setOverrideWasmCursor(&resizingCursor, window2->screen());
+ }
+ } else { // off resizing area
+ if (isCursorOverridden) {
+ isCursorOverridden = false;
+ QWasmCursor::clearOverrideWasmCursor(window2->screen());
+ }
+ }
+ }
+
+ if (!(htmlWindow->m_windowState & Qt::WindowFullScreen) && !(htmlWindow->m_windowState & Qt::WindowMaximized)) {
+ if (resizeMode == QWasmCompositor::ResizeNone && draggedWindow) {
+ draggedWindow->setX(draggedWindow->x() + mouseEvent->movementX);
+ draggedWindow->setY(draggedWindow->y() + mouseEvent->movementY);
+ }
+
+ if (resizeMode != QWasmCompositor::ResizeNone && !(htmlWindow->m_windowState & Qt::WindowFullScreen)) {
+ QPoint delta = QPoint(mouseEvent->targetX, mouseEvent->targetY) - resizePoint;
+ resizeWindow(draggedWindow, resizeMode, resizeStartRect, delta);
+ }
+ }
+ break;
+ }
+ default: // MOUSELEAVE MOUSEENTER
+ break;
+ };
+ if (!window2 && buttonEventType == QEvent::MouseButtonRelease) {
+ window2 = lastWindow;
+ lastWindow = nullptr;
+ interior = true;
+ }
+ bool accepted = true;
+ if (window2 && interior) {
+ accepted = QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(
+ window2, QWasmIntegration::getTimestamp(), localPoint, globalPoint, pressedButtons, button, buttonEventType, modifiers);
+ }
+ return accepted;
+}
+
+bool QWasmCompositor::processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent)
+{
+ Qt::Key qtKey;
+ QString keyText;
+ QEvent::Type keyType = QEvent::None;
+ switch (eventType) {
+ case EMSCRIPTEN_EVENT_KEYPRESS:
+ case EMSCRIPTEN_EVENT_KEYDOWN: // down
+ keyType = QEvent::KeyPress;
+ keyText = this->eventTranslator->getKeyText(keyEvent);
+ qtKey = this->eventTranslator->getKey(keyEvent);
+ break;
+ case EMSCRIPTEN_EVENT_KEYUP: // up
+ keyType = QEvent::KeyRelease;
+ this->eventTranslator->setStickyDeadKey(keyEvent);
+ break;
+ default:
+ break;
+ };
+
+ if (keyType == QEvent::None)
+ return 0;
+
+ QFlags<Qt::KeyboardModifier> modifiers = eventTranslator->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)) {
+ if (qtKey == Qt::Key_V) {
+ QWasmIntegration::get()->getWasmClipboard()->isPaste = true;
+ }
+ return false;
+ }
+
+ bool accepted = false;
+
+ if (keyType == QEvent::KeyPress &&
+ modifiers.testFlag(Qt::ControlModifier)
+ && qtKey == Qt::Key_V) {
+ QWasmIntegration::get()->getWasmClipboard()->isPaste = true;
+ accepted = false; // continue on to event
+ } 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 &&
+ modifiers.testFlag(Qt::ControlModifier)
+ && qtKey == Qt::Key_C) {
+ QWasmIntegration::get()->getWasmClipboard()->isPaste = false;
+ accepted = false; // continue on to event
+ }
+
+ return accepted;
+}
+
+bool QWasmCompositor::processWheel(int eventType, const EmscriptenWheelEvent *wheelEvent)
+{
+ Q_UNUSED(eventType);
+
+ EmscriptenMouseEvent mouseEvent = wheelEvent->mouse;
+
+ int scrollFactor = 0;
+ switch (wheelEvent->deltaMode) {
+ case DOM_DELTA_PIXEL://chrome safari
+ scrollFactor = 1;
+ break;
+ case DOM_DELTA_LINE: //firefox
+ scrollFactor = 12;
+ break;
+ case DOM_DELTA_PAGE:
+ scrollFactor = 20;
+ break;
+ };
+
+ if (g_useNaturalScrolling) //macOS platform has document oriented scrolling
+ scrollFactor = -scrollFactor;
+
+ Qt::KeyboardModifiers modifiers = eventTranslator->translateMouseEventModifier(&mouseEvent);
+ QPoint targetPoint(mouseEvent.targetX, mouseEvent.targetY);
+ QPoint globalPoint = screen()->geometry().topLeft() + targetPoint;
+
+ QWindow *window2 = 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);
+
+ bool accepted = QWindowSystemInterface::handleWheelEvent(
+ window2, QWasmIntegration::getTimestamp(), localPoint,
+ globalPoint, QPoint(), pixelDelta, modifiers);
+ return accepted;
+}
+
+int QWasmCompositor::handleTouch(int eventType, const EmscriptenTouchEvent *touchEvent)
+{
+ QList<QWindowSystemInterface::TouchPoint> touchPointList;
+ touchPointList.reserve(touchEvent->numTouches);
+ QWindow *window2;
+
+ for (int i = 0; i < touchEvent->numTouches; i++) {
+
+ const EmscriptenTouchPoint *touches = &touchEvent->touches[i];
+
+ 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;
+
+ touchPoint.area = QRect(0, 0, 8, 8);
+ touchPoint.id = touches->identifier;
+ 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:
+ if (tp != pressedTouchIds.constEnd()) {
+ touchPoint.state = (stationaryTouchPoint
+ ? QEventPoint::State::Stationary
+ : QEventPoint::State::Updated);
+ } else {
+ touchPoint.state = QEventPoint::State::Pressed;
+ }
+ pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
+
+ break;
+ case EMSCRIPTEN_EVENT_TOUCHEND:
+ touchPoint.state = QEventPoint::State::Released;
+ pressedTouchIds.remove(touchPoint.id);
+ break;
+ case EMSCRIPTEN_EVENT_TOUCHMOVE:
+ touchPoint.state = (stationaryTouchPoint
+ ? QEventPoint::State::Stationary
+ : QEventPoint::State::Updated);
+
+ pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
+ break;
+ default:
+ break;
+ }
+
+ touchPointList.append(touchPoint);
+ }
+
+ QFlags<Qt::KeyboardModifier> keyModifier = eventTranslator->translateTouchEventModifier(touchEvent);
+
+ bool accepted = QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(
+ window2, QWasmIntegration::getTimestamp(), touchDevice, touchPointList, keyModifier);
+
+ if (eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL)
+ accepted = QWindowSystemInterface::handleTouchCancelEvent(window2, QWasmIntegration::getTimestamp(), touchDevice, keyModifier);
+
+ return static_cast<int>(accepted);
+}
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h
index 1a51016c03..1feda04870 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.h
+++ b/src/plugins/platforms/wasm/qwasmcompositor.h
@@ -36,6 +36,12 @@
#include <QtOpenGL/qopengltextureblitter.h>
#include <QtGui/qpalette.h>
#include <QtGui/qpainter.h>
+#include <QtGui/qinputdevice.h>
+
+#include <QPointer>
+#include <QPointingDevice>
+
+#include <emscripten/html5.h>
QT_BEGIN_NAMESPACE
@@ -43,6 +49,7 @@ class QWasmWindow;
class QWasmScreen;
class QOpenGLContext;
class QOpenGLTexture;
+class QWasmEventTranslator;
class QWasmCompositedWindow
{
@@ -63,6 +70,7 @@ class QWasmCompositor : public QObject
public:
QWasmCompositor(QWasmScreen *screen);
~QWasmCompositor();
+ void deregisterEventHandlers();
void destroy();
enum QWasmSubControl {
@@ -84,6 +92,18 @@ public:
};
Q_DECLARE_FLAGS(StateFlags, QWasmStateFlag)
+ enum ResizeMode {
+ ResizeNone,
+ ResizeTopLeft,
+ ResizeTop,
+ ResizeTopRight,
+ ResizeRight,
+ ResizeBottomRight,
+ ResizeBottom,
+ ResizeBottomLeft,
+ ResizeLeft
+ };
+
struct QWasmTitleBarOptions {
QRect rect;
Qt::WindowFlags flags;
@@ -128,9 +148,17 @@ public:
void deliverUpdateRequests();
void deliverUpdateRequest(QWasmWindow *window, UpdateRequestDeliveryType updateType);
void handleBackingStoreFlush();
+ bool processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent);
+ bool processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent);
+ bool processWheel(int eventType, const EmscriptenWheelEvent *wheelEvent);
+ int handleTouch(int eventType, const EmscriptenTouchEvent *touchEvent);
+ void resizeWindow(QWindow *window, QWasmCompositor::ResizeMode mode, QRect startRect, QPoint amount);
+
+private slots:
void frame();
private:
+ void initEventHandlers();
void notifyTopWindowChanged(QWasmWindow *window);
void drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
void drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
@@ -156,6 +184,21 @@ private:
int m_requestAnimationFrameId = -1;
bool m_inDeliverUpdateRequest = false;
+ QPointer<QWindow> draggedWindow;
+ QPointer<QWindow> pressedWindow;
+ QPointer<QWindow> lastWindow;
+ Qt::MouseButtons pressedButtons;
+
+ QWasmCompositor::ResizeMode resizeMode;
+ QPoint resizePoint;
+ QRect resizeStartRect;
+ QPointingDevice *touchDevice;
+
+ QMap <int, QPointF> pressedTouchIds;
+
+ QCursor overriddenCursor;
+ bool isCursorOverridden = false;
+
static QPalette makeWindowPalette();
void drawFrameWindow(QWasmFrameOptions options, QPainter *painter);
@@ -163,6 +206,15 @@ private:
void drawShadePanel(QWasmTitleBarOptions options, QPainter *painter);
void drawItemPixmap(QPainter *painter, const QRect &rect,
int alignment, const QPixmap &pixmap) const;
+
+ static int keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
+ static int mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
+ static int focus_cb(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData);
+ static int wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData);
+
+ static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
+
+ QWasmEventTranslator *eventTranslator;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QWasmCompositor::SubControls)
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
index 34b1a7358a..0285ace1e6 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
@@ -177,101 +177,12 @@ static constexpr const auto DeadKeyShiftTbl = qMakeArray(
>::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_usePlatformMacSpecifics = false;
-
-bool g_useNaturalScrolling = true; // natural scrolling is default on linux/windows
-
-static void mouseWheelEvent(emscripten::val event) {
-
- emscripten::val wheelInterted = event["webkitDirectionInvertedFromDevice"];
-
- if (wheelInterted.as<bool>()) {
- g_useNaturalScrolling = true;
- }
-}
-
-EMSCRIPTEN_BINDINGS(qtMouseModule) {
- function("qtMouseWheelEvent", &mouseWheelEvent);
-}
-
-QWasmEventTranslator::QWasmEventTranslator(QWasmScreen *screen)
- : QObject(screen)
- , draggedWindow(nullptr)
- , lastWindow(nullptr)
- , pressedButtons(Qt::NoButton)
- , resizeMode(QWasmWindow::ResizeNone)
+QWasmEventTranslator::QWasmEventTranslator() : QObject()
{
- touchDevice = new QPointingDevice("touchscreen", 1, QInputDevice::DeviceType::TouchScreen,
- QPointingDevice::PointerType::Finger,
- QPointingDevice::Capability::Position | QPointingDevice::Capability::Area | QPointingDevice::Capability::NormalizedPosition,
- 10, 0);
- QWindowSystemInterface::registerInputDevice(touchDevice);
-
- initEventHandlers();
}
QWasmEventTranslator::~QWasmEventTranslator()
{
- // deregister event handlers
- QByteArray canvasSelector = "#" + screen()->canvasId().toUtf8();
- emscripten_set_keydown_callback(canvasSelector.constData(), 0, 0, NULL);
- emscripten_set_keyup_callback(canvasSelector.constData(), 0, 0, NULL);
-
- emscripten_set_mousedown_callback(canvasSelector.constData(), 0, 0, NULL);
- emscripten_set_mouseup_callback(canvasSelector.constData(), 0, 0, NULL);
- emscripten_set_mousemove_callback(canvasSelector.constData(), 0, 0, NULL);
-
- emscripten_set_focus_callback(canvasSelector.constData(), 0, 0, NULL);
-
- emscripten_set_wheel_callback(canvasSelector.constData(), 0, 0, NULL);
-
- emscripten_set_touchstart_callback(canvasSelector.constData(), 0, 0, NULL);
- emscripten_set_touchend_callback(canvasSelector.constData(), 0, 0, NULL);
- emscripten_set_touchmove_callback(canvasSelector.constData(), 0, 0, NULL);
- emscripten_set_touchcancel_callback(canvasSelector.constData(), 0, 0, NULL);
-}
-
-void QWasmEventTranslator::initEventHandlers()
-{
- QByteArray canvasSelector = "#" + screen()->canvasId().toUtf8();
-
- // The Platform Detect: expand coverage and move as needed
- enum Platform {
- GenericPlatform,
- MacOSPlatform
- };
- Platform platform = Platform(emscripten::val::global("navigator")["platform"]
- .call<bool>("includes", emscripten::val("Mac")));
- g_usePlatformMacSpecifics = (platform == MacOSPlatform);
-
- if (platform == MacOSPlatform) {
- g_useNaturalScrolling = false; // make this !default on macOS
-
- if (!emscripten::val::global("window")["safari"].isUndefined()) {
- val canvas = screen()->canvas();
- canvas.call<void>("addEventListener",
- val("wheel"),
- val::module_property("qtMouseWheelEvent"));
- }
- }
-
- emscripten_set_keydown_callback(canvasSelector.constData(), (void *)this, 1, &keyboard_cb);
- emscripten_set_keyup_callback(canvasSelector.constData(), (void *)this, 1, &keyboard_cb);
-
- emscripten_set_mousedown_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
- emscripten_set_mouseup_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
- emscripten_set_mousemove_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
-
- emscripten_set_focus_callback(canvasSelector.constData(), (void *)this, 1, &focus_cb);
-
- emscripten_set_wheel_callback(canvasSelector.constData(), (void *)this, 1, &wheel_cb);
-
- emscripten_set_touchstart_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
- emscripten_set_touchend_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
- emscripten_set_touchmove_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
- emscripten_set_touchcancel_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
}
template <typename Event>
@@ -294,13 +205,15 @@ QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translatKeyModifier(const Eve
else
keyModifier |= Qt::MetaModifier;
}
+
return keyModifier;
}
-QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateKeyboardEventModifier(const EmscriptenKeyboardEvent *keyEvent)
+QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateKeyboardEventModifier(const EmscriptenKeyboardEvent *event)
{
- QFlags<Qt::KeyboardModifier> keyModifier = translatKeyModifier(keyEvent);
- if (keyEvent->location == DOM_KEY_LOCATION_NUMPAD) {
+ QFlags<Qt::KeyboardModifier> keyModifier = translatKeyModifier(event);
+
+ if (event->location == DOM_KEY_LOCATION_NUMPAD) {
keyModifier |= Qt::KeypadModifier;
}
@@ -312,17 +225,9 @@ QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateMouseEventModifier(c
return translatKeyModifier(mouseEvent);
}
-int QWasmEventTranslator::keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
+QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateTouchEventModifier(const EmscriptenTouchEvent *touchEvent)
{
- QWasmEventTranslator *wasmTranslator = reinterpret_cast<QWasmEventTranslator *>(userData);
- bool accepted = wasmTranslator->processKeyboard(eventType, keyEvent);
-
- return accepted ? 1 : 0;
-}
-
-QWasmScreen *QWasmEventTranslator::screen()
-{
- return static_cast<QWasmScreen *>(parent());
+ return translatKeyModifier(touchEvent);
}
Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey)
@@ -367,335 +272,6 @@ Qt::MouseButton QWasmEventTranslator::translateMouseButton(unsigned short button
return Qt::NoButton;
}
-int QWasmEventTranslator::mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
-{
- QWasmEventTranslator *translator = (QWasmEventTranslator*)userData;
- bool accepted = translator->processMouse(eventType,mouseEvent);
- return accepted;
-}
-
-void resizeWindow(QWindow *window, QWasmWindow::ResizeMode mode,
- QRect startRect, QPoint amount)
-{
- if (mode == QWasmWindow::ResizeNone)
- return;
-
- bool top = mode == QWasmWindow::ResizeTopLeft ||
- mode == QWasmWindow::ResizeTop ||
- mode == QWasmWindow::ResizeTopRight;
-
- bool bottom = mode == QWasmWindow::ResizeBottomLeft ||
- mode == QWasmWindow::ResizeBottom ||
- mode == QWasmWindow::ResizeBottomRight;
-
- bool left = mode == QWasmWindow::ResizeLeft ||
- mode == QWasmWindow::ResizeTopLeft ||
- mode == QWasmWindow::ResizeBottomLeft;
-
- bool right = mode == QWasmWindow::ResizeRight ||
- mode == QWasmWindow::ResizeTopRight ||
- mode == QWasmWindow::ResizeBottomRight;
-
- int x1 = startRect.left();
- int y1 = startRect.top();
- int x2 = startRect.right();
- int y2 = startRect.bottom();
-
- if (left)
- x1 += amount.x();
- if (top)
- y1 += amount.y();
- if (right)
- x2 += amount.x();
- if (bottom)
- y2 += amount.y();
-
- int w = x2-x1;
- int h = y2-y1;
-
- if (w < window->minimumWidth()) {
- if (left)
- x1 -= window->minimumWidth() - w;
-
- w = window->minimumWidth();
- }
-
- if (h < window->minimumHeight()) {
- if (top)
- y1 -= window->minimumHeight() - h;
-
- h = window->minimumHeight();
- }
-
- window->setGeometry(x1, y1, w, h);
-}
-
-bool QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent)
-{
- QPoint targetPoint(mouseEvent->targetX, mouseEvent->targetY);
- QPoint globalPoint = screen()->geometry().topLeft() + targetPoint;
-
- QEvent::Type buttonEventType = QEvent::None;
- Qt::MouseButton button = Qt::NoButton;
- Qt::KeyboardModifiers modifiers = translateMouseEventModifier(mouseEvent);
-
- QWindow *window2 = nullptr;
- if (resizeMode == QWasmWindow::ResizeNone)
- window2 = screen()->compositor()->windowAt(globalPoint, 5);
-
- if (window2 == nullptr) {
- window2 = lastWindow;
- } else {
- lastWindow = window2;
- }
-
- QPoint localPoint = window2->mapFromGlobal(globalPoint);
- bool interior = window2->geometry().contains(globalPoint);
-
- QWasmWindow *htmlWindow = static_cast<QWasmWindow*>(window2->handle());
- switch (eventType) {
- case EMSCRIPTEN_EVENT_MOUSEDOWN:
- {
- button = translateMouseButton(mouseEvent->button);
-
- if (window2)
- window2->requestActivate();
-
- pressedButtons.setFlag(button);
-
- pressedWindow = window2;
- buttonEventType = QEvent::MouseButtonPress;
-
- // button overview:
- // 0 = primary mouse button, usually left click
- // 1 = middle mouse button, usually mouse wheel
- // 2 = right mouse button, usually right click
- // from: https://w3c.github.io/uievents/#dom-mouseevent-button
- if (mouseEvent->button == 0) {
- if (!(htmlWindow->m_windowState & Qt::WindowFullScreen) && !(htmlWindow->m_windowState & Qt::WindowMaximized)) {
- if (htmlWindow && window2->flags().testFlag(Qt::WindowTitleHint) && htmlWindow->isPointOnTitle(globalPoint))
- draggedWindow = window2;
- else if (htmlWindow && htmlWindow->isPointOnResizeRegion(globalPoint)) {
- draggedWindow = window2;
- resizeMode = htmlWindow->resizeModeAtPoint(globalPoint);
- resizePoint = globalPoint;
- resizeStartRect = window2->geometry();
- }
- }
- }
-
- htmlWindow->injectMousePressed(localPoint, globalPoint, button, modifiers);
- break;
- }
- case EMSCRIPTEN_EVENT_MOUSEUP:
- {
- button = translateMouseButton(mouseEvent->button);
- pressedButtons.setFlag(button, false);
- buttonEventType = QEvent::MouseButtonRelease;
- QWasmWindow *oldWindow = nullptr;
-
- if (mouseEvent->button == 0 && pressedWindow) {
- oldWindow = static_cast<QWasmWindow*>(pressedWindow->handle());
- pressedWindow = nullptr;
- }
-
- if (draggedWindow && pressedButtons.testFlag(Qt::NoButton)) {
- draggedWindow = nullptr;
- resizeMode = QWasmWindow::ResizeNone;
- }
-
- if (oldWindow)
- oldWindow->injectMouseReleased(localPoint, globalPoint, button, modifiers);
- else
- htmlWindow->injectMouseReleased(localPoint, globalPoint, button, modifiers);
- break;
- }
- case EMSCRIPTEN_EVENT_MOUSEMOVE: // drag event
- {
- buttonEventType = QEvent::MouseMove;
-
- if (htmlWindow && pressedButtons.testFlag(Qt::NoButton)) {
-
- if (htmlWindow->isPointOnResizeRegion(globalPoint)) {
- QCursor resizingCursor = cursorForMode(htmlWindow->resizeModeAtPoint(globalPoint));
-
- if (resizingCursor != window2->cursor()) {
- isCursorOverridden = true;
- QWasmCursor::setOverrideWasmCursor(&resizingCursor, window2->screen());
- }
- } else { // off resizing area
- if (isCursorOverridden) {
- isCursorOverridden = false;
- QWasmCursor::clearOverrideWasmCursor(window2->screen());
- }
- }
- }
-
- if (!(htmlWindow->m_windowState & Qt::WindowFullScreen) && !(htmlWindow->m_windowState & Qt::WindowMaximized)) {
- if (resizeMode == QWasmWindow::ResizeNone && draggedWindow) {
- draggedWindow->setX(draggedWindow->x() + mouseEvent->movementX);
- draggedWindow->setY(draggedWindow->y() + mouseEvent->movementY);
- }
-
- if (resizeMode != QWasmWindow::ResizeNone && !(htmlWindow->m_windowState & Qt::WindowFullScreen)) {
- QPoint delta = QPoint(mouseEvent->targetX, mouseEvent->targetY) - resizePoint;
- resizeWindow(draggedWindow, resizeMode, resizeStartRect, delta);
- }
- }
- break;
- }
- default: // MOUSELEAVE MOUSEENTER
- break;
- };
- if (!window2 && buttonEventType == QEvent::MouseButtonRelease) {
- window2 = lastWindow;
- lastWindow = nullptr;
- interior = true;
- }
- bool accepted = true;
- if (window2 && interior) {
- accepted = QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(
- window2, getTimestamp(), localPoint, globalPoint, pressedButtons, button, buttonEventType, modifiers);
- }
- return accepted;
-}
-
-int QWasmEventTranslator::focus_cb(int /*eventType*/, const EmscriptenFocusEvent */*focusEvent*/, void */*userData*/)
-{
- return 0;
-}
-
-int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
-{
- Q_UNUSED(eventType);
-
- QWasmEventTranslator *eventTranslator = static_cast<QWasmEventTranslator *>(userData);
- EmscriptenMouseEvent mouseEvent = wheelEvent->mouse;
-
- int scrollFactor = 0;
- switch (wheelEvent->deltaMode) {
- case DOM_DELTA_PIXEL://chrome safari
- scrollFactor = 1;
- break;
- case DOM_DELTA_LINE: //firefox
- scrollFactor = 12;
- break;
- case DOM_DELTA_PAGE:
- scrollFactor = 20;
- break;
- };
-
- if (g_useNaturalScrolling) //macOS platform has document oriented scrolling
- scrollFactor = -scrollFactor;
-
- QWasmEventTranslator *translator = (QWasmEventTranslator*)userData;
- Qt::KeyboardModifiers modifiers = translator->translateMouseEventModifier(&mouseEvent);
- QPoint targetPoint(mouseEvent.targetX, mouseEvent.targetY);
- QPoint globalPoint = eventTranslator->screen()->geometry().topLeft() + targetPoint;
-
- 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);
-
- bool accepted = QWindowSystemInterface::handleWheelEvent(window2, getTimestamp(), localPoint,
- globalPoint, QPoint(), pixelDelta, modifiers);
- return static_cast<int>(accepted);
-}
-
-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;
-
- for (int i = 0; i < touchEvent->numTouches; i++) {
-
- const EmscriptenTouchPoint *touches = &touchEvent->touches[i];
-
- 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;
-
- touchPoint.area = QRect(0, 0, 8, 8);
- touchPoint.id = touches->identifier;
- 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:
- if (tp != pressedTouchIds.constEnd()) {
- touchPoint.state = (stationaryTouchPoint
- ? QEventPoint::State::Stationary
- : QEventPoint::State::Updated);
- } else {
- touchPoint.state = QEventPoint::State::Pressed;
- }
- pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
-
- break;
- case EMSCRIPTEN_EVENT_TOUCHEND:
- touchPoint.state = QEventPoint::State::Released;
- pressedTouchIds.remove(touchPoint.id);
- break;
- case EMSCRIPTEN_EVENT_TOUCHMOVE:
- touchPoint.state = (stationaryTouchPoint
- ? QEventPoint::State::Stationary
- : QEventPoint::State::Updated);
-
- pressedTouchIds.insert(touchPoint.id, touchPoint.normalPosition);
- break;
- default:
- break;
- }
-
- touchPointList.append(touchPoint);
- }
-
- QFlags<Qt::KeyboardModifier> keyModifier = translatKeyModifier(touchEvent);
-
- bool accepted = QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(
- window2, getTimestamp(), touchDevice, touchPointList, keyModifier);
-
- if (eventType == EMSCRIPTEN_EVENT_TOUCHCANCEL)
- accepted = QWindowSystemInterface::handleTouchCancelEvent(window2, getTimestamp(), touchDevice, keyModifier);
-
- return static_cast<int>(accepted);
-}
-
-quint64 QWasmEventTranslator::getTimestamp()
-{
- return emscripten_performance_now();
-}
-
struct KeyMapping { Qt::Key from, to; };
constexpr KeyMapping tildeKeyTable[] = { // ~
@@ -750,12 +326,12 @@ static Qt::Key find(const KeyMapping (&map)[N], Qt::Key key) noexcept
return find_impl(map, map + N, key);
}
-Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey)
+Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey, bool is_mac)
{
Qt::Key wasmKey = Qt::Key_unknown;
if (deadKey == Qt::Key_QuoteLeft ) {
- if (g_usePlatformMacSpecifics) { // ` macOS: Key_Dead_Grave
+ if (is_mac) { // ` macOS: Key_Dead_Grave
wasmKey = find(graveKeyTable, accentBaseKey);
} else {
wasmKey = find(diaeresisKeyTable, accentBaseKey);
@@ -790,121 +366,83 @@ Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBa
return wasmKey;
}
-bool QWasmEventTranslator::processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent)
+QCursor QWasmEventTranslator::cursorForMode(QWasmCompositor::ResizeMode m)
+{
+ switch (m) {
+ case QWasmCompositor::ResizeTopLeft:
+ case QWasmCompositor::ResizeBottomRight:
+ return Qt::SizeFDiagCursor;
+ case QWasmCompositor::ResizeBottomLeft:
+ case QWasmCompositor::ResizeTopRight:
+ return Qt::SizeBDiagCursor;
+ case QWasmCompositor::ResizeTop:
+ case QWasmCompositor::ResizeBottom:
+ return Qt::SizeVerCursor;
+ case QWasmCompositor::ResizeLeft:
+ case QWasmCompositor::ResizeRight:
+ return Qt::SizeHorCursor;
+ case QWasmCompositor::ResizeNone:
+ return Qt::ArrowCursor;
+ }
+ return Qt::ArrowCursor;
+}
+
+QString QWasmEventTranslator::getKeyText(const EmscriptenKeyboardEvent *keyEvent)
{
+ QString keyText;
Qt::Key qtKey = translateEmscriptKey(keyEvent);
+ //Qt::KeyboardModifiers modifiers = translateKeyboardEventModifier(keyEvent);
- Qt::KeyboardModifiers modifiers = translateKeyboardEventModifier(keyEvent);
+ if (m_emDeadKey != Qt::Key_unknown) {
+ Qt::Key transformedKey = translateDeadKey(m_emDeadKey, qtKey);
- 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;
- }
+ 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;
- }
+ }
+ } 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);
+ return keyText;
+}
- // 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)) {
- if (qtKey == Qt::Key_V) {
- QWasmIntegration::get()->getWasmClipboard()->isPaste = true;
- }
- return false;
- }
+Qt::Key QWasmEventTranslator::getKey(const EmscriptenKeyboardEvent *keyEvent)
+{
+ Qt::Key qtKey = translateEmscriptKey(keyEvent);
- bool accepted = false;
-
- if (keyType == QEvent::KeyPress &&
- mods.testFlag(Qt::ControlModifier)
- && qtKey == Qt::Key_V) {
- QWasmIntegration::get()->getWasmClipboard()->isPaste = true;
- accepted = false; // continue on to event
- } 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()->isPaste = false;
- accepted = false; // continue on to event
+ 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;
}
- return accepted;
+ return qtKey;
}
-QCursor QWasmEventTranslator::cursorForMode(QWasmWindow::ResizeMode m)
+void QWasmEventTranslator::setStickyDeadKey(const EmscriptenKeyboardEvent *keyEvent)
{
- switch (m) {
- case QWasmWindow::ResizeTopLeft:
- case QWasmWindow::ResizeBottomRight:
- return Qt::SizeFDiagCursor;
- case QWasmWindow::ResizeBottomLeft:
- case QWasmWindow::ResizeTopRight:
- return Qt::SizeBDiagCursor;
- case QWasmWindow::ResizeTop:
- case QWasmWindow::ResizeBottom:
- return Qt::SizeVerCursor;
- case QWasmWindow::ResizeLeft:
- case QWasmWindow::ResizeRight:
- return Qt::SizeHorCursor;
- case QWasmWindow::ResizeNone:
- return Qt::ArrowCursor;
+ Qt::Key qtKey = translateEmscriptKey(keyEvent);
+
+ if (m_emStickyDeadKey && qtKey != Qt::Key_Alt) {
+ m_emStickyDeadKey = false;
}
- return Qt::ArrowCursor;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h
index 0b579691c5..341971d79f 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.h
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h
@@ -49,59 +49,37 @@ class QWasmEventTranslator : public QObject
public:
- explicit QWasmEventTranslator(QWasmScreen *screen);
+ explicit QWasmEventTranslator();
~QWasmEventTranslator();
- static int keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
- static int mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
- static int focus_cb(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData);
- static int wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData);
-
- static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
-
- void processEvents();
- void initEventHandlers();
- int handleTouch(int eventType, const EmscriptenTouchEvent *touchEvent);
-
-Q_SIGNALS:
- void getWindowAt(const QPoint &point, QWindow **window);
-private:
- QWasmScreen *screen();
- Qt::Key translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey);
template <typename Event>
QFlags<Qt::KeyboardModifier> translatKeyModifier(const Event *event);
+
+ static Qt::Key translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey);
QFlags<Qt::KeyboardModifier> translateKeyboardEventModifier(const EmscriptenKeyboardEvent *keyEvent);
QFlags<Qt::KeyboardModifier> translateMouseEventModifier(const EmscriptenMouseEvent *mouseEvent);
- Qt::MouseButton translateMouseButton(unsigned short button);
+ QFlags<Qt::KeyboardModifier> translateTouchEventModifier(const EmscriptenTouchEvent *touchEvent);
+ static Qt::MouseButton translateMouseButton(unsigned short button);
+ static QCursor cursorForMode(QWasmCompositor::ResizeMode mode);
- bool processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent);
- bool processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent);
+ QString getKeyText(const EmscriptenKeyboardEvent *keyEvent);
+ Qt::Key getKey(const EmscriptenKeyboardEvent *keyEvent);
+ void setStickyDeadKey(const EmscriptenKeyboardEvent *keyEvent);
- Qt::Key translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey);
+ void setIsMac(bool is_mac) {g_usePlatformMacSpecifics = is_mac;};
- QMap <int, QPointF> pressedTouchIds;
+Q_SIGNALS:
+ void getWindowAt(const QPoint &point, QWindow **window);
+private:
+ bool g_usePlatformMacSpecifics = false;
+ static Qt::Key translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey, bool is_mac = false);
private:
- QPointer<QWindow> draggedWindow;
- QPointer<QWindow> pressedWindow;
- QPointer<QWindow> lastWindow;
- Qt::MouseButtons pressedButtons;
-
- QWasmWindow::ResizeMode resizeMode;
- QPoint resizePoint;
- QRect resizeStartRect;
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- QPointingDevice *touchDevice;
-#else
- QTouchDevice *touchDevice;
-#endif
static quint64 getTimestamp();
Qt::Key m_emDeadKey = Qt::Key_unknown;
bool m_emStickyDeadKey = false;
- QCursor cursorForMode(QWasmWindow::ResizeMode mode);
- QCursor overriddenCursor;
- bool isCursorOverridden = false;
+
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index 3dfd8cfe12..031128563e 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -328,4 +328,9 @@ void QWasmIntegration::resizeAllScreens()
canvasAndScreen.second->updateQScreenAndCanvasRenderSize();
}
+quint64 QWasmIntegration::getTimestamp()
+{
+ return emscripten_performance_now();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h
index 16c48e1ea1..46fab8e818 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.h
+++ b/src/plugins/platforms/wasm/qwasmintegration.h
@@ -89,6 +89,7 @@ public:
void resizeAllScreens();
void updateDpi();
void removeBackingStore(QWindow* window);
+ static quint64 getTimestamp();
private:
mutable QWasmFontDatabase *m_fontDb;
diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp
index 3cc067bbe7..eb77dc65b9 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.cpp
+++ b/src/plugins/platforms/wasm/qwasmscreen.cpp
@@ -55,7 +55,7 @@ const char * QWasmScreen::m_canvasResizeObserverCallbackContextPropertyName = "d
QWasmScreen::QWasmScreen(const emscripten::val &canvas)
: m_canvas(canvas)
, m_compositor(new QWasmCompositor(this))
- , m_eventTranslator(new QWasmEventTranslator(this))
+ , m_eventTranslator(new QWasmEventTranslator())
{
updateQScreenAndCanvasRenderSize();
m_canvas.call<void>("focus");
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index 3819e8daa6..a25b5a262c 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -274,7 +274,7 @@ bool QWasmWindow::isPointOnResizeRegion(QPoint point) const
return resizeRegion().contains(point);
}
-QWasmWindow::ResizeMode QWasmWindow::resizeModeAtPoint(QPoint point) const
+QWasmCompositor::ResizeMode QWasmWindow::resizeModeAtPoint(QPoint point) const
{
QPoint p1 = window()->frameGeometry().topLeft() - QPoint(5, 5);
QPoint p2 = window()->frameGeometry().bottomRight() + QPoint(5, 5);
@@ -291,28 +291,28 @@ QWasmWindow::ResizeMode QWasmWindow::resizeModeAtPoint(QPoint point) const
if (top.contains(point)) {
// Top
if (left.contains(point))
- return ResizeTopLeft;
+ return QWasmCompositor::ResizeTopLeft;
if (center.contains(point))
- return ResizeTop;
+ return QWasmCompositor::ResizeTop;
if (right.contains(point))
- return ResizeTopRight;
+ return QWasmCompositor::ResizeTopRight;
} else if (middle.contains(point)) {
// Middle
if (left.contains(point))
- return ResizeLeft;
+ return QWasmCompositor::ResizeLeft;
if (right.contains(point))
- return ResizeRight;
+ return QWasmCompositor::ResizeRight;
} else if (bottom.contains(point)) {
// Bottom
if (left.contains(point))
- return ResizeBottomLeft;
+ return QWasmCompositor::ResizeBottomLeft;
if (center.contains(point))
- return ResizeBottom;
+ return QWasmCompositor::ResizeBottom;
if (right.contains(point))
- return ResizeBottomRight;
+ return QWasmCompositor::ResizeBottomRight;
}
- return ResizeNone;
+ return QWasmCompositor::ResizeNone;
}
QRect getSubControlRect(const QWasmWindow *window, QWasmCompositor::SubControls subControl)
diff --git a/src/plugins/platforms/wasm/qwasmwindow.h b/src/plugins/platforms/wasm/qwasmwindow.h
index 5df6d9dc66..686a26430e 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.h
+++ b/src/plugins/platforms/wasm/qwasmwindow.h
@@ -39,23 +39,9 @@
QT_BEGIN_NAMESPACE
-class QWasmCompositor;
-
class QWasmWindow : public QPlatformWindow
{
public:
- enum ResizeMode {
- ResizeNone,
- ResizeTopLeft,
- ResizeTop,
- ResizeTopRight,
- ResizeRight,
- ResizeBottomRight,
- ResizeBottom,
- ResizeBottomLeft,
- ResizeLeft
- };
-
QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore);
~QWasmWindow();
void destroy();
@@ -92,7 +78,7 @@ public:
QRegion resizeRegion() const;
bool isPointOnTitle(QPoint point) const;
bool isPointOnResizeRegion(QPoint point) const;
- ResizeMode resizeModeAtPoint(QPoint point) const;
+ QWasmCompositor::ResizeMode resizeModeAtPoint(QPoint point) const;
QRect maxButtonRect() const;
QRect minButtonRect() const;
QRect closeButtonRect() const;