GCC Code Coverage Report


Directory: ./
File: server/surface_p.h
Date: 2024-01-22 17:25:27
Exec Total Coverage
Lines: 25 26 96.2%
Branches: 28 58 48.3%

Line Branch Exec Source
1 /********************************************************************
2 Copyright © 2020 Roman Gilg <subdiff@gmail.com>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) version 3, or any
8 later version accepted by the membership of KDE e.V. (or its
9 successor approved by the membership of KDE e.V.), which shall
10 act as a proxy defined in Section 6 of version 3 of the license.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 *********************************************************************/
20 #pragma once
21
22 #include "surface.h"
23
24 #include "wayland/resource.h"
25
26 #include <QHash>
27 #include <QVector>
28
29 #include <deque>
30 #include <functional>
31 #include <unordered_map>
32 #include <wayland-server.h>
33
34 namespace Wrapland::Server
35 {
36
37 class Feedbacks;
38 class IdleInhibitor;
39 class LayerSurfaceV1;
40 class XdgShellSurface;
41
42 class SurfaceState
43 {
44 public:
45
1/2
✓ Branch 0 taken 1294 times.
✗ Branch 1 not taken.
2588 SurfaceState() = default;
46
47 SurfaceState(SurfaceState const&) = delete;
48 SurfaceState& operator=(SurfaceState const&) = delete;
49
50 SurfaceState(SurfaceState&&) noexcept = delete;
51 248 SurfaceState& operator=(SurfaceState&&) noexcept = default;
52
53 1294 ~SurfaceState() = default;
54
55 surface_state pub;
56
57
1/2
✓ Branch 0 taken 1294 times.
✗ Branch 1 not taken.
1294 QRegion bufferDamage = QRegion();
58
59 1294 bool destinationSizeIsSet = false;
60
61 std::deque<wl_resource*> callbacks;
62
63 1294 QSize destinationSize = QSize();
64
65
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1294 times.
1294 std::unique_ptr<Feedbacks> feedbacks{std::make_unique<Feedbacks>()};
66 };
67
68 class Surface::Private : public Wayland::Resource<Surface>
69 {
70 public:
71 Private(Client* client, uint32_t version, uint32_t id, Surface* q_ptr);
72 ~Private() override;
73
74 void addChild(Subsurface* child);
75 void removeChild(Subsurface* child);
76
77 bool raiseChild(Subsurface* subsurface, Surface* sibling);
78 bool lowerChild(Subsurface* subsurface, Surface* sibling);
79
80 void setShadow(Shadow* shadow);
81 void setBlur(Blur* blur);
82 void setSlide(Slide* slide);
83 void setContrast(Contrast* contrast);
84
85 void setSourceRectangle(QRectF const& source);
86 void setDestinationSize(QSize const& dest);
87 void addPresentationFeedback(PresentationFeedback* feedback) const;
88
89 void installPointerConstraint(LockedPointerV1* lock);
90 void installPointerConstraint(ConfinedPointerV1* confinement);
91 void installIdleInhibitor(IdleInhibitor* inhibitor);
92 void installViewport(Viewport* vp);
93
94 void commit();
95
96 void updateCurrentState(bool forceChildren);
97 void updateCurrentState(SurfaceState& source, bool forceChildren);
98
99 bool has_role() const;
100
101 bool had_buffer_attached{false};
102
103 XdgShellSurface* shellSurface = nullptr;
104 Subsurface* subsurface = nullptr;
105 LayerSurfaceV1* layer_surface{nullptr};
106
107 SurfaceState current;
108 SurfaceState pending;
109
110 QRegion trackedDamage;
111
112 // Workaround for https://bugreports.qt.io/browse/QTBUG-52192:
113 // A subsurface needs to be considered mapped even if it doesn't have a buffer attached.
114 // Otherwise Qt's sub-surfaces will never be visible and the client will freeze due to
115 // waiting on the frame callback of the never visible surface.
116 // bool subsurfaceIsMapped = true;
117
118 std::vector<WlOutput*> outputs;
119
120 uint32_t feedbackId = 0;
121 std::unordered_map<uint32_t, std::unique_ptr<Feedbacks>> waitingFeedbacks;
122
123 LockedPointerV1* lockedPointer{nullptr};
124 ConfinedPointerV1* confinedPointer{nullptr};
125 Viewport* viewport{nullptr};
126 QHash<WlOutput*, QMetaObject::Connection> outputDestroyedConnections;
127 QVector<IdleInhibitor*> idleInhibitors;
128
129 private:
130 void update_buffer(SurfaceState const& source, bool& resized);
131 void copy_to_current(SurfaceState const& source, bool& resized);
132 void synced_child_update();
133
134 void damage(QRect const& rect);
135 void damageBuffer(QRect const& rect);
136
137 void setScale(qint32 scale);
138 void setTransform(output_transform transform);
139
140 void addFrameCallback(uint32_t callback);
141 void attachBuffer(wl_resource* wlBuffer, QPoint const& offset);
142
143 void setOpaque(QRegion const& region);
144 void setInput(QRegion const& region, bool isInfinite);
145
146 /**
147 * Posts Wayland error in case the source rectangle needs to be integer valued but is not.
148 */
149 void soureRectangleIntegerCheck(QSize const& destinationSize,
150 QRectF const& sourceRectangle) const;
151 /**
152 * Posts Wayland error in case the source rectangle is not contained in surface size.
153 */
154 void soureRectangleContainCheck(Buffer const* buffer,
155 output_transform transform,
156 qint32 scale,
157 QRectF const& sourceRectangle) const;
158
159 static void destroyFrameCallback(wl_resource* wlResource);
160
161 static void attachCallback(wl_client* wlClient,
162 wl_resource* wlResource,
163 wl_resource* buffer,
164 int32_t pos_x,
165 int32_t pos_y);
166 static void damageCallback(wl_client* wlClient,
167 wl_resource* wlResource,
168 int32_t pos_x,
169 int32_t pos_y,
170 int32_t width,
171 int32_t height);
172 static void frameCallback(wl_client* wlClient, wl_resource* wlResource, uint32_t callback);
173 static void
174 opaqueRegionCallback(wl_client* wlClient, wl_resource* wlResource, wl_resource* wlRegion);
175 static void
176 inputRegionCallback(wl_client* wlClient, wl_resource* wlResource, wl_resource* wlRegion);
177 static void commitCallback(wl_client* wlClient, wl_resource* wlResource);
178
179 // Since version 2.
180 static void
181 bufferTransformCallback(wl_client* wlClient, wl_resource* wlResource, int32_t transform);
182
183 // Since version 3.
184 static void bufferScaleCallback(wl_client* wlClient, wl_resource* wlResource, int32_t scale);
185
186 // Since version 4.
187 static void damageBufferCallback(wl_client* wlClient,
188 wl_resource* wlResource,
189 int32_t pos_x,
190 int32_t pos_y,
191 int32_t width,
192 int32_t height);
193
194 template<typename Obj>
195 3 bool needs_resource_reset(Obj const& current,
196 Obj const& pending,
197 Obj const& obj,
198 surface_change change) const
199 {
200 3 auto const is_current = current == obj;
201 3 auto const is_pending_set = this->pending.pub.updates & change;
202 3 auto const obj_is_pending = pending == obj;
203
204
3/16
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
3 if (is_pending_set && obj_is_pending) {
205 // The object is pending. Needs to be changed in any case.
206 return true;
207 }
208
209 // Needs reset if the object is current and there is no other pending object.
210
3/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
3 return is_current || !is_pending_set;
211 3 }
212
213 template<typename Obj>
214 920 void move_state_resource(SurfaceState const& source,
215 surface_change change,
216 Obj*& current,
217 Obj* const& pending,
218 QMetaObject::Connection& destroy_notifier,
219 std::function<void(Obj*)> resetter) const
220 {
221
8/8
✓ Branch 0 taken 226 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 228 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 228 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 228 times.
✓ Branch 7 taken 2 times.
920 if (!(source.pub.updates & change)) {
222 910 return;
223 }
224
225 10 QObject::disconnect(destroy_notifier);
226 10 current = pending;
227
228
5/8
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
10 if (!current) {
229 1 return;
230 }
231
232
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
9 destroy_notifier = QObject::connect(
233 12 current, &Obj::resourceDestroyed, handle, [resetter, current] { resetter(current); });
234 920 }
235
236 static const struct wl_surface_interface s_interface;
237
238 QMetaObject::Connection constrainsOneShotConnection;
239 QMetaObject::Connection constrainsUnboundConnection;
240
241
2/4
✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 515 times.
515 struct {
242 QMetaObject::Connection blur;
243 QMetaObject::Connection contrast;
244 QMetaObject::Connection shadow;
245 QMetaObject::Connection slide;
246 } destroy_notifiers;
247
248 Surface* q_ptr;
249 };
250
251 class Feedbacks : public QObject
252 {
253 Q_OBJECT
254 public:
255 explicit Feedbacks(QObject* parent = nullptr);
256 ~Feedbacks() override;
257
258 bool active();
259 void add(PresentationFeedback* feedback);
260 void setOutput(Server::output* output);
261 void handleOutputRemoval();
262
263 void presented(uint32_t tvSecHi,
264 uint32_t tvSecLo,
265 uint32_t tvNsec,
266 uint32_t refresh,
267 uint32_t seqHi,
268 uint32_t seqLo,
269 Surface::PresentationKinds kinds);
270 void discard();
271
272 private:
273 std::vector<PresentationFeedback*> m_feedbacks;
274 Server::output* m_output = nullptr;
275 };
276
277 }
278