summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/wasm/qwasmwindowclientarea.cpp
blob: d6c6b14b57f3ff627b5259f0ba04c40eb0506c33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// 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 QPointF pointInTargetWindowCoords = m_window->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 auto geometryF = m_screen->geometry().toRectF();
    const QPointF targetPointClippedToScreen(
            qBound(geometryF.left(), pointInScreen.x(), geometryF.right()),
            qBound(geometryF.top(), pointInScreen.y(), geometryF.bottom()));

    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