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>
This commit is contained in:
parent
434595865b
commit
19507dc678
@ -939,8 +939,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
|
|||||||
|
|
||||||
const QPoint targetPointInScreenCoords = screen()->geometry().topLeft() + event.point;
|
const QPoint targetPointInScreenCoords = screen()->geometry().topLeft() + event.point;
|
||||||
|
|
||||||
QEvent::Type buttonEventType = QEvent::None;
|
|
||||||
|
|
||||||
QWindow *const targetWindow = ([this, &targetPointInScreenCoords]() -> QWindow * {
|
QWindow *const targetWindow = ([this, &targetPointInScreenCoords]() -> QWindow * {
|
||||||
auto *targetWindow =
|
auto *targetWindow =
|
||||||
m_windowManipulation.operation() == WindowManipulation::Operation::None ?
|
m_windowManipulation.operation() == WindowManipulation::Operation::None ?
|
||||||
@ -968,7 +966,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
|
|||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case EventType::PointerDown:
|
case EventType::PointerDown:
|
||||||
{
|
{
|
||||||
buttonEventType = QEvent::MouseButtonPress;
|
|
||||||
if (targetWindow)
|
if (targetWindow)
|
||||||
targetWindow->requestActivate();
|
targetWindow->requestActivate();
|
||||||
|
|
||||||
@ -981,8 +978,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
|
|||||||
}
|
}
|
||||||
case EventType::PointerUp:
|
case EventType::PointerUp:
|
||||||
{
|
{
|
||||||
buttonEventType = QEvent::MouseButtonRelease;
|
|
||||||
|
|
||||||
m_windowManipulation.onPointerUp(event);
|
m_windowManipulation.onPointerUp(event);
|
||||||
|
|
||||||
if (m_pressedWindow) {
|
if (m_pressedWindow) {
|
||||||
@ -997,8 +992,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
|
|||||||
}
|
}
|
||||||
case EventType::PointerMove:
|
case EventType::PointerMove:
|
||||||
{
|
{
|
||||||
buttonEventType = QEvent::MouseMove;
|
|
||||||
|
|
||||||
if (wasmTargetWindow && event.mouseButtons.testFlag(Qt::NoButton)) {
|
if (wasmTargetWindow && event.mouseButtons.testFlag(Qt::NoButton)) {
|
||||||
const bool isOnResizeRegion = wasmTargetWindow->isPointOnResizeRegion(targetPointInScreenCoords);
|
const bool isOnResizeRegion = wasmTargetWindow->isPointOnResizeRegion(targetPointInScreenCoords);
|
||||||
|
|
||||||
@ -1033,24 +1026,51 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
|
|||||||
leaveWindow(m_lastMouseTargetWindow);
|
leaveWindow(m_lastMouseTargetWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldDeliverEvent = pointerIsWithinTargetWindowBounds;
|
const bool eventAccepted = deliverEventToTarget(event, targetWindow);
|
||||||
QWindow *eventTarget = targetWindow;
|
|
||||||
if (!eventTarget && event.type == EventType::PointerUp) {
|
|
||||||
eventTarget = m_lastMouseTargetWindow;
|
|
||||||
m_lastMouseTargetWindow = nullptr;
|
|
||||||
shouldDeliverEvent = 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)
|
if (!eventAccepted && event.type == EventType::PointerDown)
|
||||||
QGuiApplicationPrivate::instance()->closeAllPopups();
|
QGuiApplicationPrivate::instance()->closeAllPopups();
|
||||||
return eventAccepted;
|
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;
|
||||||
|
deliveringToPreviouslyClickedWindow = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
QWasmCompositor::WindowManipulation::WindowManipulation(QWasmScreen *screen)
|
||||||
: m_screen(screen)
|
: m_screen(screen)
|
||||||
{
|
{
|
||||||
@ -1124,14 +1144,10 @@ void QWasmCompositor::WindowManipulation::onPointerMove(
|
|||||||
if (operation() == Operation::None || event.pointerId != m_state->pointerId)
|
if (operation() == Operation::None || event.pointerId != m_state->pointerId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto pointInScreenCoords = m_screen->geometry().topLeft() + event.point;
|
|
||||||
|
|
||||||
switch (operation()) {
|
switch (operation()) {
|
||||||
case Operation::Move: {
|
case Operation::Move: {
|
||||||
const QPoint targetPointClippedToScreen(
|
const QPoint targetPointClippedToScreen =
|
||||||
std::max(m_screen->geometry().left(), std::min(m_screen->geometry().right(), pointInScreenCoords.x())),
|
m_screen->translateAndClipGlobalPoint(event.point);
|
||||||
std::max(m_screen->geometry().top(), std::min(m_screen->geometry().bottom(), pointInScreenCoords.y())));
|
|
||||||
|
|
||||||
const QPoint difference = targetPointClippedToScreen -
|
const QPoint difference = targetPointClippedToScreen -
|
||||||
std::get<MoveState>(m_state->operationSpecific).m_lastPointInScreenCoords;
|
std::get<MoveState>(m_state->operationSpecific).m_lastPointInScreenCoords;
|
||||||
|
|
||||||
@ -1141,6 +1157,7 @@ void QWasmCompositor::WindowManipulation::onPointerMove(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Operation::Resize: {
|
case Operation::Resize: {
|
||||||
|
const auto pointInScreenCoords = m_screen->geometry().topLeft() + event.point;
|
||||||
resizeWindow(pointInScreenCoords -
|
resizeWindow(pointInScreenCoords -
|
||||||
std::get<ResizeState>(m_state->operationSpecific).m_originInScreenCoords);
|
std::get<ResizeState>(m_state->operationSpecific).m_originInScreenCoords);
|
||||||
break;
|
break;
|
||||||
|
@ -208,6 +208,7 @@ private:
|
|||||||
static int wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData);
|
static int wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData);
|
||||||
|
|
||||||
bool processPointer(const PointerEvent& event);
|
bool processPointer(const PointerEvent& event);
|
||||||
|
bool deliverEventToTarget(const PointerEvent& event, QWindow *eventTarget);
|
||||||
|
|
||||||
static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
|
static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
#include <QtCore/qnamespace.h>
|
#include <QtCore/qnamespace.h>
|
||||||
|
#include <QtGui/qevent.h>
|
||||||
|
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
|
|
||||||
@ -29,6 +30,11 @@ enum class PointerType {
|
|||||||
Other,
|
Other,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class WindowArea {
|
||||||
|
NonClient,
|
||||||
|
Client,
|
||||||
|
};
|
||||||
|
|
||||||
namespace KeyboardModifier {
|
namespace KeyboardModifier {
|
||||||
namespace internal
|
namespace internal
|
||||||
{
|
{
|
||||||
@ -129,7 +135,24 @@ struct Q_CORE_EXPORT MouseEvent : public Event
|
|||||||
static constexpr Qt::MouseButtons buttonsFromWeb(unsigned short webButtons) {
|
static constexpr Qt::MouseButtons buttonsFromWeb(unsigned short webButtons) {
|
||||||
// Coincidentally, Qt and web bitfields match.
|
// Coincidentally, Qt and web bitfields match.
|
||||||
return Qt::MouseButtons::fromInt(webButtons);
|
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
|
struct Q_CORE_EXPORT PointerEvent : public MouseEvent
|
||||||
|
@ -263,6 +263,15 @@ QWindow *QWasmScreen::topLevelAt(const QPoint &p) const
|
|||||||
return m_compositor->windowAt(p);
|
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()
|
void QWasmScreen::invalidateSize()
|
||||||
{
|
{
|
||||||
m_geometry = QRect();
|
m_geometry = QRect();
|
||||||
|
@ -53,6 +53,8 @@ public:
|
|||||||
QWindow *topWindow() const;
|
QWindow *topWindow() const;
|
||||||
QWindow *topLevelAt(const QPoint &p) const override;
|
QWindow *topLevelAt(const QPoint &p) const override;
|
||||||
|
|
||||||
|
QPoint translateAndClipGlobalPoint(const QPoint &p) const;
|
||||||
|
|
||||||
void invalidateSize();
|
void invalidateSize();
|
||||||
void updateQScreenAndCanvasRenderSize();
|
void updateQScreenAndCanvasRenderSize();
|
||||||
void installCanvasResizeObserver();
|
void installCanvasResizeObserver();
|
||||||
|
@ -1079,14 +1079,14 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event)
|
|||||||
if (state == nullptr || !state->dragging)
|
if (state == nullptr || !state->dragging)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifndef Q_OS_MAC
|
#if !defined(Q_OS_MAC) && !defined(Q_OS_WASM)
|
||||||
if (state->nca) {
|
if (state->nca) {
|
||||||
endDrag();
|
endDrag();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case QEvent::NonClientAreaMouseButtonRelease:
|
case QEvent::NonClientAreaMouseButtonRelease:
|
||||||
#ifdef Q_OS_MAC
|
#if defined(Q_OS_MAC) || defined(Q_OS_WASM)
|
||||||
if (state)
|
if (state)
|
||||||
endDrag();
|
endDrag();
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user