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