summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMikolaj Boc <mikolaj.boc@qt.io>2022-07-20 14:29:06 +0200
committerMikolaj Boc <mikolaj.boc@qt.io>2022-08-19 15:15:06 +0200
commit0edf92aa4eaf5f7ade95291f5514c569b7806325 (patch)
tree88cc2de8a1ff533ebe9620ad77f44dc0906f8f7a /src
parentfe1319a4c8b49840605cf7335e222191e418c85d (diff)
Deliver non-client area mouse events to WASM windows
QWasmCompositor now delivers non-client area mouse events to windows as it should, which fixes a lot of issues with window manipulation. One of such issues is re-docking of dock widgets. Fixes: QTBUG-105092 Change-Id: I9de45b7e1b1a80b64387031eb0cc0b31a4be2571 Reviewed-by: Lorn Potter <lorn.potter@gmail.com> (cherry picked from commit 19507dc6788f252cd0795d80d9a39d22f1306882) Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp67
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.h1
-rw-r--r--src/plugins/platforms/wasm/qwasmevent.h25
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.cpp9
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.h2
-rw-r--r--src/widgets/widgets/qdockwidget.cpp4
6 files changed, 80 insertions, 28 deletions
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index 85c2783439..f804542b34 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -939,8 +939,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
const QPoint targetPointInScreenCoords = screen()->geometry().topLeft() + event.point;
- QEvent::Type buttonEventType = QEvent::None;
-
QWindow *const targetWindow = ([this, &targetPointInScreenCoords]() -> QWindow * {
auto *targetWindow =
m_windowManipulation.operation() == WindowManipulation::Operation::None ?
@@ -968,7 +966,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
switch (event.type) {
case EventType::PointerDown:
{
- buttonEventType = QEvent::MouseButtonPress;
if (targetWindow)
targetWindow->requestActivate();
@@ -981,8 +978,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
}
case EventType::PointerUp:
{
- buttonEventType = QEvent::MouseButtonRelease;
-
m_windowManipulation.onPointerUp(event);
if (m_pressedWindow) {
@@ -997,8 +992,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
}
case EventType::PointerMove:
{
- buttonEventType = QEvent::MouseMove;
-
if (wasmTargetWindow && event.mouseButtons.testFlag(Qt::NoButton)) {
const bool isOnResizeRegion = wasmTargetWindow->isPointOnResizeRegion(targetPointInScreenCoords);
@@ -1033,22 +1026,49 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
leaveWindow(m_lastMouseTargetWindow);
}
- bool shouldDeliverEvent = pointerIsWithinTargetWindowBounds;
- QWindow *eventTarget = targetWindow;
- if (!eventTarget && event.type == EventType::PointerUp) {
+ const bool eventAccepted = deliverEventToTarget(event, targetWindow);
+ if (!eventAccepted && event.type == EventType::PointerDown)
+ QGuiApplicationPrivate::instance()->closeAllPopups();
+ return eventAccepted;
+}
+
+bool QWasmCompositor::deliverEventToTarget(const PointerEvent &event, QWindow *eventTarget)
+{
+ const QPoint pointInScreenCoords = screen()->geometry().topLeft() + event.point;
+ const QPoint targetPointClippedToScreen(
+ std::max(screen()->geometry().left(),
+ std::min(screen()->geometry().right(), pointInScreenCoords.x())),
+ std::max(screen()->geometry().top(),
+ std::min(screen()->geometry().bottom(), pointInScreenCoords.y())));
+
+ bool deliveringToPreviouslyClickedWindow = false;
+
+ if (!eventTarget) {
+ if (event.type != EventType::PointerUp || !m_lastMouseTargetWindow)
+ return false;
+
eventTarget = m_lastMouseTargetWindow;
m_lastMouseTargetWindow = nullptr;
- shouldDeliverEvent = true;
+ deliveringToPreviouslyClickedWindow = true;
}
- const bool eventAccepted =
- eventTarget != nullptr && shouldDeliverEvent &&
- QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(
- eventTarget, QWasmIntegration::getTimestamp(), pointInTargetWindowCoords, targetPointInScreenCoords,
- event.mouseButtons, event.mouseButton, buttonEventType, event.modifiers);
- if (!eventAccepted && event.type == EventType::PointerDown)
- QGuiApplicationPrivate::instance()->closeAllPopups();
- return eventAccepted;
+ WindowArea windowArea = WindowArea::Client;
+ if (!eventTarget->geometry().contains(targetPointClippedToScreen)
+ && !deliveringToPreviouslyClickedWindow) {
+ if (!eventTarget->frameGeometry().contains(targetPointClippedToScreen))
+ return false;
+ windowArea = WindowArea::NonClient;
+ }
+
+ const QEvent::Type eventType =
+ MouseEvent::mouseEventTypeFromEventType(event.type, windowArea);
+
+ return eventType != QEvent::None &&
+ QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(
+ eventTarget, QWasmIntegration::getTimestamp(),
+ eventTarget->mapFromGlobal(targetPointClippedToScreen),
+ targetPointClippedToScreen, event.mouseButtons, event.mouseButton,
+ eventType, event.modifiers);
}
QWasmCompositor::WindowManipulation::WindowManipulation(QWasmScreen *screen)
@@ -1124,14 +1144,10 @@ void QWasmCompositor::WindowManipulation::onPointerMove(
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 targetPointClippedToScreen =
+ m_screen->translateAndClipGlobalPoint(event.point);
const QPoint difference = targetPointClippedToScreen -
std::get<MoveState>(m_state->operationSpecific).m_lastPointInScreenCoords;
@@ -1141,6 +1157,7 @@ void QWasmCompositor::WindowManipulation::onPointerMove(
break;
}
case Operation::Resize: {
+ const auto pointInScreenCoords = m_screen->geometry().topLeft() + event.point;
resizeWindow(pointInScreenCoords -
std::get<ResizeState>(m_state->operationSpecific).m_originInScreenCoords);
break;
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h
index b7a93d110b..2cfd355b61 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.h
+++ b/src/plugins/platforms/wasm/qwasmcompositor.h
@@ -208,6 +208,7 @@ private:
static int wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData);
bool processPointer(const PointerEvent& event);
+ bool deliverEventToTarget(const PointerEvent& event, QWindow *eventTarget);
static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
diff --git a/src/plugins/platforms/wasm/qwasmevent.h b/src/plugins/platforms/wasm/qwasmevent.h
index 784591fb95..df9276b746 100644
--- a/src/plugins/platforms/wasm/qwasmevent.h
+++ b/src/plugins/platforms/wasm/qwasmevent.h
@@ -8,6 +8,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qnamespace.h>
+#include <QtGui/qevent.h>
#include <QPoint>
@@ -29,6 +30,11 @@ enum class PointerType {
Other,
};
+enum class WindowArea {
+ NonClient,
+ Client,
+};
+
namespace KeyboardModifier {
namespace internal
{
@@ -129,7 +135,24 @@ struct Q_CORE_EXPORT MouseEvent : public Event
static constexpr Qt::MouseButtons buttonsFromWeb(unsigned short webButtons) {
// Coincidentally, Qt and web bitfields match.
return Qt::MouseButtons::fromInt(webButtons);
-}
+ }
+
+ static constexpr QEvent::Type mouseEventTypeFromEventType(
+ EventType eventType, WindowArea windowArea) {
+ switch (eventType) {
+ case EventType::PointerDown :
+ return windowArea == WindowArea::Client ?
+ QEvent::MouseButtonPress : QEvent::NonClientAreaMouseButtonPress;
+ case EventType::PointerUp :
+ return windowArea == WindowArea::Client ?
+ QEvent::MouseButtonRelease : QEvent::NonClientAreaMouseButtonRelease;
+ case EventType::PointerMove :
+ return windowArea == WindowArea::Client ?
+ QEvent::MouseMove : QEvent::NonClientAreaMouseMove;
+ default:
+ return QEvent::None;
+ }
+ }
};
struct Q_CORE_EXPORT PointerEvent : public MouseEvent
diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp
index 42ca608da1..350832ebf5 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.cpp
+++ b/src/plugins/platforms/wasm/qwasmscreen.cpp
@@ -258,6 +258,15 @@ QWindow *QWasmScreen::topLevelAt(const QPoint &p) const
return m_compositor->windowAt(p);
}
+QPoint QWasmScreen::translateAndClipGlobalPoint(const QPoint &p) const
+{
+ return QPoint(
+ std::max(screen()->geometry().left(),
+ std::min(screen()->geometry().right(), screen()->geometry().left() + p.x())),
+ std::max(screen()->geometry().top(),
+ std::min(screen()->geometry().bottom(), screen()->geometry().top() + p.y())));
+}
+
void QWasmScreen::invalidateSize()
{
m_geometry = QRect();
diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h
index 0e7d5f1e43..405ea7e7b8 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.h
+++ b/src/plugins/platforms/wasm/qwasmscreen.h
@@ -53,6 +53,8 @@ public:
QWindow *topWindow() const;
QWindow *topLevelAt(const QPoint &p) const override;
+ QPoint translateAndClipGlobalPoint(const QPoint &p) const;
+
void invalidateSize();
void updateQScreenAndCanvasRenderSize();
void installCanvasResizeObserver();
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index ec5e4d51d5..6072740db8 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -1079,14 +1079,14 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event)
if (state == nullptr || !state->dragging)
break;
-#ifndef Q_OS_MAC
+#if !defined(Q_OS_MAC) && !defined(Q_OS_WASM)
if (state->nca) {
endDrag();
}
#endif
break;
case QEvent::NonClientAreaMouseButtonRelease:
-#ifdef Q_OS_MAC
+#if defined(Q_OS_MAC) || defined(Q_OS_WASM)
if (state)
endDrag();
#endif