diff options
Diffstat (limited to 'sway/server.c')
-rw-r--r-- | sway/server.c | 282 |
1 files changed, 237 insertions, 45 deletions
diff --git a/sway/server.c b/sway/server.c index f51fcfe2..cc20e89d 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -7,25 +7,37 @@ | |||
7 | #include <wlr/backend.h> | 7 | #include <wlr/backend.h> |
8 | #include <wlr/backend/headless.h> | 8 | #include <wlr/backend/headless.h> |
9 | #include <wlr/backend/multi.h> | 9 | #include <wlr/backend/multi.h> |
10 | #include <wlr/backend/noop.h> | 10 | #include <wlr/config.h> |
11 | #include <wlr/backend/session.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_drm.h> | ||
15 | #include <wlr/types/wlr_export_dmabuf_v1.h> | 17 | #include <wlr/types/wlr_export_dmabuf_v1.h> |
18 | #include <wlr/types/wlr_fractional_scale_v1.h> | ||
16 | #include <wlr/types/wlr_gamma_control_v1.h> | 19 | #include <wlr/types/wlr_gamma_control_v1.h> |
17 | #include <wlr/types/wlr_idle.h> | 20 | #include <wlr/types/wlr_idle_notify_v1.h> |
18 | #include <wlr/types/wlr_layer_shell_v1.h> | 21 | #include <wlr/types/wlr_layer_shell_v1.h> |
22 | #include <wlr/types/wlr_linux_dmabuf_v1.h> | ||
19 | #include <wlr/types/wlr_pointer_constraints_v1.h> | 23 | #include <wlr/types/wlr_pointer_constraints_v1.h> |
20 | #include <wlr/types/wlr_primary_selection_v1.h> | 24 | #include <wlr/types/wlr_primary_selection_v1.h> |
21 | #include <wlr/types/wlr_relative_pointer_v1.h> | 25 | #include <wlr/types/wlr_relative_pointer_v1.h> |
22 | #include <wlr/types/wlr_screencopy_v1.h> | 26 | #include <wlr/types/wlr_screencopy_v1.h> |
27 | #include <wlr/types/wlr_security_context_v1.h> | ||
23 | #include <wlr/types/wlr_server_decoration.h> | 28 | #include <wlr/types/wlr_server_decoration.h> |
29 | #include <wlr/types/wlr_single_pixel_buffer_v1.h> | ||
30 | #include <wlr/types/wlr_subcompositor.h> | ||
24 | #include <wlr/types/wlr_tablet_v2.h> | 31 | #include <wlr/types/wlr_tablet_v2.h> |
25 | #include <wlr/types/wlr_viewporter.h> | 32 | #include <wlr/types/wlr_viewporter.h> |
26 | #include <wlr/types/wlr_xcursor_manager.h> | 33 | #include <wlr/types/wlr_xcursor_manager.h> |
34 | #include <wlr/types/wlr_xdg_activation_v1.h> | ||
27 | #include <wlr/types/wlr_xdg_decoration_v1.h> | 35 | #include <wlr/types/wlr_xdg_decoration_v1.h> |
36 | #include <wlr/types/wlr_xdg_foreign_registry.h> | ||
37 | #include <wlr/types/wlr_xdg_foreign_v1.h> | ||
38 | #include <wlr/types/wlr_xdg_foreign_v2.h> | ||
28 | #include <wlr/types/wlr_xdg_output_v1.h> | 39 | #include <wlr/types/wlr_xdg_output_v1.h> |
40 | #include <xf86drm.h> | ||
29 | #include "config.h" | 41 | #include "config.h" |
30 | #include "list.h" | 42 | #include "list.h" |
31 | #include "log.h" | 43 | #include "log.h" |
@@ -34,41 +46,177 @@ | |||
34 | #include "sway/input/input-manager.h" | 46 | #include "sway/input/input-manager.h" |
35 | #include "sway/output.h" | 47 | #include "sway/output.h" |
36 | #include "sway/server.h" | 48 | #include "sway/server.h" |
49 | #include "sway/input/cursor.h" | ||
37 | #include "sway/tree/root.h" | 50 | #include "sway/tree/root.h" |
51 | |||
38 | #if HAVE_XWAYLAND | 52 | #if HAVE_XWAYLAND |
53 | #include <wlr/xwayland/shell.h> | ||
39 | #include "sway/xwayland.h" | 54 | #include "sway/xwayland.h" |
40 | #endif | 55 | #endif |
41 | 56 | ||
42 | bool server_privileged_prepare(struct sway_server *server) { | 57 | #if WLR_HAS_DRM_BACKEND |
43 | sway_log(SWAY_DEBUG, "Preparing Wayland server initialization"); | 58 | #include <wlr/types/wlr_drm_lease_v1.h> |
59 | #endif | ||
60 | |||
61 | #define SWAY_XDG_SHELL_VERSION 2 | ||
62 | #define SWAY_LAYER_SHELL_VERSION 4 | ||
63 | |||
64 | bool allow_unsupported_gpu = false; | ||
65 | |||
66 | #if WLR_HAS_DRM_BACKEND | ||
67 | static void handle_drm_lease_request(struct wl_listener *listener, void *data) { | ||
68 | /* We only offer non-desktop outputs, but in the future we might want to do | ||
69 | * more logic here. */ | ||
70 | |||
71 | struct wlr_drm_lease_request_v1 *req = data; | ||
72 | struct wlr_drm_lease_v1 *lease = wlr_drm_lease_request_v1_grant(req); | ||
73 | if (!lease) { | ||
74 | sway_log(SWAY_ERROR, "Failed to grant lease request"); | ||
75 | wlr_drm_lease_request_v1_reject(req); | ||
76 | } | ||
77 | } | ||
78 | #endif | ||
79 | |||
80 | static bool is_privileged(const struct wl_global *global) { | ||
81 | #if WLR_HAS_DRM_BACKEND | ||
82 | if (server.drm_lease_manager != NULL) { | ||
83 | struct wlr_drm_lease_device_v1 *drm_lease_dev; | ||
84 | wl_list_for_each(drm_lease_dev, &server.drm_lease_manager->devices, link) { | ||
85 | if (drm_lease_dev->global == global) { | ||
86 | return true; | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | return | ||
93 | global == server.output_manager_v1->global || | ||
94 | global == server.output_power_manager_v1->global || | ||
95 | global == server.input_method->global || | ||
96 | global == server.foreign_toplevel_manager->global || | ||
97 | global == server.data_control_manager_v1->global || | ||
98 | global == server.screencopy_manager_v1->global || | ||
99 | global == server.export_dmabuf_manager_v1->global || | ||
100 | global == server.security_context_manager_v1->global || | ||
101 | global == server.gamma_control_manager_v1->global || | ||
102 | global == server.layer_shell->global || | ||
103 | global == server.session_lock.manager->global || | ||
104 | global == server.input->keyboard_shortcuts_inhibit->global || | ||
105 | global == server.input->virtual_keyboard->global || | ||
106 | global == server.input->virtual_pointer->global; | ||
107 | } | ||
108 | |||
109 | static bool filter_global(const struct wl_client *client, | ||
110 | const struct wl_global *global, void *data) { | ||
111 | #if HAVE_XWAYLAND | ||
112 | struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; | ||
113 | if (xwayland && global == xwayland->shell_v1->global) { | ||
114 | return xwayland->server != NULL && client == xwayland->server->client; | ||
115 | } | ||
116 | #endif | ||
117 | |||
118 | // Restrict usage of privileged protocols to unsandboxed clients | ||
119 | // TODO: add a way for users to configure an allow-list | ||
120 | const struct wlr_security_context_v1_state *security_context = | ||
121 | wlr_security_context_manager_v1_lookup_client( | ||
122 | server.security_context_manager_v1, (struct wl_client *)client); | ||
123 | if (is_privileged(global)) { | ||
124 | return security_context == NULL; | ||
125 | } | ||
126 | |||
127 | return true; | ||
128 | } | ||
129 | |||
130 | static void detect_proprietary(struct wlr_backend *backend, void *data) { | ||
131 | int drm_fd = wlr_backend_get_drm_fd(backend); | ||
132 | if (drm_fd < 0) { | ||
133 | return; | ||
134 | } | ||
135 | |||
136 | drmVersion *version = drmGetVersion(drm_fd); | ||
137 | if (version == NULL) { | ||
138 | sway_log(SWAY_ERROR, "drmGetVersion() failed"); | ||
139 | return; | ||
140 | } | ||
141 | |||
142 | bool is_unsupported = false; | ||
143 | if (strcmp(version->name, "nvidia-drm") == 0) { | ||
144 | is_unsupported = true; | ||
145 | sway_log(SWAY_ERROR, "!!! Proprietary Nvidia drivers are in use !!!"); | ||
146 | if (!allow_unsupported_gpu) { | ||
147 | sway_log(SWAY_ERROR, "Use Nouveau instead"); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | if (strcmp(version->name, "evdi") == 0) { | ||
152 | is_unsupported = true; | ||
153 | sway_log(SWAY_ERROR, "!!! Proprietary DisplayLink drivers are in use !!!"); | ||
154 | } | ||
155 | |||
156 | if (!allow_unsupported_gpu && is_unsupported) { | ||
157 | sway_log(SWAY_ERROR, | ||
158 | "Proprietary drivers are NOT supported. To launch sway anyway, " | ||
159 | "launch with --unsupported-gpu and DO NOT report issues."); | ||
160 | exit(EXIT_FAILURE); | ||
161 | } | ||
162 | |||
163 | drmFreeVersion(version); | ||
164 | } | ||
165 | |||
166 | bool server_init(struct sway_server *server) { | ||
167 | sway_log(SWAY_DEBUG, "Initializing Wayland server"); | ||
44 | server->wl_display = wl_display_create(); | 168 | server->wl_display = wl_display_create(); |
45 | server->wl_event_loop = wl_display_get_event_loop(server->wl_display); | 169 | server->wl_event_loop = wl_display_get_event_loop(server->wl_display); |
46 | server->backend = wlr_backend_autocreate(server->wl_display); | ||
47 | 170 | ||
171 | wl_display_set_global_filter(server->wl_display, filter_global, NULL); | ||
172 | |||
173 | root = root_create(server->wl_display); | ||
174 | |||
175 | server->backend = wlr_backend_autocreate(server->wl_event_loop, &server->session); | ||
48 | if (!server->backend) { | 176 | if (!server->backend) { |
49 | sway_log(SWAY_ERROR, "Unable to create backend"); | 177 | sway_log(SWAY_ERROR, "Unable to create backend"); |
50 | return false; | 178 | return false; |
51 | } | 179 | } |
52 | return true; | ||
53 | } | ||
54 | 180 | ||
55 | bool server_init(struct sway_server *server) { | 181 | wlr_multi_for_each_backend(server->backend, detect_proprietary, NULL); |
56 | sway_log(SWAY_DEBUG, "Initializing Wayland server"); | 182 | |
183 | server->renderer = wlr_renderer_autocreate(server->backend); | ||
184 | if (!server->renderer) { | ||
185 | sway_log(SWAY_ERROR, "Failed to create renderer"); | ||
186 | return false; | ||
187 | } | ||
188 | |||
189 | wlr_renderer_init_wl_shm(server->renderer, server->wl_display); | ||
190 | |||
191 | if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) { | ||
192 | server->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer( | ||
193 | server->wl_display, 4, server->renderer); | ||
194 | } | ||
195 | if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL && | ||
196 | debug.legacy_wl_drm) { | ||
197 | wlr_drm_create(server->wl_display, server->renderer); | ||
198 | } | ||
57 | 199 | ||
58 | struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend); | 200 | server->allocator = wlr_allocator_autocreate(server->backend, |
59 | assert(renderer); | 201 | server->renderer); |
202 | if (!server->allocator) { | ||
203 | sway_log(SWAY_ERROR, "Failed to create allocator"); | ||
204 | return false; | ||
205 | } | ||
60 | 206 | ||
61 | wlr_renderer_init_wl_display(renderer, server->wl_display); | 207 | server->compositor = wlr_compositor_create(server->wl_display, 6, |
208 | server->renderer); | ||
62 | 209 | ||
63 | server->compositor = wlr_compositor_create(server->wl_display, renderer); | 210 | wlr_subcompositor_create(server->wl_display); |
64 | server->compositor_new_surface.notify = handle_compositor_new_surface; | ||
65 | wl_signal_add(&server->compositor->events.new_surface, | ||
66 | &server->compositor_new_surface); | ||
67 | 211 | ||
68 | server->data_device_manager = | 212 | server->data_device_manager = |
69 | wlr_data_device_manager_create(server->wl_display); | 213 | wlr_data_device_manager_create(server->wl_display); |
70 | 214 | ||
71 | wlr_gamma_control_manager_v1_create(server->wl_display); | 215 | server->gamma_control_manager_v1 = |
216 | wlr_gamma_control_manager_v1_create(server->wl_display); | ||
217 | server->gamma_control_set_gamma.notify = handle_gamma_control_set_gamma; | ||
218 | wl_signal_add(&server->gamma_control_manager_v1->events.set_gamma, | ||
219 | &server->gamma_control_set_gamma); | ||
72 | 220 | ||
73 | server->new_output.notify = handle_new_output; | 221 | server->new_output.notify = handle_new_output; |
74 | wl_signal_add(&server->backend->events.new_output, &server->new_output); | 222 | wl_signal_add(&server->backend->events.new_output, &server->new_output); |
@@ -78,19 +226,20 @@ bool server_init(struct sway_server *server) { | |||
78 | 226 | ||
79 | wlr_xdg_output_manager_v1_create(server->wl_display, root->output_layout); | 227 | wlr_xdg_output_manager_v1_create(server->wl_display, root->output_layout); |
80 | 228 | ||
81 | server->idle = wlr_idle_create(server->wl_display); | 229 | server->idle_notifier_v1 = wlr_idle_notifier_v1_create(server->wl_display); |
82 | server->idle_inhibit_manager_v1 = | 230 | sway_idle_inhibit_manager_v1_init(); |
83 | sway_idle_inhibit_manager_v1_create(server->wl_display, server->idle); | ||
84 | 231 | ||
85 | server->layer_shell = wlr_layer_shell_v1_create(server->wl_display); | 232 | server->layer_shell = wlr_layer_shell_v1_create(server->wl_display, |
233 | SWAY_LAYER_SHELL_VERSION); | ||
86 | wl_signal_add(&server->layer_shell->events.new_surface, | 234 | wl_signal_add(&server->layer_shell->events.new_surface, |
87 | &server->layer_shell_surface); | 235 | &server->layer_shell_surface); |
88 | server->layer_shell_surface.notify = handle_layer_shell_surface; | 236 | server->layer_shell_surface.notify = handle_layer_shell_surface; |
89 | 237 | ||
90 | server->xdg_shell = wlr_xdg_shell_create(server->wl_display); | 238 | server->xdg_shell = wlr_xdg_shell_create(server->wl_display, |
91 | wl_signal_add(&server->xdg_shell->events.new_surface, | 239 | SWAY_XDG_SHELL_VERSION); |
92 | &server->xdg_shell_surface); | 240 | wl_signal_add(&server->xdg_shell->events.new_toplevel, |
93 | server->xdg_shell_surface.notify = handle_xdg_shell_surface; | 241 | &server->xdg_shell_toplevel); |
242 | server->xdg_shell_toplevel.notify = handle_xdg_shell_toplevel; | ||
94 | 243 | ||
95 | server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); | 244 | server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); |
96 | 245 | ||
@@ -121,8 +270,7 @@ bool server_init(struct sway_server *server) { | |||
121 | wl_signal_add(&server->pointer_constraints->events.new_constraint, | 270 | wl_signal_add(&server->pointer_constraints->events.new_constraint, |
122 | &server->pointer_constraint); | 271 | &server->pointer_constraint); |
123 | 272 | ||
124 | server->presentation = | 273 | wlr_presentation_create(server->wl_display, server->backend); |
125 | wlr_presentation_create(server->wl_display, server->backend); | ||
126 | 274 | ||
127 | server->output_manager_v1 = | 275 | server->output_manager_v1 = |
128 | wlr_output_manager_v1_create(server->wl_display); | 276 | wlr_output_manager_v1_create(server->wl_display); |
@@ -144,16 +292,57 @@ bool server_init(struct sway_server *server) { | |||
144 | server->foreign_toplevel_manager = | 292 | server->foreign_toplevel_manager = |
145 | wlr_foreign_toplevel_manager_v1_create(server->wl_display); | 293 | wlr_foreign_toplevel_manager_v1_create(server->wl_display); |
146 | 294 | ||
147 | wlr_export_dmabuf_manager_v1_create(server->wl_display); | 295 | sway_session_lock_init(); |
148 | wlr_screencopy_manager_v1_create(server->wl_display); | 296 | |
149 | wlr_data_control_manager_v1_create(server->wl_display); | 297 | #if WLR_HAS_DRM_BACKEND |
150 | wlr_primary_selection_v1_device_manager_create(server->wl_display); | 298 | server->drm_lease_manager= |
299 | wlr_drm_lease_v1_manager_create(server->wl_display, server->backend); | ||
300 | if (server->drm_lease_manager) { | ||
301 | server->drm_lease_request.notify = handle_drm_lease_request; | ||
302 | wl_signal_add(&server->drm_lease_manager->events.request, | ||
303 | &server->drm_lease_request); | ||
304 | } else { | ||
305 | sway_log(SWAY_DEBUG, "Failed to create wlr_drm_lease_device_v1"); | ||
306 | sway_log(SWAY_INFO, "VR will not be available"); | ||
307 | } | ||
308 | #endif | ||
309 | |||
310 | server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display); | ||
311 | server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display); | ||
312 | server->data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display); | ||
313 | server->security_context_manager_v1 = wlr_security_context_manager_v1_create(server->wl_display); | ||
151 | wlr_viewporter_create(server->wl_display); | 314 | wlr_viewporter_create(server->wl_display); |
315 | wlr_single_pixel_buffer_manager_v1_create(server->wl_display); | ||
316 | server->content_type_manager_v1 = | ||
317 | wlr_content_type_manager_v1_create(server->wl_display, 1); | ||
318 | wlr_fractional_scale_manager_v1_create(server->wl_display, 1); | ||
319 | |||
320 | struct wlr_xdg_foreign_registry *foreign_registry = | ||
321 | wlr_xdg_foreign_registry_create(server->wl_display); | ||
322 | wlr_xdg_foreign_v1_create(server->wl_display, foreign_registry); | ||
323 | wlr_xdg_foreign_v2_create(server->wl_display, foreign_registry); | ||
324 | |||
325 | server->xdg_activation_v1 = wlr_xdg_activation_v1_create(server->wl_display); | ||
326 | server->xdg_activation_v1_request_activate.notify = | ||
327 | xdg_activation_v1_handle_request_activate; | ||
328 | wl_signal_add(&server->xdg_activation_v1->events.request_activate, | ||
329 | &server->xdg_activation_v1_request_activate); | ||
330 | server->xdg_activation_v1_new_token.notify = | ||
331 | xdg_activation_v1_handle_new_token; | ||
332 | wl_signal_add(&server->xdg_activation_v1->events.new_token, | ||
333 | &server->xdg_activation_v1_new_token); | ||
334 | |||
335 | struct wlr_cursor_shape_manager_v1 *cursor_shape_manager = | ||
336 | wlr_cursor_shape_manager_v1_create(server->wl_display, 1); | ||
337 | server->request_set_cursor_shape.notify = handle_request_set_cursor_shape; | ||
338 | wl_signal_add(&cursor_shape_manager->events.request_set_shape, &server->request_set_cursor_shape); | ||
339 | |||
340 | wl_list_init(&server->pending_launcher_ctxs); | ||
152 | 341 | ||
153 | // Avoid using "wayland-0" as display socket | 342 | // Avoid using "wayland-0" as display socket |
154 | char name_candidate[16]; | 343 | char name_candidate[16]; |
155 | for (int i = 1; i <= 32; ++i) { | 344 | for (unsigned int i = 1; i <= 32; ++i) { |
156 | sprintf(name_candidate, "wayland-%d", i); | 345 | snprintf(name_candidate, sizeof(name_candidate), "wayland-%u", i); |
157 | if (wl_display_add_socket(server->wl_display, name_candidate) >= 0) { | 346 | if (wl_display_add_socket(server->wl_display, name_candidate) >= 0) { |
158 | server->socket = strdup(name_candidate); | 347 | server->socket = strdup(name_candidate); |
159 | break; | 348 | break; |
@@ -166,27 +355,26 @@ bool server_init(struct sway_server *server) { | |||
166 | return false; | 355 | return false; |
167 | } | 356 | } |
168 | 357 | ||
169 | server->noop_backend = wlr_noop_backend_create(server->wl_display); | 358 | 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) { | 359 | if (!server->headless_backend) { |
177 | sway_log(SWAY_INFO, "Failed to create secondary headless backend, " | 360 | sway_log(SWAY_ERROR, "Failed to create secondary headless backend"); |
178 | "starting without it"); | 361 | wlr_backend_destroy(server->backend); |
362 | return false; | ||
179 | } else { | 363 | } else { |
180 | wlr_multi_backend_add(server->backend, server->headless_backend); | 364 | wlr_multi_backend_add(server->backend, server->headless_backend); |
181 | } | 365 | } |
182 | 366 | ||
367 | struct wlr_output *wlr_output = | ||
368 | wlr_headless_add_output(server->headless_backend, 800, 600); | ||
369 | wlr_output_set_name(wlr_output, "FALLBACK"); | ||
370 | root->fallback_output = output_create(wlr_output); | ||
371 | |||
183 | // This may have been set already via -Dtxn-timeout | 372 | // This may have been set already via -Dtxn-timeout |
184 | if (!server->txn_timeout_ms) { | 373 | if (!server->txn_timeout_ms) { |
185 | server->txn_timeout_ms = 200; | 374 | server->txn_timeout_ms = 200; |
186 | } | 375 | } |
187 | 376 | ||
188 | server->dirty_nodes = create_list(); | 377 | server->dirty_nodes = create_list(); |
189 | server->transactions = create_list(); | ||
190 | 378 | ||
191 | server->input = input_manager_create(server); | 379 | server->input = input_manager_create(server); |
192 | input_manager_get_default_seat(); // create seat0 | 380 | input_manager_get_default_seat(); // create seat0 |
@@ -202,7 +390,6 @@ void server_fini(struct sway_server *server) { | |||
202 | wl_display_destroy_clients(server->wl_display); | 390 | wl_display_destroy_clients(server->wl_display); |
203 | wl_display_destroy(server->wl_display); | 391 | wl_display_destroy(server->wl_display); |
204 | list_free(server->dirty_nodes); | 392 | list_free(server->dirty_nodes); |
205 | list_free(server->transactions); | ||
206 | } | 393 | } |
207 | 394 | ||
208 | bool server_start(struct sway_server *server) { | 395 | bool server_start(struct sway_server *server) { |
@@ -231,6 +418,10 @@ bool server_start(struct sway_server *server) { | |||
231 | } | 418 | } |
232 | #endif | 419 | #endif |
233 | 420 | ||
421 | if (config->primary_selection) { | ||
422 | wlr_primary_selection_v1_device_manager_create(server->wl_display); | ||
423 | } | ||
424 | |||
234 | sway_log(SWAY_INFO, "Starting backend on wayland display '%s'", | 425 | sway_log(SWAY_INFO, "Starting backend on wayland display '%s'", |
235 | server->socket); | 426 | server->socket); |
236 | if (!wlr_backend_start(server->backend)) { | 427 | if (!wlr_backend_start(server->backend)) { |
@@ -238,6 +429,7 @@ bool server_start(struct sway_server *server) { | |||
238 | wlr_backend_destroy(server->backend); | 429 | wlr_backend_destroy(server->backend); |
239 | return false; | 430 | return false; |
240 | } | 431 | } |
432 | |||
241 | return true; | 433 | return true; |
242 | } | 434 | } |
243 | 435 | ||