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 
35 #include <wayland-server-core.h>
36 #include <wayland-util.hpp>
37 
40 namespace 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);
598  global_base_t(const global_base_t& g);
599  global_base_t(global_base_t&& g) noexcept;
600  ~global_base_t();
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.