aboutsummaryrefslogtreecommitdiffstats
path: root/sway/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/server.c')
-rw-r--r--sway/server.c259
1 files changed, 220 insertions, 39 deletions
diff --git a/sway/server.c b/sway/server.c
index 627d80d6..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,23 +6,34 @@
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/session.h>
11#include <wlr/config.h> 9#include <wlr/config.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>
15#include <wlr/types/wlr_drm_lease_v1.h> 16#include <wlr/types/wlr_data_device.h>
16#include <wlr/types/wlr_drm.h> 17#include <wlr/types/wlr_drm.h>
17#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>
18#include <wlr/types/wlr_gamma_control_v1.h> 22#include <wlr/types/wlr_gamma_control_v1.h>
19#include <wlr/types/wlr_idle.h> 23#include <wlr/types/wlr_idle_notify_v1.h>
20#include <wlr/types/wlr_layer_shell_v1.h> 24#include <wlr/types/wlr_layer_shell_v1.h>
21#include <wlr/types/wlr_linux_dmabuf_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>
22#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>
23#include <wlr/types/wlr_primary_selection_v1.h> 30#include <wlr/types/wlr_primary_selection_v1.h>
24#include <wlr/types/wlr_relative_pointer_v1.h> 31#include <wlr/types/wlr_relative_pointer_v1.h>
25#include <wlr/types/wlr_screencopy_v1.h> 32#include <wlr/types/wlr_screencopy_v1.h>
33#include <wlr/types/wlr_security_context_v1.h>
26#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>
27#include <wlr/types/wlr_subcompositor.h> 37#include <wlr/types/wlr_subcompositor.h>
28#include <wlr/types/wlr_tablet_v2.h> 38#include <wlr/types/wlr_tablet_v2.h>
29#include <wlr/types/wlr_viewporter.h> 39#include <wlr/types/wlr_viewporter.h>
@@ -34,6 +44,7 @@
34#include <wlr/types/wlr_xdg_foreign_v1.h> 44#include <wlr/types/wlr_xdg_foreign_v1.h>
35#include <wlr/types/wlr_xdg_foreign_v2.h> 45#include <wlr/types/wlr_xdg_foreign_v2.h>
36#include <wlr/types/wlr_xdg_output_v1.h> 46#include <wlr/types/wlr_xdg_output_v1.h>
47#include <xf86drm.h>
37#include "config.h" 48#include "config.h"
38#include "list.h" 49#include "list.h"
39#include "log.h" 50#include "log.h"
@@ -42,24 +53,25 @@
42#include "sway/input/input-manager.h" 53#include "sway/input/input-manager.h"
43#include "sway/output.h" 54#include "sway/output.h"
44#include "sway/server.h" 55#include "sway/server.h"
56#include "sway/input/cursor.h"
45#include "sway/tree/root.h" 57#include "sway/tree/root.h"
58
46#if HAVE_XWAYLAND 59#if HAVE_XWAYLAND
60#include <wlr/xwayland/shell.h>
47#include "sway/xwayland.h" 61#include "sway/xwayland.h"
48#endif 62#endif
49 63
50bool server_privileged_prepare(struct sway_server *server) { 64#if WLR_HAS_DRM_BACKEND
51 sway_log(SWAY_DEBUG, "Preparing Wayland server initialization"); 65#include <wlr/types/wlr_drm_lease_v1.h>
52 server->wl_display = wl_display_create(); 66#endif
53 server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
54 server->backend = wlr_backend_autocreate(server->wl_display);
55 67
56 if (!server->backend) { 68#define SWAY_XDG_SHELL_VERSION 5
57 sway_log(SWAY_ERROR, "Unable to create backend"); 69#define SWAY_LAYER_SHELL_VERSION 4
58 return false; 70#define SWAY_FOREIGN_TOPLEVEL_LIST_VERSION 1
59 }
60 return true;
61}
62 71
72bool allow_unsupported_gpu = false;
73
74#if WLR_HAS_DRM_BACKEND
63static void handle_drm_lease_request(struct wl_listener *listener, void *data) { 75static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
64 /* We only offer non-desktop outputs, but in the future we might want to do 76 /* We only offer non-desktop outputs, but in the future we might want to do
65 * more logic here. */ 77 * more logic here. */
@@ -71,11 +83,151 @@ static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
71 wlr_drm_lease_request_v1_reject(req); 83 wlr_drm_lease_request_v1_reject(req);
72 } 84 }
73} 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}
74 139
75#define SWAY_XDG_SHELL_VERSION 2 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}
76 214
77bool server_init(struct sway_server *server) { 215bool server_init(struct sway_server *server) {
78 sway_log(SWAY_DEBUG, "Initializing Wayland server"); 216 sway_log(SWAY_DEBUG, "Initializing Wayland server");
217 server->wl_display = wl_display_create();
218 server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
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);
225 if (!server->backend) {
226 sway_log(SWAY_ERROR, "Unable to create backend");
227 return false;
228 }
229
230 wlr_multi_for_each_backend(server->backend, detect_proprietary, NULL);
79 231
80 server->renderer = wlr_renderer_autocreate(server->backend); 232 server->renderer = wlr_renderer_autocreate(server->backend);
81 if (!server->renderer) { 233 if (!server->renderer) {
@@ -83,12 +235,17 @@ bool server_init(struct sway_server *server) {
83 return false; 235 return false;
84 } 236 }
85 237
238 server->renderer_lost.notify = handle_renderer_lost;
239 wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
240
86 wlr_renderer_init_wl_shm(server->renderer, server->wl_display); 241 wlr_renderer_init_wl_shm(server->renderer, server->wl_display);
87 242
88 if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) { 243 if (wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF) != NULL) {
89 wlr_drm_create(server->wl_display, server->renderer); 244 server->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer(
90 server->linux_dmabuf_v1 = 245 server->wl_display, 4, server->renderer);
91 wlr_linux_dmabuf_v1_create(server->wl_display, server->renderer); 246 if (debug.legacy_wl_drm) {
247 wlr_drm_create(server->wl_display, server->renderer);
248 }
92 } 249 }
93 250
94 server->allocator = wlr_allocator_autocreate(server->backend, 251 server->allocator = wlr_allocator_autocreate(server->backend,
@@ -98,18 +255,19 @@ bool server_init(struct sway_server *server) {
98 return false; 255 return false;
99 } 256 }
100 257
101 server->compositor = wlr_compositor_create(server->wl_display, 258 server->compositor = wlr_compositor_create(server->wl_display, 6,
102 server->renderer); 259 server->renderer);
103 server->compositor_new_surface.notify = handle_compositor_new_surface;
104 wl_signal_add(&server->compositor->events.new_surface,
105 &server->compositor_new_surface);
106 260
107 wlr_subcompositor_create(server->wl_display); 261 wlr_subcompositor_create(server->wl_display);
108 262
109 server->data_device_manager = 263 server->data_device_manager =
110 wlr_data_device_manager_create(server->wl_display); 264 wlr_data_device_manager_create(server->wl_display);
111 265
112 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);
113 271
114 server->new_output.notify = handle_new_output; 272 server->new_output.notify = handle_new_output;
115 wl_signal_add(&server->backend->events.new_output, &server->new_output); 273 wl_signal_add(&server->backend->events.new_output, &server->new_output);
@@ -119,20 +277,20 @@ bool server_init(struct sway_server *server) {
119 277
120 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);
121 279
122 server->idle = wlr_idle_create(server->wl_display); 280 server->idle_notifier_v1 = wlr_idle_notifier_v1_create(server->wl_display);
123 server->idle_inhibit_manager_v1 = 281 sway_idle_inhibit_manager_v1_init();
124 sway_idle_inhibit_manager_v1_create(server->wl_display, server->idle);
125 282
126 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);
127 wl_signal_add(&server->layer_shell->events.new_surface, 285 wl_signal_add(&server->layer_shell->events.new_surface,
128 &server->layer_shell_surface); 286 &server->layer_shell_surface);
129 server->layer_shell_surface.notify = handle_layer_shell_surface; 287 server->layer_shell_surface.notify = handle_layer_shell_surface;
130 288
131 server->xdg_shell = wlr_xdg_shell_create(server->wl_display, 289 server->xdg_shell = wlr_xdg_shell_create(server->wl_display,
132 SWAY_XDG_SHELL_VERSION); 290 SWAY_XDG_SHELL_VERSION);
133 wl_signal_add(&server->xdg_shell->events.new_surface, 291 wl_signal_add(&server->xdg_shell->events.new_toplevel,
134 &server->xdg_shell_surface); 292 &server->xdg_shell_toplevel);
135 server->xdg_shell_surface.notify = handle_xdg_shell_surface; 293 server->xdg_shell_toplevel.notify = handle_xdg_shell_toplevel;
136 294
137 server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); 295 server->tablet_v2 = wlr_tablet_v2_create(server->wl_display);
138 296
@@ -163,8 +321,7 @@ bool server_init(struct sway_server *server) {
163 wl_signal_add(&server->pointer_constraints->events.new_constraint, 321 wl_signal_add(&server->pointer_constraints->events.new_constraint,
164 &server->pointer_constraint); 322 &server->pointer_constraint);
165 323
166 server->presentation = 324 wlr_presentation_create(server->wl_display, server->backend);
167 wlr_presentation_create(server->wl_display, server->backend);
168 325
169 server->output_manager_v1 = 326 server->output_manager_v1 =
170 wlr_output_manager_v1_create(server->wl_display); 327 wlr_output_manager_v1_create(server->wl_display);
@@ -183,11 +340,14 @@ bool server_init(struct sway_server *server) {
183 &server->output_power_manager_set_mode); 340 &server->output_power_manager_set_mode);
184 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);
185 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);
186 server->foreign_toplevel_manager = 345 server->foreign_toplevel_manager =
187 wlr_foreign_toplevel_manager_v1_create(server->wl_display); 346 wlr_foreign_toplevel_manager_v1_create(server->wl_display);
188 347
189 sway_session_lock_init(); 348 sway_session_lock_init();
190 349
350#if WLR_HAS_DRM_BACKEND
191 server->drm_lease_manager= 351 server->drm_lease_manager=
192 wlr_drm_lease_v1_manager_create(server->wl_display, server->backend); 352 wlr_drm_lease_v1_manager_create(server->wl_display, server->backend);
193 if (server->drm_lease_manager) { 353 if (server->drm_lease_manager) {
@@ -198,12 +358,17 @@ bool server_init(struct sway_server *server) {
198 sway_log(SWAY_DEBUG, "Failed to create wlr_drm_lease_device_v1"); 358 sway_log(SWAY_DEBUG, "Failed to create wlr_drm_lease_device_v1");
199 sway_log(SWAY_INFO, "VR will not be available"); 359 sway_log(SWAY_INFO, "VR will not be available");
200 } 360 }
361#endif
201 362
202 wlr_export_dmabuf_manager_v1_create(server->wl_display); 363 server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display);
203 wlr_screencopy_manager_v1_create(server->wl_display); 364 server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display);
204 wlr_data_control_manager_v1_create(server->wl_display); 365 server->data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display);
205 wlr_primary_selection_v1_device_manager_create(server->wl_display); 366 server->security_context_manager_v1 = wlr_security_context_manager_v1_create(server->wl_display);
206 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);
207 372
208 struct wlr_xdg_foreign_registry *foreign_registry = 373 struct wlr_xdg_foreign_registry *foreign_registry =
209 wlr_xdg_foreign_registry_create(server->wl_display); 374 wlr_xdg_foreign_registry_create(server->wl_display);
@@ -215,6 +380,17 @@ bool server_init(struct sway_server *server) {
215 xdg_activation_v1_handle_request_activate; 380 xdg_activation_v1_handle_request_activate;
216 wl_signal_add(&server->xdg_activation_v1->events.request_activate, 381 wl_signal_add(&server->xdg_activation_v1->events.request_activate,
217 &server->xdg_activation_v1_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);
218 394
219 // Avoid using "wayland-0" as display socket 395 // Avoid using "wayland-0" as display socket
220 char name_candidate[16]; 396 char name_candidate[16];
@@ -232,7 +408,7 @@ bool server_init(struct sway_server *server) {
232 return false; 408 return false;
233 } 409 }
234 410
235 server->headless_backend = wlr_headless_backend_create(server->wl_display); 411 server->headless_backend = wlr_headless_backend_create(server->wl_event_loop);
236 if (!server->headless_backend) { 412 if (!server->headless_backend) {
237 sway_log(SWAY_ERROR, "Failed to create secondary headless backend"); 413 sway_log(SWAY_ERROR, "Failed to create secondary headless backend");
238 wlr_backend_destroy(server->backend); 414 wlr_backend_destroy(server->backend);
@@ -265,6 +441,7 @@ void server_fini(struct sway_server *server) {
265 wlr_xwayland_destroy(server->xwayland.wlr_xwayland); 441 wlr_xwayland_destroy(server->xwayland.wlr_xwayland);
266#endif 442#endif
267 wl_display_destroy_clients(server->wl_display); 443 wl_display_destroy_clients(server->wl_display);
444 wlr_backend_destroy(server->backend);
268 wl_display_destroy(server->wl_display); 445 wl_display_destroy(server->wl_display);
269 list_free(server->dirty_nodes); 446 list_free(server->dirty_nodes);
270} 447}
@@ -295,6 +472,10 @@ bool server_start(struct sway_server *server) {
295 } 472 }
296#endif 473#endif
297 474
475 if (config->primary_selection) {
476 wlr_primary_selection_v1_device_manager_create(server->wl_display);
477 }
478
298 sway_log(SWAY_INFO, "Starting backend on wayland display '%s'", 479 sway_log(SWAY_INFO, "Starting backend on wayland display '%s'",
299 server->socket); 480 server->socket);
300 if (!wlr_backend_start(server->backend)) { 481 if (!wlr_backend_start(server->backend)) {