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>
This commit is contained in:
parent
b99c08dd4e
commit
5359d420af
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
Qt::Key qtKey = translateEmscriptKey(keyEvent);
|
||||
|
||||
Qt::KeyboardModifiers modifiers = translateKeyboardEventModifier(keyEvent);
|
||||
|
||||
QString keyText;
|
||||
QEvent::Type keyType = QEvent::None;
|
||||
switch (eventType) {
|
||||
case EMSCRIPTEN_EVENT_KEYPRESS:
|
||||
case EMSCRIPTEN_EVENT_KEYDOWN: // down
|
||||
keyType = QEvent::KeyPress;
|
||||
|
||||
if (m_emDeadKey != Qt::Key_unknown) {
|
||||
|
||||
Qt::Key transformedKey = translateDeadKey(m_emDeadKey, qtKey);
|
||||
|
||||
if (transformedKey != Qt::Key_unknown)
|
||||
qtKey = transformedKey;
|
||||
|
||||
if (keyEvent->shiftKey == 0) {
|
||||
for (auto it = KeyTbl.cbegin(); it != KeyTbl.end(); ++it) {
|
||||
if (it != KeyTbl.end() && (qtKey == static_cast<Qt::Key>(it->qt))) {
|
||||
keyText = it->em;
|
||||
m_emDeadKey = Qt::Key_unknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto it = DeadKeyShiftTbl.cbegin(); it != DeadKeyShiftTbl.end(); ++it) {
|
||||
if (it != DeadKeyShiftTbl.end() && (qtKey == static_cast<Qt::Key>(it->qt))) {
|
||||
keyText = it->em;
|
||||
m_emDeadKey = Qt::Key_unknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (qstrncmp(keyEvent->key, "Dead", 4) == 0 || qtKey == Qt::Key_AltGr) {
|
||||
qtKey = translateEmscriptKey(keyEvent);
|
||||
m_emStickyDeadKey = true;
|
||||
if (keyEvent->shiftKey == 1 && qtKey == Qt::Key_QuoteLeft)
|
||||
qtKey = Qt::Key_AsciiTilde;
|
||||
m_emDeadKey = qtKey;
|
||||
}
|
||||
break;
|
||||
case EMSCRIPTEN_EVENT_KEYUP: // up
|
||||
keyType = QEvent::KeyRelease;
|
||||
if (m_emStickyDeadKey && qtKey != Qt::Key_Alt) {
|
||||
m_emStickyDeadKey = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
if (keyType == QEvent::None)
|
||||
return 0;
|
||||
|
||||
QFlags<Qt::KeyboardModifier> mods = translateKeyboardEventModifier(keyEvent);
|
||||
|
||||
// Clipboard fallback path: cut/copy/paste are handled by clipboard event
|
||||
// handlers if direct clipboard access is not available.
|
||||
if (!QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi && modifiers & Qt::ControlModifier &&
|
||||
(qtKey == Qt::Key_X || qtKey == Qt::Key_C || qtKey == Qt::Key_V)) {
|
||||
if (qtKey == Qt::Key_V) {
|
||||
QWasmIntegration::get()->getWasmClipboard()->isPaste = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
return accepted;
|
||||
}
|
||||
|
||||
QCursor QWasmEventTranslator::cursorForMode(QWasmWindow::ResizeMode m)
|
||||
QCursor QWasmEventTranslator::cursorForMode(QWasmCompositor::ResizeMode m)
|
||||
{
|
||||
switch (m) {
|
||||
case QWasmWindow::ResizeTopLeft:
|
||||
case QWasmWindow::ResizeBottomRight:
|
||||
case QWasmCompositor::ResizeTopLeft:
|
||||
case QWasmCompositor::ResizeBottomRight:
|
||||
return Qt::SizeFDiagCursor;
|
||||
case QWasmWindow::ResizeBottomLeft:
|
||||
case QWasmWindow::ResizeTopRight:
|
||||
case QWasmCompositor::ResizeBottomLeft:
|
||||
case QWasmCompositor::ResizeTopRight:
|
||||
return Qt::SizeBDiagCursor;
|
||||
case QWasmWindow::ResizeTop:
|
||||
case QWasmWindow::ResizeBottom:
|
||||
case QWasmCompositor::ResizeTop:
|
||||
case QWasmCompositor::ResizeBottom:
|
||||
return Qt::SizeVerCursor;
|
||||
case QWasmWindow::ResizeLeft:
|
||||
case QWasmWindow::ResizeRight:
|
||||
case QWasmCompositor::ResizeLeft:
|
||||
case QWasmCompositor::ResizeRight:
|
||||
return Qt::SizeHorCursor;
|
||||
case QWasmWindow::ResizeNone:
|
||||
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);
|
||||
|
||||
if (m_emDeadKey != Qt::Key_unknown) {
|
||||
Qt::Key transformedKey = translateDeadKey(m_emDeadKey, qtKey);
|
||||
|
||||
if (transformedKey != Qt::Key_unknown)
|
||||
qtKey = transformedKey;
|
||||
|
||||
if (keyEvent->shiftKey == 0) {
|
||||
for (auto it = KeyTbl.cbegin(); it != KeyTbl.end(); ++it) {
|
||||
if (it != KeyTbl.end() && (qtKey == static_cast<Qt::Key>(it->qt))) {
|
||||
keyText = it->em;
|
||||
m_emDeadKey = Qt::Key_unknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto it = DeadKeyShiftTbl.cbegin(); it != DeadKeyShiftTbl.end(); ++it) {
|
||||
if (it != DeadKeyShiftTbl.end() && (qtKey == static_cast<Qt::Key>(it->qt))) {
|
||||
keyText = it->em;
|
||||
m_emDeadKey = Qt::Key_unknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return keyText;
|
||||
}
|
||||
|
||||
Qt::Key QWasmEventTranslator::getKey(const EmscriptenKeyboardEvent *keyEvent)
|
||||
{
|
||||
Qt::Key qtKey = translateEmscriptKey(keyEvent);
|
||||
|
||||
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 qtKey;
|
||||
}
|
||||
|
||||
void QWasmEventTranslator::setStickyDeadKey(const EmscriptenKeyboardEvent *keyEvent)
|
||||
{
|
||||
Qt::Key qtKey = translateEmscriptKey(keyEvent);
|
||||
|
||||
if (m_emStickyDeadKey && qtKey != Qt::Key_Alt) {
|
||||
m_emStickyDeadKey = false;
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -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);
|
||||
template <typename Event>
|
||||
QFlags<Qt::KeyboardModifier> translatKeyModifier(const Event *event);
|
||||
|
||||
static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
|
||||
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 Qt::MouseButton translateMouseButton(unsigned short button);
|
||||
static QCursor cursorForMode(QWasmCompositor::ResizeMode mode);
|
||||
|
||||
void processEvents();
|
||||
void initEventHandlers();
|
||||
int handleTouch(int eventType, const EmscriptenTouchEvent *touchEvent);
|
||||
QString getKeyText(const EmscriptenKeyboardEvent *keyEvent);
|
||||
Qt::Key getKey(const EmscriptenKeyboardEvent *keyEvent);
|
||||
void setStickyDeadKey(const EmscriptenKeyboardEvent *keyEvent);
|
||||
|
||||
void setIsMac(bool is_mac) {g_usePlatformMacSpecifics = is_mac;};
|
||||
|
||||
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);
|
||||
QFlags<Qt::KeyboardModifier> translateKeyboardEventModifier(const EmscriptenKeyboardEvent *keyEvent);
|
||||
QFlags<Qt::KeyboardModifier> translateMouseEventModifier(const EmscriptenMouseEvent *mouseEvent);
|
||||
Qt::MouseButton translateMouseButton(unsigned short button);
|
||||
|
||||
bool processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent);
|
||||
bool processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent);
|
||||
|
||||
Qt::Key translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey);
|
||||
|
||||
QMap <int, QPointF> pressedTouchIds;
|
||||
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
|
||||
|
@ -328,4 +328,9 @@ void QWasmIntegration::resizeAllScreens()
|
||||
canvasAndScreen.second->updateQScreenAndCanvasRenderSize();
|
||||
}
|
||||
|
||||
quint64 QWasmIntegration::getTimestamp()
|
||||
{
|
||||
return emscripten_performance_now();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -89,6 +89,7 @@ public:
|
||||
void resizeAllScreens();
|
||||
void updateDpi();
|
||||
void removeBackingStore(QWindow* window);
|
||||
static quint64 getTimestamp();
|
||||
|
||||
private:
|
||||
mutable QWasmFontDatabase *m_fontDb;
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user