1 | // Copyright (C) 2017 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "qwlqttouch_p.h" |
5 | #include "qwaylandview.h" |
6 | #include <QPointingDevice> |
7 | #include <QTouchEvent> |
8 | #include <QWindow> |
9 | |
10 | QT_BEGIN_NAMESPACE |
11 | |
12 | namespace QtWayland { |
13 | |
14 | static const int maxRawPos = 24; |
15 | |
16 | TouchExtensionGlobal::TouchExtensionGlobal(QWaylandCompositor *compositor) |
17 | : QWaylandCompositorExtensionTemplate(compositor) |
18 | , QtWaylandServer::qt_touch_extension(compositor->display(), 1) |
19 | , m_compositor(compositor) |
20 | , m_posData(maxRawPos * 2) |
21 | { |
22 | } |
23 | |
24 | TouchExtensionGlobal::~TouchExtensionGlobal() |
25 | { |
26 | } |
27 | |
28 | static inline int toFixed(qreal f) |
29 | { |
30 | return int(f * 10000); |
31 | } |
32 | |
33 | bool TouchExtensionGlobal::postTouchEvent(QTouchEvent *event, QWaylandSurface *surface) |
34 | { |
35 | const QList<QTouchEvent::TouchPoint> points = event->points(); |
36 | const int pointCount = points.size(); |
37 | if (!pointCount) |
38 | return false; |
39 | |
40 | wl_client *surfaceClient = surface->client()->client(); |
41 | uint32_t time = m_compositor->currentTimeMsecs(); |
42 | const int rescount = m_resources.size(); |
43 | |
44 | for (int res = 0; res < rescount; ++res) { |
45 | Resource *target = m_resources.at(res); |
46 | if (target->client() != surfaceClient) |
47 | continue; |
48 | |
49 | // We will use no touch_frame type of event, to reduce the number of |
50 | // events flowing through the wire. Instead, the number of points sent is |
51 | // included in the touch point events. |
52 | int sentPointCount = 0; |
53 | for (int i = 0; i < pointCount; ++i) { |
54 | if (points.at(i).state() != QEventPoint::Stationary) |
55 | ++sentPointCount; |
56 | } |
57 | |
58 | for (int i = 0; i < pointCount; ++i) { |
59 | const QTouchEvent::TouchPoint &tp(points.at(i)); |
60 | // Stationary points are never sent. They are cached on client side. |
61 | if (tp.state() == QEventPoint::Stationary) |
62 | continue; |
63 | |
64 | uint32_t id = tp.id(); |
65 | uint32_t state = (tp.state() & 0xFFFF) | (sentPointCount << 16); |
66 | uint32_t flags = (int(event->pointingDevice()->capabilities()) << 16); |
67 | |
68 | int x = toFixed(f: tp.position().x()); |
69 | int y = toFixed(f: tp.position().y()); |
70 | int nx = toFixed(f: tp.normalizedPosition().x()); |
71 | int ny = toFixed(f: tp.normalizedPosition().y()); |
72 | int w = toFixed(f: tp.ellipseDiameters().width()); |
73 | int h = toFixed(f: tp.ellipseDiameters().height()); |
74 | int vx = toFixed(f: tp.velocity().x()); |
75 | int vy = toFixed(f: tp.velocity().y()); |
76 | uint32_t pressure = uint32_t(tp.pressure() * 255); |
77 | |
78 | QByteArray rawData; |
79 | send_touch(target->handle, |
80 | time, id, state, |
81 | x, y, nx, ny, w, h, |
82 | pressure, vx, vy, |
83 | flags, rawData); |
84 | } |
85 | |
86 | return true; |
87 | } |
88 | |
89 | return false; |
90 | } |
91 | |
92 | void TouchExtensionGlobal::setBehviorFlags(BehaviorFlags flags) |
93 | { |
94 | if (m_flags == flags) |
95 | return; |
96 | |
97 | m_flags = flags; |
98 | behaviorFlagsChanged(); |
99 | } |
100 | |
101 | void TouchExtensionGlobal::touch_extension_bind_resource(Resource *resource) |
102 | { |
103 | m_resources.append(resource); |
104 | send_configure(resource->handle, m_flags); |
105 | } |
106 | |
107 | void TouchExtensionGlobal::touch_extension_destroy_resource(Resource *resource) |
108 | { |
109 | m_resources.removeOne(resource); |
110 | } |
111 | |
112 | } |
113 | |
114 | QT_END_NAMESPACE |
115 | |
116 | #include "moc_qwlqttouch_p.cpp" |
117 | |