Improve window dragging on WASM
Window dragging has been considerably improved by replacing the mouse events by pointer events and placing a pointer lock on WASM canvas, so that off-browser window events are delivered to us. Translation of the drag origin has been limited to inside the canvas, so that a window cannot be dragged so far that it becomes offscreen and is unreachable. Change-Id: Id177c630a6466f04464a513371d6b97d3a098b6a Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
This commit is contained in:
parent
57b4e30ff8
commit
5a4e5c62af
@ -15,12 +15,14 @@ qt_internal_add_plugin(QWasmIntegrationPlugin
|
||||
qwasmclipboard.cpp qwasmclipboard.h
|
||||
qwasmcompositor.cpp qwasmcompositor.h
|
||||
qwasmcursor.cpp qwasmcursor.h
|
||||
qwasmevent.cpp qwasmevent.h
|
||||
qwasmeventdispatcher.cpp qwasmeventdispatcher.h
|
||||
qwasmeventtranslator.cpp qwasmeventtranslator.h
|
||||
qwasmfontdatabase.cpp qwasmfontdatabase.h
|
||||
qwasmintegration.cpp qwasmintegration.h
|
||||
qwasmoffscreensurface.cpp qwasmoffscreensurface.h
|
||||
qwasmopenglcontext.cpp qwasmopenglcontext.h
|
||||
qwasmplatform.cpp qwasmplatform.h
|
||||
qwasmscreen.cpp qwasmscreen.h
|
||||
qwasmservices.cpp qwasmservices.h
|
||||
qwasmstring.cpp qwasmstring.h
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "qwasmeventtranslator.h"
|
||||
#include "qwasmeventdispatcher.h"
|
||||
#include "qwasmclipboard.h"
|
||||
#include "qwasmevent.h"
|
||||
|
||||
#include <QtOpenGL/qopengltexture.h>
|
||||
|
||||
@ -58,6 +59,7 @@ EMSCRIPTEN_BINDINGS(qtMouseModule) {
|
||||
|
||||
QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
|
||||
: QObject(screen)
|
||||
, m_windowManipulation(screen)
|
||||
, m_blitter(new QOpenGLTextureBlitter)
|
||||
, m_eventTranslator(std::make_unique<QWasmEventTranslator>())
|
||||
{
|
||||
@ -87,12 +89,6 @@ void QWasmCompositor::deregisterEventHandlers()
|
||||
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_mouseenter_callback(canvasSelector.constData(), 0, 0, NULL);
|
||||
emscripten_set_mouseleave_callback(canvasSelector.constData(), 0, 0, NULL);
|
||||
|
||||
emscripten_set_focus_callback(canvasSelector.constData(), 0, 0, NULL);
|
||||
|
||||
emscripten_set_wheel_callback(canvasSelector.constData(), 0, 0, NULL);
|
||||
@ -133,9 +129,7 @@ void QWasmCompositor::initEventHandlers()
|
||||
{
|
||||
QByteArray canvasSelector = screen()->canvasTargetId().toUtf8();
|
||||
|
||||
m_eventTranslator->g_usePlatformMacSpecifics
|
||||
= (QWasmIntegration::get()->platform == QWasmIntegration::MacOSPlatform);
|
||||
if (QWasmIntegration::get()->platform == QWasmIntegration::MacOSPlatform) {
|
||||
if (platform() == Platform::MacOS) {
|
||||
if (!emscripten::val::global("window")["safari"].isUndefined()) {
|
||||
val canvas = screen()->canvas();
|
||||
canvas.call<void>("addEventListener",
|
||||
@ -149,11 +143,17 @@ void QWasmCompositor::initEventHandlers()
|
||||
emscripten_set_keydown_callback(canvasSelector.constData(), (void *)this, UseCapture, &keyboard_cb);
|
||||
emscripten_set_keyup_callback(canvasSelector.constData(), (void *)this, UseCapture, &keyboard_cb);
|
||||
|
||||
emscripten_set_mousedown_callback(canvasSelector.constData(), (void *)this, UseCapture, &mouse_cb);
|
||||
emscripten_set_mouseup_callback(canvasSelector.constData(), (void *)this, UseCapture, &mouse_cb);
|
||||
emscripten_set_mousemove_callback(canvasSelector.constData(), (void *)this, UseCapture, &mouse_cb);
|
||||
emscripten_set_mouseenter_callback(canvasSelector.constData(), (void *)this, UseCapture, &mouse_cb);
|
||||
emscripten_set_mouseleave_callback(canvasSelector.constData(), (void *)this, UseCapture, &mouse_cb);
|
||||
val canvas = screen()->canvas();
|
||||
const auto callback = std::function([this](emscripten::val event) {
|
||||
if (processPointer(*PointerEvent::fromWeb(event)))
|
||||
event.call<void>("preventDefault");
|
||||
});
|
||||
|
||||
m_pointerDownCallback = std::make_unique<qstdweb::EventCallback>(canvas, "pointerdown", callback);
|
||||
m_pointerMoveCallback = std::make_unique<qstdweb::EventCallback>(canvas, "pointermove", callback);
|
||||
m_pointerUpCallback = std::make_unique<qstdweb::EventCallback>(canvas, "pointerup", callback);
|
||||
m_pointerEnterCallback = std::make_unique<qstdweb::EventCallback>(canvas, "pointerenter", callback);
|
||||
m_pointerLeaveCallback = std::make_unique<qstdweb::EventCallback>(canvas, "pointerleave", callback);
|
||||
|
||||
emscripten_set_focus_callback(canvasSelector.constData(), (void *)this, UseCapture, &focus_cb);
|
||||
|
||||
@ -164,7 +164,6 @@ void QWasmCompositor::initEventHandlers()
|
||||
emscripten_set_touchmove_callback(canvasSelector.constData(), (void *)this, UseCapture, &touchCallback);
|
||||
emscripten_set_touchcancel_callback(canvasSelector.constData(), (void *)this, UseCapture, &touchCallback);
|
||||
|
||||
val canvas = screen()->canvas();
|
||||
canvas.call<void>("addEventListener",
|
||||
std::string("drop"),
|
||||
val::module_property("qtDrop"), val(true));
|
||||
@ -859,60 +858,27 @@ void QWasmCompositor::frame()
|
||||
m_context->swapBuffers(someWindow->window());
|
||||
}
|
||||
|
||||
void QWasmCompositor::resizeWindow(QWindow *window, QWasmCompositor::ResizeMode mode,
|
||||
QRect startRect, QPoint amount)
|
||||
void QWasmCompositor::WindowManipulation::resizeWindow(const QPoint& amount)
|
||||
{
|
||||
if (mode == QWasmCompositor::ResizeNone)
|
||||
return;
|
||||
const auto& minShrink = std::get<ResizeState>(m_state->operationSpecific).m_minShrink;
|
||||
const auto& maxGrow = std::get<ResizeState>(m_state->operationSpecific).m_maxGrow;
|
||||
const auto& resizeMode = std::get<ResizeState>(m_state->operationSpecific).m_resizeMode;
|
||||
|
||||
bool top = mode == QWasmCompositor::ResizeTopLeft ||
|
||||
mode == QWasmCompositor::ResizeTop ||
|
||||
mode == QWasmCompositor::ResizeTopRight;
|
||||
const QPoint cappedGrowVector(
|
||||
std::min(maxGrow.x(), std::max(minShrink.x(),
|
||||
(resizeMode & Left) ? -amount.x() : (resizeMode & Right) ? amount.x() : 0)),
|
||||
std::min(maxGrow.y(), std::max(minShrink.y(),
|
||||
(resizeMode & Top) ? -amount.y() : (resizeMode & Bottom) ? amount.y() : 0)));
|
||||
|
||||
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);
|
||||
const auto& initialBounds =
|
||||
std::get<ResizeState>(m_state->operationSpecific).m_initialWindowBounds;
|
||||
m_state->window->setGeometry(
|
||||
initialBounds.adjusted(
|
||||
(resizeMode & Left) ? -cappedGrowVector.x() : 0,
|
||||
(resizeMode & Top) ? -cappedGrowVector.y() : 0,
|
||||
(resizeMode & Right) ? cappedGrowVector.x() : 0,
|
||||
(resizeMode & Bottom) ? cappedGrowVector.y() : 0
|
||||
));
|
||||
}
|
||||
|
||||
void QWasmCompositor::notifyTopWindowChanged(QWasmWindow *window)
|
||||
@ -945,12 +911,6 @@ int QWasmCompositor::keyboard_cb(int eventType, const EmscriptenKeyboardEvent *k
|
||||
return static_cast<int>(wasmCompositor->processKeyboard(eventType, keyEvent));
|
||||
}
|
||||
|
||||
int QWasmCompositor::mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
|
||||
{
|
||||
QWasmCompositor *compositor = (QWasmCompositor*)userData;
|
||||
return static_cast<int>(compositor->processMouse(eventType, mouseEvent));
|
||||
}
|
||||
|
||||
int QWasmCompositor::focus_cb(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData)
|
||||
{
|
||||
Q_UNUSED(eventType)
|
||||
@ -972,19 +932,18 @@ int QWasmCompositor::touchCallback(int eventType, const EmscriptenTouchEvent *to
|
||||
return static_cast<int>(compositor->handleTouch(eventType, touchEvent));
|
||||
}
|
||||
|
||||
bool QWasmCompositor::processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent)
|
||||
bool QWasmCompositor::processPointer(const PointerEvent& event)
|
||||
{
|
||||
const Qt::MouseButton button = QWasmEventTranslator::translateMouseButton(mouseEvent->button);
|
||||
if (event.pointerType != PointerType::Mouse)
|
||||
return false;
|
||||
|
||||
const QPoint targetPointInCanvasCoords(mouseEvent->targetX, mouseEvent->targetY);
|
||||
const QPoint targetPointInScreenCoords = screen()->geometry().topLeft() + targetPointInCanvasCoords;
|
||||
const QPoint targetPointInScreenCoords = screen()->geometry().topLeft() + event.point;
|
||||
|
||||
QEvent::Type buttonEventType = QEvent::None;
|
||||
Qt::KeyboardModifiers modifiers = m_eventTranslator->translateMouseEventModifier(mouseEvent);
|
||||
|
||||
QWindow *const targetWindow = ([this, &targetPointInScreenCoords]() -> QWindow * {
|
||||
auto *targetWindow =
|
||||
m_resizeMode == QWasmCompositor::ResizeNone ?
|
||||
m_windowManipulation.operation() == WindowManipulation::Operation::None ?
|
||||
screen()->compositor()->windowAt(targetPointInScreenCoords, 5) : nullptr;
|
||||
|
||||
return targetWindow ? targetWindow : m_lastMouseTargetWindow.get();
|
||||
@ -1006,57 +965,41 @@ bool QWasmCompositor::processMouse(int eventType, const EmscriptenMouseEvent *mo
|
||||
Qt::WindowStates windowState = targetWindow->windowState();
|
||||
const bool isTargetWindowResizable = !windowState.testFlag(Qt::WindowMaximized) && !windowState.testFlag(Qt::WindowFullScreen);
|
||||
|
||||
switch (eventType) {
|
||||
case EMSCRIPTEN_EVENT_MOUSEDOWN:
|
||||
switch (event.type) {
|
||||
case EventType::PointerDown:
|
||||
{
|
||||
buttonEventType = QEvent::MouseButtonPress;
|
||||
m_pressedButtons.setFlag(button);
|
||||
|
||||
if (targetWindow)
|
||||
targetWindow->requestActivate();
|
||||
|
||||
m_pressedWindow = targetWindow;
|
||||
|
||||
if (isTargetWindowResizable && button == Qt::MouseButton::LeftButton && !isTargetWindowBlocked) {
|
||||
if (wasmTargetWindow->isPointOnTitle(targetPointInScreenCoords)) {
|
||||
m_windowBeingManipulated = targetWindow;
|
||||
} else if (wasmTargetWindow->isPointOnResizeRegion(targetPointInScreenCoords)) {
|
||||
m_windowBeingManipulated = targetWindow;
|
||||
m_resizeMode = wasmTargetWindow->resizeModeAtPoint(targetPointInScreenCoords);
|
||||
m_resizePoint = targetPointInScreenCoords;
|
||||
m_resizeStartRect = targetWindow->geometry();
|
||||
}
|
||||
}
|
||||
m_windowManipulation.onPointerDown(event, targetWindow);
|
||||
|
||||
wasmTargetWindow->injectMousePressed(pointInTargetWindowCoords, targetPointInScreenCoords, button, modifiers);
|
||||
wasmTargetWindow->injectMousePressed(pointInTargetWindowCoords, targetPointInScreenCoords, event.mouseButton, event.modifiers);
|
||||
break;
|
||||
}
|
||||
case EMSCRIPTEN_EVENT_MOUSEUP:
|
||||
case EventType::PointerUp:
|
||||
{
|
||||
buttonEventType = QEvent::MouseButtonRelease;
|
||||
|
||||
m_pressedButtons.setFlag(button, false);
|
||||
|
||||
if (m_windowBeingManipulated && m_pressedButtons.testFlag(Qt::NoButton)) {
|
||||
m_windowBeingManipulated = nullptr;
|
||||
m_resizeMode = QWasmCompositor::ResizeNone;
|
||||
}
|
||||
m_windowManipulation.onPointerUp(event);
|
||||
|
||||
if (m_pressedWindow) {
|
||||
// Always deliver the released event to the same window that was pressed
|
||||
AsWasmWindow(m_pressedWindow)->injectMouseReleased(pointInTargetWindowCoords, targetPointInScreenCoords, button, modifiers);
|
||||
if (button == Qt::MouseButton::LeftButton)
|
||||
AsWasmWindow(m_pressedWindow)->injectMouseReleased(pointInTargetWindowCoords, targetPointInScreenCoords, event.mouseButton, event.modifiers);
|
||||
if (event.mouseButton == Qt::MouseButton::LeftButton)
|
||||
m_pressedWindow = nullptr;
|
||||
} else {
|
||||
wasmTargetWindow->injectMouseReleased(pointInTargetWindowCoords, targetPointInScreenCoords, button, modifiers);
|
||||
wasmTargetWindow->injectMouseReleased(pointInTargetWindowCoords, targetPointInScreenCoords, event.mouseButton, event.modifiers);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EMSCRIPTEN_EVENT_MOUSEMOVE:
|
||||
case EventType::PointerMove:
|
||||
{
|
||||
buttonEventType = QEvent::MouseMove;
|
||||
|
||||
if (wasmTargetWindow && m_pressedButtons.testFlag(Qt::NoButton)) {
|
||||
if (wasmTargetWindow && event.mouseButtons.testFlag(Qt::NoButton)) {
|
||||
const bool isOnResizeRegion = wasmTargetWindow->isPointOnResizeRegion(targetPointInScreenCoords);
|
||||
|
||||
if (isTargetWindowResizable && isOnResizeRegion && !isTargetWindowBlocked) {
|
||||
@ -1073,34 +1016,26 @@ bool QWasmCompositor::processMouse(int eventType, const EmscriptenMouseEvent *mo
|
||||
}
|
||||
}
|
||||
|
||||
if (m_windowBeingManipulated) {
|
||||
if (m_resizeMode == QWasmCompositor::ResizeNone) {
|
||||
m_windowBeingManipulated->setPosition(
|
||||
m_windowBeingManipulated->position() + QPoint(mouseEvent->movementX, mouseEvent->movementY));
|
||||
} else {
|
||||
const QPoint delta = targetPointInCanvasCoords - m_resizePoint;
|
||||
resizeWindow(m_windowBeingManipulated, m_resizeMode, m_resizeStartRect, delta);
|
||||
}
|
||||
}
|
||||
m_windowManipulation.onPointerMove(event);
|
||||
break;
|
||||
}
|
||||
case EMSCRIPTEN_EVENT_MOUSEENTER:
|
||||
processMouseEnter(mouseEvent);
|
||||
case EventType::PointerEnter:
|
||||
processMouseEnter(nullptr);
|
||||
break;
|
||||
case EMSCRIPTEN_EVENT_MOUSELEAVE:
|
||||
case EventType::PointerLeave:
|
||||
processMouseLeave();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
if (!pointerIsWithinTargetWindowBounds && m_pressedButtons.testFlag(Qt::NoButton)) {
|
||||
if (!pointerIsWithinTargetWindowBounds && event.mouseButtons.testFlag(Qt::NoButton)) {
|
||||
leaveWindow(m_lastMouseTargetWindow);
|
||||
}
|
||||
|
||||
bool shouldDeliverEvent = pointerIsWithinTargetWindowBounds;
|
||||
QWindow *eventTarget = targetWindow;
|
||||
if (!eventTarget && buttonEventType == QEvent::MouseButtonRelease) {
|
||||
if (!eventTarget && event.type == EventType::PointerUp) {
|
||||
eventTarget = m_lastMouseTargetWindow;
|
||||
m_lastMouseTargetWindow = nullptr;
|
||||
shouldDeliverEvent = true;
|
||||
@ -1109,13 +1044,122 @@ bool QWasmCompositor::processMouse(int eventType, const EmscriptenMouseEvent *mo
|
||||
eventTarget != nullptr && shouldDeliverEvent &&
|
||||
QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(
|
||||
eventTarget, QWasmIntegration::getTimestamp(), pointInTargetWindowCoords, targetPointInScreenCoords,
|
||||
m_pressedButtons, button, buttonEventType, modifiers);
|
||||
event.mouseButtons, event.mouseButton, buttonEventType, event.modifiers);
|
||||
|
||||
if (!eventAccepted && buttonEventType == QEvent::MouseButtonPress)
|
||||
if (!eventAccepted && event.type == EventType::PointerDown)
|
||||
QGuiApplicationPrivate::instance()->closeAllPopups();
|
||||
return eventAccepted;
|
||||
}
|
||||
|
||||
QWasmCompositor::WindowManipulation::WindowManipulation(QWasmScreen *screen)
|
||||
: m_screen(screen)
|
||||
{
|
||||
Q_ASSERT(!!screen);
|
||||
}
|
||||
|
||||
QWasmCompositor::WindowManipulation::Operation QWasmCompositor::WindowManipulation::operation() const
|
||||
{
|
||||
if (!m_state)
|
||||
return Operation::None;
|
||||
|
||||
return std::holds_alternative<MoveState>(m_state->operationSpecific)
|
||||
? Operation::Move : Operation::Resize;
|
||||
}
|
||||
|
||||
void QWasmCompositor::WindowManipulation::onPointerDown(
|
||||
const PointerEvent& event, QWindow* windowAtPoint)
|
||||
{
|
||||
// Only one operation at a time.
|
||||
if (operation() != Operation::None)
|
||||
return;
|
||||
|
||||
if (event.mouseButton != Qt::MouseButton::LeftButton)
|
||||
return;
|
||||
|
||||
const bool isTargetWindowResizable =
|
||||
!windowAtPoint->windowStates().testFlag(Qt::WindowMaximized) &&
|
||||
!windowAtPoint->windowStates().testFlag(Qt::WindowFullScreen);
|
||||
if (!isTargetWindowResizable)
|
||||
return;
|
||||
|
||||
const bool isTargetWindowBlocked =
|
||||
QGuiApplicationPrivate::instance()->isWindowBlocked(windowAtPoint);
|
||||
if (isTargetWindowBlocked)
|
||||
return;
|
||||
|
||||
const auto pointInScreenCoords = m_screen->geometry().topLeft() + event.point;
|
||||
|
||||
std::unique_ptr<std::variant<ResizeState, MoveState>> operationSpecific;
|
||||
if (AsWasmWindow(windowAtPoint)->isPointOnTitle(pointInScreenCoords)) {
|
||||
operationSpecific = std::make_unique<std::variant<ResizeState, MoveState>>(MoveState {
|
||||
.m_lastPointInScreenCoords = pointInScreenCoords
|
||||
});
|
||||
} else if (AsWasmWindow(windowAtPoint)->isPointOnResizeRegion(pointInScreenCoords)) {
|
||||
operationSpecific = std::make_unique<std::variant<ResizeState, MoveState>>(ResizeState {
|
||||
.m_resizeMode = AsWasmWindow(windowAtPoint)->resizeModeAtPoint(pointInScreenCoords),
|
||||
.m_originInScreenCoords = pointInScreenCoords,
|
||||
.m_initialWindowBounds = windowAtPoint->geometry(),
|
||||
.m_minShrink = QPoint(windowAtPoint->minimumWidth() - windowAtPoint->geometry().width(),
|
||||
windowAtPoint->minimumHeight() - windowAtPoint->geometry().height()),
|
||||
.m_maxGrow = QPoint(
|
||||
windowAtPoint->maximumWidth() - windowAtPoint->geometry().width(),
|
||||
windowAtPoint->maximumHeight() - windowAtPoint->geometry().height()),
|
||||
});
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
m_state.reset(new OperationState{
|
||||
.pointerId = event.pointerId,
|
||||
.window = windowAtPoint,
|
||||
.operationSpecific = std::move(*operationSpecific),
|
||||
});
|
||||
|
||||
m_screen->canvas().call<void>("setPointerCapture", event.pointerId);
|
||||
}
|
||||
|
||||
void QWasmCompositor::WindowManipulation::onPointerMove(
|
||||
const PointerEvent& event)
|
||||
{
|
||||
if (operation() == Operation::None || event.pointerId != m_state->pointerId)
|
||||
return;
|
||||
|
||||
const auto pointInScreenCoords = m_screen->geometry().topLeft() + event.point;
|
||||
|
||||
switch (operation()) {
|
||||
case Operation::Move: {
|
||||
const QPoint targetPointClippedToScreen(
|
||||
std::max(m_screen->geometry().left(), std::min(m_screen->geometry().right(), pointInScreenCoords.x())),
|
||||
std::max(m_screen->geometry().top(), std::min(m_screen->geometry().bottom(), pointInScreenCoords.y())));
|
||||
|
||||
const QPoint difference = targetPointClippedToScreen -
|
||||
std::get<MoveState>(m_state->operationSpecific).m_lastPointInScreenCoords;
|
||||
|
||||
std::get<MoveState>(m_state->operationSpecific).m_lastPointInScreenCoords = targetPointClippedToScreen;
|
||||
|
||||
m_state->window->setPosition(m_state->window->position() + difference);
|
||||
break;
|
||||
}
|
||||
case Operation::Resize: {
|
||||
resizeWindow(pointInScreenCoords -
|
||||
std::get<ResizeState>(m_state->operationSpecific).m_originInScreenCoords);
|
||||
break;
|
||||
}
|
||||
case Operation::None:
|
||||
Q_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QWasmCompositor::WindowManipulation::onPointerUp(const PointerEvent& event)
|
||||
{
|
||||
if (operation() == Operation::None || event.mouseButtons != 0 || event.pointerId != m_state->pointerId)
|
||||
return;
|
||||
|
||||
m_state.reset();
|
||||
m_screen->canvas().call<void>("releasePointerCapture", event.pointerId);
|
||||
}
|
||||
|
||||
bool QWasmCompositor::processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent)
|
||||
{
|
||||
Qt::Key qtKey;
|
||||
@ -1139,7 +1183,7 @@ bool QWasmCompositor::processKeyboard(int eventType, const EmscriptenKeyboardEve
|
||||
if (keyType == QEvent::None)
|
||||
return 0;
|
||||
|
||||
QFlags<Qt::KeyboardModifier> modifiers = m_eventTranslator->translateKeyboardEventModifier(keyEvent);
|
||||
QFlags<Qt::KeyboardModifier> modifiers = KeyboardModifier::getForEvent(*keyEvent);
|
||||
|
||||
// Clipboard fallback path: cut/copy/paste are handled by clipboard event
|
||||
// handlers if direct clipboard access is not available.
|
||||
@ -1180,7 +1224,7 @@ bool QWasmCompositor::processWheel(int eventType, const EmscriptenWheelEvent *wh
|
||||
{
|
||||
Q_UNUSED(eventType);
|
||||
|
||||
EmscriptenMouseEvent mouseEvent = wheelEvent->mouse;
|
||||
const EmscriptenMouseEvent* mouseEvent = &wheelEvent->mouse;
|
||||
|
||||
int scrollFactor = 0;
|
||||
switch (wheelEvent->deltaMode) {
|
||||
@ -1197,8 +1241,8 @@ bool QWasmCompositor::processWheel(int eventType, const EmscriptenWheelEvent *wh
|
||||
|
||||
scrollFactor = -scrollFactor; // Web scroll deltas are inverted from Qt deltas.
|
||||
|
||||
Qt::KeyboardModifiers modifiers = m_eventTranslator->translateMouseEventModifier(&mouseEvent);
|
||||
QPoint targetPointInCanvasCoords(mouseEvent.targetX, mouseEvent.targetY);
|
||||
Qt::KeyboardModifiers modifiers = KeyboardModifier::getForEvent(*mouseEvent);
|
||||
QPoint targetPointInCanvasCoords(mouseEvent->targetX, mouseEvent->targetY);
|
||||
QPoint targetPointInScreenCoords = screen()->geometry().topLeft() + targetPointInCanvasCoords;
|
||||
|
||||
QWindow *targetWindow = screen()->compositor()->windowAt(targetPointInScreenCoords, 5);
|
||||
@ -1287,7 +1331,7 @@ int QWasmCompositor::handleTouch(int eventType, const EmscriptenTouchEvent *touc
|
||||
touchPointList.append(touchPoint);
|
||||
}
|
||||
|
||||
QFlags<Qt::KeyboardModifier> keyModifier = m_eventTranslator->translateTouchEventModifier(touchEvent);
|
||||
QFlags<Qt::KeyboardModifier> keyModifier = KeyboardModifier::getForEvent(*touchEvent);
|
||||
|
||||
bool accepted = false;
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <QtGui/qpalette.h>
|
||||
#include <QtGui/qpainter.h>
|
||||
#include <QtGui/qinputdevice.h>
|
||||
#include <QtCore/private/qstdweb_p.h>
|
||||
|
||||
#include <QPointer>
|
||||
#include <QPointingDevice>
|
||||
@ -21,6 +22,7 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct PointerEvent;
|
||||
class QWasmWindow;
|
||||
class QWasmScreen;
|
||||
class QOpenGLContext;
|
||||
@ -69,16 +71,23 @@ public:
|
||||
};
|
||||
Q_DECLARE_FLAGS(StateFlags, QWasmStateFlag)
|
||||
|
||||
enum ResizeDimension {
|
||||
Left = 1,
|
||||
Right = 1 << 1,
|
||||
Top = 1 << 2,
|
||||
Bottom = 1 << 3
|
||||
};
|
||||
|
||||
enum ResizeMode {
|
||||
ResizeNone,
|
||||
ResizeTopLeft,
|
||||
ResizeTop,
|
||||
ResizeTopRight,
|
||||
ResizeRight,
|
||||
ResizeBottomRight,
|
||||
ResizeBottom,
|
||||
ResizeBottomLeft,
|
||||
ResizeLeft
|
||||
ResizeTopLeft = Top | Left,
|
||||
ResizeTop = Top,
|
||||
ResizeTopRight = Top | Right,
|
||||
ResizeRight = Right,
|
||||
ResizeBottomRight = Bottom | Right,
|
||||
ResizeBottom = Bottom,
|
||||
ResizeBottomLeft = Bottom | Left,
|
||||
ResizeLeft = Left
|
||||
};
|
||||
|
||||
struct QWasmTitleBarOptions {
|
||||
@ -125,11 +134,9 @@ 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);
|
||||
|
||||
bool processMouseEnter(const EmscriptenMouseEvent *mouseEvent);
|
||||
bool processMouseLeave();
|
||||
@ -140,6 +147,47 @@ private slots:
|
||||
void frame();
|
||||
|
||||
private:
|
||||
class WindowManipulation {
|
||||
public:
|
||||
enum class Operation {
|
||||
None,
|
||||
Move,
|
||||
Resize,
|
||||
};
|
||||
|
||||
WindowManipulation(QWasmScreen* screen);
|
||||
|
||||
void onPointerDown(const PointerEvent& event, QWindow* windowAtPoint);
|
||||
void onPointerMove(const PointerEvent& event);
|
||||
void onPointerUp(const PointerEvent& event);
|
||||
|
||||
Operation operation() const;
|
||||
|
||||
private:
|
||||
struct ResizeState {
|
||||
ResizeMode m_resizeMode;
|
||||
QPoint m_originInScreenCoords;
|
||||
QRect m_initialWindowBounds;
|
||||
const QPoint m_minShrink;
|
||||
const QPoint m_maxGrow;
|
||||
};
|
||||
struct MoveState {
|
||||
QPoint m_lastPointInScreenCoords;
|
||||
};
|
||||
struct OperationState
|
||||
{
|
||||
int pointerId;
|
||||
QPointer<QWindow> window;
|
||||
std::variant<ResizeState, MoveState> operationSpecific;
|
||||
};
|
||||
|
||||
void resizeWindow(const QPoint& amount);
|
||||
|
||||
QWasmScreen *m_screen;
|
||||
|
||||
std::unique_ptr<OperationState> m_state;
|
||||
};
|
||||
|
||||
void notifyTopWindowChanged(QWasmWindow *window);
|
||||
void drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
|
||||
void drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
|
||||
@ -156,12 +204,15 @@ private:
|
||||
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);
|
||||
|
||||
bool processPointer(const PointerEvent& event);
|
||||
|
||||
static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
|
||||
|
||||
WindowManipulation m_windowManipulation;
|
||||
|
||||
QScopedPointer<QOpenGLContext> m_context;
|
||||
QScopedPointer<QOpenGLTextureBlitter> m_blitter;
|
||||
|
||||
@ -170,7 +221,6 @@ private:
|
||||
QRegion m_globalDamage; // damage caused by expose, window close, etc.
|
||||
bool m_needComposit = false;
|
||||
bool m_inFlush = false;
|
||||
bool m_inResize = false;
|
||||
bool m_isEnabled = true;
|
||||
QSize m_targetSize;
|
||||
qreal m_targetDevicePixelRatio = 1;
|
||||
@ -179,14 +229,15 @@ private:
|
||||
int m_requestAnimationFrameId = -1;
|
||||
bool m_inDeliverUpdateRequest = false;
|
||||
|
||||
QPointer<QWindow> m_windowBeingManipulated;
|
||||
QPointer<QWindow> m_pressedWindow;
|
||||
QPointer<QWindow> m_lastMouseTargetWindow;
|
||||
Qt::MouseButtons m_pressedButtons = Qt::NoButton;
|
||||
|
||||
ResizeMode m_resizeMode = ResizeNone;
|
||||
QPoint m_resizePoint;
|
||||
QRect m_resizeStartRect;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_pointerDownCallback;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_pointerMoveCallback;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_pointerUpCallback;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_pointerLeaveCallback;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_pointerEnterCallback;
|
||||
|
||||
std::unique_ptr<QPointingDevice> m_touchDevice;
|
||||
|
||||
QMap <int, QPointF> m_pressedTouchIds;
|
||||
|
@ -64,8 +64,7 @@ static void dropEvent(val event)
|
||||
if (wasmDrag->m_mimeData)
|
||||
delete wasmDrag->m_mimeData;
|
||||
wasmDrag->m_mimeData = new QMimeData;
|
||||
int button = event["button"].as<int>();
|
||||
wasmDrag->m_qButton = QWasmEventTranslator::translateMouseButton(button);
|
||||
wasmDrag->m_qButton = MouseEvent::buttonFromWeb(event["button"].as<int>());
|
||||
|
||||
wasmDrag->m_keyModifiers = Qt::NoModifier;
|
||||
if (event["altKey"].as<bool>())
|
||||
|
53
src/plugins/platforms/wasm/qwasmevent.cpp
Normal file
53
src/plugins/platforms/wasm/qwasmevent.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include "qwasmevent.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace KeyboardModifier
|
||||
{
|
||||
template <>
|
||||
QFlags<Qt::KeyboardModifier> getForEvent<EmscriptenKeyboardEvent>(
|
||||
const EmscriptenKeyboardEvent& event)
|
||||
{
|
||||
return internal::Helper<EmscriptenKeyboardEvent>::getModifierForEvent(event) |
|
||||
(event.location == DOM_KEY_LOCATION_NUMPAD ? Qt::KeypadModifier : Qt::NoModifier);
|
||||
}
|
||||
} // namespace KeyboardModifier
|
||||
|
||||
std::optional<PointerEvent> PointerEvent::fromWeb(emscripten::val event)
|
||||
{
|
||||
PointerEvent ret;
|
||||
|
||||
const auto eventType = ([&event]() -> std::optional<EventType> {
|
||||
const auto eventTypeString = event["type"].as<std::string>();
|
||||
|
||||
if (eventTypeString == "pointermove")
|
||||
return EventType::PointerMove;
|
||||
else if (eventTypeString == "pointerup")
|
||||
return EventType::PointerUp;
|
||||
else if (eventTypeString == "pointerdown")
|
||||
return EventType::PointerDown;
|
||||
else if (eventTypeString == "pointerenter")
|
||||
return EventType::PointerEnter;
|
||||
else if (eventTypeString == "pointerleave")
|
||||
return EventType::PointerLeave;
|
||||
return std::nullopt;
|
||||
})();
|
||||
if (!eventType)
|
||||
return std::nullopt;
|
||||
|
||||
ret.type = *eventType;
|
||||
ret.pointerType = event["pointerType"].as<std::string>() == "mouse" ?
|
||||
PointerType::Mouse : PointerType::Other;
|
||||
ret.mouseButton = MouseEvent::buttonFromWeb(event["button"].as<int>());
|
||||
ret.mouseButtons = MouseEvent::buttonsFromWeb(event["buttons"].as<unsigned short>());
|
||||
ret.point = QPoint(event["x"].as<int>(), event["y"].as<int>());
|
||||
ret.pointerId = event["pointerId"].as<int>();
|
||||
ret.modifiers = KeyboardModifier::getForEvent(event);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
145
src/plugins/platforms/wasm/qwasmevent.h
Normal file
145
src/plugins/platforms/wasm/qwasmevent.h
Normal file
@ -0,0 +1,145 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#ifndef QWASMEVENT_H
|
||||
#define QWASMEVENT_H
|
||||
|
||||
#include "qwasmplatform.h"
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qnamespace.h>
|
||||
|
||||
#include <QPoint>
|
||||
|
||||
#include <emscripten/html5.h>
|
||||
#include <emscripten/val.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
enum class EventType {
|
||||
PointerDown,
|
||||
PointerMove,
|
||||
PointerUp,
|
||||
PointerEnter,
|
||||
PointerLeave,
|
||||
};
|
||||
|
||||
enum class PointerType {
|
||||
Mouse,
|
||||
Other,
|
||||
};
|
||||
|
||||
namespace KeyboardModifier {
|
||||
namespace internal
|
||||
{
|
||||
// Check for the existence of shiftKey, ctrlKey, altKey and metaKey in a type.
|
||||
// Based on that, we can safely assume we are dealing with an emscripten event type.
|
||||
template<typename T>
|
||||
struct IsEmscriptenEvent
|
||||
{
|
||||
template<typename U, EM_BOOL U::*, EM_BOOL U::*, EM_BOOL U::*, EM_BOOL U::*>
|
||||
struct SFINAE {};
|
||||
template<typename U> static char Test(
|
||||
SFINAE<U, &U::shiftKey, &U::ctrlKey, &U::altKey, &U::metaKey>*);
|
||||
template<typename U> static int Test(...);
|
||||
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
|
||||
};
|
||||
|
||||
template<class T, typename Enable = void>
|
||||
struct Helper;
|
||||
|
||||
template<class T>
|
||||
struct Helper<T, std::enable_if_t<IsEmscriptenEvent<T>::value>>
|
||||
{
|
||||
static QFlags<Qt::KeyboardModifier> getModifierForEvent(const T& event) {
|
||||
QFlags<Qt::KeyboardModifier> keyModifier = Qt::NoModifier;
|
||||
if (event.shiftKey)
|
||||
keyModifier |= Qt::ShiftModifier;
|
||||
if (event.ctrlKey)
|
||||
keyModifier |= platform() == Platform::MacOS ? Qt::MetaModifier : Qt::ControlModifier;
|
||||
if (event.altKey)
|
||||
keyModifier |= Qt::AltModifier;
|
||||
if (event.metaKey)
|
||||
keyModifier |= platform() == Platform::MacOS ? Qt::ControlModifier : Qt::MetaModifier;
|
||||
|
||||
return keyModifier;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Helper<emscripten::val>
|
||||
{
|
||||
static QFlags<Qt::KeyboardModifier> getModifierForEvent(const emscripten::val& event) {
|
||||
QFlags<Qt::KeyboardModifier> keyModifier = Qt::NoModifier;
|
||||
if (event["shiftKey"].as<bool>())
|
||||
keyModifier |= Qt::ShiftModifier;
|
||||
if (event["ctrlKey"].as<bool>())
|
||||
keyModifier |= platform() == Platform::MacOS ? Qt::MetaModifier : Qt::ControlModifier;
|
||||
if (event["altKey"].as<bool>())
|
||||
keyModifier |= Qt::AltModifier;
|
||||
if (event["metaKey"].as<bool>())
|
||||
keyModifier |= platform() == Platform::MacOS ? Qt::ControlModifier : Qt::MetaModifier;
|
||||
if (event["constructor"]["name"].as<std::string>() == "KeyboardEvent" &&
|
||||
event["location"].as<unsigned int>() == DOM_KEY_LOCATION_NUMPAD) {
|
||||
keyModifier |= Qt::KeypadModifier;
|
||||
}
|
||||
|
||||
return keyModifier;
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
template <typename Event>
|
||||
QFlags<Qt::KeyboardModifier> getForEvent(const Event& event)
|
||||
{
|
||||
return internal::Helper<Event>::getModifierForEvent(event);
|
||||
}
|
||||
|
||||
template <>
|
||||
QFlags<Qt::KeyboardModifier> getForEvent<EmscriptenKeyboardEvent>(
|
||||
const EmscriptenKeyboardEvent& event);
|
||||
|
||||
} // namespace KeyboardModifier
|
||||
|
||||
struct Q_CORE_EXPORT Event
|
||||
{
|
||||
EventType type;
|
||||
};
|
||||
|
||||
struct Q_CORE_EXPORT MouseEvent : public Event
|
||||
{
|
||||
QPoint point;
|
||||
Qt::MouseButton mouseButton;
|
||||
Qt::MouseButtons mouseButtons;
|
||||
QFlags<Qt::KeyboardModifier> modifiers;
|
||||
|
||||
static constexpr Qt::MouseButton buttonFromWeb(int webButton) {
|
||||
switch (webButton) {
|
||||
case 0:
|
||||
return Qt::LeftButton;
|
||||
case 1:
|
||||
return Qt::MiddleButton;
|
||||
case 2:
|
||||
return Qt::RightButton;
|
||||
default:
|
||||
return Qt::NoButton;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr Qt::MouseButtons buttonsFromWeb(unsigned short webButtons) {
|
||||
// Coincidentally, Qt and web bitfields match.
|
||||
return Qt::MouseButtons::fromInt(webButtons);
|
||||
}
|
||||
};
|
||||
|
||||
struct Q_CORE_EXPORT PointerEvent : public MouseEvent
|
||||
{
|
||||
static std::optional<PointerEvent> fromWeb(emscripten::val webEvent);
|
||||
|
||||
PointerType pointerType;
|
||||
int pointerId;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QWASMEVENT_H
|
@ -160,54 +160,6 @@ QWasmEventTranslator::~QWasmEventTranslator()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Event>
|
||||
QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translatKeyModifier(const Event *event)
|
||||
{
|
||||
// macOS CTRL <-> META switching. We most likely want to enable
|
||||
// the existing switching code in QtGui, but for now do it here.
|
||||
|
||||
QFlags<Qt::KeyboardModifier> keyModifier = Qt::NoModifier;
|
||||
if (event->shiftKey)
|
||||
keyModifier |= Qt::ShiftModifier;
|
||||
if (event->ctrlKey) {
|
||||
if (g_usePlatformMacSpecifics)
|
||||
keyModifier |= Qt::MetaModifier;
|
||||
else
|
||||
keyModifier |= Qt::ControlModifier;
|
||||
}
|
||||
if (event->altKey)
|
||||
keyModifier |= Qt::AltModifier;
|
||||
if (event->metaKey) {
|
||||
if (g_usePlatformMacSpecifics)
|
||||
keyModifier |= Qt::ControlModifier;
|
||||
else
|
||||
keyModifier |= Qt::MetaModifier;
|
||||
}
|
||||
|
||||
return keyModifier;
|
||||
}
|
||||
|
||||
QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateKeyboardEventModifier(const EmscriptenKeyboardEvent *event)
|
||||
{
|
||||
QFlags<Qt::KeyboardModifier> keyModifier = translatKeyModifier(event);
|
||||
|
||||
if (event->location == DOM_KEY_LOCATION_NUMPAD) {
|
||||
keyModifier |= Qt::KeypadModifier;
|
||||
}
|
||||
|
||||
return keyModifier;
|
||||
}
|
||||
|
||||
QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateMouseEventModifier(const EmscriptenMouseEvent *mouseEvent)
|
||||
{
|
||||
return translatKeyModifier(mouseEvent);
|
||||
}
|
||||
|
||||
QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateTouchEventModifier(const EmscriptenTouchEvent *touchEvent)
|
||||
{
|
||||
return translatKeyModifier(touchEvent);
|
||||
}
|
||||
|
||||
Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey)
|
||||
{
|
||||
Qt::Key qtKey = Qt::Key_unknown;
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <QtGui/qinputdevice.h>
|
||||
#include <QHash>
|
||||
#include <QCursor>
|
||||
#include "qwasmevent.h"
|
||||
#include "qwasmplatform.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -26,25 +28,7 @@ public:
|
||||
explicit QWasmEventTranslator();
|
||||
~QWasmEventTranslator();
|
||||
|
||||
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);
|
||||
QFlags<Qt::KeyboardModifier> translateTouchEventModifier(const EmscriptenTouchEvent *touchEvent);
|
||||
static constexpr Qt::MouseButton translateMouseButton(unsigned short button) {
|
||||
switch (button) {
|
||||
case 0:
|
||||
return Qt::LeftButton;
|
||||
case 1:
|
||||
return Qt::MiddleButton;
|
||||
case 2:
|
||||
return Qt::RightButton;
|
||||
default:
|
||||
return Qt::NoButton;
|
||||
}
|
||||
}
|
||||
static QCursor cursorForMode(QWasmCompositor::ResizeMode mode);
|
||||
|
||||
QString getKeyText(const EmscriptenKeyboardEvent *keyEvent, Qt::Key key);
|
||||
|
@ -50,7 +50,7 @@ QWasmInputContext::QWasmInputContext()
|
||||
m_inputElement.set("style", "position:absolute;left:-1000px;top:-1000px"); // offscreen
|
||||
m_inputElement.set("contentaediable","true");
|
||||
|
||||
if (QWasmIntegration::get()->platform == QWasmIntegration::AndroidPlatform) {
|
||||
if (platform() == Platform::Android) {
|
||||
emscripten::val body = document["body"];
|
||||
body.call<void>("appendChild", m_inputElement);
|
||||
|
||||
@ -65,8 +65,7 @@ QWasmInputContext::QWasmInputContext()
|
||||
&androidKeyboardCallback);
|
||||
|
||||
}
|
||||
if (QWasmIntegration::get()->platform == QWasmIntegration::MacOSPlatform ||
|
||||
QWasmIntegration::get()->platform == QWasmIntegration::iPhonePlatform)
|
||||
if (platform() == Platform::MacOS || platform() == Platform::iPhone)
|
||||
{
|
||||
auto callback = [=](emscripten::val) {
|
||||
m_inputElement["parentElement"].call<void>("removeChild", m_inputElement);
|
||||
@ -81,7 +80,7 @@ QWasmInputContext::QWasmInputContext()
|
||||
|
||||
QWasmInputContext::~QWasmInputContext()
|
||||
{
|
||||
if (QWasmIntegration::get()->platform == QWasmIntegration::AndroidPlatform)
|
||||
if (platform() == Platform::Android)
|
||||
emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, 0, NULL);
|
||||
}
|
||||
|
||||
@ -107,7 +106,7 @@ void QWasmInputContext::update(Qt::InputMethodQueries queries)
|
||||
|
||||
void QWasmInputContext::showInputPanel()
|
||||
{
|
||||
if (QWasmIntegration::get()->platform == QWasmIntegration::WindowsPlatform
|
||||
if (platform() == Platform::Windows
|
||||
&& inputPanelIsOpen) // call this only once for win32
|
||||
return;
|
||||
// this is called each time the keyboard is touched
|
||||
@ -119,9 +118,9 @@ void QWasmInputContext::showInputPanel()
|
||||
// captured by the keyboard event handler installed on the
|
||||
// canvas.
|
||||
|
||||
if (QWasmIntegration::get()->platform == QWasmIntegration::MacOSPlatform // keep for compatibility
|
||||
|| QWasmIntegration::get()->platform == QWasmIntegration::iPhonePlatform
|
||||
|| QWasmIntegration::get()->platform == QWasmIntegration::WindowsPlatform) {
|
||||
if (platform() == Platform::MacOS // keep for compatibility
|
||||
|| platform() == Platform::iPhone
|
||||
|| platform() == Platform::Windows) {
|
||||
emscripten::val canvas = focusCanvas();
|
||||
if (canvas == emscripten::val::undefined())
|
||||
return;
|
||||
|
@ -86,22 +86,6 @@ QWasmIntegration::QWasmIntegration()
|
||||
s_instance = this;
|
||||
|
||||
touchPoints = emscripten::val::global("navigator")["maxTouchPoints"].as<int>();
|
||||
// The Platform Detect: expand coverage as needed
|
||||
platform = GenericPlatform;
|
||||
emscripten::val rawPlatform = emscripten::val::global("navigator")["platform"];
|
||||
|
||||
if (rawPlatform.call<bool>("includes", emscripten::val("Mac")))
|
||||
platform = MacOSPlatform;
|
||||
if (rawPlatform.call<bool>("includes", emscripten::val("iPhone")))
|
||||
platform = iPhonePlatform;
|
||||
if (rawPlatform.call<bool>("includes", emscripten::val("Win32")))
|
||||
platform = WindowsPlatform;
|
||||
if (rawPlatform.call<bool>("includes", emscripten::val("Linux"))) {
|
||||
platform = LinuxPlatform;
|
||||
emscripten::val uAgent = emscripten::val::global("navigator")["userAgent"];
|
||||
if (uAgent.call<bool>("includes", emscripten::val("Android")))
|
||||
platform = AndroidPlatform;
|
||||
}
|
||||
|
||||
// Create screens for container elements. Each container element can be a div element (preferred),
|
||||
// or a canvas element (legacy). Qt versions prior to 6.x read the "qtCanvasElements" module property,
|
||||
|
@ -40,15 +40,6 @@ class QWasmIntegration : public QObject, public QPlatformIntegration
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Platform {
|
||||
GenericPlatform,
|
||||
MacOSPlatform,
|
||||
WindowsPlatform,
|
||||
LinuxPlatform,
|
||||
AndroidPlatform,
|
||||
iPhonePlatform
|
||||
};
|
||||
|
||||
QWasmIntegration();
|
||||
~QWasmIntegration();
|
||||
|
||||
@ -89,7 +80,6 @@ public:
|
||||
void removeBackingStore(QWindow* window);
|
||||
static quint64 getTimestamp();
|
||||
|
||||
Platform platform;
|
||||
int touchPoints;
|
||||
|
||||
private:
|
||||
|
31
src/plugins/platforms/wasm/qwasmplatform.cpp
Normal file
31
src/plugins/platforms/wasm/qwasmplatform.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include "qwasmplatform.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Platform platform()
|
||||
{
|
||||
static const Platform qtDetectedPlatform = ([]() {
|
||||
// The Platform Detect: expand coverage as needed
|
||||
emscripten::val rawPlatform = emscripten::val::global("navigator")["platform"];
|
||||
|
||||
if (rawPlatform.call<bool>("includes", emscripten::val("Mac")))
|
||||
return Platform::MacOS;
|
||||
if (rawPlatform.call<bool>("includes", emscripten::val("iPhone")))
|
||||
return Platform::iPhone;
|
||||
if (rawPlatform.call<bool>("includes", emscripten::val("Win32")))
|
||||
return Platform::Windows;
|
||||
if (rawPlatform.call<bool>("includes", emscripten::val("Linux"))) {
|
||||
emscripten::val uAgent = emscripten::val::global("navigator")["userAgent"];
|
||||
if (uAgent.call<bool>("includes", emscripten::val("Android")))
|
||||
return Platform::Android;
|
||||
return Platform::Linux;
|
||||
}
|
||||
return Platform::Generic;
|
||||
})();
|
||||
return qtDetectedPlatform;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
29
src/plugins/platforms/wasm/qwasmplatform.h
Normal file
29
src/plugins/platforms/wasm/qwasmplatform.h
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#ifndef QWASMPLATFORM_H
|
||||
#define QWASMPLATFORM_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qnamespace.h>
|
||||
|
||||
#include <QPoint>
|
||||
|
||||
#include <emscripten/val.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
enum class Platform {
|
||||
Generic,
|
||||
MacOS,
|
||||
Windows,
|
||||
Linux,
|
||||
Android,
|
||||
iPhone,
|
||||
};
|
||||
|
||||
Platform platform();
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QWASMPLATFORM_H
|
Loading…
Reference in New Issue
Block a user