aboutsummaryrefslogtreecommitdiffstats
path: root/sway/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/server.c')
-rw-r--r--sway/server.c282
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
42bool 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
64bool allow_unsupported_gpu = false;
65
66#if WLR_HAS_DRM_BACKEND
67static 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
80static 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
109static 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
130static 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
166bool 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
55bool 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
208bool server_start(struct sway_server *server) { 395bool 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