Wayland++ 1.0.0
C++ Bindings for Wayland
Loading...
Searching...
No Matches
wayland-util.hpp
1/*
2 * Copyright (c) 2014-2022, Nils Christopher Brause, Philipp Kerling
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef WAYLAND_UTIL_HPP
27#define WAYLAND_UTIL_HPP
28
29#include <algorithm>
30#include <memory>
31#include <stdexcept>
32#include <string>
33#include <typeinfo>
34#include <utility>
35#include <vector>
36
37#include <wayland-client-core.h>
38
39#define wl_array_for_each_cpp(pos, array) \
40 for((pos) = static_cast<decltype(pos)>((array)->data); \
41 reinterpret_cast<const char*>(pos) < (reinterpret_cast<const char*>((array)->data) + (array)->size); \
42 (pos)++)
43
44namespace wayland
45{
46 class proxy_t;
47
48 class array_t;
49
50 namespace server
51 {
52 class resource_t;
53 }
54
55 namespace detail
56 {
65 int check_return_value(int return_value, std::string const &function_name);
66
72 template<typename native_t>
73 class basic_wrapper
74 {
75 private:
76 native_t *object = nullptr;
77
78 protected:
79 basic_wrapper(native_t *object)
80 : object{object}
81 {
82 }
83
84 public:
85 basic_wrapper() = default;
86 ~basic_wrapper() noexcept = default;
87
88 basic_wrapper(basic_wrapper const &other)
89 {
90 *this = other;
91 }
92
93 basic_wrapper(basic_wrapper &&other) noexcept
94 {
95 *this = std::move(other);
96 }
97
98 native_t *c_ptr() const
99 {
100 if(!object)
101 throw std::runtime_error("Tried to access empty object");
102 return object;
103 }
104
105 bool has_object() const
106 {
107 return object;
108 }
109
110 operator bool() const
111 {
112 return has_object();
113 }
114
115 operator native_t*() const
116 {
117 return c_ptr();
118 }
119
120 basic_wrapper& operator=(const basic_wrapper &right)
121 {
122 // Check for self-assignment
123 if(this == &right)
124 return *this;
125 object = right.object;
126 return *this;
127 }
128
129 basic_wrapper& operator=(basic_wrapper &&right) noexcept
130 {
131 std::swap(object, right.object);
132 return *this;
133 }
134
135 bool operator==(const basic_wrapper &right) const
136 {
137 return object == right.object;
138 }
139
140 bool operator!=(const basic_wrapper &right) const
141 {
142 return !(*this == right); // Reuse equals operator
143 }
144 };
145
151 template<typename native_t>
152 class refcounted_wrapper
153 {
154 private:
155 std::shared_ptr<native_t> object;
156
157 protected:
158 refcounted_wrapper(std::shared_ptr<native_t> object)
159 : object{std::move(object)}
160 {
161 }
162
163 std::shared_ptr<native_t> ref_ptr() const
164 {
165 return object;
166 }
167
168 public:
169 refcounted_wrapper() = default;
170 ~refcounted_wrapper() noexcept = default;
171
172 refcounted_wrapper(refcounted_wrapper const &other)
173 {
174 *this = other;
175 }
176
177 refcounted_wrapper(refcounted_wrapper &&other) noexcept
178 {
179 *this = std::move(other);
180 }
181
182 native_t *c_ptr() const
183 {
184 if(!object)
185 throw std::runtime_error("Tried to access empty object");
186 return object.get();
187 }
188
189 bool has_object() const
190 {
191 return !!object;
192 }
193
194 operator bool() const
195 {
196 return has_object();
197 }
198
199 operator native_t*() const
200 {
201 return c_ptr();
202 }
203
204 refcounted_wrapper& operator=(const refcounted_wrapper &right)
205 {
206 // Check for self-assignment
207 if(this == &right)
208 return *this;
209 object = right.object;
210 return *this;
211 }
212
213 refcounted_wrapper& operator=(refcounted_wrapper &&right) noexcept
214 {
215 std::swap(object, right.object);
216 return *this;
217 }
218
219 bool operator==(const refcounted_wrapper &right) const
220 {
221 return object == right.object;
222 }
223
224 bool operator!=(const refcounted_wrapper &right) const
225 {
226 return !(*this == right); // Reuse equals operator
227 }
228 };
229
230 class any
231 {
232 private:
233 class base
234 {
235 public:
236 base() = default;
237 base(const base&) = default;
238 base(base&&) noexcept = default;
239 base& operator=(const base&) = default;
240 base& operator=(base&&) noexcept = default;
241 virtual ~base() noexcept = default;
242 virtual const std::type_info &type_info() const = 0;
243 virtual base *clone() const = 0;
244 };
245
246 template <typename T>
247 class derived : public base
248 {
249 private:
250 T val;
251 friend class any;
252
253 public:
254 derived(T t)
255 : val(std::move(t)) { }
256
257 const std::type_info &type_info() const override
258 {
259 return typeid(T);
260 }
261
262 base *clone() const override
263 {
264 return new derived<T>(val);
265 }
266 };
267
268 base *val = nullptr;
269
270 public:
271 any() = default;
272
273 any(const any &a)
274 : val(a.val ? a.val->clone() : nullptr) { }
275
276 any(any &&a) noexcept
277 {
278 operator=(std::move(a));
279 }
280
281 template <typename T>
282 any(const T &t)
283 : val(new derived<T>(t)) { }
284
285 ~any() noexcept
286 {
287 delete val;
288 }
289
290 any &operator=(const any &a)
291 {
292 if(&a != this)
293 {
294 delete val;
295 val = a.val ? a.val->clone() : nullptr;
296 }
297 return *this;
298 }
299
300 any &operator=(any &&a) noexcept
301 {
302 std::swap(val, a.val);
303 return *this;
304 }
305
306 template <typename T>
307 any &operator=(const T &t)
308 {
309 if(val && typeid(T) == val->type_info())
310 static_cast<derived<T>*>(val)->val = t;
311 else
312 {
313 delete val;
314 val = new derived<T>(t);
315 }
316 return *this;
317 }
318
319 template <typename T>
320 T &get()
321 {
322 if(val && typeid(T) == val->type_info())
323 return static_cast<derived<T>*>(val)->val;
324 throw std::bad_cast();
325 }
326
327 template <typename T>
328 const T &get() const
329 {
330 if(val && typeid(T) == val->type_info())
331 return static_cast<derived<T>*>(val)->val;
332 throw std::bad_cast();
333 }
334 };
335
336 template<unsigned int size, int id = 0>
337 class bitfield
338 {
339 uint32_t v = 0;
340 static const uint32_t mask = (1 << size) - 1;
341
342 public:
343 explicit bitfield(const uint32_t value = 0)
344 : v(value)
345 {
346 }
347
348 explicit operator uint32_t() const
349 {
350 return v;
351 }
352
353 operator bool() const
354 {
355 return v;
356 }
357
358 bitfield(const bitfield<size, id> &b)
359 {
360 operator=(b);
361 }
362
363 bitfield(bitfield<size, id>&&) noexcept = default;
364
365 ~bitfield() noexcept = default;
366
367 bool operator==(const bitfield<size, id> &b)
368 {
369 return v == b.v;
370 }
371
372 bool operator!=(const bitfield<size, id> &b)
373 {
374 return !operator==(b);
375 }
376
377 bitfield<size, id> &operator=(const bitfield<size, id> &b)
378 {
379 // Check for self-assignment
380 if(this != &b)
381 v = static_cast<uint32_t>(b);
382 return *this;
383 }
384
385 bitfield<size, id> &operator=(bitfield<size, id> &&) noexcept = default;
386
387 bitfield<size, id> operator|(const bitfield<size, id> &b) const
388 {
389 return bitfield<size, id>(v | static_cast<uint32_t>(b));
390 }
391
392 bitfield<size, id> operator&(const bitfield<size, id> &b) const
393 {
394 return bitfield<size, id>(v & static_cast<uint32_t>(b));
395 }
396
397 bitfield<size, id> operator^(const bitfield<size, id> &b) const
398 {
399 return bitfield<size, id>((v ^ static_cast<uint32_t>(b)) & mask);
400 }
401
402 bitfield<size, id> operator~() const
403 {
404 return bitfield<size, id>(~v & mask);
405 }
406
407 bitfield<size, id> &operator|=(const bitfield<size, id> &b)
408 {
409 operator=(*this | b);
410 return *this;
411 }
412
413 bitfield<size, id> &operator&=(const bitfield<size, id> &b)
414 {
415 operator=(*this & b);
416 return *this;
417 }
418
419 bitfield<size, id> &operator^=(const bitfield<size, id> &b)
420 {
421 operator=(*this ^ b);
422 return *this;
423 }
424 };
425
426 class argument_t
427 {
428 private:
429 wl_argument argument = { .i = 0 };
430 bool is_array{false};
431
432 // Uninitialized argument - only for internal use
433 argument_t() = default;
434 public:
435
436 argument_t(const argument_t &arg);
437 argument_t(argument_t &&) noexcept = default;
438 argument_t &operator=(const argument_t &arg);
439 argument_t &operator=(argument_t&&) noexcept = default;
440 ~argument_t() noexcept;
441
442 // handles integers
443 argument_t(uint32_t i);
444 argument_t(int32_t i);
445
446 // handles wl_fixed_t
447 argument_t(double f);
448
449 // handles strings
450 argument_t(const std::string &s);
451
452 // handles objects
453 argument_t(wl_object *o);
454
455 // handles arrays
456 argument_t(const array_t& a);
457
458 // handles null objects, for example for new-id arguments
459 argument_t(std::nullptr_t);
460
461 // handles file descriptors (have same type as signed integers, so extra function)
462 static argument_t fd(int fileno);
463
467 wl_argument get_c_argument() const;
468 };
469 }
470
471 class array_t
472 {
473 private:
474 wl_array a = { 0, 0, nullptr };
475
476 array_t(wl_array *arr);
477 void get(wl_array *arr) const;
478
479 friend class proxy_t;
480 friend class detail::argument_t;
481 friend class server::resource_t;
482
483 public:
484 array_t();
485 array_t(const array_t &arr);
486 array_t(array_t &&arr) noexcept;
487
488 template <typename T> array_t(const std::vector<T> &v)
489 {
490 wl_array_init(&a);
491 wl_array_add(&a, v.size()*sizeof(T));
492 T *p = nullptr;
493 unsigned int c = 0;
494 wl_array_for_each_cpp(p, &a)
495 *p = v.at(c++);
496 }
497
498 ~array_t();
499 array_t &operator=(const array_t &arr);
500 array_t &operator=(array_t &&arr) noexcept;
501
502 template <typename T> array_t &operator=(const std::vector<T> &v)
503 {
504 wl_array_release(&a);
505 wl_array_init(&a);
506 wl_array_add(&a, v.size()*sizeof(T));
507 T *p = nullptr;
508 unsigned int c = 0;
509 wl_array_for_each_cpp(p, &a)
510 *p = v.at(c++);
511 return *this;
512 }
513
514 template <typename T> operator std::vector<T>() const
515 {
516 std::vector<T> v;
517 T *p = nullptr;
518 wl_array_for_each_cpp(p, &a)
519 v.push_back(*p);
520 return v;
521 }
522 };
523}
524
525#endif
Represents a protocol object on the client side.