diff options
Diffstat (limited to 'sway/extensions.c')
-rw-r--r-- | sway/extensions.c | 407 |
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 | |||
16 | struct desktop_shell_state desktop_shell; | ||
17 | struct decoration_state decoration_state; | ||
18 | |||
19 | static 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 | |||
38 | void 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 | |||
50 | void 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 | |||
63 | void 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 | |||
87 | static 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 | |||
115 | static 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 | |||
138 | static 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 | |||
142 | static void desktop_unlock(struct wl_client *client, struct wl_resource *resource) { | ||
143 | sway_log(L_ERROR, "desktop_unlock is not currently supported"); | ||
144 | } | ||
145 | |||
146 | static 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 | |||
150 | static void desktop_ready(struct wl_client *client, struct wl_resource *resource) { | ||
151 | // nop | ||
152 | } | ||
153 | |||
154 | static 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 | |||
167 | static 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 | |||
177 | static 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 | |||
192 | static 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 | |||
226 | static 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 | |||
231 | static struct lock_interface swaylock_implementation = { | ||
232 | .set_lock_surface = set_lock_surface, | ||
233 | .unlock = unlock | ||
234 | }; | ||
235 | |||
236 | static 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 | |||
251 | static void gamma_control_destroy(struct wl_client *client, struct wl_resource *res) { | ||
252 | wl_resource_destroy(res); | ||
253 | } | ||
254 | |||
255 | static 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 | |||
275 | static void gamma_control_reset_gamma(struct wl_client *client, | ||
276 | struct wl_resource *resource) { | ||
277 | // This space intentionally left blank | ||
278 | } | ||
279 | |||
280 | static 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 | |||
286 | static void gamma_control_manager_destroy(struct wl_client *client, | ||
287 | struct wl_resource *res) { | ||
288 | wl_resource_destroy(res); | ||
289 | } | ||
290 | |||
291 | static 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 | |||
304 | static struct gamma_control_manager_interface gamma_manager_implementation = { | ||
305 | .destroy = gamma_control_manager_destroy, | ||
306 | .get_gamma_control = gamma_control_manager_get | ||
307 | }; | ||
308 | |||
309 | static 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 | |||
323 | static void server_decoration_release(struct wl_client *client, | ||
324 | struct wl_resource *resource) { | ||
325 | wl_resource_destroy(resource); | ||
326 | } | ||
327 | |||
328 | void 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 | |||
339 | static 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 | |||
358 | static struct org_kde_kwin_server_decoration_interface server_decoration_implementation = { | ||
359 | .release = server_decoration_release, | ||
360 | .request_mode = server_decoration_request_mode, | ||
361 | }; | ||
362 | |||
363 | static 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 | ||
375 | static struct org_kde_kwin_server_decoration_manager_interface server_decoration_manager_implementation = { | ||
376 | .create = server_decoration_manager_create, | ||
377 | }; | ||
378 | |||
379 | static 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 | |||
395 | void 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 | } | ||