Wayland++ 1.0.0
C++ Bindings for Wayland
wayland-server.hpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022, Nils Christopher Brause
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_SERVER_HPP
27#define WAYLAND_SERVER_HPP
28
29#include <atomic>
30#include <functional>
31#include <list>
32#include <memory>
33#include <string>
34#include <cstdint>
35
36#include <wayland-server-core.h>
37#include <wayland-util.hpp>
38
41namespace wayland
42{
43 namespace server
44 {
45 namespace detail
46 {
47 struct listener_t
48 {
49 wl_listener listener = { { nullptr, nullptr }, nullptr };
50 void *user = nullptr;
51 };
52 }
53
58 using log_handler = std::function<void(std::string)>;
59
68 void set_log_handler(const log_handler& handler);
69
70 class client_t;
71 class global_base_t;
72 template <class resource> class global_t;
73 class event_loop_t;
74 class event_source_t;
75
76 class display_t
77 {
78 private:
79 struct data_t
80 {
81 std::function<void()> destroy;
82 std::function<void(client_t&)> client_created;
83 detail::listener_t destroy_listener;
84 detail::listener_t client_created_listener;
85 std::function<bool(client_t, global_base_t)> filter_func;
86 wayland::detail::any user_data;
87 std::atomic<unsigned int> counter{1};
88 };
89
90 wl_display *display = nullptr;
91 data_t *data = nullptr;
92
93 static void destroy_func(wl_listener *listener, void *data);
94 static void client_created_func(wl_listener *listener, void *cl);
95 static data_t *wl_display_get_user_data(wl_display *display);
96 static bool c_filter_func(const wl_client *client, const wl_global *global, void *data);
97
98 protected:
99 display_t(wl_display *c);
100 void init();
101 void fini();
102
103 friend class client_t;
104
105 public:
110 display_t();
111
121 ~display_t();
122 display_t(const display_t& d);
123 display_t(display_t&& d) noexcept;
124 display_t &operator=(const display_t& d);
125 display_t &operator=(display_t&& d) noexcept;
126 bool operator==(const display_t& d) const;
127 wl_display *c_ptr() const;
128 wayland::detail::any &user_data();
129
135 event_loop_t get_event_loop() const;
136
158 int add_socket(const std::string& name) const;
159
165 std::string add_socket_auto() const;
166
176 int add_socket_fd(int sock_fd) const;
177
183 void terminate() const;
184
190 void run() const;
191
198 void flush_clients() const;
199
205 uint32_t get_serial() const;
206
212 uint32_t next_serial() const;
213 std::function<void()> &on_destroy();
214
219 std::function<void(client_t&)> &on_client_created();
220
227 client_t client_create(int fd);
228
236 std::list<client_t> get_client_list() const;
237
252 void set_global_filter(const std::function<bool(client_t, global_base_t)>& filter);
253 };
254
255 class resource_t;
256
257 class client_t
258 {
259 private:
260 struct data_t
261 {
262 wl_client *client = nullptr;
263 std::function<void()> destroy;
264 detail::listener_t destroy_listener;
265 wayland::detail::any user_data;
266 std::atomic<unsigned int> counter{1};
267 bool destroyed = false;
268 };
269
270 wl_client *client = nullptr;
271 data_t *data = nullptr;
272
273 static void destroy_func(wl_listener *listener, void *data);
274 static wl_iterator_result resource_iterator(wl_resource *resource, void *data);
275 static data_t *wl_client_get_user_data(wl_client *client);
276
277 protected:
278 client_t(wl_client *c);
279 void init();
280 void fini();
281
282 friend class display_t;
283 friend class resource_t;
284 template <class resource> friend class global_t;
285
286 public:
310 client_t(display_t &display, int fd);
311 client_t() = delete;
312 ~client_t();
313 client_t(const client_t &c);
314 client_t(client_t &&c) noexcept;
315 client_t &operator=(const client_t& c);
316 client_t &operator=(client_t&& c) noexcept;
317 bool operator==(const client_t &c) const;
318 wl_client *c_ptr() const;
319 wayland::detail::any &user_data();
320
328 void flush() const;
329
345 void get_credentials(pid_t &pid, uid_t &uid, gid_t &gid) const;
346
373 int get_fd() const;
374 std::function<void()> &on_destroy();
375
384 resource_t get_object(uint32_t id);
385
392 void post_no_memory() const;
393
401 void post_implementation_error(std::string const& msg) const;
402
411 template <typename...types>
412 void post_implementation_error(std::string const& msg, types&&... args)
413 {
414 wl_client_post_implementation_error(c_ptr(), msg.c_str(), std::forward<types...>(args...));
415 }
416
421 display_t get_display() const;
422
427 std::list<resource_t> get_resource_list() const;
428 };
429
430 class resource_t
431 {
432 protected:
433 // base class for event listener storage.
434 struct events_base_t
435 {
436 events_base_t() = default;
437 events_base_t(const events_base_t& e) = default;
438 events_base_t(events_base_t&& e) = default;
439 events_base_t& operator=(const events_base_t& e) = default;
440 events_base_t& operator=(events_base_t&& e) = default;
441 virtual ~events_base_t() = default;
442 };
443
444 private:
445 struct data_t
446 {
447 std::shared_ptr<events_base_t> events;
448 std::function<void()> destroy;
449 detail::listener_t destroy_listener;
450 wayland::detail::any user_data;
451 std::atomic<unsigned int> counter{1};
452 bool destroyed = false;
453 };
454
455 wl_resource *resource = nullptr;
456 data_t *data = nullptr;
457
458 static void destroy_func(wl_listener *listener, void *data);
459 static int c_dispatcher(const void *implementation, void *target,
460 uint32_t opcode, const wl_message *message,
461 wl_argument *args);
462 static int dummy_dispatcher(int opcode, const std::vector<wayland::detail::any>& args, const std::shared_ptr<resource_t::events_base_t>& events);
463
464 protected:
465 // Interface desctiption filled in by the each interface class
466 static constexpr const wl_interface *interface = nullptr;
467
468 /*
469 Sets the dispatcher and its user data. User data must be an
470 instance of a class derived from events_base_t, allocated with
471 new. Will automatically be deleted upon destruction.
472 */
473 void set_events(const std::shared_ptr<events_base_t>& events,
474 int(*dispatcher)(int, const std::vector<wayland::detail::any>&, const std::shared_ptr<resource_t::events_base_t>&));
475
476 // Retrieve the perviously set user data
477 std::shared_ptr<events_base_t> get_events() const;
478
479 void post_event_array(uint32_t opcode, const std::vector<wayland::detail::argument_t>& v) const;
480 void queue_event_array(uint32_t opcode, const std::vector<wayland::detail::argument_t>& v) const;
481
482 template <typename...T>
483 void post_event(uint32_t opcode, T...args) const
484 {
485 std::vector<wayland::detail::argument_t> v = { wayland::detail::argument_t(args)... };
486 if(c_ptr())
487 post_event_array(opcode, v);
488 }
489
490 template <typename...T>
491 void queue_event(uint32_t opcode, T...args) const
492 {
493 std::vector<wayland::detail::argument_t> v = { wayland::detail::argument_t(args)... };
494 if(c_ptr())
495 queue_event_array(opcode, v);
496 }
497
498 template <typename...T>
499 void send_event(bool post, uint32_t opcode, T...args) const
500 {
501 if(post)
502 post_event(opcode, args...);
503 else
504 queue_event(opcode, args...);
505 }
506
507 void post_error(uint32_t code, const std::string& msg) const;
508
509 resource_t(wl_resource *c);
510 void init();
511 void fini();
512
513 friend class client_t;
514
515 public:
516 resource_t() = default;
517
528 resource_t(const client_t& client, const wl_interface *interface, int version, uint32_t id);
529 ~resource_t();
530 resource_t(const resource_t &r);
531 resource_t(resource_t &&r) noexcept;
532 resource_t &operator=(const resource_t& r);
533 resource_t &operator=(resource_t&& r) noexcept;
534 bool operator==(const resource_t& r) const;
535 operator bool() const;
536 wl_resource *c_ptr() const;
537 wayland::detail::any &user_data();
538
543 bool proxy_has_object() const;
544
551 void post_no_memory() const;
552
557 uint32_t get_id() const;
558
563 client_t get_client() const;
564
569 unsigned int get_version() const;
570
575 std::string get_class();
576 std::function<void()> &on_destroy();
577 };
578
581 {
582 private:
583 void fini();
584 bool has_interface(const wl_interface *interface) const;
585
586 wl_global *global = nullptr;
587
588 protected:
589 struct data_t
590 {
591 wayland::detail::any user_data;
592 std::atomic<unsigned int> counter{1};
593 } *data = nullptr;
594
595 global_base_t(display_t &display, const wl_interface* interface, int version, data_t *dat, wl_global_bind_func_t func);
596
597 public:
598 global_base_t(wl_global *g);
600 global_base_t(global_base_t&& g) noexcept;
602 global_base_t &operator=(const global_base_t& g);
603 global_base_t &operator=(global_base_t&& g) noexcept;
604 bool operator==(const global_base_t& g) const;
605 wl_global *c_ptr() const;
606 wayland::detail::any &user_data();
607
613 template <typename resource>
614 bool has_interface() // instead if wl_global_get_interface
615 {
616 return has_interface(resource::interface);
617 }
618 };
619
624 template <class resource>
625 class global_t : public global_base_t
626 {
627 private:
628 struct data_t : public global_base_t::data_t
629 {
630 std::function<void(client_t, resource)> bind;
631 };
632
633 static void bind_func(wl_client *cl, void *d, uint32_t ver, uint32_t id)
634 {
635 auto *data = reinterpret_cast<data_t*>(d);
636 client_t client(cl);
637 resource res(client, ver, id);
638 if(data->bind)
639 data->bind(client, res);
640 }
641
642 public:
643 global_t() = delete;
644
650 global_t(display_t &display, unsigned int version = resource::max_version)
651 : global_base_t(display, resource::interface, version, new data_t, bind_func)
652 {
653 }
654
661 std::function<void(client_t, resource)> &on_bind()
662 {
663 return static_cast<data_t*>(data)->bind;
664 }
665 };
666
667 struct fd_event_mask_t : public wayland::detail::bitfield<2, -1>
668 {
669 fd_event_mask_t(const wayland::detail::bitfield<2, -1> &b)
670 : wayland::detail::bitfield<2, -1>(b) {}
671 fd_event_mask_t(const uint32_t value)
672 : wayland::detail::bitfield<2, -1>(value) {}
673 static const wayland::detail::bitfield<2, -1> readable;
674 static const wayland::detail::bitfield<2, -1> writable;
675 static const wayland::detail::bitfield<2, -1> hangup;
676 static const wayland::detail::bitfield<2, -1> error;
677 };
678
679 class event_loop_t
680 {
681 private:
682 struct data_t
683 {
684 std::function<void()> destroy;
685 detail::listener_t destroy_listener;
686 std::list<std::function<int(int, uint32_t)>> fd_funcs;
687 std::list<std::function<int()>> timer_funcs;
688 std::list<std::function<int(int)>> signal_funcs;
689 std::list<std::function<void()>> idle_funcs;
690 wayland::detail::any user_data;
691 bool do_delete = true;
692 std::atomic<unsigned int> counter{1};
693 };
694
695 wl_event_loop *event_loop = nullptr;
696 data_t *data = nullptr;
697
698 static data_t *wl_event_loop_get_user_data(wl_event_loop *client);
699 static void destroy_func(wl_listener *listener, void *data);
700 static int event_loop_fd_func(int fd, uint32_t mask, void *data);
701 static int event_loop_timer_func(void *data);
702 static int event_loop_signal_func(int signal_number, void *data);
703 static void event_loop_idle_func(void *data);
704
705 protected:
706 event_loop_t(wl_event_loop *p);
707 void init();
708 void fini();
709
710 friend class display_t;
711
712 public:
713 event_loop_t();
714 ~event_loop_t();
715 event_loop_t(const event_loop_t& e);
716 event_loop_t(event_loop_t&& e) noexcept;
717 event_loop_t &operator=(const event_loop_t& e);
718 event_loop_t &operator=(event_loop_t&& e) noexcept;
719 bool operator==(const event_loop_t& e) const;
720 wl_event_loop *c_ptr() const;
721 wayland::detail::any &user_data();
722
741 event_source_t add_fd(int fd, const fd_event_mask_t& mask, const std::function<int(int, uint32_t)> &func);
742
751 event_source_t add_timer(const std::function<int()> &func);
752
767 event_source_t add_signal(int signal_number, const std::function<int(int)> &func);
768
784 event_source_t add_idle(const std::function<void()> &func);
785 const std::function<void()> &on_destroy();
786
804 int dispatch(int timeout) const;
805
808 void dispatch_idle() const;
809
823 int get_fd() const;
824 };
825
826 class event_source_t : public wayland::detail::refcounted_wrapper<wl_event_source>
827 {
828 private:
829 wl_event_source *event_source = nullptr;
830
831 protected:
832 event_source_t(wl_event_source *p);
833 friend class event_loop_t;
834
835 public:
836 event_source_t() = delete;
837 wl_event_source *c_ptr() const;
838
852 int timer_update(int ms_delay) const;
853
869 int fd_update(const fd_event_mask_t& mask) const;
870
883 void check() const;
884 };
885 }
886}
887
888#endif
Refcounted wrapper for C objects.
global_t(display_t &display, unsigned int version=resource::max_version)
std::function< void(client_t, resource)> & on_bind()
void set_log_handler(log_handler handler)
Set C library log handler.
std::function< void(std::string)> log_handler
Type for functions that handle log messages.