5 #include <wayland-server.h>
6 #include <wayland-client.h>
9 #include "libds/output.h"
10 #include "xdg-shell-client-protocol.h"
14 static const struct ds_backend_interface wl_backend_interface;
15 static void wl_backend_handle_display_destroy(struct wl_listener *listener,
17 static bool wl_backend_server_init(struct ds_wl_backend *wl_backend,
18 struct ds_wl_backend_server *server, const char *name);
19 static void wl_backend_server_finish(struct ds_wl_backend_server *server);
20 static int wl_backend_handle_dispatch_events(int fd, uint32_t mask,
23 WL_EXPORT struct ds_backend *
24 ds_wl_backend_create(struct wl_display *display, const char *server_name)
26 struct ds_wl_backend *wl_backend;
27 struct wl_event_loop *loop;
30 wl_backend = calloc(1, sizeof *wl_backend);
32 ds_log_errno(DS_ERR, "Could not allocate memory");
36 ds_backend_init(&wl_backend->base, &wl_backend_interface);
38 wl_backend->display = display;
39 wl_list_init(&wl_backend->buffers);
40 wl_list_init(&wl_backend->outputs);
41 wl_list_init(&wl_backend->seats);
43 if (!wl_backend_server_init(wl_backend, &wl_backend->server, server_name)) {
44 ds_err("Failed to initialize Wayland Server");
48 loop = wl_display_get_event_loop(wl_backend->display);
49 fd = wl_display_get_fd(wl_backend->server.display);
51 wl_backend->server_event_source =
52 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
53 wl_backend_handle_dispatch_events, wl_backend);
54 if (!wl_backend->server_event_source) {
55 ds_err("Failed to create event source");
58 wl_event_source_check(wl_backend->server_event_source);
60 wl_backend->display_destroy.notify = wl_backend_handle_display_destroy;
61 wl_display_add_destroy_listener(display, &wl_backend->display_destroy);
63 ds_inf("Wayland backend(%p) created: server name \"%s\"",
64 wl_backend, server_name);
66 return &wl_backend->base;
69 wl_backend_server_finish(&wl_backend->server);
71 ds_backend_finish(&wl_backend->base);
77 struct ds_wl_backend *
78 wl_backend_from_backend(struct ds_backend *backend)
80 assert(backend->iface == &wl_backend_interface);
81 return (struct ds_wl_backend *)backend;
85 wl_backend_iface_start(struct ds_backend *ds_backend)
87 struct ds_wl_backend *backend;
89 backend = wl_backend_from_backend(ds_backend);
91 ds_inf("Starting wayland backend");
93 for (size_t i = 0; i < backend->requested_outputs; i++)
94 create_wl_output(backend);
100 wl_backend_destroy(struct ds_wl_backend *backend)
102 struct ds_wl_output *output, *tmp_output;
103 struct ds_wl_buffer *buffer, *tmp_buffer;
104 struct ds_wl_seat *seat, *tmp_seat;
106 ds_dbg("Destroy wayland backend(%p)", backend);
108 wl_list_for_each_safe(output, tmp_output, &backend->outputs, link)
109 ds_output_destroy(&output->base);
111 wl_list_for_each_safe(buffer, tmp_buffer, &backend->buffers, link)
112 destroy_wl_buffer(buffer);
114 wl_list_for_each_safe(seat, tmp_seat, &backend->seats, link)
115 destroy_wl_seat(seat);
117 ds_backend_finish(&backend->base);
119 wl_list_remove(&backend->display_destroy.link);
121 wl_event_source_remove(backend->server_event_source);
123 wl_backend_server_finish(&backend->server);
129 wl_backend_iface_destroy(struct ds_backend *backend)
131 struct ds_wl_backend *wl_backend;
136 wl_backend = wl_backend_from_backend(backend);
138 wl_backend_destroy(wl_backend);
141 static const struct ds_backend_interface wl_backend_interface =
143 .start = wl_backend_iface_start,
144 .destroy = wl_backend_iface_destroy,
149 wl_backend_handle_display_destroy(struct wl_listener *listener, void *data)
151 struct ds_wl_backend *wl_backend;
153 wl_backend = wl_container_of(listener, wl_backend, display_destroy);
154 wl_backend_destroy(wl_backend);
158 shm_handle_format(void *data, struct wl_shm *shm, uint32_t shm_format)
162 static const struct wl_shm_listener shm_listener =
164 .format = shm_handle_format,
168 xdg_wm_base_handle_ping(void *data, struct xdg_wm_base *base, uint32_t serial)
170 xdg_wm_base_pong(base, serial);
173 static const struct xdg_wm_base_listener xdg_wm_base_listener =
175 .ping = xdg_wm_base_handle_ping,
179 registry_handle_global(void *data, struct wl_registry *registry,
180 uint32_t name, const char *iface, uint32_t version)
182 struct ds_wl_backend_server *server = data;
183 struct ds_wl_seat *seat;
185 ds_log(DS_DBG, "Wayland global: %s v%d", iface, version);
187 if (strcmp(iface, wl_compositor_interface.name) == 0) {
188 server->compositor = wl_registry_bind(registry, name,
189 &wl_compositor_interface, 4);
191 else if (strcmp(iface, xdg_wm_base_interface.name) == 0) {
192 server->xdg_wm_base = wl_registry_bind(registry, name,
193 &xdg_wm_base_interface, 1);
194 xdg_wm_base_add_listener(server->xdg_wm_base,
195 &xdg_wm_base_listener, NULL);
197 else if (strcmp(iface, wl_shm_interface.name) == 0) {
198 server->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
199 wl_shm_add_listener(server->shm, &shm_listener, server);
201 else if (strcmp(iface, wl_seat_interface.name) == 0) {
202 seat = create_wl_seat(server->backend, name, version);
204 ds_err("Could not create ds_wl_seat");
208 wl_list_insert(&server->backend->seats, &seat->link);
213 registry_handle_global_remove(void *data, struct wl_registry *registry,
219 static const struct wl_registry_listener registry_listener =
221 .global = registry_handle_global,
222 .global_remove = registry_handle_global_remove,
226 wl_backend_server_init(struct ds_wl_backend *wl_backend, struct ds_wl_backend_server *server, const char *name)
228 server->backend = wl_backend;
230 server->display = wl_display_connect(name);
231 if (!server->display) {
232 ds_log_errno(DS_ERR, "Could not connect to display: name \"%s\"", name);
236 server->registry = wl_display_get_registry(server->display);
237 if (!server->registry) {
238 ds_log_errno(DS_ERR, "Could not get wl_registry");
242 wl_registry_add_listener(server->registry, ®istry_listener, server);
244 wl_display_roundtrip(server->display);
246 if (!server->compositor) {
247 ds_err("Wayland Server does not support wl_compositor");
251 if (!server->xdg_wm_base) {
252 ds_err("Wayland Server does not support xdg_wm_base");
259 if (server->compositor)
260 wl_compositor_destroy(server->compositor);
262 if (server->xdg_wm_base)
263 xdg_wm_base_destroy(server->xdg_wm_base);
265 wl_registry_destroy(server->registry);
267 wl_display_disconnect(server->display);
273 wl_backend_server_finish(struct ds_wl_backend_server *server)
275 xdg_wm_base_destroy(server->xdg_wm_base);
276 wl_compositor_destroy(server->compositor);
277 wl_registry_destroy(server->registry);
278 wl_display_disconnect(server->display);
282 wl_backend_handle_dispatch_events(int fd, uint32_t mask, void *data)
284 struct ds_wl_backend *wl_backend = data;
285 struct ds_wl_backend_server *server = &wl_backend->server;
288 if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
289 if (mask & WL_EVENT_ERROR) {
290 ds_err("Failed to read from Wayland Server");
292 wl_display_terminate(wl_backend->display);
297 if (mask & WL_EVENT_READABLE)
298 count = wl_display_dispatch(server->display);
300 if (mask & WL_EVENT_WRITABLE)
301 wl_display_flush(server->display);
304 count = wl_display_dispatch_pending(server->display);
305 wl_display_flush(server->display);
309 ds_err("Failed to dispatch Wayland Server");
310 wl_display_terminate(wl_backend->display);