summaryrefslogtreecommitdiffstats
path: root/sway/extensions.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/extensions.c')
-rw-r--r--sway/extensions.c407
1 files changed, 0 insertions, 407 deletions
diff --git a/sway/extensions.c b/sway/extensions.c
deleted file mode 100644
index 91746561..00000000
--- a/sway/extensions.c
+++ /dev/null
@@ -1,407 +0,0 @@
1#include <stdlib.h>
2#include <wlc/wlc.h>
3#include <wlc/wlc-wayland.h>
4#include <wlc/wlc-render.h>
5#include "wayland-desktop-shell-server-protocol.h"
6#include "wayland-swaylock-server-protocol.h"
7#include "wayland-gamma-control-server-protocol.h"
8#include "wayland-server-decoration-server-protocol.h"
9#include "sway/layout.h"
10#include "sway/input_state.h"
11#include "sway/extensions.h"
12#include "sway/security.h"
13#include "sway/ipc-server.h"
14#include "log.h"
15
16struct desktop_shell_state desktop_shell;
17struct decoration_state decoration_state;
18
19static struct panel_config *find_or_create_panel_config(struct wl_resource *resource) {
20 for (int i = 0; i < desktop_shell.panels->length; i++) {
21 struct panel_config *conf = desktop_shell.panels->items[i];
22 if (conf->wl_resource == resource) {
23 sway_log(L_DEBUG, "Found existing panel config for resource %p", resource);
24 return conf;
25 }
26 }
27 sway_log(L_DEBUG, "Creating panel config for resource %p", resource);
28 struct panel_config *config = calloc(1, sizeof(struct panel_config));
29 if (!config) {
30 sway_log(L_ERROR, "Unable to create panel config");
31 return NULL;
32 }
33 list_add(desktop_shell.panels, config);
34 config->wl_resource = resource;
35 return config;
36}
37
38void background_surface_destructor(struct wl_resource *resource) {
39 sway_log(L_DEBUG, "Background surface killed");
40 int i;
41 for (i = 0; i < desktop_shell.backgrounds->length; ++i) {
42 struct background_config *config = desktop_shell.backgrounds->items[i];
43 if (config->wl_surface_res == resource) {
44 list_del(desktop_shell.backgrounds, i);
45 break;
46 }
47 }
48}
49
50void panel_surface_destructor(struct wl_resource *resource) {
51 sway_log(L_DEBUG, "Panel surface killed");
52 int i;
53 for (i = 0; i < desktop_shell.panels->length; ++i) {
54 struct panel_config *config = desktop_shell.panels->items[i];
55 if (config->wl_surface_res == resource) {
56 list_del(desktop_shell.panels, i);
57 arrange_windows(&root_container, -1, -1);
58 break;
59 }
60 }
61}
62
63void lock_surface_destructor(struct wl_resource *resource) {
64 sway_log(L_DEBUG, "Lock surface killed");
65 int i;
66 for (i = 0; i < desktop_shell.lock_surfaces->length; ++i) {
67 struct wl_resource *surface = desktop_shell.lock_surfaces->items[i];
68 if (surface == resource) {
69 list_del(desktop_shell.lock_surfaces, i);
70 arrange_windows(&root_container, -1, -1);
71 break;
72 }
73 }
74 if (desktop_shell.lock_surfaces->length == 0) {
75 sway_log(L_DEBUG, "Desktop shell unlocked");
76 desktop_shell.is_locked = false;
77
78 // We need to now give focus back to the focus which we internally
79 // track, since when we lock sway we don't actually change our internal
80 // focus tracking.
81 swayc_t *focus = get_focused_container(swayc_active_workspace());
82 set_focused_container(focus);
83 wlc_view_focus(focus->handle);
84 }
85}
86
87static void set_background(struct wl_client *client, struct wl_resource *resource,
88 struct wl_resource *_output, struct wl_resource *surface) {
89 pid_t pid;
90 wl_client_get_credentials(client, &pid, NULL, NULL);
91 if (!(get_feature_policy_mask(pid) & FEATURE_BACKGROUND)) {
92 sway_log(L_INFO, "Denying background feature to %d", pid);
93 return;
94 }
95 wlc_handle output = wlc_handle_from_wl_output_resource(_output);
96 if (!output) {
97 return;
98 }
99 sway_log(L_DEBUG, "Setting surface %p as background for output %d", surface, (int)output);
100 struct background_config *config = malloc(sizeof(struct background_config));
101 if (!config) {
102 sway_log(L_ERROR, "Unable to allocate background config");
103 return;
104 }
105 config->client = client;
106 config->output = output;
107 config->surface = wlc_resource_from_wl_surface_resource(surface);
108 config->wl_surface_res = surface;
109 list_add(desktop_shell.backgrounds, config);
110 wl_resource_set_destructor(surface, background_surface_destructor);
111 arrange_windows(swayc_by_handle(output), -1, -1);
112 wlc_output_schedule_render(config->output);
113}
114
115static void set_panel(struct wl_client *client, struct wl_resource *resource,
116 struct wl_resource *_output, struct wl_resource *surface) {
117 pid_t pid;
118 wl_client_get_credentials(client, &pid, NULL, NULL);
119 if (!(get_feature_policy_mask(pid) & FEATURE_PANEL)) {
120 sway_log(L_INFO, "Denying panel feature to %d", pid);
121 return;
122 }
123 wlc_handle output = wlc_handle_from_wl_output_resource(_output);
124 if (!output) {
125 return;
126 }
127 sway_log(L_DEBUG, "Setting surface %p as panel for output %d (wl_resource: %p)", surface, (int)output, resource);
128 struct panel_config *config = find_or_create_panel_config(resource);
129 config->output = output;
130 config->client = client;
131 config->surface = wlc_resource_from_wl_surface_resource(surface);
132 config->wl_surface_res = surface;
133 wl_resource_set_destructor(surface, panel_surface_destructor);
134 arrange_windows(&root_container, -1, -1);
135 wlc_output_schedule_render(config->output);
136}
137
138static void desktop_set_lock_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface) {
139 sway_log(L_ERROR, "desktop_set_lock_surface is not currently supported");
140}
141
142static void desktop_unlock(struct wl_client *client, struct wl_resource *resource) {
143 sway_log(L_ERROR, "desktop_unlock is not currently supported");
144}
145
146static void set_grab_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface) {
147 sway_log(L_ERROR, "desktop_set_grab_surface is not currently supported");
148}
149
150static void desktop_ready(struct wl_client *client, struct wl_resource *resource) {
151 // nop
152}
153
154static void set_panel_position(struct wl_client *client, struct wl_resource *resource, uint32_t position) {
155 pid_t pid;
156 wl_client_get_credentials(client, &pid, NULL, NULL);
157 if (!(get_feature_policy_mask(pid) & FEATURE_PANEL)) {
158 sway_log(L_INFO, "Denying panel feature to %d", pid);
159 return;
160 }
161 struct panel_config *config = find_or_create_panel_config(resource);
162 sway_log(L_DEBUG, "Panel position for wl_resource %p changed %d => %d", resource, config->panel_position, position);
163 config->panel_position = position;
164 arrange_windows(&root_container, -1, -1);
165}
166
167static struct desktop_shell_interface desktop_shell_implementation = {
168 .set_background = set_background,
169 .set_panel = set_panel,
170 .set_lock_surface = desktop_set_lock_surface,
171 .unlock = desktop_unlock,
172 .set_grab_surface = set_grab_surface,
173 .desktop_ready = desktop_ready,
174 .set_panel_position = set_panel_position
175};
176
177static void desktop_shell_bind(struct wl_client *client, void *data,
178 uint32_t version, uint32_t id) {
179 if (version > 3) {
180 // Unsupported version
181 return;
182 }
183
184 struct wl_resource *resource = wl_resource_create(client, &desktop_shell_interface, version, id);
185 if (!resource) {
186 wl_client_post_no_memory(client);
187 }
188
189 wl_resource_set_implementation(resource, &desktop_shell_implementation, NULL, NULL);
190}
191
192static void set_lock_surface(struct wl_client *client, struct wl_resource *resource,
193 struct wl_resource *_output, struct wl_resource *surface) {
194 pid_t pid;
195 wl_client_get_credentials(client, &pid, NULL, NULL);
196 if (!(get_feature_policy_mask(pid) & FEATURE_LOCK)) {
197 sway_log(L_INFO, "Denying lock feature to %d", pid);
198 return;
199 }
200 swayc_t *output = swayc_by_handle(wlc_handle_from_wl_output_resource(_output));
201 swayc_t *view = swayc_by_handle(wlc_handle_from_wl_surface_resource(surface));
202 sway_log(L_DEBUG, "Setting lock surface to %p", view);
203 if (view && output) {
204 swayc_t *workspace = output->focused;
205 if (!swayc_is_child_of(view, workspace)) {
206 move_container_to(view, workspace);
207 }
208 // make the view floating so it doesn't rearrange other siblings.
209 if (!view->is_floating) {
210 destroy_container(remove_child(view));
211 add_floating(workspace, view);
212 }
213 wlc_view_set_state(view->handle, WLC_BIT_FULLSCREEN, true);
214 wlc_view_bring_to_front(view->handle);
215 wlc_view_focus(view->handle);
216 desktop_shell.is_locked = true;
217 input_init();
218 arrange_windows(workspace, -1, -1);
219 list_add(desktop_shell.lock_surfaces, surface);
220 wl_resource_set_destructor(surface, lock_surface_destructor);
221 } else {
222 sway_log(L_ERROR, "Attempted to set lock surface to non-view");
223 }
224}
225
226static void unlock(struct wl_client *client, struct wl_resource *resource) {
227 sway_log(L_ERROR, "unlock is not currently supported");
228 // This isn't really necessary, we just unlock when the client exits.
229}
230
231static struct lock_interface swaylock_implementation = {
232 .set_lock_surface = set_lock_surface,
233 .unlock = unlock
234};
235
236static void swaylock_bind(struct wl_client *client, void *data,
237 uint32_t version, uint32_t id) {
238 if (version > 1) {
239 // Unsupported version
240 return;
241 }
242
243 struct wl_resource *resource = wl_resource_create(client, &lock_interface, version, id);
244 if (!resource) {
245 wl_client_post_no_memory(client);
246 }
247
248 wl_resource_set_implementation(resource, &swaylock_implementation, NULL, NULL);
249}
250
251static void gamma_control_destroy(struct wl_client *client, struct wl_resource *res) {
252 wl_resource_destroy(res);
253}
254
255static void gamma_control_set_gamma(struct wl_client *client,
256 struct wl_resource *res, struct wl_array *red,
257 struct wl_array *green, struct wl_array *blue) {
258 if (red->size != green->size || red->size != blue->size) {
259 wl_resource_post_error(res, GAMMA_CONTROL_ERROR_INVALID_GAMMA,
260 "The gamma ramps don't have the same size");
261 return;
262 }
263 uint16_t *r = (uint16_t *)red->data;
264 uint16_t *g = (uint16_t *)green->data;
265 uint16_t *b = (uint16_t *)blue->data;
266 wlc_handle output = wlc_handle_from_wl_output_resource(
267 wl_resource_get_user_data(res));
268 if (!output) {
269 return;
270 }
271 sway_log(L_DEBUG, "Setting gamma for output");
272 wlc_output_set_gamma(output, red->size / sizeof(uint16_t), r, g, b);
273}
274
275static void gamma_control_reset_gamma(struct wl_client *client,
276 struct wl_resource *resource) {
277 // This space intentionally left blank
278}
279
280static struct gamma_control_interface gamma_control_implementation = {
281 .destroy = gamma_control_destroy,
282 .set_gamma = gamma_control_set_gamma,
283 .reset_gamma = gamma_control_reset_gamma
284};
285
286static void gamma_control_manager_destroy(struct wl_client *client,
287 struct wl_resource *res) {
288 wl_resource_destroy(res);
289}
290
291static void gamma_control_manager_get(struct wl_client *client,
292 struct wl_resource *res, uint32_t id, struct wl_resource *_output) {
293 struct wl_resource *manager_res = wl_resource_create(client,
294 &gamma_control_interface, wl_resource_get_version(res), id);
295 wlc_handle output = wlc_handle_from_wl_output_resource(_output);
296 if (!output) {
297 return;
298 }
299 wl_resource_set_implementation(manager_res, &gamma_control_implementation,
300 _output, NULL);
301 gamma_control_send_gamma_size(manager_res, wlc_output_get_gamma_size(output));
302}
303
304static struct gamma_control_manager_interface gamma_manager_implementation = {
305 .destroy = gamma_control_manager_destroy,
306 .get_gamma_control = gamma_control_manager_get
307};
308
309static void gamma_control_manager_bind(struct wl_client *client, void *data,
310 uint32_t version, uint32_t id) {
311 if (version > 1) {
312 // Unsupported version
313 return;
314 }
315 struct wl_resource *resource = wl_resource_create(client,
316 &gamma_control_manager_interface, version, id);
317 if (!resource) {
318 wl_client_post_no_memory(client);
319 }
320 wl_resource_set_implementation(resource, &gamma_manager_implementation, NULL, NULL);
321}
322
323static void server_decoration_release(struct wl_client *client,
324 struct wl_resource *resource) {
325 wl_resource_destroy(resource);
326}
327
328void server_decoration_enable_csd(wlc_handle handle) {
329 swayc_t *view = swayc_by_handle(handle);
330 if (!view) {
331 sway_log(L_DEBUG, "view invalid");
332 return;
333 }
334 sway_log(L_DEBUG, "%s requested client side decorations", view->name);
335 view->border_type = B_NONE;
336 update_geometry(view);
337}
338
339static void server_decoration_request_mode(struct wl_client *client,
340 struct wl_resource *resource, uint32_t mode) {
341 sway_log(L_DEBUG, "Client requested server decoration mode %d", mode);
342 if (mode == ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER) {
343 return;
344 }
345 struct wl_resource *surface = wl_resource_get_user_data(resource);
346 if (!surface) {
347 sway_log(L_DEBUG, "surface invalid");
348 return;
349 }
350 wlc_handle handle = wlc_handle_from_wl_surface_resource(surface);
351 if (!handle) {
352 list_add(decoration_state.csd_resources, surface);
353 return;
354 }
355 server_decoration_enable_csd(handle);
356}
357
358static struct org_kde_kwin_server_decoration_interface server_decoration_implementation = {
359 .release = server_decoration_release,
360 .request_mode = server_decoration_request_mode,
361};
362
363static void server_decoration_manager_create(struct wl_client *client,
364 struct wl_resource *resource, uint32_t id, struct wl_resource *surface) {
365 sway_log(L_DEBUG, "Client requested server decoration manager");
366 struct wl_resource *manager = wl_resource_create(client,
367 &org_kde_kwin_server_decoration_interface, 1, id);
368 if (!manager) {
369 wl_client_post_no_memory(client);
370 }
371 wl_resource_set_implementation(manager, &server_decoration_implementation, surface, NULL);
372}
373
374// Jesus christ KDE, these names are whack as hell
375static struct org_kde_kwin_server_decoration_manager_interface server_decoration_manager_implementation = {
376 .create = server_decoration_manager_create,
377};
378
379static void server_decoration_manager_bind(struct wl_client *client, void *data,
380 uint32_t version, uint32_t id) {
381 if (version > 1) {
382 // Unsupported version
383 return;
384 }
385 struct wl_resource *resource = wl_resource_create(client,
386 &org_kde_kwin_server_decoration_manager_interface, version, id);
387 if (!resource) {
388 wl_client_post_no_memory(client);
389 }
390 wl_resource_set_implementation(resource, &server_decoration_manager_implementation, NULL, NULL);
391 org_kde_kwin_server_decoration_manager_send_default_mode(resource,
392 ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER);
393}
394
395void register_extensions(void) {
396 wl_global_create(wlc_get_wl_display(), &desktop_shell_interface, 3, NULL, desktop_shell_bind);
397 desktop_shell.backgrounds = create_list();
398 desktop_shell.panels = create_list();
399 desktop_shell.lock_surfaces = create_list();
400 desktop_shell.is_locked = false;
401 decoration_state.csd_resources = create_list();
402 wl_global_create(wlc_get_wl_display(), &lock_interface, 1, NULL, swaylock_bind);
403 wl_global_create(wlc_get_wl_display(), &gamma_control_manager_interface, 1,
404 NULL, gamma_control_manager_bind);
405 wl_global_create(wlc_get_wl_display(), &org_kde_kwin_server_decoration_manager_interface ,
406 1, NULL, server_decoration_manager_bind);
407}