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;
|
||||
|
||||
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,24 +1026,51 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
|
||||
leaveWindow(m_lastMouseTargetWindow);
|
||||
}
|
||||
|
||||
bool shouldDeliverEvent = pointerIsWithinTargetWindowBounds;
|
||||
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);
|
||||
|
||||
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;
|
||||
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)
|
||||
: m_screen(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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -263,6 +263,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();
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user