aboutsummaryrefslogtreecommitdiffstats
path: root/sway/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/server.c')
-rw-r--r--sway/server.c244
1 files changed, 214 insertions, 30 deletions
diff --git a/sway/server.c b/sway/server.c
index a87fc7cf..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,24 +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>
26#include <wlr/types/wlr_single_pixel_buffer_v1.h> 33#include <wlr/types/wlr_security_context_v1.h>
27#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>
28#include <wlr/types/wlr_subcompositor.h> 37#include <wlr/types/wlr_subcompositor.h>
29#include <wlr/types/wlr_tablet_v2.h> 38#include <wlr/types/wlr_tablet_v2.h>
30#include <wlr/types/wlr_viewporter.h> 39#include <wlr/types/wlr_viewporter.h>
@@ -35,6 +44,7 @@
35#include <wlr/types/wlr_xdg_foreign_v1.h> 44#include <wlr/types/wlr_xdg_foreign_v1.h>
36#include <wlr/types/wlr_xdg_foreign_v2.h> 45#include <wlr/types/wlr_xdg_foreign_v2.h>
37#include <wlr/types/wlr_xdg_output_v1.h> 46#include <wlr/types/wlr_xdg_output_v1.h>
47#include <xf86drm.h>
38#include "config.h" 48#include "config.h"
39#include "list.h" 49#include "list.h"
40#include "log.h" 50#include "log.h"
@@ -43,11 +53,25 @@
43#include "sway/input/input-manager.h" 53#include "sway/input/input-manager.h"
44#include "sway/output.h" 54#include "sway/output.h"
45#include "sway/server.h" 55#include "sway/server.h"
56#include "sway/input/cursor.h"
46#include "sway/tree/root.h" 57#include "sway/tree/root.h"
58
47#if HAVE_XWAYLAND 59#if HAVE_XWAYLAND
60#include <wlr/xwayland/shell.h>
48#include "sway/xwayland.h" 61#include "sway/xwayland.h"
49#endif 62#endif
50 63
64#if WLR_HAS_DRM_BACKEND
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
51static void handle_drm_lease_request(struct wl_listener *listener, void *data) { 75static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
52 /* 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
53 * more logic here. */ 77 * more logic here. */
@@ -59,32 +83,169 @@ static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
59 wlr_drm_lease_request_v1_reject(req); 83 wlr_drm_lease_request_v1_reject(req);
60 } 84 }
61} 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;
62 199
63#define SWAY_XDG_SHELL_VERSION 2 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}
64 214
65bool server_init(struct sway_server *server) { 215bool server_init(struct sway_server *server) {
66 sway_log(SWAY_DEBUG, "Initializing Wayland server"); 216 sway_log(SWAY_DEBUG, "Initializing Wayland server");
67 server->wl_display = wl_display_create(); 217 server->wl_display = wl_display_create();
68 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);
69 server->backend = wlr_backend_autocreate(server->wl_display);
70 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);
71 if (!server->backend) { 225 if (!server->backend) {
72 sway_log(SWAY_ERROR, "Unable to create backend"); 226 sway_log(SWAY_ERROR, "Unable to create backend");
73 return false; 227 return false;
74 } 228 }
75 229
230 wlr_multi_for_each_backend(server->backend, detect_proprietary, NULL);
231
76 server->renderer = wlr_renderer_autocreate(server->backend); 232 server->renderer = wlr_renderer_autocreate(server->backend);
77 if (!server->renderer) { 233 if (!server->renderer) {
78 sway_log(SWAY_ERROR, "Failed to create renderer"); 234 sway_log(SWAY_ERROR, "Failed to create renderer");
79 return false; 235 return false;
80 } 236 }
81 237
238 server->renderer_lost.notify = handle_renderer_lost;
239 wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
240
82 wlr_renderer_init_wl_shm(server->renderer, server->wl_display); 241 wlr_renderer_init_wl_shm(server->renderer, server->wl_display);
83 242
84 if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) { 243 if (wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF) != NULL) {
85 wlr_drm_create(server->wl_display, server->renderer); 244 server->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer(
86 server->linux_dmabuf_v1 = 245 server->wl_display, 4, server->renderer);
87 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 }
88 } 249 }
89 250
90 server->allocator = wlr_allocator_autocreate(server->backend, 251 server->allocator = wlr_allocator_autocreate(server->backend,
@@ -94,18 +255,19 @@ bool server_init(struct sway_server *server) {
94 return false; 255 return false;
95 } 256 }
96 257
97 server->compositor = wlr_compositor_create(server->wl_display, 258 server->compositor = wlr_compositor_create(server->wl_display, 6,
98 server->renderer); 259 server->renderer);
99 server->compositor_new_surface.notify = handle_compositor_new_surface;
100 wl_signal_add(&server->compositor->events.new_surface,
101 &server->compositor_new_surface);
102 260
103 wlr_subcompositor_create(server->wl_display); 261 wlr_subcompositor_create(server->wl_display);
104 262
105 server->data_device_manager = 263 server->data_device_manager =
106 wlr_data_device_manager_create(server->wl_display); 264 wlr_data_device_manager_create(server->wl_display);
107 265
108 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);
109 271
110 server->new_output.notify = handle_new_output; 272 server->new_output.notify = handle_new_output;
111 wl_signal_add(&server->backend->events.new_output, &server->new_output); 273 wl_signal_add(&server->backend->events.new_output, &server->new_output);
@@ -115,20 +277,20 @@ bool server_init(struct sway_server *server) {
115 277
116 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);
117 279
118 server->idle = wlr_idle_create(server->wl_display); 280 server->idle_notifier_v1 = wlr_idle_notifier_v1_create(server->wl_display);
119 server->idle_inhibit_manager_v1 = 281 sway_idle_inhibit_manager_v1_init();
120 sway_idle_inhibit_manager_v1_create(server->wl_display, server->idle);
121 282
122 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);
123 wl_signal_add(&server->layer_shell->events.new_surface, 285 wl_signal_add(&server->layer_shell->events.new_surface,
124 &server->layer_shell_surface); 286 &server->layer_shell_surface);
125 server->layer_shell_surface.notify = handle_layer_shell_surface; 287 server->layer_shell_surface.notify = handle_layer_shell_surface;
126 288
127 server->xdg_shell = wlr_xdg_shell_create(server->wl_display, 289 server->xdg_shell = wlr_xdg_shell_create(server->wl_display,
128 SWAY_XDG_SHELL_VERSION); 290 SWAY_XDG_SHELL_VERSION);
129 wl_signal_add(&server->xdg_shell->events.new_surface, 291 wl_signal_add(&server->xdg_shell->events.new_toplevel,
130 &server->xdg_shell_surface); 292 &server->xdg_shell_toplevel);
131 server->xdg_shell_surface.notify = handle_xdg_shell_surface; 293 server->xdg_shell_toplevel.notify = handle_xdg_shell_toplevel;
132 294
133 server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); 295 server->tablet_v2 = wlr_tablet_v2_create(server->wl_display);
134 296
@@ -159,8 +321,7 @@ bool server_init(struct sway_server *server) {
159 wl_signal_add(&server->pointer_constraints->events.new_constraint, 321 wl_signal_add(&server->pointer_constraints->events.new_constraint,
160 &server->pointer_constraint); 322 &server->pointer_constraint);
161 323
162 server->presentation = 324 wlr_presentation_create(server->wl_display, server->backend);
163 wlr_presentation_create(server->wl_display, server->backend);
164 325
165 server->output_manager_v1 = 326 server->output_manager_v1 =
166 wlr_output_manager_v1_create(server->wl_display); 327 wlr_output_manager_v1_create(server->wl_display);
@@ -179,11 +340,14 @@ bool server_init(struct sway_server *server) {
179 &server->output_power_manager_set_mode); 340 &server->output_power_manager_set_mode);
180 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);
181 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);
182 server->foreign_toplevel_manager = 345 server->foreign_toplevel_manager =
183 wlr_foreign_toplevel_manager_v1_create(server->wl_display); 346 wlr_foreign_toplevel_manager_v1_create(server->wl_display);
184 347
185 sway_session_lock_init(); 348 sway_session_lock_init();
186 349
350#if WLR_HAS_DRM_BACKEND
187 server->drm_lease_manager= 351 server->drm_lease_manager=
188 wlr_drm_lease_v1_manager_create(server->wl_display, server->backend); 352 wlr_drm_lease_v1_manager_create(server->wl_display, server->backend);
189 if (server->drm_lease_manager) { 353 if (server->drm_lease_manager) {
@@ -194,13 +358,17 @@ bool server_init(struct sway_server *server) {
194 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");
195 sway_log(SWAY_INFO, "VR will not be available"); 359 sway_log(SWAY_INFO, "VR will not be available");
196 } 360 }
361#endif
197 362
198 wlr_export_dmabuf_manager_v1_create(server->wl_display); 363 server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display);
199 wlr_screencopy_manager_v1_create(server->wl_display); 364 server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display);
200 wlr_data_control_manager_v1_create(server->wl_display); 365 server->data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display);
201 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);
202 wlr_viewporter_create(server->wl_display); 367 wlr_viewporter_create(server->wl_display);
203 wlr_single_pixel_buffer_manager_v1_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);
204 372
205 struct wlr_xdg_foreign_registry *foreign_registry = 373 struct wlr_xdg_foreign_registry *foreign_registry =
206 wlr_xdg_foreign_registry_create(server->wl_display); 374 wlr_xdg_foreign_registry_create(server->wl_display);
@@ -212,6 +380,17 @@ bool server_init(struct sway_server *server) {
212 xdg_activation_v1_handle_request_activate; 380 xdg_activation_v1_handle_request_activate;
213 wl_signal_add(&server->xdg_activation_v1->events.request_activate, 381 wl_signal_add(&server->xdg_activation_v1->events.request_activate,
214 &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);
215 394
216 // Avoid using "wayland-0" as display socket 395 // Avoid using "wayland-0" as display socket
217 char name_candidate[16]; 396 char name_candidate[16];
@@ -229,7 +408,7 @@ bool server_init(struct sway_server *server) {
229 return false; 408 return false;
230 } 409 }
231 410
232 server->headless_backend = wlr_headless_backend_create(server->wl_display); 411 server->headless_backend = wlr_headless_backend_create(server->wl_event_loop);
233 if (!server->headless_backend) { 412 if (!server->headless_backend) {
234 sway_log(SWAY_ERROR, "Failed to create secondary headless backend"); 413 sway_log(SWAY_ERROR, "Failed to create secondary headless backend");
235 wlr_backend_destroy(server->backend); 414 wlr_backend_destroy(server->backend);
@@ -262,6 +441,7 @@ void server_fini(struct sway_server *server) {
262 wlr_xwayland_destroy(server->xwayland.wlr_xwayland); 441 wlr_xwayland_destroy(server->xwayland.wlr_xwayland);
263#endif 442#endif
264 wl_display_destroy_clients(server->wl_display); 443 wl_display_destroy_clients(server->wl_display);
444 wlr_backend_destroy(server->backend);
265 wl_display_destroy(server->wl_display); 445 wl_display_destroy(server->wl_display);
266 list_free(server->dirty_nodes); 446 list_free(server->dirty_nodes);
267} 447}
@@ -292,6 +472,10 @@ bool server_start(struct sway_server *server) {
292 } 472 }
293#endif 473#endif
294 474
475 if (config->primary_selection) {
476 wlr_primary_selection_v1_device_manager_create(server->wl_display);
477 }
478
295 sway_log(SWAY_INFO, "Starting backend on wayland display '%s'", 479 sway_log(SWAY_INFO, "Starting backend on wayland display '%s'",
296 server->socket); 480 server->socket);
297 if (!wlr_backend_start(server->backend)) { 481 if (!wlr_backend_start(server->backend)) {