Handle the mouse events in the window itself
It is now not the screen that handles all of the events and relays them to individual windows, but the window elements themselves. This allows us to get rid of manual window targeting logic and let the browser do its job. Fixes: QTBUG-107217 Pick-to: 6.5 Change-Id: I4dc5a74b1343f027f72c1da4623b99cd28bfbb38 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
parent
cf2651ae80
commit
c15a8750bc
@ -35,6 +35,7 @@ qt_internal_add_plugin(QWasmIntegrationPlugin
|
||||
qwasmstylepixmaps_p.h
|
||||
qwasmtheme.cpp qwasmtheme.h
|
||||
qwasmwindow.cpp qwasmwindow.h
|
||||
qwasmwindowclientarea.cpp qwasmwindowclientarea.h
|
||||
qwasmwindownonclientarea.cpp qwasmwindownonclientarea.h
|
||||
qwasminputcontext.cpp qwasminputcontext.h
|
||||
qwasmdrag.cpp qwasmdrag.h
|
||||
|
@ -60,8 +60,6 @@ QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
|
||||
|
||||
QWasmCompositor::~QWasmCompositor()
|
||||
{
|
||||
m_windowUnderMouse.clear();
|
||||
|
||||
if (m_requestAnimationFrameId != -1)
|
||||
emscripten_cancel_animation_frame(m_requestAnimationFrameId);
|
||||
|
||||
@ -75,8 +73,6 @@ void QWasmCompositor::deregisterEventHandlers()
|
||||
emscripten_set_keydown_callback(screenElementSelector.constData(), 0, 0, NULL);
|
||||
emscripten_set_keyup_callback(screenElementSelector.constData(), 0, 0, NULL);
|
||||
|
||||
emscripten_set_focus_callback(screenElementSelector.constData(), 0, 0, NULL);
|
||||
|
||||
emscripten_set_wheel_callback(screenElementSelector.constData(), 0, 0, NULL);
|
||||
|
||||
emscripten_set_touchstart_callback(screenElementSelector.constData(), 0, 0, NULL);
|
||||
@ -112,26 +108,6 @@ void QWasmCompositor::initEventHandlers()
|
||||
emscripten_set_keyup_callback(screenElementSelector.constData(), (void *)this, UseCapture,
|
||||
&keyboard_cb);
|
||||
|
||||
val screenElement = screen()->element();
|
||||
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>(screenElement, "pointerdown", callback);
|
||||
m_pointerMoveCallback =
|
||||
std::make_unique<qstdweb::EventCallback>(screenElement, "pointermove", callback);
|
||||
m_pointerUpCallback =
|
||||
std::make_unique<qstdweb::EventCallback>(screenElement, "pointerup", callback);
|
||||
m_pointerEnterCallback =
|
||||
std::make_unique<qstdweb::EventCallback>(screenElement, "pointerenter", callback);
|
||||
m_pointerLeaveCallback =
|
||||
std::make_unique<qstdweb::EventCallback>(screenElement, "pointerleave", callback);
|
||||
|
||||
emscripten_set_focus_callback(screenElementSelector.constData(), (void *)this, UseCapture,
|
||||
&focus_cb);
|
||||
|
||||
emscripten_set_wheel_callback(screenElementSelector.constData(), (void *)this, UseCapture,
|
||||
&wheel_cb);
|
||||
|
||||
@ -144,10 +120,10 @@ void QWasmCompositor::initEventHandlers()
|
||||
emscripten_set_touchcancel_callback(screenElementSelector.constData(), (void *)this, UseCapture,
|
||||
&touchCallback);
|
||||
|
||||
screenElement.call<void>("addEventListener", std::string("drop"),
|
||||
val::module_property("qtDrop"), val(true));
|
||||
screenElement.set("data-qtdropcontext", // ? unique
|
||||
emscripten::val(quintptr(reinterpret_cast<void *>(screen()))));
|
||||
screen()->element().call<void>("addEventListener", std::string("drop"),
|
||||
val::module_property("qtDrop"), val(true));
|
||||
screen()->element().set("data-qtdropcontext", // ? unique
|
||||
emscripten::val(quintptr(reinterpret_cast<void *>(screen()))));
|
||||
}
|
||||
|
||||
void QWasmCompositor::addWindow(QWasmWindow *window)
|
||||
@ -162,8 +138,6 @@ void QWasmCompositor::removeWindow(QWasmWindow *window)
|
||||
{
|
||||
m_requestUpdateWindows.remove(window);
|
||||
m_windowStack.removeWindow(window);
|
||||
if (m_lastMouseTargetWindow == window->window())
|
||||
m_lastMouseTargetWindow = nullptr;
|
||||
if (m_windowStack.topWindow())
|
||||
m_windowStack.topWindow()->requestActivateWindow();
|
||||
|
||||
@ -344,15 +318,6 @@ int QWasmCompositor::keyboard_cb(int eventType, const EmscriptenKeyboardEvent *k
|
||||
return static_cast<int>(wasmCompositor->processKeyboard(eventType, keyEvent));
|
||||
}
|
||||
|
||||
int QWasmCompositor::focus_cb(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData)
|
||||
{
|
||||
Q_UNUSED(eventType)
|
||||
Q_UNUSED(focusEvent)
|
||||
Q_UNUSED(userData)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QWasmCompositor::wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
|
||||
{
|
||||
QWasmCompositor *compositor = (QWasmCompositor *) userData;
|
||||
@ -365,112 +330,6 @@ int QWasmCompositor::touchCallback(int eventType, const EmscriptenTouchEvent *to
|
||||
return static_cast<int>(compositor->processTouch(eventType, touchEvent));
|
||||
}
|
||||
|
||||
bool QWasmCompositor::processPointer(const PointerEvent& event)
|
||||
{
|
||||
if (event.pointerType != PointerType::Mouse)
|
||||
return false;
|
||||
|
||||
const auto pointInScreen = screen()->mapFromLocal(event.localPoint);
|
||||
|
||||
QWindow *const targetWindow = ([this, pointInScreen]() -> QWindow * {
|
||||
auto *targetWindow = m_mouseCaptureWindow != nullptr
|
||||
? m_mouseCaptureWindow.get()
|
||||
: windowAt(pointInScreen, 5);
|
||||
|
||||
return targetWindow ? targetWindow : m_lastMouseTargetWindow.get();
|
||||
})();
|
||||
if (!targetWindow)
|
||||
return false;
|
||||
m_lastMouseTargetWindow = targetWindow;
|
||||
|
||||
const QPoint pointInTargetWindowCoords = targetWindow->mapFromGlobal(pointInScreen);
|
||||
const bool pointerIsWithinTargetWindowBounds = targetWindow->geometry().contains(pointInScreen);
|
||||
|
||||
if (m_mouseInScreen && m_windowUnderMouse != targetWindow
|
||||
&& pointerIsWithinTargetWindowBounds) {
|
||||
// delayed mouse enter
|
||||
enterWindow(targetWindow, pointInTargetWindowCoords, pointInScreen);
|
||||
m_windowUnderMouse = targetWindow;
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case EventType::PointerDown:
|
||||
{
|
||||
screen()->element().call<void>("setPointerCapture", event.pointerId);
|
||||
|
||||
if (targetWindow)
|
||||
targetWindow->requestActivate();
|
||||
|
||||
break;
|
||||
}
|
||||
case EventType::PointerUp:
|
||||
{
|
||||
screen()->element().call<void>("releasePointerCapture", event.pointerId);
|
||||
|
||||
break;
|
||||
}
|
||||
case EventType::PointerEnter:
|
||||
processMouseEnter(nullptr);
|
||||
break;
|
||||
case EventType::PointerLeave:
|
||||
processMouseLeave();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
if (!pointerIsWithinTargetWindowBounds && event.mouseButtons.testFlag(Qt::NoButton)) {
|
||||
leaveWindow(m_lastMouseTargetWindow);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Q_ASSERT(!m_mouseCaptureWindow || m_mouseCaptureWindow.get() == eventTarget);
|
||||
|
||||
const auto pointInScreen = screen()->mapFromLocal(event.localPoint);
|
||||
|
||||
const QPoint targetPointClippedToScreen(
|
||||
std::max(screen()->geometry().left(),
|
||||
std::min(screen()->geometry().right(), pointInScreen.x())),
|
||||
std::max(screen()->geometry().top(),
|
||||
std::min(screen()->geometry().bottom(), pointInScreen.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 (!deliveringToPreviouslyClickedWindow && !m_mouseCaptureWindow
|
||||
&& !eventTarget->geometry().contains(targetPointClippedToScreen)) {
|
||||
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(
|
||||
eventTarget, QWasmIntegration::getTimestamp(),
|
||||
eventTarget->mapFromGlobal(targetPointClippedToScreen),
|
||||
targetPointClippedToScreen, event.mouseButtons, event.mouseButton,
|
||||
eventType, event.modifiers);
|
||||
}
|
||||
|
||||
bool QWasmCompositor::processKeyboard(int eventType, const EmscriptenKeyboardEvent *emKeyEvent)
|
||||
{
|
||||
constexpr bool ProceedToNativeEvent = false;
|
||||
@ -521,9 +380,8 @@ bool QWasmCompositor::processWheel(int eventType, const EmscriptenWheelEvent *wh
|
||||
scrollFactor = -scrollFactor; // Web scroll deltas are inverted from Qt deltas.
|
||||
|
||||
Qt::KeyboardModifiers modifiers = KeyboardModifier::getForEvent(*mouseEvent);
|
||||
QPoint targetPointInScreenElementCoords(mouseEvent->targetX, mouseEvent->targetY);
|
||||
QPoint targetPointInScreenCoords =
|
||||
screen()->geometry().topLeft() + targetPointInScreenElementCoords;
|
||||
screen()->mapFromLocal(QPoint(mouseEvent->targetX, mouseEvent->targetY));
|
||||
|
||||
QWindow *targetWindow = screen()->compositor()->windowAt(targetPointInScreenCoords, 5);
|
||||
if (!targetWindow)
|
||||
@ -555,9 +413,8 @@ bool QWasmCompositor::processTouch(int eventType, const EmscriptenTouchEvent *to
|
||||
|
||||
const EmscriptenTouchPoint *touches = &touchEvent->touches[i];
|
||||
|
||||
QPoint targetPointInScreenElementCoords(touches->targetX, touches->targetY);
|
||||
QPoint targetPointInScreenCoords =
|
||||
screen()->geometry().topLeft() + targetPointInScreenElementCoords;
|
||||
screen()->mapFromLocal(QPoint(touches->targetX, touches->targetY));
|
||||
|
||||
targetWindow = screen()->compositor()->windowAt(targetPointInScreenCoords, 5);
|
||||
if (targetWindow == nullptr)
|
||||
@ -624,39 +481,3 @@ bool QWasmCompositor::processTouch(int eventType, const EmscriptenTouchEvent *to
|
||||
|
||||
return static_cast<int>(accepted);
|
||||
}
|
||||
|
||||
void QWasmCompositor::setCapture(QWasmWindow *window)
|
||||
{
|
||||
Q_ASSERT(std::find(m_windowStack.begin(), m_windowStack.end(), window) != m_windowStack.end());
|
||||
m_mouseCaptureWindow = window->window();
|
||||
}
|
||||
|
||||
void QWasmCompositor::releaseCapture()
|
||||
{
|
||||
m_mouseCaptureWindow = nullptr;
|
||||
}
|
||||
|
||||
void QWasmCompositor::leaveWindow(QWindow *window)
|
||||
{
|
||||
m_windowUnderMouse = nullptr;
|
||||
QWindowSystemInterface::handleLeaveEvent(window);
|
||||
}
|
||||
|
||||
void QWasmCompositor::enterWindow(QWindow *window, const QPoint &pointInTargetWindowCoords, const QPoint &targetPointInScreenCoords)
|
||||
{
|
||||
QWindowSystemInterface::handleEnterEvent(window, pointInTargetWindowCoords, targetPointInScreenCoords);
|
||||
}
|
||||
|
||||
bool QWasmCompositor::processMouseEnter(const EmscriptenMouseEvent *mouseEvent)
|
||||
{
|
||||
Q_UNUSED(mouseEvent)
|
||||
// mouse has entered the screen area
|
||||
m_mouseInScreen = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QWasmCompositor::processMouseLeave()
|
||||
{
|
||||
m_mouseInScreen = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -80,15 +80,10 @@ private:
|
||||
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);
|
||||
bool deliverEventToTarget(const PointerEvent& event, QWindow *eventTarget);
|
||||
|
||||
static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
|
||||
|
||||
bool processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent);
|
||||
bool processWheel(int eventType, const EmscriptenWheelEvent *wheelEvent);
|
||||
bool processMouseEnter(const EmscriptenMouseEvent *mouseEvent);
|
||||
bool processMouseLeave();
|
||||
bool processTouch(int eventType, const EmscriptenTouchEvent *touchEvent);
|
||||
|
||||
void enterWindow(QWindow *window, const QPoint &localPoint, const QPoint &globalPoint);
|
||||
@ -106,25 +101,11 @@ private:
|
||||
int m_requestAnimationFrameId = -1;
|
||||
bool m_inDeliverUpdateRequest = false;
|
||||
|
||||
QPointer<QWindow> m_lastMouseTargetWindow;
|
||||
QPointer<QWindow> m_mouseCaptureWindow;
|
||||
|
||||
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;
|
||||
|
||||
bool m_isResizeCursorDisplayed = false;
|
||||
|
||||
std::unique_ptr<QWasmEventTranslator> m_eventTranslator;
|
||||
|
||||
bool m_mouseInScreen = false;
|
||||
QPointer<QWindow> m_windowUnderMouse;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -29,7 +29,6 @@ const char *Style = R"css(
|
||||
|
||||
.qt-window {
|
||||
box-shadow: rgb(0 0 0 / 20%) 0px 10px 16px 0px, rgb(0 0 0 / 19%) 0px 6px 20px 0px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
background-color: lightgray;
|
||||
}
|
||||
@ -41,7 +40,6 @@ const char *Style = R"css(
|
||||
|
||||
.resize-outline {
|
||||
position: absolute;
|
||||
pointer-events: all;
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -119,7 +117,6 @@ const char *Style = R"css(
|
||||
overflow: hidden;
|
||||
height: 18px;
|
||||
padding-bottom: 4px;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.qt-window.has-title-bar .title-bar {
|
||||
@ -184,7 +181,6 @@ const char *Style = R"css(
|
||||
}
|
||||
.title-bar .action-button {
|
||||
pointer-events: all;
|
||||
align-self: end;
|
||||
}
|
||||
|
||||
.qt-window.blocked div {
|
||||
|
@ -39,7 +39,7 @@ std::optional<PointerEvent> PointerEvent::fromWeb(emscripten::val event)
|
||||
return std::nullopt;
|
||||
|
||||
ret.type = *eventType;
|
||||
ret.currentTarget = event["currentTarget"];
|
||||
ret.target = event["target"];
|
||||
ret.pointerType = event["pointerType"].as<std::string>() == "mouse" ?
|
||||
PointerType::Mouse : PointerType::Other;
|
||||
ret.mouseButton = MouseEvent::buttonFromWeb(event["button"].as<int>());
|
||||
|
@ -110,7 +110,7 @@ QFlags<Qt::KeyboardModifier> getForEvent<EmscriptenKeyboardEvent>(
|
||||
struct Q_CORE_EXPORT Event
|
||||
{
|
||||
EventType type;
|
||||
emscripten::val currentTarget = emscripten::val::undefined();
|
||||
emscripten::val target = emscripten::val::undefined();
|
||||
};
|
||||
|
||||
struct Q_CORE_EXPORT MouseEvent : public Event
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "qwasmbase64iconstore.h"
|
||||
#include "qwasmdom.h"
|
||||
#include "qwasmwindow.h"
|
||||
#include "qwasmwindowclientarea.h"
|
||||
#include "qwasmscreen.h"
|
||||
#include "qwasmstylepixmaps_p.h"
|
||||
#include "qwasmcompositor.h"
|
||||
@ -24,6 +25,8 @@
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include <QtCore/private/qstdweb_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_GUI_EXPORT int qt_defaultDpiX();
|
||||
@ -45,6 +48,8 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingSt
|
||||
m_nonClientArea = std::make_unique<NonClientArea>(this, m_qtWindow);
|
||||
m_nonClientArea->titleBar()->setTitle(window()->title());
|
||||
|
||||
m_clientArea = std::make_unique<ClientArea>(this, compositor->screen(), m_canvas);
|
||||
|
||||
m_qtWindow.call<void>("appendChild", m_windowContents);
|
||||
|
||||
m_canvas["classList"].call<void>("add", emscripten::val("qt-window-content"));
|
||||
@ -65,6 +70,16 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingSt
|
||||
emscripten::val::module_property("specialHTMLTargets").set(canvasSelector(), m_canvas);
|
||||
|
||||
m_compositor->addWindow(this);
|
||||
|
||||
const auto callback = std::function([this](emscripten::val event) {
|
||||
if (processPointer(*PointerEvent::fromWeb(event)))
|
||||
event.call<void>("preventDefault");
|
||||
});
|
||||
|
||||
m_pointerEnterCallback =
|
||||
std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerenter", callback);
|
||||
m_pointerLeaveCallback =
|
||||
std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerleave", callback);
|
||||
}
|
||||
|
||||
QWasmWindow::~QWasmWindow()
|
||||
@ -106,8 +121,8 @@ void QWasmWindow::onNonClientAreaInteraction()
|
||||
bool QWasmWindow::onNonClientEvent(const PointerEvent &event)
|
||||
{
|
||||
QPoint pointInScreen = platformScreen()->mapFromLocal(
|
||||
dom::mapPoint(event.currentTarget, platformScreen()->element(), event.localPoint));
|
||||
return QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(
|
||||
dom::mapPoint(event.target, platformScreen()->element(), event.localPoint));
|
||||
return QWindowSystemInterface::handleMouseEvent(
|
||||
window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
|
||||
pointInScreen, event.mouseButtons, event.mouseButton, ([event]() {
|
||||
switch (event.type) {
|
||||
@ -287,12 +302,6 @@ void QWasmWindow::propagateSizeHints()
|
||||
}
|
||||
}
|
||||
|
||||
bool QWasmWindow::startSystemResize(Qt::Edges)
|
||||
{
|
||||
// TODO(mikolajboc): This can only be implemented if per-window events are up and running
|
||||
return false;
|
||||
}
|
||||
|
||||
void QWasmWindow::invalidate()
|
||||
{
|
||||
m_compositor->requestUpdateWindow(this);
|
||||
@ -374,6 +383,29 @@ void QWasmWindow::applyWindowState()
|
||||
setGeometry(newGeom);
|
||||
}
|
||||
|
||||
bool QWasmWindow::processPointer(const PointerEvent &event)
|
||||
{
|
||||
if (event.pointerType != PointerType::Mouse)
|
||||
return false;
|
||||
|
||||
switch (event.type) {
|
||||
case EventType::PointerEnter: {
|
||||
const auto pointInScreen = platformScreen()->mapFromLocal(
|
||||
dom::mapPoint(event.target, platformScreen()->element(), event.localPoint));
|
||||
QWindowSystemInterface::handleEnterEvent(
|
||||
window(), m_window->mapFromGlobal(pointInScreen), pointInScreen);
|
||||
break;
|
||||
}
|
||||
case EventType::PointerLeave:
|
||||
QWindowSystemInterface::handleLeaveEvent(window());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QRect QWasmWindow::normalGeometry() const
|
||||
{
|
||||
return m_normalGeometry;
|
||||
@ -418,11 +450,8 @@ void QWasmWindow::requestActivateWindow()
|
||||
|
||||
bool QWasmWindow::setMouseGrabEnabled(bool grab)
|
||||
{
|
||||
if (grab)
|
||||
m_compositor->setCapture(this);
|
||||
else
|
||||
m_compositor->releaseCapture();
|
||||
return true;
|
||||
Q_UNUSED(grab);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QWasmWindow::windowEvent(QEvent *event)
|
||||
|
@ -20,6 +20,12 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace qstdweb {
|
||||
class EventCallback;
|
||||
}
|
||||
|
||||
class ClientArea;
|
||||
|
||||
class QWasmWindow final : public QPlatformWindow
|
||||
{
|
||||
public:
|
||||
@ -59,7 +65,6 @@ public:
|
||||
bool setKeyboardGrabEnabled(bool) override { return false; }
|
||||
bool setMouseGrabEnabled(bool grab) final;
|
||||
bool windowEvent(QEvent *event) final;
|
||||
bool startSystemResize(Qt::Edges edges) final;
|
||||
|
||||
QWasmScreen *platformScreen() const;
|
||||
void setBackingStore(QWasmBackingStore *store) { m_backingStore = store; }
|
||||
@ -76,6 +81,8 @@ private:
|
||||
bool hasTitleBar() const;
|
||||
void applyWindowState();
|
||||
|
||||
bool processPointer(const PointerEvent &event);
|
||||
|
||||
QWindow *m_window = nullptr;
|
||||
QWasmCompositor *m_compositor = nullptr;
|
||||
QWasmBackingStore *m_backingStore = nullptr;
|
||||
@ -89,13 +96,21 @@ private:
|
||||
emscripten::val m_context2d = emscripten::val::undefined();
|
||||
|
||||
std::unique_ptr<NonClientArea> m_nonClientArea;
|
||||
std::unique_ptr<ClientArea> m_clientArea;
|
||||
|
||||
std::unique_ptr<qstdweb::EventCallback> m_pointerLeaveCallback;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_pointerEnterCallback;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_pointerMoveCallback;
|
||||
|
||||
Qt::WindowStates m_state = Qt::WindowNoState;
|
||||
Qt::WindowStates m_previousWindowState = Qt::WindowNoState;
|
||||
|
||||
Qt::WindowFlags m_flags = Qt::Widget;
|
||||
|
||||
QPoint m_lastPointerMovePoint;
|
||||
|
||||
WId m_winId = 0;
|
||||
bool m_wantCapture = false;
|
||||
bool m_hasTitle = false;
|
||||
bool m_needsCompositor = false;
|
||||
long m_requestAnimationFrameId = -1;
|
||||
|
93
src/plugins/platforms/wasm/qwasmwindowclientarea.cpp
Normal file
93
src/plugins/platforms/wasm/qwasmwindowclientarea.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include "qwasmwindowclientarea.h"
|
||||
|
||||
#include "qwasmdom.h"
|
||||
#include "qwasmevent.h"
|
||||
#include "qwasmscreen.h"
|
||||
#include "qwasmwindow.h"
|
||||
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
#include <QtCore/qassert.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
ClientArea::ClientArea(QWasmWindow *window, QWasmScreen *screen, emscripten::val element)
|
||||
: m_screen(screen), m_window(window), m_element(element)
|
||||
{
|
||||
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>(element, "pointerdown", callback);
|
||||
m_pointerMoveCallback =
|
||||
std::make_unique<qstdweb::EventCallback>(element, "pointermove", callback);
|
||||
m_pointerUpCallback = std::make_unique<qstdweb::EventCallback>(element, "pointerup", callback);
|
||||
}
|
||||
|
||||
bool ClientArea::processPointer(const PointerEvent &event)
|
||||
{
|
||||
if (event.pointerType != PointerType::Mouse)
|
||||
return false;
|
||||
|
||||
const auto localScreenPoint =
|
||||
dom::mapPoint(event.target, m_screen->element(), event.localPoint);
|
||||
const auto pointInScreen = m_screen->mapFromLocal(localScreenPoint);
|
||||
|
||||
const QPoint pointInTargetWindowCoords = m_window->mapFromGlobal(pointInScreen);
|
||||
|
||||
switch (event.type) {
|
||||
case EventType::PointerDown: {
|
||||
m_element.call<void>("setPointerCapture", event.pointerId);
|
||||
m_window->window()->requestActivate();
|
||||
break;
|
||||
}
|
||||
case EventType::PointerUp: {
|
||||
m_element.call<void>("releasePointerCapture", event.pointerId);
|
||||
break;
|
||||
}
|
||||
case EventType::PointerEnter:;
|
||||
QWindowSystemInterface::handleEnterEvent(
|
||||
m_window->window(), pointInTargetWindowCoords, pointInScreen);
|
||||
break;
|
||||
case EventType::PointerLeave:
|
||||
QWindowSystemInterface::handleLeaveEvent(m_window->window());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
const bool eventAccepted = deliverEvent(event);
|
||||
if (!eventAccepted && event.type == EventType::PointerDown)
|
||||
QGuiApplicationPrivate::instance()->closeAllPopups();
|
||||
return eventAccepted;
|
||||
}
|
||||
|
||||
bool ClientArea::deliverEvent(const PointerEvent &event)
|
||||
{
|
||||
const auto pointInScreen = m_screen->mapFromLocal(
|
||||
dom::mapPoint(event.target, m_screen->element(), event.localPoint));
|
||||
|
||||
const QPoint targetPointClippedToScreen(
|
||||
std::max(m_screen->geometry().left(),
|
||||
std::min(m_screen->geometry().right(), pointInScreen.x())),
|
||||
std::max(m_screen->geometry().top(),
|
||||
std::min(m_screen->geometry().bottom(), pointInScreen.y())));
|
||||
|
||||
const QEvent::Type eventType =
|
||||
MouseEvent::mouseEventTypeFromEventType(event.type, WindowArea::Client);
|
||||
|
||||
return eventType != QEvent::None
|
||||
&& QWindowSystemInterface::handleMouseEvent(
|
||||
m_window->window(), QWasmIntegration::getTimestamp(),
|
||||
m_window->window()->mapFromGlobal(targetPointClippedToScreen),
|
||||
targetPointClippedToScreen, event.mouseButtons, event.mouseButton, eventType,
|
||||
event.modifiers);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
42
src/plugins/platforms/wasm/qwasmwindowclientarea.h
Normal file
42
src/plugins/platforms/wasm/qwasmwindowclientarea.h
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#ifndef QWASMWINDOWCLIENTAREA_H
|
||||
#define QWASMWINDOWCLIENTAREA_H
|
||||
|
||||
#include <QtCore/qnamespace.h>
|
||||
|
||||
#include <emscripten/val.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace qstdweb {
|
||||
class EventCallback;
|
||||
}
|
||||
|
||||
struct PointerEvent;
|
||||
class QWasmScreen;
|
||||
class QWasmWindow;
|
||||
|
||||
class ClientArea
|
||||
{
|
||||
public:
|
||||
ClientArea(QWasmWindow *window, QWasmScreen *screen, emscripten::val element);
|
||||
|
||||
private:
|
||||
bool processPointer(const PointerEvent &event);
|
||||
bool deliverEvent(const PointerEvent &event);
|
||||
|
||||
std::unique_ptr<qstdweb::EventCallback> m_pointerDownCallback;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_pointerMoveCallback;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_pointerUpCallback;
|
||||
|
||||
QWasmScreen *m_screen;
|
||||
QWasmWindow *m_window;
|
||||
emscripten::val m_element;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
#endif // QWASMWINDOWNONCLIENTAREA_H
|
@ -55,14 +55,16 @@ void WebImageButton::setCallbacks(Callbacks callbacks)
|
||||
if (callbacks) {
|
||||
if (!m_webClickEventCallback) {
|
||||
m_webMouseDownEventCallback = std::make_unique<qstdweb::EventCallback>(
|
||||
m_containerElement, "mousedown", [this](emscripten::val event) {
|
||||
m_containerElement, "pointerdown", [this](emscripten::val event) {
|
||||
event.call<void>("preventDefault");
|
||||
event.call<void>("stopPropagation");
|
||||
m_callbacks.onInteraction();
|
||||
});
|
||||
m_webClickEventCallback = std::make_unique<qstdweb::EventCallback>(
|
||||
m_containerElement, "click",
|
||||
[this](emscripten::val) { m_callbacks.onClick(); });
|
||||
m_containerElement, "click", [this](emscripten::val event) {
|
||||
m_callbacks.onClick();
|
||||
event.call<void>("stopPropagation");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
m_webMouseDownEventCallback.reset();
|
||||
@ -104,12 +106,10 @@ Resizer::ResizerElement::ResizerElement(emscripten::val parentElement, Qt::Edges
|
||||
event.call<void>("preventDefault");
|
||||
event.call<void>("stopPropagation");
|
||||
});
|
||||
m_mouseDragEvent = std::make_unique<qstdweb::EventCallback>(
|
||||
m_mouseMoveEvent = std::make_unique<qstdweb::EventCallback>(
|
||||
m_element, "pointermove", [this](emscripten::val event) {
|
||||
if (onPointerMove(*PointerEvent::fromWeb(event))) {
|
||||
if (onPointerMove(*PointerEvent::fromWeb(event)))
|
||||
event.call<void>("preventDefault");
|
||||
event.call<void>("stopPropagation");
|
||||
}
|
||||
});
|
||||
m_mouseUpEvent = std::make_unique<qstdweb::EventCallback>(
|
||||
m_element, "pointerup", [this](emscripten::val event) {
|
||||
@ -193,7 +193,7 @@ void Resizer::startResize(Qt::Edges resizeEdges, const PointerEvent &event)
|
||||
m_currentResizeData.reset(new ResizeData{
|
||||
.edges = resizeEdges,
|
||||
.originInScreenCoords = dom::mapPoint(
|
||||
event.currentTarget, m_window->platformScreen()->element(), event.localPoint),
|
||||
event.target, m_window->platformScreen()->element(), event.localPoint),
|
||||
});
|
||||
|
||||
const auto *window = m_window->window();
|
||||
@ -213,15 +213,12 @@ void Resizer::startResize(Qt::Edges resizeEdges, const PointerEvent &event)
|
||||
window->maximumHeight() - window->geometry().height()));
|
||||
|
||||
m_currentResizeData->initialBounds = window->geometry();
|
||||
|
||||
// TODO(mikolajboc): Implement system resize
|
||||
// .m_originInScreenCoords = m_systemDragInitData.lastMouseMovePoint,
|
||||
}
|
||||
|
||||
void Resizer::continueResize(const PointerEvent &event)
|
||||
{
|
||||
const auto pointInScreen = dom::mapPoint(
|
||||
event.currentTarget, m_window->platformScreen()->element(), event.localPoint);
|
||||
const auto pointInScreen =
|
||||
dom::mapPoint(event.target, m_window->platformScreen()->element(), event.localPoint);
|
||||
const auto amount = pointInScreen - m_currentResizeData->originInScreenCoords;
|
||||
const QPoint cappedGrowVector(
|
||||
std::min(m_currentResizeData->maxGrow.x(),
|
||||
@ -310,11 +307,10 @@ TitleBar::TitleBar(QWasmWindow *window, emscripten::val parentElement)
|
||||
event.call<void>("preventDefault");
|
||||
event.call<void>("stopPropagation");
|
||||
});
|
||||
m_mouseDragEvent = std::make_unique<qstdweb::EventCallback>(
|
||||
m_mouseMoveEvent = std::make_unique<qstdweb::EventCallback>(
|
||||
m_element, "pointermove", [this](emscripten::val event) {
|
||||
if (onPointerMove(*PointerEvent::fromWeb(event))) {
|
||||
event.call<void>("preventDefault");
|
||||
event.call<void>("stopPropagation");
|
||||
}
|
||||
});
|
||||
m_mouseUpEvent = std::make_unique<qstdweb::EventCallback>(
|
||||
|
@ -137,7 +137,7 @@ public:
|
||||
Resizer *m_resizer;
|
||||
|
||||
std::unique_ptr<qstdweb::EventCallback> m_mouseDownEvent;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_mouseDragEvent;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_mouseMoveEvent;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_mouseUpEvent;
|
||||
};
|
||||
|
||||
@ -203,7 +203,7 @@ private:
|
||||
QPoint m_lastMovePoint;
|
||||
|
||||
std::unique_ptr<qstdweb::EventCallback> m_mouseDownEvent;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_mouseDragEvent;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_mouseMoveEvent;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_mouseUpEvent;
|
||||
std::unique_ptr<qstdweb::EventCallback> m_doubleClickEvent;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user