Wayland++ 0.2.8
C++ Bindings for Wayland
wayland-util.hpp
1/*
2 * Copyright (c) 2014-2019, 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#include <stdexcept>
37
38#include <wayland-client-core.h>
39
40#define wl_array_for_each_cpp(pos, array) \
41 for ((pos) = static_cast<decltype(pos)>((array)->data); \
42 reinterpret_cast<const char*>(pos) < (reinterpret_cast<const char*>((array)->data) + (array)->size); \
43 (pos)++)
44
45namespace wayland
46{
47 class proxy_t;
48
49 class array_t;
50
51 namespace detail
52 {
61 int check_return_value(int return_value, std::string const &function_name);
62
68 template<typename native_t>
70 {
71 private:
72 native_t *object = nullptr;
73
74 protected:
75 basic_wrapper(native_t *object)
76 : object{object}
77 {
78 }
79
80 public:
81 basic_wrapper() = default;
82 ~basic_wrapper() noexcept = default;
83
84 basic_wrapper(basic_wrapper const &other)
85 {
86 *this = other;
87 }
88
89 basic_wrapper(basic_wrapper &&other) noexcept
90 {
91 *this = std::move(other);
92 }
93
94 native_t *c_ptr() const
95 {
96 if(!object)
97 throw std::runtime_error("Tried to access empty object");
98 return object;
99 }
100
101 bool has_object() const
102 {
103 return object;
104 }
105
106 operator bool() const
107 {
108 return has_object();
109 }
110
111 operator native_t*() const
112 {
113 return c_ptr();
114 }
115
116 basic_wrapper& operator=(const basic_wrapper &right)
117 {
118 // Check for self-assignment
119 if(this == &right)
120 return *this;
121 object = right.object;
122 return *this;
123 }
124
125 basic_wrapper& operator=(basic_wrapper &&right) noexcept
126 {
127 std::swap(object, right.object);
128 return *this;
129 }
130
131 bool operator==(const basic_wrapper &right) const
132 {
133 return object == right.object;
134 }
135
136 bool operator!=(const basic_wrapper &right) const
137 {
138 return !(*this == right); // Reuse equals operator
139 }
140 };
141
147 template<typename native_t>
149 {
150 private:
151 std::shared_ptr<native_t> object;
152
153 protected:
154 refcounted_wrapper(std::shared_ptr<native_t> object)
155 : object{std::move(object)}
156 {
157 }
158
159 std::shared_ptr<native_t> ref_ptr() const
160 {
161 return object;
162 }
163
164 public:
165 refcounted_wrapper() = default;
166 ~refcounted_wrapper() noexcept = default;
167
169 {
170 *this = other;
171 }
172
173 refcounted_wrapper(refcounted_wrapper &&other) noexcept
174 {
175 *this = std::move(other);
176 }
177
178 native_t *c_ptr() const
179 {
180 if(!object)
181 throw std::runtime_error("Tried to access empty object");
182 return object.get();
183 }
184
185 bool has_object() const
186 {
187 return !!object;
188 }
189
190 operator bool() const
191 {
192 return has_object();
193 }
194
195 operator native_t*() const
196 {
197 return c_ptr();
198 }
199
200 refcounted_wrapper& operator=(const refcounted_wrapper &right)
201 {
202 // Check for self-assignment
203 if(this == &right)
204 return *this;
205 object = right.object;
206 return *this;
207 }
208
209 refcounted_wrapper& operator=(refcounted_wrapper &&right) noexcept
210 {
211 std::swap(object, right.object);
212 return *this;
213 }
214
215 bool operator==(const refcounted_wrapper &right) const
216 {
217 return object == right.object;
218 }
219
220 bool operator!=(const refcounted_wrapper &right) const
221 {
222 return !(*this == right); // Reuse equals operator
223 }
224 };
225
226 class any
227 {
228 private:
229 class base
230 {
231 public:
232 base() = default;
233 base(const base&) = default;
234 base(base&&) noexcept = default;
235 base& operator=(const base&) = default;
236 base& operator=(base&&) noexcept = default;
237 virtual ~base() noexcept = default;
238 virtual const std::type_info &type_info() const = 0;
239 virtual base *clone() const = 0;
240 };
241
242 template <typename T>
243 class derived : public base
244 {
245 private:
246 T val;
247 friend class any;
248
249 public:
250 derived(T t)
251 : val(std::move(t)) { }
252
253 const std::type_info &type_info() const override
254 {
255 return typeid(T);
256 }
257
258 base *clone() const override
259 {
260 return new derived<T>(val);
261 }
262 };
263
264 base *val = nullptr;
265
266 public:
267 any() = default;
268
269 any(const any &a)
270 : val(a.val ? a.val->clone() : nullptr) { }
271
272 any(any &&a) noexcept
273 {
274 operator=(std::move(a));
275 }
276
277 template <typename T>
278 any(const T &t)
279 : val(new derived<T>(t)) { }
280
281 ~any() noexcept
282 {
283 delete val;
284 }
285
286 any &operator=(const any &a)
287 {
288 if (&a != this)
289 {
290 delete val;
291 val = a.val ? a.val->clone() : nullptr;
292 }
293 return *this;
294 }
295
296 any &operator=(any &&a) noexcept
297 {
298 std::swap(val, a.val);
299 return *this;
300 }
301
302 template <typename T>
303 any &operator=(const T &t)
304 {
305 if(val && typeid(T) == val->type_info())
306 static_cast<derived<T>*>(val)->val = t;
307 else
308 {
309 delete val;
310 val = new derived<T>(t);
311 }
312 return *this;
313 }
314
315 template <typename T>
316 T &get()
317 {
318 if(val && typeid(T) == val->type_info())
319 return static_cast<derived<T>*>(val)->val;
320 throw std::bad_cast();
321 }
322
323 template <typename T>
324 const T &get() const
325 {
326 if(val && typeid(T) == val->type_info())
327 return static_cast<derived<T>*>(val)->val;
328 throw std::bad_cast();
329 }
330 };
331
332 template<unsigned int size, int id = 0>
333 class bitfield
334 {
335 uint32_t v = 0;
336 static const uint32_t mask = (1 << size) - 1;
337
338 public:
339 explicit bitfield(const uint32_t value = 0)
340 : v(value)
341 {
342 }
343
344 explicit operator uint32_t() const
345 {
346 return v;
347 }
348
349 operator bool() const
350 {
351 return v;
352 }
353
354 bitfield(const bitfield<size, id> &b)
355 {
356 operator=(b);
357 }
358
359 bitfield(bitfield<size, id>&&) noexcept = default;
360
361 ~bitfield() noexcept = default;
362
363 bool operator==(const bitfield<size, id> &b)
364 {
365 return v == b.v;
366 }
367
368 bool operator!=(const bitfield<size, id> &b)
369 {
370 return !operator==(b);
371 }
372
373 bitfield<size, id> &operator=(const bitfield<size, id> &b)
374 {
375 // Check for self-assignment
376 if(this != &b)
377 v = static_cast<uint32_t>(b);
378 return *this;
379 }
380
381 bitfield<size, id> &operator=(bitfield<size, id> &&) noexcept = default;
382
383 bitfield<size, id> operator|(const bitfield<size, id> &b) const
384 {
385 return bitfield<size, id>(v | static_cast<uint32_t>(b));
386 }
387
388 bitfield<size, id> operator&(const bitfield<size, id> &b) const
389 {
390 return bitfield<size, id>(v & static_cast<uint32_t>(b));
391 }
392
393 bitfield<size, id> operator^(const bitfield<size, id> &b) const
394 {
395 return bitfield<size, id>((v ^ static_cast<uint32_t>(b)) & mask);
396 }
397
398 bitfield<size, id> operator~() const
399 {
400 return bitfield<size, id>(~v & mask);
401 }
402
403 bitfield<size, id> &operator|=(const bitfield<size, id> &b)
404 {
405 operator=(*this | b);
406 return *this;
407 }
408
409 bitfield<size, id> &operator&=(const bitfield<size, id> &b)
410 {
411 operator=(*this & b);
412 return *this;
413 }
414
415 bitfield<size, id> &operator^=(const bitfield<size, id> &b)
416 {
417 operator=(*this ^ b);
418 return *this;
419 }
420 };
421
422 class argument_t
423 {
424 private:
425 wl_argument argument = { .i = 0 };
426 bool is_array{false};
427
428 // Uninitialized argument - only for internal use
429 argument_t() = default;
430 public:
431
432 argument_t(const argument_t &arg);
433 argument_t(argument_t &&) noexcept = default;
434 argument_t &operator=(const argument_t &arg);
435 argument_t &operator=(argument_t&&) noexcept = default;
436 ~argument_t() noexcept;
437
438 // handles integers
439 argument_t(uint32_t i);
440 argument_t(int32_t i);
441
442 // handles wl_fixed_t
443 argument_t(double f);
444
445 // handles strings
446 argument_t(const std::string &s);
447
448 // handles objects
449 argument_t(wl_object *o);
450
451 // handles arrays
452 argument_t(const array_t& a);
453
454 // handles null objects, for example for new-id arguments
455 argument_t(std::nullptr_t);
456
457 // handles file descriptors (have same type as signed integers, so extra function)
458 static argument_t fd(int fileno);
459
463 wl_argument get_c_argument() const;
464 };
465 }
466
467 class array_t
468 {
469 private:
470 wl_array a = { 0, 0, nullptr };
471
472 array_t(wl_array *arr);
473 void get(wl_array *arr) const;
474
475 friend class proxy_t;
476 friend class detail::argument_t;
477
478 public:
479 array_t();
480 array_t(const array_t &arr);
481 array_t(array_t &&arr) noexcept;
482
483 template <typename T> array_t(const std::vector<T> &v)
484 {
485 wl_array_init(&a);
486 wl_array_add(&a, v.size()*sizeof(T));
487 T *p = nullptr;
488 unsigned int c = 0;
489 wl_array_for_each_cpp(p, &a)
490 *p = v.at(c++);
491 }
492
493 ~array_t();
494 array_t &operator=(const array_t &arr);
495 array_t &operator=(array_t &&arr) noexcept;
496
497 template <typename T> array_t &operator=(const std::vector<T> &v)
498 {
499 wl_array_release(&a);
500 wl_array_init(&a);
501 wl_array_add(&a, v.size()*sizeof(T));
502 T *p = nullptr;
503 unsigned int c = 0;
504 wl_array_for_each_cpp(p, &a)
505 *p = v.at(c++);
506 return *this;
507 }
508
509 template <typename T> operator std::vector<T>() const
510 {
511 std::vector<T> v;
512 T *p = nullptr;
513 wl_array_for_each_cpp(p, &a)
514 v.push_back(*p);
515 return v;
516 }
517 };
518}
519
520#endif
Non-refcounted wrapper for C objects.
Refcounted wrapper for C objects.