aboutsummaryrefslogtreecommitdiffstats
path: root/sway/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/server.c')
-rw-r--r--sway/server.c338
1 files changed, 292 insertions, 46 deletions
diff --git a/sway/server.c b/sway/server.c
index f51fcfe2..180d3a6b 100644
--- a/sway/server.c
+++ b/sway/server.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <stdbool.h> 2#include <stdbool.h>
4#include <stdlib.h> 3#include <stdlib.h>
@@ -7,25 +6,45 @@
7#include <wlr/backend.h> 6#include <wlr/backend.h>
8#include <wlr/backend/headless.h> 7#include <wlr/backend/headless.h>
9#include <wlr/backend/multi.h> 8#include <wlr/backend/multi.h>
10#include <wlr/backend/noop.h> 9#include <wlr/config.h>
11#include <wlr/backend/session.h> 10#include <wlr/render/allocator.h>
12#include <wlr/render/wlr_renderer.h> 11#include <wlr/render/wlr_renderer.h>
13#include <wlr/types/wlr_compositor.h> 12#include <wlr/types/wlr_compositor.h>
13#include <wlr/types/wlr_content_type_v1.h>
14#include <wlr/types/wlr_cursor_shape_v1.h>
14#include <wlr/types/wlr_data_control_v1.h> 15#include <wlr/types/wlr_data_control_v1.h>
16#include <wlr/types/wlr_data_device.h>
17#include <wlr/types/wlr_drm.h>
15#include <wlr/types/wlr_export_dmabuf_v1.h> 18#include <wlr/types/wlr_export_dmabuf_v1.h>
19#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
20#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
21#include <wlr/types/wlr_fractional_scale_v1.h>
16#include <wlr/types/wlr_gamma_control_v1.h> 22#include <wlr/types/wlr_gamma_control_v1.h>
17#include <wlr/types/wlr_idle.h> 23#include <wlr/types/wlr_idle_notify_v1.h>
18#include <wlr/types/wlr_layer_shell_v1.h> 24#include <wlr/types/wlr_layer_shell_v1.h>
25#include <wlr/types/wlr_linux_dmabuf_v1.h>
26#include <wlr/types/wlr_output_management_v1.h>
27#include <wlr/types/wlr_output_power_management_v1.h>
19#include <wlr/types/wlr_pointer_constraints_v1.h> 28#include <wlr/types/wlr_pointer_constraints_v1.h>
29#include <wlr/types/wlr_presentation_time.h>
20#include <wlr/types/wlr_primary_selection_v1.h> 30#include <wlr/types/wlr_primary_selection_v1.h>
21#include <wlr/types/wlr_relative_pointer_v1.h> 31#include <wlr/types/wlr_relative_pointer_v1.h>
22#include <wlr/types/wlr_screencopy_v1.h> 32#include <wlr/types/wlr_screencopy_v1.h>
33#include <wlr/types/wlr_security_context_v1.h>
23#include <wlr/types/wlr_server_decoration.h> 34#include <wlr/types/wlr_server_decoration.h>
35#include <wlr/types/wlr_session_lock_v1.h>
36#include <wlr/types/wlr_single_pixel_buffer_v1.h>
37#include <wlr/types/wlr_subcompositor.h>
24#include <wlr/types/wlr_tablet_v2.h> 38#include <wlr/types/wlr_tablet_v2.h>
25#include <wlr/types/wlr_viewporter.h> 39#include <wlr/types/wlr_viewporter.h>
26#include <wlr/types/wlr_xcursor_manager.h> 40#include <wlr/types/wlr_xcursor_manager.h>
41#include <wlr/types/wlr_xdg_activation_v1.h>
27#include <wlr/types/wlr_xdg_decoration_v1.h> 42#include <wlr/types/wlr_xdg_decoration_v1.h>
43#include <wlr/types/wlr_xdg_foreign_registry.h>
44#include <wlr/types/wlr_xdg_foreign_v1.h>
45#include <wlr/types/wlr_xdg_foreign_v2.h>
28#include <wlr/types/wlr_xdg_output_v1.h> 46#include <wlr/types/wlr_xdg_output_v1.h>
47#include <xf86drm.h>
29#include "config.h" 48#include "config.h"
30#include "list.h" 49#include "list.h"
31#include "log.h" 50#include "log.h"
@@ -34,41 +53,221 @@
34#include "sway/input/input-manager.h" 53#include "sway/input/input-manager.h"
35#include "sway/output.h" 54#include "sway/output.h"
36#include "sway/server.h" 55#include "sway/server.h"
56#include "sway/input/cursor.h"
37#include "sway/tree/root.h" 57#include "sway/tree/root.h"
58
38#if HAVE_XWAYLAND 59#if HAVE_XWAYLAND
60#include <wlr/xwayland/shell.h>
39#include "sway/xwayland.h" 61#include "sway/xwayland.h"
40#endif 62#endif
41 63
42bool server_privileged_prepare(struct sway_server *server) { 64#if WLR_HAS_DRM_BACKEND
43 sway_log(SWAY_DEBUG, "Preparing Wayland server initialization"); 65#include <wlr/types/wlr_drm_lease_v1.h>
66#endif
67
68#define SWAY_XDG_SHELL_VERSION 5
69#define SWAY_LAYER_SHELL_VERSION 4
70#define SWAY_FOREIGN_TOPLEVEL_LIST_VERSION 1
71
72bool allow_unsupported_gpu = false;
73
74#if WLR_HAS_DRM_BACKEND
75static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
76 /* We only offer non-desktop outputs, but in the future we might want to do
77 * more logic here. */
78
79 struct wlr_drm_lease_request_v1 *req = data;
80 struct wlr_drm_lease_v1 *lease = wlr_drm_lease_request_v1_grant(req);
81 if (!lease) {
82 sway_log(SWAY_ERROR, "Failed to grant lease request");
83 wlr_drm_lease_request_v1_reject(req);
84 }
85}
86#endif
87
88static bool is_privileged(const struct wl_global *global) {
89#if WLR_HAS_DRM_BACKEND
90 if (server.drm_lease_manager != NULL) {
91 struct wlr_drm_lease_device_v1 *drm_lease_dev;
92 wl_list_for_each(drm_lease_dev, &server.drm_lease_manager->devices, link) {
93 if (drm_lease_dev->global == global) {
94 return true;
95 }
96 }
97 }
98#endif
99
100 return
101 global == server.output_manager_v1->global ||
102 global == server.output_power_manager_v1->global ||
103 global == server.input_method->global ||
104 global == server.foreign_toplevel_list->global ||
105 global == server.foreign_toplevel_manager->global ||
106 global == server.data_control_manager_v1->global ||
107 global == server.screencopy_manager_v1->global ||
108 global == server.export_dmabuf_manager_v1->global ||
109 global == server.security_context_manager_v1->global ||
110 global == server.gamma_control_manager_v1->global ||
111 global == server.layer_shell->global ||
112 global == server.session_lock.manager->global ||
113 global == server.input->keyboard_shortcuts_inhibit->global ||
114 global == server.input->virtual_keyboard->global ||
115 global == server.input->virtual_pointer->global ||
116 global == server.input->transient_seat_manager->global;
117}
118
119static bool filter_global(const struct wl_client *client,
120 const struct wl_global *global, void *data) {
121#if HAVE_XWAYLAND
122 struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland;
123 if (xwayland && global == xwayland->shell_v1->global) {
124 return xwayland->server != NULL && client == xwayland->server->client;
125 }
126#endif
127
128 // Restrict usage of privileged protocols to unsandboxed clients
129 // TODO: add a way for users to configure an allow-list
130 const struct wlr_security_context_v1_state *security_context =
131 wlr_security_context_manager_v1_lookup_client(
132 server.security_context_manager_v1, (struct wl_client *)client);
133 if (is_privileged(global)) {
134 return security_context == NULL;
135 }
136
137 return true;
138}
139
140static void detect_proprietary(struct wlr_backend *backend, void *data) {
141 int drm_fd = wlr_backend_get_drm_fd(backend);
142 if (drm_fd < 0) {
143 return;
144 }
145
146 drmVersion *version = drmGetVersion(drm_fd);
147 if (version == NULL) {
148 sway_log(SWAY_ERROR, "drmGetVersion() failed");
149 return;
150 }
151
152 bool is_unsupported = false;
153 if (strcmp(version->name, "nvidia-drm") == 0) {
154 is_unsupported = true;
155 sway_log(SWAY_ERROR, "!!! Proprietary Nvidia drivers are in use !!!");
156 if (!allow_unsupported_gpu) {
157 sway_log(SWAY_ERROR, "Use Nouveau instead");
158 }
159 }
160
161 if (strcmp(version->name, "evdi") == 0) {
162 is_unsupported = true;
163 sway_log(SWAY_ERROR, "!!! Proprietary DisplayLink drivers are in use !!!");
164 }
165
166 if (!allow_unsupported_gpu && is_unsupported) {
167 sway_log(SWAY_ERROR,
168 "Proprietary drivers are NOT supported. To launch sway anyway, "
169 "launch with --unsupported-gpu and DO NOT report issues.");
170 exit(EXIT_FAILURE);
171 }
172
173 drmFreeVersion(version);
174}
175
176static void handle_renderer_lost(struct wl_listener *listener, void *data) {
177 struct sway_server *server = wl_container_of(listener, server, renderer_lost);
178
179 sway_log(SWAY_INFO, "Re-creating renderer after GPU reset");
180
181 struct wlr_renderer *renderer = wlr_renderer_autocreate(server->backend);
182 if (renderer == NULL) {
183 sway_log(SWAY_ERROR, "Unable to create renderer");
184 return;
185 }
186
187 struct wlr_allocator *allocator =
188 wlr_allocator_autocreate(server->backend, renderer);
189 if (allocator == NULL) {
190 sway_log(SWAY_ERROR, "Unable to create allocator");
191 wlr_renderer_destroy(renderer);
192 return;
193 }
194
195 struct wlr_renderer *old_renderer = server->renderer;
196 struct wlr_allocator *old_allocator = server->allocator;
197 server->renderer = renderer;
198 server->allocator = allocator;
199
200 wl_list_remove(&server->renderer_lost.link);
201 wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
202
203 wlr_compositor_set_renderer(server->compositor, renderer);
204
205 for (int i = 0; i < root->outputs->length; ++i) {
206 struct sway_output *output = root->outputs->items[i];
207 wlr_output_init_render(output->wlr_output,
208 server->allocator, server->renderer);
209 }
210
211 wlr_allocator_destroy(old_allocator);
212 wlr_renderer_destroy(old_renderer);
213}
214
215bool server_init(struct sway_server *server) {
216 sway_log(SWAY_DEBUG, "Initializing Wayland server");
44 server->wl_display = wl_display_create(); 217 server->wl_display = wl_display_create();
45 server->wl_event_loop = wl_display_get_event_loop(server->wl_display); 218 server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
46 server->backend = wlr_backend_autocreate(server->wl_display);
47 219
220 wl_display_set_global_filter(server->wl_display, filter_global, NULL);
221
222 root = root_create(server->wl_display);
223
224 server->backend = wlr_backend_autocreate(server->wl_event_loop, &server->session);
48 if (!server->backend) { 225 if (!server->backend) {
49 sway_log(SWAY_ERROR, "Unable to create backend"); 226 sway_log(SWAY_ERROR, "Unable to create backend");
50 return false; 227 return false;
51 } 228 }
52 return true;
53}
54 229
55bool server_init(struct sway_server *server) { 230 wlr_multi_for_each_backend(server->backend, detect_proprietary, NULL);
56 sway_log(SWAY_DEBUG, "Initializing Wayland server");
57 231
58 struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend); 232 server->renderer = wlr_renderer_autocreate(server->backend);
59 assert(renderer); 233 if (!server->renderer) {
234 sway_log(SWAY_ERROR, "Failed to create renderer");
235 return false;
236 }
60 237
61 wlr_renderer_init_wl_display(renderer, server->wl_display); 238 server->renderer_lost.notify = handle_renderer_lost;
239 wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
62 240
63 server->compositor = wlr_compositor_create(server->wl_display, renderer); 241 wlr_renderer_init_wl_shm(server->renderer, server->wl_display);
64 server->compositor_new_surface.notify = handle_compositor_new_surface; 242
65 wl_signal_add(&server->compositor->events.new_surface, 243 if (wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF) != NULL) {
66 &server->compositor_new_surface); 244 server->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer(
245 server->wl_display, 4, server->renderer);
246 if (debug.legacy_wl_drm) {
247 wlr_drm_create(server->wl_display, server->renderer);
248 }
249 }
250
251 server->allocator = wlr_allocator_autocreate(server->backend,
252 server->renderer);
253 if (!server->allocator) {
254 sway_log(SWAY_ERROR, "Failed to create allocator");
255 return false;
256 }
257
258 server->compositor = wlr_compositor_create(server->wl_display, 6,
259 server->renderer);
260
261 wlr_subcompositor_create(server->wl_display);
67 262
68 server->data_device_manager = 263 server->data_device_manager =
69 wlr_data_device_manager_create(server->wl_display); 264 wlr_data_device_manager_create(server->wl_display);
70 265
71 wlr_gamma_control_manager_v1_create(server->wl_display); 266 server->gamma_control_manager_v1 =
267 wlr_gamma_control_manager_v1_create(server->wl_display);
268 server->gamma_control_set_gamma.notify = handle_gamma_control_set_gamma;
269 wl_signal_add(&server->gamma_control_manager_v1->events.set_gamma,
270 &server->gamma_control_set_gamma);
72 271
73 server->new_output.notify = handle_new_output; 272 server->new_output.notify = handle_new_output;
74 wl_signal_add(&server->backend->events.new_output, &server->new_output); 273 wl_signal_add(&server->backend->events.new_output, &server->new_output);
@@ -78,19 +277,20 @@ bool server_init(struct sway_server *server) {
78 277
79 wlr_xdg_output_manager_v1_create(server->wl_display, root->output_layout); 278 wlr_xdg_output_manager_v1_create(server->wl_display, root->output_layout);
80 279
81 server->idle = wlr_idle_create(server->wl_display); 280 server->idle_notifier_v1 = wlr_idle_notifier_v1_create(server->wl_display);
82 server->idle_inhibit_manager_v1 = 281 sway_idle_inhibit_manager_v1_init();
83 sway_idle_inhibit_manager_v1_create(server->wl_display, server->idle);
84 282
85 server->layer_shell = wlr_layer_shell_v1_create(server->wl_display); 283 server->layer_shell = wlr_layer_shell_v1_create(server->wl_display,
284 SWAY_LAYER_SHELL_VERSION);
86 wl_signal_add(&server->layer_shell->events.new_surface, 285 wl_signal_add(&server->layer_shell->events.new_surface,
87 &server->layer_shell_surface); 286 &server->layer_shell_surface);
88 server->layer_shell_surface.notify = handle_layer_shell_surface; 287 server->layer_shell_surface.notify = handle_layer_shell_surface;
89 288
90 server->xdg_shell = wlr_xdg_shell_create(server->wl_display); 289 server->xdg_shell = wlr_xdg_shell_create(server->wl_display,
91 wl_signal_add(&server->xdg_shell->events.new_surface, 290 SWAY_XDG_SHELL_VERSION);
92 &server->xdg_shell_surface); 291 wl_signal_add(&server->xdg_shell->events.new_toplevel,
93 server->xdg_shell_surface.notify = handle_xdg_shell_surface; 292 &server->xdg_shell_toplevel);
293 server->xdg_shell_toplevel.notify = handle_xdg_shell_toplevel;
94 294
95 server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); 295 server->tablet_v2 = wlr_tablet_v2_create(server->wl_display);
96 296
@@ -121,8 +321,7 @@ bool server_init(struct sway_server *server) {
121 wl_signal_add(&server->pointer_constraints->events.new_constraint, 321 wl_signal_add(&server->pointer_constraints->events.new_constraint,
122 &server->pointer_constraint); 322 &server->pointer_constraint);
123 323
124 server->presentation = 324 wlr_presentation_create(server->wl_display, server->backend);
125 wlr_presentation_create(server->wl_display, server->backend);
126 325
127 server->output_manager_v1 = 326 server->output_manager_v1 =
128 wlr_output_manager_v1_create(server->wl_display); 327 wlr_output_manager_v1_create(server->wl_display);
@@ -141,19 +340,62 @@ bool server_init(struct sway_server *server) {
141 &server->output_power_manager_set_mode); 340 &server->output_power_manager_set_mode);
142 server->input_method = wlr_input_method_manager_v2_create(server->wl_display); 341 server->input_method = wlr_input_method_manager_v2_create(server->wl_display);
143 server->text_input = wlr_text_input_manager_v3_create(server->wl_display); 342 server->text_input = wlr_text_input_manager_v3_create(server->wl_display);
343 server->foreign_toplevel_list =
344 wlr_ext_foreign_toplevel_list_v1_create(server->wl_display, SWAY_FOREIGN_TOPLEVEL_LIST_VERSION);
144 server->foreign_toplevel_manager = 345 server->foreign_toplevel_manager =
145 wlr_foreign_toplevel_manager_v1_create(server->wl_display); 346 wlr_foreign_toplevel_manager_v1_create(server->wl_display);
146 347
147 wlr_export_dmabuf_manager_v1_create(server->wl_display); 348 sway_session_lock_init();
148 wlr_screencopy_manager_v1_create(server->wl_display); 349
149 wlr_data_control_manager_v1_create(server->wl_display); 350#if WLR_HAS_DRM_BACKEND
150 wlr_primary_selection_v1_device_manager_create(server->wl_display); 351 server->drm_lease_manager=
352 wlr_drm_lease_v1_manager_create(server->wl_display, server->backend);
353 if (server->drm_lease_manager) {
354 server->drm_lease_request.notify = handle_drm_lease_request;
355 wl_signal_add(&server->drm_lease_manager->events.request,
356 &server->drm_lease_request);
357 } else {
358 sway_log(SWAY_DEBUG, "Failed to create wlr_drm_lease_device_v1");
359 sway_log(SWAY_INFO, "VR will not be available");
360 }
361#endif
362
363 server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display);
364 server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display);
365 server->data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display);
366 server->security_context_manager_v1 = wlr_security_context_manager_v1_create(server->wl_display);
151 wlr_viewporter_create(server->wl_display); 367 wlr_viewporter_create(server->wl_display);
368 wlr_single_pixel_buffer_manager_v1_create(server->wl_display);
369 server->content_type_manager_v1 =
370 wlr_content_type_manager_v1_create(server->wl_display, 1);
371 wlr_fractional_scale_manager_v1_create(server->wl_display, 1);
372
373 struct wlr_xdg_foreign_registry *foreign_registry =
374 wlr_xdg_foreign_registry_create(server->wl_display);
375 wlr_xdg_foreign_v1_create(server->wl_display, foreign_registry);
376 wlr_xdg_foreign_v2_create(server->wl_display, foreign_registry);
377
378 server->xdg_activation_v1 = wlr_xdg_activation_v1_create(server->wl_display);
379 server->xdg_activation_v1_request_activate.notify =
380 xdg_activation_v1_handle_request_activate;
381 wl_signal_add(&server->xdg_activation_v1->events.request_activate,
382 &server->xdg_activation_v1_request_activate);
383 server->xdg_activation_v1_new_token.notify =
384 xdg_activation_v1_handle_new_token;
385 wl_signal_add(&server->xdg_activation_v1->events.new_token,
386 &server->xdg_activation_v1_new_token);
387
388 struct wlr_cursor_shape_manager_v1 *cursor_shape_manager =
389 wlr_cursor_shape_manager_v1_create(server->wl_display, 1);
390 server->request_set_cursor_shape.notify = handle_request_set_cursor_shape;
391 wl_signal_add(&cursor_shape_manager->events.request_set_shape, &server->request_set_cursor_shape);
392
393 wl_list_init(&server->pending_launcher_ctxs);
152 394
153 // Avoid using "wayland-0" as display socket 395 // Avoid using "wayland-0" as display socket
154 char name_candidate[16]; 396 char name_candidate[16];
155 for (int i = 1; i <= 32; ++i) { 397 for (unsigned int i = 1; i <= 32; ++i) {
156 sprintf(name_candidate, "wayland-%d", i); 398 snprintf(name_candidate, sizeof(name_candidate), "wayland-%u", i);
157 if (wl_display_add_socket(server->wl_display, name_candidate) >= 0) { 399 if (wl_display_add_socket(server->wl_display, name_candidate) >= 0) {
158 server->socket = strdup(name_candidate); 400 server->socket = strdup(name_candidate);
159 break; 401 break;
@@ -166,27 +408,26 @@ bool server_init(struct sway_server *server) {
166 return false; 408 return false;
167 } 409 }
168 410
169 server->noop_backend = wlr_noop_backend_create(server->wl_display); 411 server->headless_backend = wlr_headless_backend_create(server->wl_event_loop);
170
171 struct wlr_output *wlr_output = wlr_noop_add_output(server->noop_backend);
172 root->noop_output = output_create(wlr_output);
173
174 server->headless_backend =
175 wlr_headless_backend_create_with_renderer(server->wl_display, renderer);
176 if (!server->headless_backend) { 412 if (!server->headless_backend) {
177 sway_log(SWAY_INFO, "Failed to create secondary headless backend, " 413 sway_log(SWAY_ERROR, "Failed to create secondary headless backend");
178 "starting without it"); 414 wlr_backend_destroy(server->backend);
415 return false;
179 } else { 416 } else {
180 wlr_multi_backend_add(server->backend, server->headless_backend); 417 wlr_multi_backend_add(server->backend, server->headless_backend);
181 } 418 }
182 419
420 struct wlr_output *wlr_output =
421 wlr_headless_add_output(server->headless_backend, 800, 600);
422 wlr_output_set_name(wlr_output, "FALLBACK");
423 root->fallback_output = output_create(wlr_output);
424
183 // This may have been set already via -Dtxn-timeout 425 // This may have been set already via -Dtxn-timeout
184 if (!server->txn_timeout_ms) { 426 if (!server->txn_timeout_ms) {
185 server->txn_timeout_ms = 200; 427 server->txn_timeout_ms = 200;
186 } 428 }
187 429
188 server->dirty_nodes = create_list(); 430 server->dirty_nodes = create_list();
189 server->transactions = create_list();
190 431
191 server->input = input_manager_create(server); 432 server->input = input_manager_create(server);
192 input_manager_get_default_seat(); // create seat0 433 input_manager_get_default_seat(); // create seat0
@@ -200,9 +441,9 @@ void server_fini(struct sway_server *server) {
200 wlr_xwayland_destroy(server->xwayland.wlr_xwayland); 441 wlr_xwayland_destroy(server->xwayland.wlr_xwayland);
201#endif 442#endif
202 wl_display_destroy_clients(server->wl_display); 443 wl_display_destroy_clients(server->wl_display);
444 wlr_backend_destroy(server->backend);
203 wl_display_destroy(server->wl_display); 445 wl_display_destroy(server->wl_display);
204 list_free(server->dirty_nodes); 446 list_free(server->dirty_nodes);
205 list_free(server->transactions);
206} 447}
207 448
208bool server_start(struct sway_server *server) { 449bool server_start(struct sway_server *server) {
@@ -231,6 +472,10 @@ bool server_start(struct sway_server *server) {
231 } 472 }
232#endif 473#endif
233 474
475 if (config->primary_selection) {
476 wlr_primary_selection_v1_device_manager_create(server->wl_display);
477 }
478
234 sway_log(SWAY_INFO, "Starting backend on wayland display '%s'", 479 sway_log(SWAY_INFO, "Starting backend on wayland display '%s'",
235 server->socket); 480 server->socket);
236 if (!wlr_backend_start(server->backend)) { 481 if (!wlr_backend_start(server->backend)) {
@@ -238,6 +483,7 @@ bool server_start(struct sway_server *server) {
238 wlr_backend_destroy(server->backend); 483 wlr_backend_destroy(server->backend);
239 return false; 484 return false;
240 } 485 }
486
241 return true; 487 return true;
242} 488}
243 489