Directory: | ./ |
---|---|
File: | src/client/wlr_output_configuration_v1.cpp |
Date: | 2024-01-22 17:25:27 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 125 | 155 | 80.6% |
Branches: | 28 | 55 | 50.9% |
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 | #include "wlr_output_configuration_v1.h" | ||
21 | |||
22 | #include "event_queue.h" | ||
23 | #include "wayland_pointer_p.h" | ||
24 | #include "wlr_output_manager_v1.h" | ||
25 | |||
26 | #include "wayland-wlr-output-management-v1-client-protocol.h" | ||
27 | |||
28 | #include <memory> | ||
29 | #include <vector> | ||
30 | |||
31 | namespace Wrapland | ||
32 | { | ||
33 | namespace Client | ||
34 | { | ||
35 | |||
36 | 4 | struct ConfigurationHead { | |
37 | 2 | ~ConfigurationHead() | |
38 | { | ||
39 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (native) { |
40 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | zwlr_output_configuration_head_v1_destroy(native); |
41 | 1 | } | |
42 | 2 | } | |
43 | |||
44 | 2 | WlrOutputHeadV1* head = nullptr; | |
45 | 2 | zwlr_output_configuration_head_v1* native = nullptr; | |
46 | |||
47 | 2 | WlrOutputModeV1* mode = nullptr; | |
48 | |||
49 | 2 | struct { | |
50 | QSize size; | ||
51 | 2 | int refresh = -1; | |
52 | } customMode; | ||
53 | |||
54 | QPoint position; | ||
55 | 2 | bool positionSet = false; | |
56 | 2 | WlrOutputHeadV1::Transform transform = WlrOutputHeadV1::Transform::Normal; | |
57 | 2 | bool transformSet = false; | |
58 | 2 | double scale = 1.; | |
59 | 2 | bool scaleSet = false; | |
60 | 2 | bool adapt_sync{false}; | |
61 | 2 | bool adapt_sync_set{false}; | |
62 | }; | ||
63 | |||
64 | class Q_DECL_HIDDEN WlrOutputConfigurationV1::Private | ||
65 | { | ||
66 | public: | ||
67 | 2 | Private() = default; | |
68 | |||
69 | void setup(zwlr_output_configuration_v1* outputConfiguration); | ||
70 | |||
71 | WaylandPointer<zwlr_output_configuration_v1, zwlr_output_configuration_v1_destroy> | ||
72 | outputConfiguration; | ||
73 | static const struct zwlr_output_configuration_v1_listener s_listener; | ||
74 | 1 | EventQueue* queue = nullptr; | |
75 | |||
76 | void send(); | ||
77 | ConfigurationHead* getConfigurationHead(WlrOutputHeadV1* head); | ||
78 | |||
79 | std::vector<std::unique_ptr<ConfigurationHead>> heads; | ||
80 | WlrOutputConfigurationV1* q; | ||
81 | |||
82 | private: | ||
83 | static void succeededCallback(void* data, zwlr_output_configuration_v1* config); | ||
84 | static void failedCallback(void* data, zwlr_output_configuration_v1* config); | ||
85 | static void cancelledCallback(void* data, zwlr_output_configuration_v1* config); | ||
86 | }; | ||
87 | |||
88 | const zwlr_output_configuration_v1_listener WlrOutputConfigurationV1::Private::s_listener = { | ||
89 | succeededCallback, | ||
90 | failedCallback, | ||
91 | cancelledCallback, | ||
92 | }; | ||
93 | |||
94 | 1 | void WlrOutputConfigurationV1::Private::succeededCallback(void* data, | |
95 | zwlr_output_configuration_v1* config) | ||
96 | { | ||
97 | Q_UNUSED(config); | ||
98 | 1 | auto priv = reinterpret_cast<WlrOutputConfigurationV1::Private*>(data); | |
99 | 1 | Q_EMIT priv->q->succeeded(); | |
100 | 1 | } | |
101 | |||
102 | ✗ | void WlrOutputConfigurationV1::Private::failedCallback(void* data, | |
103 | zwlr_output_configuration_v1* config) | ||
104 | { | ||
105 | Q_UNUSED(config); | ||
106 | ✗ | auto priv = reinterpret_cast<WlrOutputConfigurationV1::Private*>(data); | |
107 | ✗ | Q_EMIT priv->q->failed(); | |
108 | } | ||
109 | |||
110 | ✗ | void WlrOutputConfigurationV1::Private::cancelledCallback(void* data, | |
111 | zwlr_output_configuration_v1* config) | ||
112 | { | ||
113 | Q_UNUSED(config); | ||
114 | ✗ | auto priv = reinterpret_cast<WlrOutputConfigurationV1::Private*>(data); | |
115 | ✗ | Q_EMIT priv->q->cancelled(); | |
116 | } | ||
117 | |||
118 | 1 | WlrOutputConfigurationV1::WlrOutputConfigurationV1(QObject* parent) | |
119 | 1 | : QObject(parent) | |
120 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | , d(new Private) |
121 | 1 | { | |
122 | 1 | d->q = this; | |
123 | 1 | } | |
124 | |||
125 | 2 | WlrOutputConfigurationV1::~WlrOutputConfigurationV1() | |
126 | 2 | { | |
127 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | release(); |
128 | 2 | } | |
129 | |||
130 | 1 | void WlrOutputConfigurationV1::setup(zwlr_output_configuration_v1* outputConfiguration) | |
131 | { | ||
132 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | Q_ASSERT(outputConfiguration); |
133 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | Q_ASSERT(!d->outputConfiguration); |
134 | |||
135 | 1 | d->outputConfiguration.setup(outputConfiguration); | |
136 | 1 | d->setup(outputConfiguration); | |
137 | 1 | } | |
138 | |||
139 | 1 | void WlrOutputConfigurationV1::Private::setup(zwlr_output_configuration_v1* outputConfiguration) | |
140 | { | ||
141 | 1 | zwlr_output_configuration_v1_add_listener(outputConfiguration, &s_listener, this); | |
142 | 1 | } | |
143 | |||
144 | 9 | ConfigurationHead* WlrOutputConfigurationV1::Private::getConfigurationHead(WlrOutputHeadV1* head) | |
145 | { | ||
146 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
|
16 | for (auto& configurationHead : heads) { |
147 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
|
14 | if (configurationHead->head == head) { |
148 | 7 | return configurationHead.get(); | |
149 | } | ||
150 | } | ||
151 | |||
152 | // Create a new configuration head struct and hand a reference back by calling this function | ||
153 | // again. | ||
154 | 2 | std::unique_ptr<ConfigurationHead> configurationHead(new ConfigurationHead); | |
155 | 2 | configurationHead->head = head; | |
156 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | heads.push_back(std::move(configurationHead)); |
157 | |||
158 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | return getConfigurationHead(head); |
159 | 9 | } | |
160 | |||
161 | 1 | void WlrOutputConfigurationV1::Private::send() | |
162 | { | ||
163 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (auto& head : heads) { |
164 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (!head->native) { |
165 | 1 | continue; | |
166 | } | ||
167 | |||
168 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (head->mode) { |
169 | 1 | zwlr_output_configuration_head_v1_set_mode(head->native, *head->mode); | |
170 |
0/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | } else if (head->customMode.refresh >= 0 && head->customMode.size.isValid()) { |
171 | ✗ | zwlr_output_configuration_head_v1_set_custom_mode(head->native, | |
172 | ✗ | head->customMode.size.width(), | |
173 | ✗ | head->customMode.size.height(), | |
174 | ✗ | head->customMode.refresh); | |
175 | } | ||
176 | |||
177 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (head->positionSet) { |
178 | 1 | zwlr_output_configuration_head_v1_set_position( | |
179 | 1 | head->native, head->position.x(), head->position.y()); | |
180 | 1 | } | |
181 | |||
182 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (head->transformSet) { |
183 | 2 | auto toNative = [](WlrOutputHeadV1::Transform transform) { | |
184 |
1/9✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
1 | switch (transform) { |
185 | case WlrOutputHeadV1::Transform::Normal: | ||
186 | ✗ | return WL_OUTPUT_TRANSFORM_NORMAL; | |
187 | case WlrOutputHeadV1::Transform::Rotated90: | ||
188 | 1 | return WL_OUTPUT_TRANSFORM_90; | |
189 | case WlrOutputHeadV1::Transform::Rotated180: | ||
190 | ✗ | return WL_OUTPUT_TRANSFORM_180; | |
191 | case WlrOutputHeadV1::Transform::Rotated270: | ||
192 | ✗ | return WL_OUTPUT_TRANSFORM_270; | |
193 | case WlrOutputHeadV1::Transform::Flipped: | ||
194 | ✗ | return WL_OUTPUT_TRANSFORM_FLIPPED; | |
195 | case WlrOutputHeadV1::Transform::Flipped90: | ||
196 | ✗ | return WL_OUTPUT_TRANSFORM_FLIPPED_90; | |
197 | case WlrOutputHeadV1::Transform::Flipped180: | ||
198 | ✗ | return WL_OUTPUT_TRANSFORM_FLIPPED_180; | |
199 | case WlrOutputHeadV1::Transform::Flipped270: | ||
200 | ✗ | return WL_OUTPUT_TRANSFORM_FLIPPED_270; | |
201 | } | ||
202 | ✗ | abort(); | |
203 | 1 | }; | |
204 | 2 | zwlr_output_configuration_head_v1_set_transform(head->native, | |
205 | 1 | toNative(head->transform)); | |
206 | 1 | } | |
207 | |||
208 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (head->scaleSet) { |
209 | 2 | zwlr_output_configuration_head_v1_set_scale(head->native, | |
210 | 1 | wl_fixed_from_double(head->scale)); | |
211 | 1 | } | |
212 | |||
213 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (head->adapt_sync_set) { |
214 | 1 | zwlr_output_configuration_head_v1_set_adaptive_sync( | |
215 | 1 | head->native, | |
216 | 1 | head->adapt_sync ? ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED | |
217 | : ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED); | ||
218 | 1 | } | |
219 | } | ||
220 | 1 | } | |
221 | |||
222 | 1 | void WlrOutputConfigurationV1::release() | |
223 | { | ||
224 | 1 | d->outputConfiguration.release(); | |
225 | 1 | } | |
226 | |||
227 | ✗ | void WlrOutputConfigurationV1::setEventQueue(EventQueue* queue) | |
228 | { | ||
229 | ✗ | d->queue = queue; | |
230 | } | ||
231 | |||
232 | ✗ | EventQueue* WlrOutputConfigurationV1::eventQueue() | |
233 | { | ||
234 | ✗ | return d->queue; | |
235 | } | ||
236 | |||
237 | ✗ | WlrOutputConfigurationV1::operator zwlr_output_configuration_v1*() | |
238 | { | ||
239 | ✗ | return d->outputConfiguration; | |
240 | } | ||
241 | |||
242 | ✗ | WlrOutputConfigurationV1::operator zwlr_output_configuration_v1*() const | |
243 | { | ||
244 | ✗ | return d->outputConfiguration; | |
245 | } | ||
246 | |||
247 | 1 | bool WlrOutputConfigurationV1::isValid() const | |
248 | { | ||
249 | 1 | return d->outputConfiguration.isValid(); | |
250 | } | ||
251 | |||
252 | 2 | void WlrOutputConfigurationV1::setEnabled(WlrOutputHeadV1* head, bool enable) | |
253 | { | ||
254 | 2 | auto configurationHead = d->getConfigurationHead(head); | |
255 | |||
256 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (enable) { |
257 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (!configurationHead->native) { |
258 | 1 | configurationHead->native | |
259 | 2 | = zwlr_output_configuration_v1_enable_head(d->outputConfiguration, *head); | |
260 | 1 | } | |
261 | 1 | } else { | |
262 | 1 | zwlr_output_configuration_v1_disable_head(d->outputConfiguration, *head); | |
263 | } | ||
264 | 2 | } | |
265 | |||
266 | 1 | void WlrOutputConfigurationV1::setMode(WlrOutputHeadV1* head, WlrOutputModeV1* mode) | |
267 | { | ||
268 | 1 | d->getConfigurationHead(head)->mode = mode; | |
269 | 1 | } | |
270 | |||
271 | 1 | void WlrOutputConfigurationV1::setTransform(WlrOutputHeadV1* head, | |
272 | WlrOutputHeadV1::Transform transform) | ||
273 | { | ||
274 | 1 | auto configurationHead = d->getConfigurationHead(head); | |
275 | |||
276 | 1 | configurationHead->transform = transform; | |
277 | 1 | configurationHead->transformSet = true; | |
278 | 1 | } | |
279 | |||
280 | 1 | void WlrOutputConfigurationV1::setPosition(WlrOutputHeadV1* head, QPoint const& pos) | |
281 | { | ||
282 | 1 | auto configurationHead = d->getConfigurationHead(head); | |
283 | |||
284 | 1 | configurationHead->position = pos; | |
285 | 1 | configurationHead->positionSet = true; | |
286 | 1 | } | |
287 | |||
288 | 1 | void WlrOutputConfigurationV1::setScale(WlrOutputHeadV1* head, double scale) | |
289 | { | ||
290 | 1 | auto configurationHead = d->getConfigurationHead(head); | |
291 | |||
292 | 1 | configurationHead->scale = scale; | |
293 | 1 | configurationHead->scaleSet = true; | |
294 | 1 | } | |
295 | |||
296 | 1 | void WlrOutputConfigurationV1::set_adaptive_sync(WlrOutputHeadV1* head, bool enable) | |
297 | { | ||
298 | 1 | auto configurationHead = d->getConfigurationHead(head); | |
299 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
2 | if (zwlr_output_configuration_head_v1_get_version(configurationHead->native) |
300 | 1 | < ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_SET_ADAPTIVE_SYNC_SINCE_VERSION) { | |
301 | ✗ | return; | |
302 | } | ||
303 | |||
304 | 1 | configurationHead->adapt_sync = enable; | |
305 | 1 | configurationHead->adapt_sync_set = true; | |
306 | 1 | } | |
307 | |||
308 | ✗ | void WlrOutputConfigurationV1::test() | |
309 | { | ||
310 | ✗ | d->send(); | |
311 | ✗ | zwlr_output_configuration_v1_test(d->outputConfiguration); | |
312 | } | ||
313 | |||
314 | 1 | void WlrOutputConfigurationV1::apply() | |
315 | { | ||
316 | 1 | d->send(); | |
317 | 1 | zwlr_output_configuration_v1_apply(d->outputConfiguration); | |
318 | 1 | } | |
319 | |||
320 | } | ||
321 | } | ||
322 |